diff --git a/.eslintrc b/.eslintrc index ba03e236..e5f35a64 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,16 +1,81 @@ { - "parserOptions": { - "ecmaVersion": 8, - "sourceType": "module", - "ecmaFeatures": { - "jsx": false + "env": { + "node": true + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "tsconfig.lint.json", + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/indent": [ + "error", + 2 + ], + "@typescript-eslint/member-delimiter-style": [ + "error", + { + "multiline": { + "delimiter": "semi", + "requireLast": true + }, + "singleline": { + "delimiter": "semi", + "requireLast": false } - }, - "rules": { - "semi": "error", - "quotes": ["error", "single"] - }, - "env": { - "es6": true - } + } + ], + "@typescript-eslint/member-ordering": "off", // to keep the same as with the java version + // "@typescript-eslint/naming-convention": "error", // constants are UPPERCASE but should be camelCase + "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/quotes": [ + "error", + "single" + ], + "@typescript-eslint/semi": [ + "error", + "always" + ], + "@typescript-eslint/type-annotation-spacing": "error", + "brace-style": [ + "error", + "1tbs" + ], + "eqeqeq": [ + "error", + "smart" + ], + "id-blacklist": [ + "error", + "any", + "Number", + "number", + "String", + "string", + "Boolean", + "boolean", + "Undefined", + "undefined" + ], + "id-match": "error", + "no-bitwise": "off", // we use a lot of these + "no-eval": "error", + "no-redeclare": "error", + "no-trailing-spaces": "error", + "no-underscore-dangle": "error", + "no-unsafe-finally": "error", + "no-var": "error", + "spaced-comment": [ + "error", + "always", + { + "markers": [ + "/" + ] + } + ] + } } diff --git a/.mocharc.js b/.mocharc.js new file mode 100644 index 00000000..1e0d61c2 --- /dev/null +++ b/.mocharc.js @@ -0,0 +1,8 @@ +const log = require('loglevel'); +if (!process.env.LOG_LEVEL) process.env.LOG_LEVEL = 'info'; +log.setLevel(process.env.LOG_LEVEL) + +module.exports = { + extension: ['js', 'ts'], + timeout: 20000, +} diff --git a/.unibeautify.json b/.unibeautify.json deleted file mode 100644 index 6019d591..00000000 --- a/.unibeautify.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "JavaScript": { - "indent_size": 4, - "indent_char": " ", - "quotes": "single" - }, - "TypeScript": { - "indent_size": 4, - "indent_char": " ", - "quotes": "single" - } -} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 59d59217..f7c814bb 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,6 @@ { - "recommendations": [ - "EditorConfig.EditorConfig", - "ms-vscode.vscode-typescript-tslint-plugin", - "dbaeumer.vscode-eslint", - ] -} + "recommendations": [ + "EditorConfig.EditorConfig", + "dbaeumer.vscode-eslint", + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 3308ef6c..9491e2ec 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,160 +2,153 @@ "version": "0.2.0", "configurations": [ { - "type": "node", + "type": "pwa-node", "request": "launch", "name": "Unit Tests", - "program": "${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/ts-mocha/bin/ts-mocha", + "resolveSourceMapLocations": [ + "!**/node_modules/**" + ], "args": [ - "./src/**/*.spec.ts", - "--colors", - "--timeout", - "999999", - "--webpack-env", - "dbg", - "--webpack-config", - "webpack.config.test.js" - ] + "-p", + "tsconfig.test.json", + "--paths", + "./src/test/**/*.spec.ts" + ], }, { - "type": "node", + "type": "pwa-node", "request": "launch", - "name": "Unit Tests - ts-node", - "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", - "args": [ - "--require", - "ts-node/register", - "-u", - "tdd", - "--timeout", - "999999", - "--colors", - "--recursive", - "./src/test/**/*.spec.ts" + "name": "Code 39 Tests", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/ts-mocha/bin/ts-mocha", + "resolveSourceMapLocations": [ + "!**/node_modules/**" ], - "internalConsoleOptions": "openOnSessionStart" + "args": [ + "-p", + "tsconfig.test.json", + "--paths", + "./src/test/core/oned/Code39*.spec.ts" + ] }, { - "type": "node", + "type": "pwa-node", "request": "launch", - "name": "Code 39 Tests", - "program": "${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack", + "name": "EAN 8 Tests", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/ts-mocha/bin/ts-mocha", + "resolveSourceMapLocations": [ + "!**/node_modules/**" + ], "args": [ - "./src/test/core/oned/Code39*.spec.ts", - "--colors", - "--timeout", - "999999", - "--webpack-env", - "dbg", - "--webpack-config", - "webpack.config.test.js" + "-p", + "tsconfig.test.json", + "--paths", + "./src/test/core/oned/Ean8*.spec.ts" ] }, { - "type": "node", + "type": "pwa-node", "request": "launch", - "name": "EAN 13 Tests - ts-node", - "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "name": "EAN 13 Tests", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/ts-mocha/bin/ts-mocha", + "resolveSourceMapLocations": [ + "!**/node_modules/**" + ], "args": [ - "--require", - "ts-node/register", - "--require", - "tsconfig-paths/register", - "-u", - "tdd", - "--timeout", - "999999", - "--colors", - "--recursive", + "-p", + "tsconfig.test.json", + "--paths", "./src/test/core/oned/Ean13*.spec.ts" - ], - "internalConsoleOptions": "openOnSessionStart" + ] }, { - "type": "node", + "type": "pwa-node", "request": "launch", "name": "PDF417 Tests", - "program": "${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/ts-mocha/bin/ts-mocha", + "resolveSourceMapLocations": [ + "!**/node_modules/**" + ], "args": [ - "./src/test/core/pdf417/", - "--recursive", - "--colors", - "--timeout", - "999999", - "--webpack-env", - "dbg", - "--webpack-config", - "webpack.config.test.js" + "-p", + "tsconfig.test.json", + "--paths", + "./src/test/core/pdf417/**/*.spec.ts" ] }, { - "type": "node", + "type": "pwa-node", "request": "launch", "name": "QR Code Tests", - "program": "${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/ts-mocha/bin/ts-mocha", + "resolveSourceMapLocations": [ + "!**/node_modules/**" + ], "args": [ - "./src/test/core/qrcode/", - "--recursive", - "--colors", - "--timeout", - "999999", - "--webpack-env", - "dbg", - "--webpack-config", - "webpack.config.test.js" + "-p", + "tsconfig.test.json", + "--paths", + "./src/test/core/qrcode/**/*.spec.ts" ] }, { - "type": "node", + "type": "pwa-node", "request": "launch", "name": "Data Matrix Tests", - "program": "${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/ts-mocha/bin/ts-mocha", + "resolveSourceMapLocations": [ + "!**/node_modules/**" + ], "args": [ - "./src/test/core/datamatrix/", - "--recursive", - "--colors", - "--timeout", - "999999", - "--webpack-env", - "dbg", - "--webpack-config", - "webpack.config.test.js" + "-p", + "tsconfig.test.json", + "--paths", + "./src/test/core/datamatrix/**/*.spec.ts" ] }, { - "type": "node", + "type": "pwa-node", "request": "launch", "name": "Aztec 2D Tests", - "program": "${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack", + "internalConsoleOptions": "openOnSessionStart", + "program": "${workspaceFolder}/node_modules/ts-mocha/bin/ts-mocha", + "resolveSourceMapLocations": [ + "!**/node_modules/**" + ], "args": [ - "./src/test/core/aztec/", - "--recursive", - "--colors", - "--timeout", - "999999", - "--webpack-env", - "dbg", - "--webpack-config", - "webpack.config.test.js" - ] + "-p", + "tsconfig.test.json", + "--paths", + "./src/test/core/aztec/**/*.spec.ts" + ], + "internalConsoleOptions": "openOnSessionStart" }, { "type": "node", "request": "launch", - "name": "Aztec 2D Tests - ts-node", + "name": "Multi-reader Tests - ts-node", "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", "args": [ "--require", "ts-node/register", + "--require", + "tsconfig-paths/register", "-u", "tdd", "--timeout", "999999", "--colors", "--recursive", - "./src/test/core/aztec/**/*.spec.ts" + "./src/test/core/multi/**/*.spec.ts" ], "internalConsoleOptions": "openOnSessionStart" } ] -} +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index c390cfaf..f0861cc4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,11 @@ // Place your settings in this file to overwrite default and user settings. { - "tslint.enable": true, - "typescript.tsdk": "node_modules\\typescript\\lib" -} + "typescript.tsdk": "node_modules\\typescript\\lib", + "eslint.format.enable": true, + "[javascript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "[typescript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + } +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 91b0d15d..df1b6ace 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,6 +62,8 @@ https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html - `int` has 32 bits, signed, so `int[]` transforms to `Int32Array`. - `char` has 2 bytes, so `char[]` transforms to `Uint16Array`. - `long` has 64 bit two's complement `integer`, can be signed or unsigned. +- `float[]` can be ported to `Float32Array`. +- `double[]` can be ported to `Float64Array`. ### JavaScript's TypedArray @@ -71,8 +73,8 @@ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects - Take care of `int` -> `number` (integer to number) port when doing bitwise transformation especially `<<`. Do a `& 0xFFFFFFFF` for ints, a &0xFF for bytes. - Take care of array initialization, in Java `new Array(N)` initializes capacity NOT size/length. -- Use `Math.floor` for any division of ints otherwise the `number` type is a floating point and keeps the numbers after the dot. -- For `float` to `int` casting use `Math.trunc`, to replicate the same effect as Java casting does. +- Use `Math.floor` for any division of `int`s otherwise the `number` type is a floating point and keeps the numbers after the dot. +- For `float`/`number` to `int` casting use `Math.trunc`, to replicate the same effect as Java casting does. ## Encoding diff --git a/README.md b/README.md index 5348cf13..6cc15fde 100644 --- a/README.md +++ b/README.md @@ -42,13 +42,13 @@ [![Test Coverage](https://api.codeclimate.com/v1/badges/2b9c6ae92412ee8e15a9/test_coverage)](https://codeclimate.com/github/zxing-js/library/test_coverage) [![BCH compliance](https://bettercodehub.com/edge/badge/zxing-js/library?branch=master)](https://bettercodehub.com/) -## Demo +## Library -See [Live Preview](https://zxing-js.github.io/library/) in browser. +This is the base library meant to be run in Node.js or WebWorkers where the HTML DOM is not available. To use browser related features got to the [browser project](https://github.com/zxing-js/browser) which extends this library. See a [Live Preview](https://zxing-js.github.io/browser/) in your browser. **Note:** All the examples are using ES6, be sure is supported in your browser or modify as needed, Chrome recommended. -## Installation +## Documentation `npm i @zxing/library --save` @@ -109,7 +109,7 @@ Special thanks to all the contributors who have contributed for this project. We [![](https://sourcerer.io/fame/odahcam/zxing-js/library/images/0)](https://sourcerer.io/fame/odahcam/zxing-js/library/links/0)[![](https://sourcerer.io/fame/odahcam/zxing-js/library/images/1)](https://sourcerer.io/fame/odahcam/zxing-js/library/links/1)[![](https://sourcerer.io/fame/odahcam/zxing-js/library/images/2)](https://sourcerer.io/fame/odahcam/zxing-js/library/links/2)[![](https://sourcerer.io/fame/odahcam/zxing-js/library/images/3)](https://sourcerer.io/fame/odahcam/zxing-js/library/links/3)[![](https://sourcerer.io/fame/odahcam/zxing-js/library/images/4)](https://sourcerer.io/fame/odahcam/zxing-js/library/links/4)[![](https://sourcerer.io/fame/odahcam/zxing-js/library/images/5)](https://sourcerer.io/fame/odahcam/zxing-js/library/links/5)[![](https://sourcerer.io/fame/odahcam/zxing-js/library/images/6)](https://sourcerer.io/fame/odahcam/zxing-js/library/links/6)[![](https://sourcerer.io/fame/odahcam/zxing-js/library/images/7)](https://sourcerer.io/fame/odahcam/zxing-js/library/links/7) -And a special thanks to [@aleris][3] who created the project itself and made available the initial QR code port. +And a special thanks to [@aleris][2] who created the project itself and made available the initial QR code port. --- @@ -117,5 +117,4 @@ And a special thanks to [@aleris][3] who created the project itself and made ava [0]: https://www.npmjs.com/package/@zxing/library [1]: https://github.com/zxing/zxing -[2]: https://caniuse.com/#feat=bigint -[3]: https://github.com/aleris +[2]: https://github.com/aleris diff --git a/_config.yml b/_config.yml index 2f7efbea..fff4ab92 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-minimal \ No newline at end of file +theme: jekyll-theme-minimal diff --git a/docs/examples/aztec-camera/index.html b/docs/examples/aztec-camera/index.html deleted file mode 100644 index 858ef9fc..00000000 --- a/docs/examples/aztec-camera/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding from camera stream - - - - - - - - -
- -
-

Scan Aztec Code from Video Camera

- -

- HOME 🏡 -

- -

This example shows how to scan an Aztec code with ZXing javascript library from the device video camera. If more - than one video input devices are available (for example front and back camera) the example shows how to read - them and use a select to change the input device.

- -
- Start - Reset -
- -
- -
- - - - -
-

-
- -

See the source code for - this example.

-
- - - -
- - - - - - - diff --git a/docs/examples/barcode-camera/index.html b/docs/examples/barcode-camera/index.html deleted file mode 100644 index ec3b29e4..00000000 --- a/docs/examples/barcode-camera/index.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - ZXing TypeScript | Demo & Examples - - - - - - - - -
- -
-

Scan barcode from Video Camera

- -

- HOME 🏡 -

- -

- This example shows how to scan a barcode with ZXing javascript library from the device video camera. If more - than one video input devices are available (for example front and back camera) the example shows how to read - them and use a select to change the input device. -

- -
- Start - Reset -
- -
- -
- - - - -
- -

See the source code for this example.

- -
- - - -
- - - - - - - diff --git a/docs/examples/barcode-image/index.html b/docs/examples/barcode-image/index.html deleted file mode 100644 index a89941a6..00000000 --- a/docs/examples/barcode-image/index.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding Barcode from images - - - - - - - - -
- -
-

Scan barcode from <img>

- -

- HOME 🏡 -

- -

- These examples show how to scan a barcode with ZXing javascript library from an image. The examples decode from - the - src in - img tag, however is also possible to decode directly from an url without an - img tag. -

- -
-

Scan barcode from Code 128

-
- Decode -
-
- -
- -
-

-
-
- -
-
- -
-

Scan barcode from EAN-13

-
- Decode -
-
- -
- -
-

-
-
- -
-
- -
-

Scan barcode from ITF

-
- Decode -
-
- -
- -
-

-
-
- -

- See the - source code - for these examples. -

- -
- - - -
- - - - - - - diff --git a/docs/examples/datamatrix-image/index.html b/docs/examples/datamatrix-image/index.html deleted file mode 100644 index 8c2848dc..00000000 --- a/docs/examples/datamatrix-image/index.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding Data Matrix from image file - - - - - - - - -
- -
-

Scan Data Matrix from Image

- -

- HOME 🏡 -

- -

- This example shows how to scan a Data Matrix with ZXing javascript library from an image. - The example decodes from the - src in - img tag, however is also possible to decode directly from an url without an - img tag. -

- -
-
- Decode -
-
- -
- -
-

-
-
- -
-
- Decode -
-
- -
- -
-

-
-
- -
-
- Decode -
-
- -
- -
-

-
-
- -

See the source code - for this example.

- -
- - - -
- - - - - - - diff --git a/docs/examples/multi-camera/index.html b/docs/examples/multi-camera/index.html deleted file mode 100644 index ba2cbb0b..00000000 --- a/docs/examples/multi-camera/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding from camera stream - - - - - - - - -
- -
-

Scan 1D/2D Code from Video Camera

- -

- HOME 🏡 -

- -

This example shows how to scan any supported 1D/2D code with ZXing javascript library from the device video - camera. If more - than one video input devices are available (for example front and back camera) the example shows how to read - them and use a select to change the input device.

- -
- Start - Reset -
- -
- -
- - - - -
- -

See the source code - for this example.

-
- - - -
- - - - - - - diff --git a/docs/examples/multi-image/index.html b/docs/examples/multi-image/index.html deleted file mode 100644 index cf01403a..00000000 --- a/docs/examples/multi-image/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding from image file - - - - - - - - -
- -
-

Scan 1D/2D Code from Image

- -

- HOME 🏡 -

- -

- This example shows how to scan any supported 1D/2D code with ZXing javascript library from an image. - The example decodes from the - src in - img tag, however is also possible to decode directly from an url without an - img tag. -

- -
- Decode -
- -
- -
- - -
- -

See the source code for this example.

- -
- - - -
- - - - - - - diff --git a/docs/examples/pdf417-image/index.html b/docs/examples/pdf417-image/index.html deleted file mode 100644 index 4297a6ab..00000000 --- a/docs/examples/pdf417-image/index.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding PDF 417 from image file - - - - - - - - -
- -
-

Scan PDF 417 from Image

- -

- HOME 🏡 -

- -

- This example shows how to scan a PDF 417 with ZXing javascript library from an image. - The example decodes from the - src in - img tag, however is also possible to decode directly from an url without an - img tag. -

- -
-
- Decode -
-
- -
- -
-

-
-
- -
-
- Decode -
-
- -
- -
-

-
-
- -
- -
-
- Decode -
-
- -
- -
-

-
-
- -

See the source code - for this example.

- -
- - - -
- - - - - - - diff --git a/docs/examples/qr-camera/index.html b/docs/examples/qr-camera/index.html deleted file mode 100644 index 0aaa4663..00000000 --- a/docs/examples/qr-camera/index.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding from camera stream - - - - - - - - -
- -
-

Scan QR Code from Video Camera

- -

- HOME 🏡 -

- -

This example shows how to scan a QR code with ZXing javascript library from the device video camera. If more - than one video input devices are available (for example front and back camera) the example shows how to read - them and use a select to change the input device.

- -
- Start - Reset -
- -
- -
- - - -
- - -
- - -
- -

See the source code for - this example.

-
- - - -
- - - - - - - diff --git a/docs/examples/qr-image/index.html b/docs/examples/qr-image/index.html deleted file mode 100644 index d773942f..00000000 --- a/docs/examples/qr-image/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding QR Code from image file - - - - - - - - -
- -
-

Scan QR Code from Image

- -

- HOME 🏡 -

- -

- This example shows how to scan a QR code with ZXing javascript library from an image. - The example decodes from the - src in - img tag, however is also possible to decode directly from an url without an - img tag. -

- -
- Decode -
- -
- -
- - -
- -

See the source code for this example.

- -
- - - -
- - - - - - - diff --git a/docs/examples/qr-svg-writer/index.html b/docs/examples/qr-svg-writer/index.html deleted file mode 100644 index e9032214..00000000 --- a/docs/examples/qr-svg-writer/index.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - ZXing | Write QR Code to SVG - - - - - - - - -
- -
-

Write QR Code to SVG

- -

- HOME 🏡 -

- -

This example shows how to write a QR code to SVG with ZXing javascript library. - -

- -
-
- -
- -
- Write - Save File -
- - -
- -

See the source code for this example.

- -
- - - -
- - - - - - - - diff --git a/docs/examples/qr-video/index.html b/docs/examples/qr-video/index.html deleted file mode 100644 index ee4507a2..00000000 --- a/docs/examples/qr-video/index.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - ZXing TypeScript | Decoding from video - - - - - - - - -
- -
-

Scan QR Code from Video File

- -

- HOME 🏡 -

- -

- This example shows how to scan a QR code with ZXing javascript library from a video file. The example decodes - from an url and shows the video while decoding, however is also possbile to decode without showing the video. -

- -
- Start - Reset -
- - - QR code video from - https://cirocosta.github.io/qcode-decoder/. -
- -
- - -
- -

- See the source code for - this example. -

- -
- - - -
- - - - - - - diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 2a119d50..00000000 --- a/docs/index.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - ZXing TypeScript | Demo & Examples - - - - - - - - -
- -
-

ZXing TypeScript Examples

- -

ZXing ("zebra crossing") TypeScript is an open-source, multi-format 1D/2D barcode image processing library ported - to TypeScript from Java.

- -

The library can be used from browser or from node. Below are links to browser demo & examples.

- -

- More information can be found in - GitHub project home page. -

- -

Scanning Examples

- - -

- View - source code on GitHub. -

- -
- - - -
- - - - diff --git a/docs/resources/blackbox/code128-1/1.png b/docs/resources/blackbox/code128-1/1.png deleted file mode 100644 index 9801bfbd..00000000 Binary files a/docs/resources/blackbox/code128-1/1.png and /dev/null differ diff --git a/docs/resources/blackbox/datamatrix/0123456789.png b/docs/resources/blackbox/datamatrix/0123456789.png deleted file mode 100644 index dbe51229..00000000 Binary files a/docs/resources/blackbox/datamatrix/0123456789.png and /dev/null differ diff --git a/docs/resources/blackbox/datamatrix/17.png b/docs/resources/blackbox/datamatrix/17.png deleted file mode 100644 index a08d0ea0..00000000 Binary files a/docs/resources/blackbox/datamatrix/17.png and /dev/null differ diff --git a/docs/resources/blackbox/datamatrix/abcdefg-64x64.png b/docs/resources/blackbox/datamatrix/abcdefg-64x64.png deleted file mode 100644 index 048cea7d..00000000 Binary files a/docs/resources/blackbox/datamatrix/abcdefg-64x64.png and /dev/null differ diff --git a/docs/resources/blackbox/ean13-1/1.png b/docs/resources/blackbox/ean13-1/1.png deleted file mode 100644 index 0a514784..00000000 Binary files a/docs/resources/blackbox/ean13-1/1.png and /dev/null differ diff --git a/docs/resources/blackbox/itf/1.png b/docs/resources/blackbox/itf/1.png deleted file mode 100644 index 5ee59c39..00000000 Binary files a/docs/resources/blackbox/itf/1.png and /dev/null differ diff --git a/docs/resources/blackbox/pdf417-2/05.png b/docs/resources/blackbox/pdf417-2/05.png deleted file mode 100644 index 1d5a3668..00000000 Binary files a/docs/resources/blackbox/pdf417-2/05.png and /dev/null differ diff --git a/docs/resources/blackbox/pdf417-2/15.png b/docs/resources/blackbox/pdf417-2/15.png deleted file mode 100644 index 4735dc62..00000000 Binary files a/docs/resources/blackbox/pdf417-2/15.png and /dev/null differ diff --git a/docs/resources/blackbox/pdf417-3/08.png b/docs/resources/blackbox/pdf417-3/08.png deleted file mode 100644 index b75ecc8f..00000000 Binary files a/docs/resources/blackbox/pdf417-3/08.png and /dev/null differ diff --git a/docs/resources/blackbox/qrcode-3/01.png b/docs/resources/blackbox/qrcode-3/01.png deleted file mode 100644 index 0516fdee..00000000 Binary files a/docs/resources/blackbox/qrcode-3/01.png and /dev/null differ diff --git a/docs/resources/qrcode-video.mp4 b/docs/resources/qrcode-video.mp4 deleted file mode 100644 index 6652b417..00000000 Binary files a/docs/resources/qrcode-video.mp4 and /dev/null differ diff --git a/documentation/examples/multi-format-reader.md b/documentation/examples/multi-format-reader.md new file mode 100644 index 00000000..9c5e3b46 --- /dev/null +++ b/documentation/examples/multi-format-reader.md @@ -0,0 +1,22 @@ + +## Using MultiFormatReader to decode multiple formats + +Basic implementation of a `MultiFormatReader`, in a common.js environment, to decode QR and data matrix formats from a `RGBLuminanceSource`. + +```javascript +const { MultiFormatReader, BarcodeFormat } = require('@zxing/library'); + +const hints = new Map(); +const formats = [BarcodeFormat.QR_CODE, BarcodeFormat.DATA_MATRIX, /*...*/]; + +hints.set(DecodeHintType.POSSIBLE_FORMATS, formats); + +const reader = new MultiFormatReader(); + +reader.setHints(hints); + +const luminanceSource = new RGBLuminanceSource(imgByteArray, imgWidth, imgHeight); +const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource)); + +reader.decodeWithState(binaryBitmap); +``` diff --git a/documentation/getting-started/quick-start.md b/documentation/getting-started/quick-start.md new file mode 100644 index 00000000..a1d26fd9 --- /dev/null +++ b/documentation/getting-started/quick-start.md @@ -0,0 +1,29 @@ +## Installation + +zxing-js/library runs on Node.js and is available as an NPM package. You can install zxing-js/library in your project's directory as usual: + +`npm i @zxing/library --save` + +or using yarn + +`yarn add @zxing/library` + +## Usage + +Example of a simple `QRCodeReader` in an ES6 environment. + +```typescript +import { BinaryBitmap, HybridBinarizer, QRCodeReader, RGBLuminanceSource } from '@zxing/library'; + +const reader = new QRCodeReader(); + +// Extracted image byte array and dimensions +const luminanceSource = new RGBLuminanceSource(imgByteArray, imgWidth, imgHeight); +const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource)); + +try { + reader.decode(binaryBitmap); +} catch (err) { + console.error(err); +} +``` diff --git a/karma.conf.js b/karma.conf.js deleted file mode 100644 index 14820795..00000000 --- a/karma.conf.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Karma configuration file. - * - * @see https://karma-runner.github.io/0.13/config/configuration-file.html - */ -import * as path from 'path'; - -const ROOT = path.resolve(__dirname, '.'); - -function rootPath() { - return path.join.apply( - path, [ROOT].concat(Array.prototype.slice.call(arguments, 0)) - ); -} - -export default function (config) { - config.set({ - - basePath: '', - - frameworks: ['mocha', 'karma-typescript', 'chai', 'sinon'], - - files: ['src/**/*.ts'], - - preprocessors: { - '**/*.ts': ['karma-typescript'] - }, - - plugins: [ - require('karma-coverage'), - require('karma-mocha'), - require('karma-chai'), - require('karma-sinon'), - require('karma-remap-coverage'), - require('karma-typescript'), - require('karma-typescript-preprocessor'), - ], - - client: { - clearContext: false // leave Jasmine Spec Runner output visible in browser - }, - - /** - * add both "karma-coverage" and "karma-remap-coverage" reporters - */ - reporters: ['progress', 'coverage', 'remap-coverage', 'dots', 'karma-typescript'], - - /** - * save interim raw coverage report in memory - */ - coverageReporter: { - type: 'in-memory' - }, - - /** - * define where to save final remaped coverage reports - */ - remapCoverageReporter: { - 'text-summary': null, - html: './coverage/html', - cobertura: './coverage/cobertura.xml' - }, - - /** - * Port to listen in browser. - */ - port: 9876, - - /** - * Cool colors in CLI - */ - colors: true, - - /** - * Wath kinda logs should be shown - */ - logLevel: config.LOG_INFO, - - /** - * Watch for code modifications - */ - autoWatch: true, - - /** - * What browsers should be used - */ - browsers: ['Chrome_headless'], - - customLaunchers: { - Chrome_headless: { - base: 'Chrome', - flags: [ - ' — headless', - ' — disable-gpu', - ' — remote-debugging-port=9222' - ] - } - }, - - /** - * Keep testing or not. - */ - singleRun: false, - - concurrency: Infinity - }); -}; diff --git a/package.json b/package.json index b0373011..9e809029 100644 --- a/package.json +++ b/package.json @@ -40,70 +40,66 @@ }, "homepage": "https://zxing-js.github.io/library/", "private": false, - "main": "./cjs/index.js", - "module": "./esm/index.js", - "typings": "./esm/index.d.ts", - "esnext": "./es2015/index.js", - "browser": "./umd/index.js", - "browser:min": "./umd/index.min.js", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "unpkg": "dist/index.umd.min.js", + "typings": "dist/index.d.ts", + "files": [ + "dist" + ], "scripts": { - "lint": "yarn tslint --project .", + "lint": "yarn eslint src --ext .js,.ts", "clean": "yarn shx rm -rf dist output", - "test": "yarn test:build && yarn test:run", - "test:build": "tsc --build tsconfig.test.json", - "test:run": "mocha -r tsconfig-paths/register --timeout 200000 output/tests/**/*.spec.js", + "type-check": "tsc --noEmit", + "type-check:watch": "yarn type-check -- --watch", + "build": "yarn clean && rollup -c", + "build:umd:min": "gzip index.min.js -c > index.min.js.gz", + "test": "ts-mocha -p tsconfig.test.json --paths 'src/test/**/*.spec.ts' --timeout 180180", "cover": "nyc --reporter=lcov --reporter=text yarn test", - "build": "yarn clean && yarn build:es2015 && yarn build:esm && yarn build:esnext && yarn build:cjs && yarn build:umd && yarn build:umd:min && yarn build:copy", - "build:es2015": "tsc --build tsconfig.lib-es2015.json", - "build:esm": "tsc --build tsconfig.lib-esm.json", - "build:esnext": "tsc --build tsconfig.lib-esm.json", - "build:cjs": "tsc --build tsconfig.lib-cjs.json", - "build:umd": "rollup -c rollup.config.js", - "build:umd:min": "cd dist/umd && terser --compress --mangle --source-map --screw-ie8 --comments -o index.min.js -- index.js && gzip index.min.js -c > index.min.js.gz", - "build:copy": "cp README.md dist && cp package.json dist && cp LICENSE dist", - "shx": "./node_modules/.bin/shx", - "tsc": "./node_modules/.bin/tsc", - "tslint": "./node_modules/.bin/tslint \"./src/**/*.ts\"" + "docs": "typedoc", + "docs:deploy": "node ./tools/docs-deploy.js", + "shx": "./node_modules/.bin/shx" }, "dependencies": { - "ts-custom-error": "^3.0.0" + "ts-custom-error": "^3.2.0" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^7.1.3", - "@types/chai": "^4.1.7", - "@types/mocha": "^5.2.6", - "@types/node": "^10.12.29", - "@types/seedrandom": "^2.4.27", - "@types/sharp": "^0.22.2", + "@rollup/plugin-commonjs": "^16.0.0", + "@rollup/plugin-node-resolve": "^10.0.0", + "@rollup/plugin-typescript": "^6.1.0", + "@types/mocha": "^8.0.4", + "@types/node": "^14.14.7", + "@types/seedrandom": "^2.4.28", + "@types/sharp": "^0.26.1", + "@typescript-eslint/eslint-plugin": "^4.7.0", + "@typescript-eslint/parser": "^4.7.0", "@zxing/text-encoding": "~0.9.0", - "chai": "^4.2.0", "codacy-coverage": "^3.4.0", - "eslint": "^5.15.1", - "karma": "^3.1.4", - "karma-chai": "^0.1.0", - "karma-chrome-launcher": "^2.2.0", - "karma-coverage": "^1.1.2", - "karma-mocha": "^1.3.0", - "karma-remap-coverage": "^0.1.5", - "karma-sinon": "^1.0.5", - "karma-sourcemap-loader": "^0.3.7", - "karma-typescript": "^3.0.13", - "karma-typescript-preprocessor": "^0.4.0", - "mocha": "^5.2.0", + "eslint": "^7.13.0", + "gh-pages": "^3.1.0", + "git-url-parse": "^11.4.0", + "loglevel": "^1.7.0", + "minimist": "^1.2.5", + "mocha": "^8.2.1", "mocha-lcov-reporter": "^1.3.0", "nyc": "^15.1.0", - "rollup": "^2.8.2", - "seedrandom": "^2.4.4", - "sharp": "^0.22.1", - "shx": "0.3.2", - "sinon": "^7.2.7", - "terser": "^5.3.7", + "rollup": "^2.33.2", + "rollup-plugin-terser": "^7.0.2", + "rollup-plugin-typescript2": "^0.29.0", + "seedrandom": "^3.0.5", + "sharp": "^0.26.2", + "shx": "0.3.3", + "sinon": "^9.2.1", + "terser": "^5.3.8", + "ts-mocha": "^8.0.0", "ts-node": "^9.0.0", "tsconfig-paths": "^3.9.0", - "tslint": "^6.1.3", - "tslint-no-circular-imports": "^0.7.0", - "typescript": "^3", - "yarn": "^1.17.3" + "tslib": "^2.0.3", + "typedoc": "^0.19.2", + "typedoc-plugin-external-module-name": "^4.0.3", + "typedoc-plugin-pages": "^1.0.1", + "typescript": "^4.0.5", + "yarn": "^1.22.10" }, "optionalDependencies": { "@zxing/text-encoding": "~0.9.0" @@ -113,4 +109,4 @@ "url": "https://opencollective.com/zxing-js", "logo": "https://opencollective.com/zxing-js/logo.txt" } -} +} \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js index ef2b9a0f..44a615f2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,18 +1,56 @@ import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import typescript from 'rollup-plugin-typescript2'; +import { terser } from 'rollup-plugin-terser'; +import pkg from './package.json'; -export default { - input: 'dist/es2015/index.js', - external: [ - '@zxing/text-encoding', - ], - plugins: [ - resolve(), - ], - context: '(globalThis || global || self || window || undefined)', - output: { - format: 'umd', - name: 'ZXing', - sourcemap: true, - file: 'dist/umd/index.js' +const extensions = ['.js', '.ts']; + +export default [ + { + input: './src/index.ts', + external: [ + '@zxing/text-encoding', + ], + context: '(globalThis || global || self || window || undefined)', + plugins: [ + resolve({ + extensions, + }), + commonjs(), + typescript({ + tsconfig: './tsconfig.lib.json', + }), + ], + output: [ + { + name: 'ZXing', + file: pkg.browser, + format: 'umd', + sourcemap: false, + plugins: [ + terser({ + output: { + comments: function (_, comment) { + let text = comment.value; + let type = comment.type; + if (type === 'comment2') { + // multiline comment + return /@preserve|@license|@cc_on/i.test(text); + } + }, + } + }) + ], + }, + { + file: pkg.main, + format: 'cjs', + }, + { + file: pkg.module, + format: 'esm', + }, + ], }, -}; +]; diff --git a/src/browser.ts b/src/browser.ts deleted file mode 100644 index 73da26fe..00000000 --- a/src/browser.ts +++ /dev/null @@ -1,13 +0,0 @@ -// browser -export * from './browser/BrowserAztecCodeReader'; -export * from './browser/BrowserBarcodeReader'; -export * from './browser/BrowserCodeReader'; -export * from './browser/BrowserDatamatrixCodeReader'; -export * from './browser/BrowserMultiFormatReader'; -export * from './browser/BrowserPDF417Reader'; -export * from './browser/BrowserQRCodeReader'; -export * from './browser/BrowserQRCodeSvgWriter'; -export * from './browser/DecodeContinuouslyCallback'; -export * from './browser/HTMLCanvasElementLuminanceSource'; -export * from './browser/HTMLVisualMediaElement'; -export * from './browser/VideoInputDevice'; diff --git a/src/browser/BrowserAztecCodeReader.ts b/src/browser/BrowserAztecCodeReader.ts deleted file mode 100644 index d669599c..00000000 --- a/src/browser/BrowserAztecCodeReader.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { BrowserCodeReader } from './BrowserCodeReader'; -import AztecReader from '../core/aztec/AztecReader'; - -/** - * Aztec Code reader to use from browser. - * - * @class BrowserAztecCodeReader - * @extends {BrowserCodeReader} - */ -export class BrowserAztecCodeReader extends BrowserCodeReader { - /** - * Creates an instance of BrowserAztecCodeReader. - * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries - * - * @memberOf BrowserAztecCodeReader - */ - public constructor(timeBetweenScansMillis: number = 500) { - super(new AztecReader(), timeBetweenScansMillis); - } -} diff --git a/src/browser/BrowserBarcodeReader.ts b/src/browser/BrowserBarcodeReader.ts deleted file mode 100644 index ba1b1573..00000000 --- a/src/browser/BrowserBarcodeReader.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { BrowserCodeReader } from './BrowserCodeReader'; -import MultiFormatOneDReader from '../core/oned/MultiFormatOneDReader'; -import DecodeHintType from '../core/DecodeHintType'; - -/** - * @deprecated Moving to @zxing/browser - * - * Barcode reader reader to use from browser. - */ -export class BrowserBarcodeReader extends BrowserCodeReader { - /** - * Creates an instance of BrowserBarcodeReader. - * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries - * @param {Map} hints - */ - public constructor(timeBetweenScansMillis: number = 500, hints?: Map) { - super(new MultiFormatOneDReader(hints), timeBetweenScansMillis, hints); - } -} diff --git a/src/browser/BrowserCodeReader.ts b/src/browser/BrowserCodeReader.ts deleted file mode 100644 index 02001816..00000000 --- a/src/browser/BrowserCodeReader.ts +++ /dev/null @@ -1,1057 +0,0 @@ -import ArgumentException from '../core/ArgumentException'; -import BinaryBitmap from '../core/BinaryBitmap'; -import ChecksumException from '../core/ChecksumException'; -import HybridBinarizer from '../core/common/HybridBinarizer'; -import DecodeHintType from '../core/DecodeHintType'; -import FormatException from '../core/FormatException'; -import NotFoundException from '../core/NotFoundException'; -import Reader from '../core/Reader'; -import Result from '../core/Result'; -import { DecodeContinuouslyCallback } from './DecodeContinuouslyCallback'; -import { HTMLCanvasElementLuminanceSource } from './HTMLCanvasElementLuminanceSource'; -import { HTMLVisualMediaElement } from './HTMLVisualMediaElement'; -import { VideoInputDevice } from './VideoInputDevice'; - -/** - * @deprecated Moving to @zxing/browser - * - * Base class for browser code reader. - */ -export class BrowserCodeReader { - - /** - * If navigator is present. - */ - public get hasNavigator() { - return typeof navigator !== 'undefined'; - } - - /** - * If mediaDevices under navigator is supported. - */ - public get isMediaDevicesSuported() { - return this.hasNavigator && !!navigator.mediaDevices; - } - - /** - * If enumerateDevices under navigator is supported. - */ - public get canEnumerateDevices() { - return !!(this.isMediaDevicesSuported && navigator.mediaDevices.enumerateDevices); - } - - /** - * This will break the loop. - */ - private _stopContinuousDecode = false; - - /** - * This will break the loop. - */ - private _stopAsyncDecode = false; - - /** - * Delay time between decode attempts made by the scanner. - */ - protected _timeBetweenDecodingAttempts: number = 0; - - /** Time between two decoding tries in milli seconds. */ - get timeBetweenDecodingAttempts(): number { - return this._timeBetweenDecodingAttempts; - } - - /** - * Change the time span the decoder waits between two decoding tries. - * - * @param {number} millis Time between two decoding tries in milli seconds. - */ - set timeBetweenDecodingAttempts(millis: number) { - this._timeBetweenDecodingAttempts = millis < 0 ? 0 : millis; - } - - /** - * The HTML canvas element, used to draw the video or image's frame for decoding. - */ - protected captureCanvas: HTMLCanvasElement; - /** - * The HTML canvas element context. - */ - protected captureCanvasContext: CanvasRenderingContext2D; - - /** - * The HTML image element, used as a fallback for the video element when decoding. - */ - protected imageElement: HTMLImageElement; - - /** - * Should contain the current registered listener for image loading, - * used to unregister that listener when needed. - */ - protected imageLoadedListener: EventListener; - - /** - * The stream output from camera. - */ - protected stream: MediaStream; - - /** - * The HTML video element, used to display the camera stream. - */ - protected videoElement: HTMLVideoElement; - - /** - * Should contain the current registered listener for video loaded-metadata, - * used to unregister that listener when needed. - */ - protected videoCanPlayListener: EventListener; - - /** - * Should contain the current registered listener for video play-ended, - * used to unregister that listener when needed. - */ - protected videoEndedListener: EventListener; - - /** - * Should contain the current registered listener for video playing, - * used to unregister that listener when needed. - */ - protected videoPlayingEventListener: EventListener; - - /** - * Sets the hints. - */ - set hints(hints: Map) { - this._hints = hints || null; - } - - /** - * Sets the hints. - */ - get hints(): Map { - return this._hints; - } - - /** - * Creates an instance of BrowserCodeReader. - * @param {Reader} reader The reader instance to decode the barcode - * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent successful decode tries - * - * @memberOf BrowserCodeReader - */ - public constructor(protected readonly reader: Reader, protected timeBetweenScansMillis: number = 500, protected _hints?: Map) { } - - /** - * Lists all the available video input devices. - */ - public async listVideoInputDevices(): Promise { - - if (!this.hasNavigator) { - throw new Error('Can\'t enumerate devices, navigator is not present.'); - } - - if (!this.canEnumerateDevices) { - throw new Error('Can\'t enumerate devices, method not supported.'); - } - - const devices = await navigator.mediaDevices.enumerateDevices(); - - const videoDevices: MediaDeviceInfo[] = []; - - for (const device of devices) { - - const kind = device.kind === 'video' ? 'videoinput' : device.kind; - - if (kind !== 'videoinput') { - continue; - } - - const deviceId = device.deviceId || (device).id; - const label = device.label || `Video device ${videoDevices.length + 1}`; - const groupId = device.groupId; - - const videoDevice = { deviceId, label, kind, groupId }; - - videoDevices.push(videoDevice); - } - - return videoDevices; - } - - - /** - * Obtain the list of available devices with type 'videoinput'. - * - * @returns {Promise} an array of available video input devices - * - * @memberOf BrowserCodeReader - * - * @deprecated Use `listVideoInputDevices` instead. - */ - public async getVideoInputDevices(): Promise { - - const devices = await this.listVideoInputDevices(); - - return devices.map(d => new VideoInputDevice(d.deviceId, d.label)); - } - - /** - * Let's you find a device using it's Id. - */ - public async findDeviceById(deviceId: string): Promise { - - const devices = await this.listVideoInputDevices(); - - if (!devices) { - return null; - } - - return devices.find(x => x.deviceId === deviceId); - } - - /** - * Decodes the barcode from the device specified by deviceId while showing the video in the specified video element. - * - * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available. - * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. - * @returns The decoding result. - * - * @memberOf BrowserCodeReader - * - * @deprecated Use `decodeOnceFromVideoDevice` instead. - */ - public async decodeFromInputVideoDevice(deviceId?: string, videoSource?: string | HTMLVideoElement): Promise { - return await this.decodeOnceFromVideoDevice(deviceId, videoSource); - } - - /** - * In one attempt, tries to decode the barcode from the device specified by deviceId while showing the video in the specified video element. - * - * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available. - * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. - * @returns The decoding result. - * - * @memberOf BrowserCodeReader - */ - public async decodeOnceFromVideoDevice(deviceId?: string, videoSource?: string | HTMLVideoElement): Promise { - - this.reset(); - - let videoConstraints: MediaTrackConstraints; - - if (!deviceId) { - videoConstraints = { facingMode: 'environment' }; - } else { - videoConstraints = { deviceId: { exact: deviceId } }; - } - - const constraints: MediaStreamConstraints = { video: videoConstraints }; - - return await this.decodeOnceFromConstraints(constraints, videoSource); - } - - /** - * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element. - * - * @param constraints the media stream constraints to get s valid media stream to decode from - * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. - * @returns The decoding result. - * - * @memberOf BrowserCodeReader - */ - public async decodeOnceFromConstraints(constraints: MediaStreamConstraints, videoSource?: string | HTMLVideoElement): Promise { - - const stream = await navigator.mediaDevices.getUserMedia(constraints); - - return await this.decodeOnceFromStream(stream, videoSource); - } - - /** - * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element. - * - * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from - * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. - * @returns {Promise} The decoding result. - * - * @memberOf BrowserCodeReader - */ - public async decodeOnceFromStream(stream: MediaStream, videoSource?: string | HTMLVideoElement): Promise { - - this.reset(); - - const video = await this.attachStreamToVideo(stream, videoSource); - const result = await this.decodeOnce(video); - - return result; - } - - /** - * Continuously decodes the barcode from the device specified by device while showing the video in the specified video element. - * - * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available. - * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. - * @returns {Promise} - * - * @memberOf BrowserCodeReader - * - * @deprecated Use `decodeFromVideoDevice` instead. - */ - public async decodeFromInputVideoDeviceContinuously(deviceId: string | null, videoSource: string | HTMLVideoElement | null, callbackFn: DecodeContinuouslyCallback): Promise { - return await this.decodeFromVideoDevice(deviceId, videoSource, callbackFn); - } - - /** - * Continuously tries to decode the barcode from the device specified by device while showing the video in the specified video element. - * - * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available. - * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. - * @returns {Promise} - * - * @memberOf BrowserCodeReader - */ - public async decodeFromVideoDevice(deviceId: string | null, videoSource: string | HTMLVideoElement | null, callbackFn: DecodeContinuouslyCallback): Promise { - - let videoConstraints: MediaTrackConstraints; - - if (!deviceId) { - videoConstraints = { facingMode: 'environment' }; - } else { - videoConstraints = { deviceId: { exact: deviceId } }; - } - - const constraints: MediaStreamConstraints = { video: videoConstraints }; - - return await this.decodeFromConstraints(constraints, videoSource, callbackFn); - } - - /** - * Continuously tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element. - * - * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from - * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. - * @returns {Promise} The decoding result. - * - * @memberOf BrowserCodeReader - */ - public async decodeFromConstraints(constraints: MediaStreamConstraints, videoSource: string | HTMLVideoElement, callbackFn: DecodeContinuouslyCallback): Promise { - - const stream = await navigator.mediaDevices.getUserMedia(constraints); - - return await this.decodeFromStream(stream, videoSource, callbackFn); - } - - /** - * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element. - * - * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from - * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. - * @returns {Promise} The decoding result. - * - * @memberOf BrowserCodeReader - */ - public async decodeFromStream(stream: MediaStream, videoSource: string | HTMLVideoElement, callbackFn: DecodeContinuouslyCallback) { - - this.reset(); - - const video = await this.attachStreamToVideo(stream, videoSource); - - return await this.decodeContinuously(video, callbackFn); - } - - /** - * Breaks the decoding loop. - */ - public stopAsyncDecode() { - this._stopAsyncDecode = true; - } - - /** - * Breaks the decoding loop. - */ - public stopContinuousDecode() { - this._stopContinuousDecode = true; - } - - /** - * Sets the new stream and request a new decoding-with-delay. - * - * @param stream The stream to be shown in the video element. - * @param decodeFn A callback for the decode method. - */ - protected async attachStreamToVideo(stream: MediaStream, videoSource: string | HTMLVideoElement): Promise { - - const videoElement = this.prepareVideoElement(videoSource); - - this.addVideoSource(videoElement, stream); - - this.videoElement = videoElement; - this.stream = stream; - - await this.playVideoOnLoadAsync(videoElement); - - return videoElement; - } - - /** - * - * @param videoElement - */ - protected playVideoOnLoadAsync(videoElement: HTMLVideoElement): Promise { - return new Promise((resolve, reject) => this.playVideoOnLoad(videoElement, () => resolve())); - } - - /** - * Binds listeners and callbacks to the videoElement. - * - * @param element - * @param callbackFn - */ - protected playVideoOnLoad(element: HTMLVideoElement, callbackFn: EventListener): void { - - this.videoEndedListener = () => this.stopStreams(); - this.videoCanPlayListener = () => this.tryPlayVideo(element); - - element.addEventListener('ended', this.videoEndedListener); - element.addEventListener('canplay', this.videoCanPlayListener); - element.addEventListener('playing', callbackFn); - - // if canplay was already fired, we won't know when to play, so just give it a try - this.tryPlayVideo(element); - } - - /** - * Checks if the given video element is currently playing. - */ - isVideoPlaying(video: HTMLVideoElement): boolean { - return video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2; - } - - /** - * Just tries to play the video and logs any errors. - * The play call is only made is the video is not already playing. - */ - async tryPlayVideo(videoElement: HTMLVideoElement): Promise { - - if (this.isVideoPlaying(videoElement)) { - console.warn('Trying to play video that is already playing.'); - return; - } - - try { - await videoElement.play(); - } catch { - console.warn('It was not possible to play the video.'); - } - } - - /** - * Searches and validates a media element. - */ - public getMediaElement(mediaElementId: string, type: string): HTMLVisualMediaElement { - - const mediaElement = document.getElementById(mediaElementId); - - if (!mediaElement) { - throw new ArgumentException(`element with id '${mediaElementId}' not found`); - } - - if (mediaElement.nodeName.toLowerCase() !== type.toLowerCase()) { - throw new ArgumentException(`element with id '${mediaElementId}' must be an ${type} element`); - } - - return mediaElement; - } - - /** - * Decodes the barcode from an image. - * - * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter. - * @param {string} [url] - * @returns {Promise} The decoding result. - * - * @memberOf BrowserCodeReader - */ - public decodeFromImage(source?: string | HTMLImageElement, url?: string): Promise { - - if (!source && !url) { - throw new ArgumentException('either imageElement with a src set or an url must be provided'); - } - - if (url && !source) { - return this.decodeFromImageUrl(url); - } - - return this.decodeFromImageElement(source); - } - - /** - * Decodes the barcode from a video. - * - * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter. - * @param {string} [url] - * @returns {Promise} The decoding result. - * - * @memberOf BrowserCodeReader - */ - public decodeFromVideo(source?: string | HTMLVideoElement, url?: string): Promise { - - if (!source && !url) { - throw new ArgumentException('Either an element with a src set or an URL must be provided'); - } - - if (url && !source) { - return this.decodeFromVideoUrl(url); - } - - return this.decodeFromVideoElement(source); - } - - /** - * Decodes continuously the barcode from a video. - * - * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter. - * @param {string} [url] - * @returns {Promise} The decoding result. - * - * @memberOf BrowserCodeReader - * - * @experimental - */ - public decodeFromVideoContinuously(source: string | HTMLVideoElement | null, url: string | null, callbackFn: DecodeContinuouslyCallback): Promise { - - if (undefined === source && undefined === url) { - throw new ArgumentException('Either an element with a src set or an URL must be provided'); - } - - if (url && !source) { - return this.decodeFromVideoUrlContinuously(url, callbackFn); - } - - return this.decodeFromVideoElementContinuously(source, callbackFn); - } - - /** - * Decodes something from an image HTML element. - */ - public decodeFromImageElement(source: string | HTMLImageElement): Promise { - - if (!source) { - throw new ArgumentException('An image element must be provided.'); - } - - this.reset(); - - const element = this.prepareImageElement(source); - - this.imageElement = element; - - let task: Promise; - - if (this.isImageLoaded(element)) { - task = this.decodeOnce(element, false, true); - } else { - task = this._decodeOnLoadImage(element); - } - - return task; - } - - /** - * Decodes something from an image HTML element. - */ - public decodeFromVideoElement(source: string | HTMLVideoElement): Promise { - - const element = this._decodeFromVideoElementSetup(source); - - return this._decodeOnLoadVideo(element); - } - - /** - * Decodes something from an image HTML element. - */ - public decodeFromVideoElementContinuously(source: string | HTMLVideoElement, callbackFn: DecodeContinuouslyCallback): Promise { - - const element = this._decodeFromVideoElementSetup(source); - - return this._decodeOnLoadVideoContinuously(element, callbackFn); - } - - /** - * Sets up the video source so it can be decoded when loaded. - * - * @param source The video source element. - */ - private _decodeFromVideoElementSetup(source: string | HTMLVideoElement) { - - if (!source) { - throw new ArgumentException('A video element must be provided.'); - } - - this.reset(); - - const element = this.prepareVideoElement(source); - - // defines the video element before starts decoding - this.videoElement = element; - - return element; - } - - /** - * Decodes an image from a URL. - */ - public decodeFromImageUrl(url?: string): Promise { - - if (!url) { - throw new ArgumentException('An URL must be provided.'); - } - - this.reset(); - - const element = this.prepareImageElement(); - - this.imageElement = element; - - const decodeTask = this._decodeOnLoadImage(element); - - element.src = url; - - return decodeTask; - } - - /** - * Decodes an image from a URL. - */ - public decodeFromVideoUrl(url: string): Promise { - - if (!url) { - throw new ArgumentException('An URL must be provided.'); - } - - this.reset(); - - // creates a new element - const element = this.prepareVideoElement(); - - const decodeTask = this.decodeFromVideoElement(element); - - element.src = url; - - return decodeTask; - } - - /** - * Decodes an image from a URL. - * - * @experimental - */ - public decodeFromVideoUrlContinuously(url: string, callbackFn: DecodeContinuouslyCallback): Promise { - - if (!url) { - throw new ArgumentException('An URL must be provided.'); - } - - this.reset(); - - // creates a new element - const element = this.prepareVideoElement(); - - const decodeTask = this.decodeFromVideoElementContinuously(element, callbackFn); - - element.src = url; - - return decodeTask; - } - - private _decodeOnLoadImage(element: HTMLImageElement): Promise { - return new Promise((resolve, reject) => { - this.imageLoadedListener = () => this.decodeOnce(element, false, true).then(resolve, reject); - element.addEventListener('load', this.imageLoadedListener); - }); - } - - private async _decodeOnLoadVideo(videoElement: HTMLVideoElement): Promise { - // plays the video - await this.playVideoOnLoadAsync(videoElement); - // starts decoding after played the video - return await this.decodeOnce(videoElement); - } - - private async _decodeOnLoadVideoContinuously(videoElement: HTMLVideoElement, callbackFn: DecodeContinuouslyCallback): Promise { - // plays the video - await this.playVideoOnLoadAsync(videoElement); - // starts decoding after played the video - this.decodeContinuously(videoElement, callbackFn); - } - - public isImageLoaded(img: HTMLImageElement) { - // During the onload event, IE correctly identifies any images that - // weren’t downloaded as not complete. Others should too. Gecko-based - // browsers act like NS4 in that they report this incorrectly. - if (!img.complete) { - return false; - } - - // However, they do have two very useful properties: naturalWidth and - // naturalHeight. These give the true size of the image. If it failed - // to load, either of these should be zero. - - if (img.naturalWidth === 0) { - return false; - } - - // No other way of checking: assume it’s ok. - return true; - } - - public prepareImageElement(imageSource?: HTMLImageElement | string): HTMLImageElement { - - let imageElement: HTMLImageElement; - - if (typeof imageSource === 'undefined') { - imageElement = document.createElement('img'); - imageElement.width = 200; - imageElement.height = 200; - } - - if (typeof imageSource === 'string') { - imageElement = this.getMediaElement(imageSource, 'img'); - } - - if (imageSource instanceof HTMLImageElement) { - imageElement = imageSource; - } - - return imageElement; - } - - /** - * Sets a HTMLVideoElement for scanning or creates a new one. - * - * @param videoSource The HTMLVideoElement to be set. - */ - public prepareVideoElement(videoSource?: HTMLVideoElement | string): HTMLVideoElement { - - let videoElement: HTMLVideoElement; - - if (!videoSource && typeof document !== 'undefined') { - videoElement = document.createElement('video'); - videoElement.width = 200; - videoElement.height = 200; - } - - if (typeof videoSource === 'string') { - videoElement = this.getMediaElement(videoSource, 'video'); - } - - if (videoSource instanceof HTMLVideoElement) { - videoElement = videoSource; - } - - // Needed for iOS 11 - videoElement.setAttribute('autoplay', 'true'); - videoElement.setAttribute('muted', 'true'); - videoElement.setAttribute('playsinline', 'true'); - - return videoElement; - } - - /** - * Tries to decode from the video input until it finds some value. - */ - public decodeOnce(element: HTMLVisualMediaElement, retryIfNotFound = true, retryIfChecksumOrFormatError = true): Promise { - - this._stopAsyncDecode = false; - - const loop = (resolve: (value?: Result | PromiseLike) => void, reject: (reason?: any) => void) => { - - if (this._stopAsyncDecode) { - reject(new NotFoundException('Video stream has ended before any code could be detected.')); - this._stopAsyncDecode = undefined; - return; - } - - try { - const result = this.decode(element); - resolve(result); - } catch (e) { - - const ifNotFound = retryIfNotFound && e instanceof NotFoundException; - const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException; - const ifChecksumOrFormat = isChecksumOrFormatError && retryIfChecksumOrFormatError; - - if (ifNotFound || ifChecksumOrFormat) { - // trying again - return setTimeout(loop, this._timeBetweenDecodingAttempts, resolve, reject); - } - - reject(e); - } - }; - - return new Promise((resolve, reject) => loop(resolve, reject)); - } - - /** - * Continuously decodes from video input. - */ - public decodeContinuously(element: HTMLVideoElement, callbackFn: DecodeContinuouslyCallback): void { - - this._stopContinuousDecode = false; - - const loop = () => { - - if (this._stopContinuousDecode) { - this._stopContinuousDecode = undefined; - return; - } - - try { - const result = this.decode(element); - callbackFn(result, null); - setTimeout(loop, this.timeBetweenScansMillis); - } catch (e) { - - callbackFn(null, e); - - const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException; - const isNotFound = e instanceof NotFoundException; - - if (isChecksumOrFormatError || isNotFound) { - // trying again - setTimeout(loop, this._timeBetweenDecodingAttempts); - } - - } - }; - - loop(); - } - - /** - * Gets the BinaryBitmap for ya! (and decodes it) - */ - public decode(element: HTMLVisualMediaElement): Result { - - // get binary bitmap for decode function - const binaryBitmap = this.createBinaryBitmap(element); - - return this.decodeBitmap(binaryBitmap); - } - - /** - * Creates a binaryBitmap based in some image source. - * - * @param mediaElement HTML element containing drawable image source. - */ - public createBinaryBitmap(mediaElement: HTMLVisualMediaElement): BinaryBitmap { - - const ctx = this.getCaptureCanvasContext(mediaElement); - - this.drawImageOnCanvas(ctx, mediaElement); - - const canvas = this.getCaptureCanvas(mediaElement); - - const luminanceSource = new HTMLCanvasElementLuminanceSource(canvas); - const hybridBinarizer = new HybridBinarizer(luminanceSource); - - return new BinaryBitmap(hybridBinarizer); - } - - /** - * - */ - protected getCaptureCanvasContext(mediaElement?: HTMLVisualMediaElement) { - - if (!this.captureCanvasContext) { - const elem = this.getCaptureCanvas(mediaElement); - const ctx = elem.getContext('2d'); - this.captureCanvasContext = ctx; - } - - return this.captureCanvasContext; - } - - /** - * - */ - protected getCaptureCanvas(mediaElement?: HTMLVisualMediaElement): HTMLCanvasElement { - - if (!this.captureCanvas) { - const elem = this.createCaptureCanvas(mediaElement); - this.captureCanvas = elem; - } - - return this.captureCanvas; - } - - /** - * Ovewriting this allows you to manipulate the snapshot image in anyway you want before decode. - */ - public drawImageOnCanvas(canvasElementContext: CanvasRenderingContext2D, srcElement: HTMLVisualMediaElement) { - canvasElementContext.drawImage(srcElement, 0, 0); - } - - /** - * Call the encapsulated readers decode - */ - public decodeBitmap(binaryBitmap: BinaryBitmap): Result { - return this.reader.decode(binaryBitmap, this._hints); - } - - /** - * 🖌 Prepares the canvas for capture and scan frames. - */ - public createCaptureCanvas(mediaElement?: HTMLVisualMediaElement): HTMLCanvasElement { - - if (typeof document === 'undefined') { - this._destroyCaptureCanvas(); - return null; - } - - const canvasElement = document.createElement('canvas'); - - let width: number; - let height: number; - - if (typeof mediaElement !== 'undefined') { - if (mediaElement instanceof HTMLVideoElement) { - width = mediaElement.videoWidth; - height = mediaElement.videoHeight; - } else if (mediaElement instanceof HTMLImageElement) { - width = mediaElement.naturalWidth || mediaElement.width; - height = mediaElement.naturalHeight || mediaElement.height; - } - } - - canvasElement.style.width = width + 'px'; - canvasElement.style.height = height + 'px'; - canvasElement.width = width; - canvasElement.height = height; - - return canvasElement; - } - - /** - * Stops the continuous scan and cleans the stream. - */ - protected stopStreams(): void { - if (this.stream) { - this.stream.getVideoTracks().forEach(t => t.stop()); - this.stream = undefined; - } - if (this._stopAsyncDecode === false) { - this.stopAsyncDecode(); - } - if (this._stopContinuousDecode === false) { - this.stopContinuousDecode(); - } - } - - /** - * Resets the code reader to the initial state. Cancels any ongoing barcode scanning from video or camera. - * - * @memberOf BrowserCodeReader - */ - public reset() { - - // stops the camera, preview and scan 🔴 - - this.stopStreams(); - - // clean and forget about HTML elements - - this._destroyVideoElement(); - this._destroyImageElement(); - this._destroyCaptureCanvas(); - } - - private _destroyVideoElement(): void { - - if (!this.videoElement) { - return; - } - - // first gives freedon to the element 🕊 - - if (typeof this.videoEndedListener !== 'undefined') { - this.videoElement.removeEventListener('ended', this.videoEndedListener); - } - - if (typeof this.videoPlayingEventListener !== 'undefined') { - this.videoElement.removeEventListener('playing', this.videoPlayingEventListener); - } - - if (typeof this.videoCanPlayListener !== 'undefined') { - this.videoElement.removeEventListener('loadedmetadata', this.videoCanPlayListener); - } - - // then forgets about that element 😢 - - this.cleanVideoSource(this.videoElement); - - this.videoElement = undefined; - } - - private _destroyImageElement(): void { - - if (!this.imageElement) { - return; - } - - // first gives freedon to the element 🕊 - - if (undefined !== this.imageLoadedListener) { - this.imageElement.removeEventListener('load', this.imageLoadedListener); - } - - // then forget about that element 😢 - - this.imageElement.src = undefined; - this.imageElement.removeAttribute('src'); - this.imageElement = undefined; - } - - /** - * Cleans canvas references 🖌 - */ - private _destroyCaptureCanvas(): void { - - // then forget about that element 😢 - - this.captureCanvasContext = undefined; - this.captureCanvas = undefined; - } - - /** - * Defines what the videoElement src will be. - * - * @param videoElement - * @param stream - */ - public addVideoSource(videoElement: HTMLVideoElement, stream: MediaStream): void { - // Older browsers may not have `srcObject` - try { - // @note Throws Exception if interrupted by a new loaded request - videoElement.srcObject = stream; - } catch (err) { - // @note Avoid using this in new browsers, as it is going away. - videoElement.src = URL.createObjectURL(stream); - } - } - - /** - * Unbinds a HTML video src property. - * - * @param videoElement - */ - private cleanVideoSource(videoElement: HTMLVideoElement): void { - - try { - videoElement.srcObject = null; - } catch (err) { - videoElement.src = ''; - } - - this.videoElement.removeAttribute('src'); - } -} diff --git a/src/browser/BrowserDatamatrixCodeReader.ts b/src/browser/BrowserDatamatrixCodeReader.ts deleted file mode 100644 index d5f86cd8..00000000 --- a/src/browser/BrowserDatamatrixCodeReader.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { BrowserCodeReader } from './BrowserCodeReader'; -import DataMatrixReader from '../core/datamatrix/DataMatrixReader'; - -/** - * @deprecated Moving to @zxing/browser - * - * QR Code reader to use from browser. - */ -export class BrowserDatamatrixCodeReader extends BrowserCodeReader { - /** - * Creates an instance of BrowserQRCodeReader. - * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries - */ - public constructor(timeBetweenScansMillis: number = 500) { - super(new DataMatrixReader(), timeBetweenScansMillis); - } -} diff --git a/src/browser/BrowserMultiFormatReader.ts b/src/browser/BrowserMultiFormatReader.ts deleted file mode 100644 index a983f14d..00000000 --- a/src/browser/BrowserMultiFormatReader.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { BrowserCodeReader } from './BrowserCodeReader'; -import MultiFormatReader from '../core/MultiFormatReader'; -import BinaryBitmap from '../core/BinaryBitmap'; -import Result from '../core/Result'; -import DecodeHintType from '../core/DecodeHintType'; - -export class BrowserMultiFormatReader extends BrowserCodeReader { - - protected readonly reader: MultiFormatReader; - - public constructor( - hints: Map = null, - timeBetweenScansMillis: number = 500 - ) { - const reader = new MultiFormatReader(); - reader.setHints(hints); - super(reader, timeBetweenScansMillis); - } - - /** - * Overwrite decodeBitmap to call decodeWithState, which will pay - * attention to the hints set in the constructor function - */ - public decodeBitmap(binaryBitmap: BinaryBitmap): Result { - return this.reader.decodeWithState(binaryBitmap); - } -} diff --git a/src/browser/BrowserPDF417Reader.ts b/src/browser/BrowserPDF417Reader.ts deleted file mode 100644 index ba8899a8..00000000 --- a/src/browser/BrowserPDF417Reader.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { BrowserCodeReader } from './BrowserCodeReader'; -import PDF417Reader from '../core/pdf417/PDF417Reader'; - -/** - * @deprecated Moving to @zxing/browser - * - * QR Code reader to use from browser. - */ -export class BrowserPDF417Reader extends BrowserCodeReader { - /** - * Creates an instance of BrowserPDF417Reader. - * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries - */ - public constructor(timeBetweenScansMillis: number = 500) { - super(new PDF417Reader(), timeBetweenScansMillis); - } -} diff --git a/src/browser/BrowserQRCodeReader.ts b/src/browser/BrowserQRCodeReader.ts deleted file mode 100644 index 0af2194e..00000000 --- a/src/browser/BrowserQRCodeReader.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { BrowserCodeReader } from './BrowserCodeReader'; -import QRCodeReader from '../core/qrcode/QRCodeReader'; - -/** - * @deprecated Moving to @zxing/browser - * - * QR Code reader to use from browser. - */ -export class BrowserQRCodeReader extends BrowserCodeReader { - /** - * Creates an instance of BrowserQRCodeReader. - * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries - */ - public constructor(timeBetweenScansMillis: number = 500) { - super(new QRCodeReader(), timeBetweenScansMillis); - } -} diff --git a/src/browser/BrowserQRCodeSvgWriter.ts b/src/browser/BrowserQRCodeSvgWriter.ts deleted file mode 100644 index c84ba10a..00000000 --- a/src/browser/BrowserQRCodeSvgWriter.ts +++ /dev/null @@ -1,168 +0,0 @@ -import EncodeHintType from '../core/EncodeHintType'; -import Encoder from '../core/qrcode/encoder/Encoder'; -import QRCode from '../core/qrcode/encoder/QRCode'; -import ErrorCorrectionLevel from '../core/qrcode/decoder/ErrorCorrectionLevel'; -import IllegalArgumentException from '../core/IllegalArgumentException'; -import IllegalStateException from '../core/IllegalStateException'; - -/** - * @deprecated Moving to @zxing/browser - */ -class BrowserQRCodeSvgWriter { - - private static readonly QUIET_ZONE_SIZE = 4; - - /** - * SVG markup NameSpace - */ - private static readonly SVG_NS = 'http://www.w3.org/2000/svg'; - - /** - * Writes and renders a QRCode SVG element. - * - * @param contents - * @param width - * @param height - * @param hints - */ - public write( - contents: string, - width: number, - height: number, - hints: Map = null - ): SVGSVGElement { - - if (contents.length === 0) { - throw new IllegalArgumentException('Found empty contents'); - } - - // if (format != BarcodeFormat.QR_CODE) { - // throw new IllegalArgumentException("Can only encode QR_CODE, but got " + format) - // } - - if (width < 0 || height < 0) { - throw new IllegalArgumentException('Requested dimensions are too small: ' + width + 'x' + height); - } - - let errorCorrectionLevel = ErrorCorrectionLevel.L; - let quietZone = BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE; - - if (hints !== null) { - - if (undefined !== hints.get(EncodeHintType.ERROR_CORRECTION)) { - errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType.ERROR_CORRECTION).toString()); - } - - if (undefined !== hints.get(EncodeHintType.MARGIN)) { - quietZone = Number.parseInt(hints.get(EncodeHintType.MARGIN).toString(), 10); - } - } - - const code = Encoder.encode(contents, errorCorrectionLevel, hints); - - return this.renderResult(code, width, height, quietZone); - } - - /** - * Renders the result and then appends it to the DOM. - */ - public writeToDom( - containerElement: string | HTMLElement, - contents: string, - width: number, - height: number, - hints: Map = null - ): void { - - if (typeof containerElement === 'string') { - containerElement = document.querySelector(containerElement); - } - - const svgElement = this.write(contents, width, height, hints); - - if (containerElement) - containerElement.appendChild(svgElement); - } - - /** - * Note that the input matrix uses 0 == white, 1 == black. - * The output matrix uses 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap). - */ - private renderResult(code: QRCode, width: number /*int*/, height: number /*int*/, quietZone: number /*int*/): SVGSVGElement { - - const input = code.getMatrix(); - - if (input === null) { - throw new IllegalStateException(); - } - - const inputWidth = input.getWidth(); - const inputHeight = input.getHeight(); - const qrWidth = inputWidth + (quietZone * 2); - const qrHeight = inputHeight + (quietZone * 2); - const outputWidth = Math.max(width, qrWidth); - const outputHeight = Math.max(height, qrHeight); - - const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight)); - - // Padding includes both the quiet zone and the extra white pixels to accommodate the requested - // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone. - // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will - // handle all the padding from 100x100 (the actual QR) up to 200x160. - const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2); - const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2); - - const svgElement = this.createSVGElement(outputWidth, outputHeight); - - for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++ , outputY += multiple) { - // Write the contents of this row of the barcode - for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++ , outputX += multiple) { - if (input.get(inputX, inputY) === 1) { - const svgRectElement = this.createSvgRectElement(outputX, outputY, multiple, multiple); - svgElement.appendChild(svgRectElement); - } - } - } - - return svgElement; - } - - /** - * Creates a SVG element. - * - * @param w SVG's width attribute - * @param h SVG's height attribute - */ - private createSVGElement(w: number, h: number): SVGSVGElement { - - const svgElement = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'svg'); - - svgElement.setAttributeNS(null, 'height', w.toString()); - svgElement.setAttributeNS(null, 'width', h.toString()); - - return svgElement; - } - - /** - * Creates a SVG rect element. - * - * @param x Element's x coordinate - * @param y Element's y coordinate - * @param w Element's width attribute - * @param h Element's height attribute - */ - private createSvgRectElement(x: number, y: number, w: number, h: number): SVGRectElement { - - const rect = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'rect'); - - rect.setAttributeNS(null, 'x', x.toString()); - rect.setAttributeNS(null, 'y', y.toString()); - rect.setAttributeNS(null, 'height', w.toString()); - rect.setAttributeNS(null, 'width', h.toString()); - rect.setAttributeNS(null, 'fill', '#000000'); - - return rect; - } -} - -export { BrowserQRCodeSvgWriter }; diff --git a/src/browser/BrowserSvgCodeWriter.ts b/src/browser/BrowserSvgCodeWriter.ts deleted file mode 100644 index 4351b225..00000000 --- a/src/browser/BrowserSvgCodeWriter.ts +++ /dev/null @@ -1,180 +0,0 @@ -import EncodeHintType from '../core/EncodeHintType'; -import Encoder from '../core/qrcode/encoder/Encoder'; -import QRCode from '../core/qrcode/encoder/QRCode'; -import ErrorCorrectionLevel from '../core/qrcode/decoder/ErrorCorrectionLevel'; -import IllegalArgumentException from '../core/IllegalArgumentException'; -import IllegalStateException from '../core/IllegalStateException'; - -/** - * @deprecated Moving to @zxing/browser - */ -abstract class BrowserSvgCodeWriter { - - /** - * Default quiet zone in pixels. - */ - private static readonly QUIET_ZONE_SIZE = 4; - - /** - * SVG markup NameSpace - */ - private static readonly SVG_NS = 'http://www.w3.org/2000/svg'; - - /** - * A HTML container element for the image. - */ - private containerElement: HTMLElement; - - /** - * Constructs. 😉 - */ - public constructor(containerElement: string | HTMLElement) { - if (typeof containerElement === 'string') { - this.containerElement = document.getElementById(containerElement); - } else { - this.containerElement = containerElement; - } - } - - /** - * Writes the QR code to a SVG and renders it in the container. - */ - public write( - contents: string, - width: number, - height: number, - hints: Map = null - ): SVGSVGElement { - - if (contents.length === 0) { - throw new IllegalArgumentException('Found empty contents'); - } - - if (width < 0 || height < 0) { - throw new IllegalArgumentException('Requested dimensions are too small: ' + width + 'x' + height); - } - - let quietZone = hints && hints.get(EncodeHintType.MARGIN) !== undefined - ? Number.parseInt(hints.get(EncodeHintType.MARGIN).toString(), 10) - : BrowserSvgCodeWriter.QUIET_ZONE_SIZE; - - const code = this.encode(hints, contents); - - return this.renderResult(code, width, height, quietZone); - } - - /** - * Encodes the content to a Barcode type. - */ - private encode(hints: Map, contents: string): QRCode { - - let errorCorrectionLevel = ErrorCorrectionLevel.L; - - if (hints && hints.get(EncodeHintType.ERROR_CORRECTION) !== undefined) { - errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType.ERROR_CORRECTION).toString()); - } - - const code = Encoder.encode(contents, errorCorrectionLevel, hints); - - return code; - } - - /** - * Renders the SVG in the container. - * - * @note the input matrix uses 0 == white, 1 == black. The output matrix uses 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap). - */ - private renderResult(code: QRCode, width: number /*int*/, height: number /*int*/, quietZone: number /*int*/): SVGSVGElement { - - // if (this.format && format != this.format) { - // throw new IllegalArgumentException("Can only encode QR_CODE, but got " + format) - // } - - const input = code.getMatrix(); - - if (input === null) { - throw new IllegalStateException(); - } - - const inputWidth = input.getWidth(); - const inputHeight = input.getHeight(); - const qrWidth = inputWidth + (quietZone * 2); - const qrHeight = inputHeight + (quietZone * 2); - const outputWidth = Math.max(width, qrWidth); - const outputHeight = Math.max(height, qrHeight); - - const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight)); - - // Padding includes both the quiet zone and the extra white pixels to accommodate the requested - // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone. - // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will - // handle all the padding from 100x100 (the actual QR) up to 200x160. - const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2); - const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2); - - const svgElement = this.createSVGElement(outputWidth, outputHeight); - - const placeholder = this.createSvgPathPlaceholderElement(width, height); - - svgElement.append(placeholder); - - this.containerElement.appendChild(svgElement); - - // 2D loop - for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++ , outputY += multiple) { - // Write the contents of this row of the barcode - for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++ , outputX += multiple) { - if (input.get(inputX, inputY) === 1) { - const svgRectElement = this.createSvgRectElement(outputX, outputY, multiple, multiple); - svgElement.appendChild(svgRectElement); - } - } - } - - return svgElement; - } - - /** - * Creates a SVG element. - */ - protected createSVGElement(w: number, h: number): SVGSVGElement { - - const el = document.createElementNS(BrowserSvgCodeWriter.SVG_NS, 'svg'); - - el.setAttributeNS(null, 'width', h.toString()); - el.setAttributeNS(null, 'height', w.toString()); - - return el; - } - - /** - * Creates a SVG rect. - */ - protected createSvgPathPlaceholderElement(w: number, h: number): SVGPathElement { - - const el = document.createElementNS(BrowserSvgCodeWriter.SVG_NS, 'path'); - - el.setAttributeNS(null, 'd', `M0 0h${w}v${h}H0z`); - el.setAttributeNS(null, 'fill', 'none'); - - return el; - } - - /** - * Creates a SVG rect. - */ - protected createSvgRectElement(x: number, y: number, w: number, h: number): SVGRectElement { - - const el = document.createElementNS(BrowserSvgCodeWriter.SVG_NS, 'rect'); - - el.setAttributeNS(null, 'x', x.toString()); - el.setAttributeNS(null, 'y', y.toString()); - el.setAttributeNS(null, 'height', w.toString()); - el.setAttributeNS(null, 'width', h.toString()); - el.setAttributeNS(null, 'fill', '#000000'); - - return el; - } -} - -export { BrowserSvgCodeWriter }; diff --git a/src/browser/DecodeContinuouslyCallback.ts b/src/browser/DecodeContinuouslyCallback.ts deleted file mode 100644 index 350464bb..00000000 --- a/src/browser/DecodeContinuouslyCallback.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Exception from '../core/Exception'; -import Result from '../core/Result'; - -/** - * Callback format for continuous decode scan. - */ -export type DecodeContinuouslyCallback = (result: Result, error?: Exception) => any; diff --git a/src/browser/HTMLCanvasElementLuminanceSource.ts b/src/browser/HTMLCanvasElementLuminanceSource.ts deleted file mode 100644 index fb5f6d98..00000000 --- a/src/browser/HTMLCanvasElementLuminanceSource.ts +++ /dev/null @@ -1,140 +0,0 @@ -import InvertedLuminanceSource from '../core/InvertedLuminanceSource'; -import LuminanceSource from '../core/LuminanceSource'; -import IllegalArgumentException from '../core/IllegalArgumentException'; - -/** - * @deprecated Moving to @zxing/browser - */ -export class HTMLCanvasElementLuminanceSource extends LuminanceSource { - - private buffer: Uint8ClampedArray; - - private static DEGREE_TO_RADIANS = Math.PI / 180; - - private tempCanvasElement: HTMLCanvasElement = null; - - public constructor(private canvas: HTMLCanvasElement) { - super(canvas.width, canvas.height); - this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(canvas); - } - - private static makeBufferFromCanvasImageData(canvas: HTMLCanvasElement): Uint8ClampedArray { - const imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height); - return HTMLCanvasElementLuminanceSource.toGrayscaleBuffer(imageData.data, canvas.width, canvas.height); - } - - private static toGrayscaleBuffer(imageBuffer: Uint8ClampedArray, width: number, height: number): Uint8ClampedArray { - const grayscaleBuffer = new Uint8ClampedArray(width * height); - for (let i = 0, j = 0, length = imageBuffer.length; i < length; i += 4, j++) { - let gray; - const alpha = imageBuffer[i + 3]; - // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent - // black (0 alpha, and then 0 RGB). They are often used, of course as the "white" area in a - // barcode image. Force any such pixel to be white: - if (alpha === 0) { - gray = 0xFF; - } else { - const pixelR = imageBuffer[i]; - const pixelG = imageBuffer[i + 1]; - const pixelB = imageBuffer[i + 2]; - // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC), - // (306*R) >> 10 is approximately equal to R*0.299, and so on. - // 0x200 >> 10 is 0.5, it implements rounding. - gray = (306 * pixelR + - 601 * pixelG + - 117 * pixelB + - 0x200) >> 10; - } - grayscaleBuffer[j] = gray; - } - return grayscaleBuffer; - } - - public getRow(y: number /*int*/, row: Uint8ClampedArray): Uint8ClampedArray { - if (y < 0 || y >= this.getHeight()) { - throw new IllegalArgumentException('Requested row is outside the image: ' + y); - } - const width: number /*int*/ = this.getWidth(); - const start = y * width; - if (row === null) { - row = this.buffer.slice(start, start + width); - } else { - if (row.length < width) { - row = new Uint8ClampedArray(width); - } - // The underlying raster of image consists of bytes with the luminance values - // TODO: can avoid set/slice? - row.set(this.buffer.slice(start, start + width)); - } - - return row; - } - - public getMatrix(): Uint8ClampedArray { - return this.buffer; - } - - public isCropSupported(): boolean { - return true; - } - - public crop(left: number /*int*/, top: number /*int*/, width: number /*int*/, height: number /*int*/): LuminanceSource { - super.crop(left, top, width, height); - return this; - } - - /** - * This is always true, since the image is a gray-scale image. - * - * @return true - */ - public isRotateSupported(): boolean { - return true; - } - - public rotateCounterClockwise(): LuminanceSource { - this.rotate(-90); - return this; - } - - public rotateCounterClockwise45(): LuminanceSource { - this.rotate(-45); - return this; - } - - private getTempCanvasElement() { - if (null === this.tempCanvasElement) { - const tempCanvasElement = this.canvas.ownerDocument.createElement('canvas'); - tempCanvasElement.width = this.canvas.width; - tempCanvasElement.height = this.canvas.height; - this.tempCanvasElement = tempCanvasElement; - } - - return this.tempCanvasElement; - } - - private rotate(angle: number) { - const tempCanvasElement = this.getTempCanvasElement(); - const tempContext = tempCanvasElement.getContext('2d'); - const angleRadians = angle * HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS; - - // Calculate and set new dimensions for temp canvas - const width = this.canvas.width; - const height = this.canvas.height; - const newWidth = Math.ceil( Math.abs(Math.cos(angleRadians)) * width + Math.abs(Math.sin(angleRadians)) * height ); - const newHeight = Math.ceil( Math.abs(Math.sin(angleRadians)) * width + Math.abs(Math.cos(angleRadians)) * height ); - tempCanvasElement.width = newWidth; - tempCanvasElement.height = newHeight; - - // Draw at center of temp canvas to prevent clipping of image data - tempContext.translate(newWidth / 2, newHeight / 2); - tempContext.rotate(angleRadians); - tempContext.drawImage(this.canvas, width / -2, height / -2); - this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(tempCanvasElement); - return this; - } - - public invert(): LuminanceSource { - return new InvertedLuminanceSource(this); - } -} diff --git a/src/browser/HTMLVisualMediaElement.ts b/src/browser/HTMLVisualMediaElement.ts deleted file mode 100644 index 446b4eb2..00000000 --- a/src/browser/HTMLVisualMediaElement.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * HTML elements that can be decoded. - */ -export type HTMLVisualMediaElement = HTMLVideoElement | HTMLImageElement; diff --git a/src/browser/VideoInputDevice.ts b/src/browser/VideoInputDevice.ts deleted file mode 100644 index 7c00896e..00000000 --- a/src/browser/VideoInputDevice.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @deprecated Moving to @zxing/browser - * - * Video input device metadata containing the id and label of the device if available. - */ -export class VideoInputDevice implements MediaDeviceInfo { - - /** @inheritdoc */ - readonly kind = 'videoinput'; - - /** @inheritdoc */ - readonly groupId: string; - - /** - * Creates an instance of VideoInputDevice. - * - * @param {string} deviceId the video input device id - * @param {string} label the label of the device if available - */ - public constructor(public deviceId: string, public label: string, groupId?: string) { - this.groupId = groupId || undefined; - } - - /** @inheritdoc */ - toJSON() { - return { - kind: this.kind, - groupId: this.groupId, - deviceId: this.deviceId, - label: this.label, - }; - } -} diff --git a/src/core/BarcodeFormat.ts b/src/core/BarcodeFormat.ts index a6a5a148..89d97f8f 100644 --- a/src/core/BarcodeFormat.ts +++ b/src/core/BarcodeFormat.ts @@ -18,7 +18,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ /** * Enumerates barcode formats known to this package. Please keep alphabetized. @@ -26,56 +26,56 @@ * @author Sean Owen */ enum BarcodeFormat { - /** Aztec 2D barcode format. */ - AZTEC, + /** Aztec 2D barcode format. */ + AZTEC, - /** CODABAR 1D format. */ - CODABAR, + /** CODABAR 1D format. */ + CODABAR, - /** Code 39 1D format. */ - CODE_39, + /** Code 39 1D format. */ + CODE_39, - /** Code 93 1D format. */ - CODE_93, + /** Code 93 1D format. */ + CODE_93, - /** Code 128 1D format. */ - CODE_128, + /** Code 128 1D format. */ + CODE_128, - /** Data Matrix 2D barcode format. */ - DATA_MATRIX, + /** Data Matrix 2D barcode format. */ + DATA_MATRIX, - /** EAN-8 1D format. */ - EAN_8, + /** EAN-8 1D format. */ + EAN_8, - /** EAN-13 1D format. */ - EAN_13, + /** EAN-13 1D format. */ + EAN_13, - /** ITF (Interleaved Two of Five) 1D format. */ - ITF, + /** ITF (Interleaved Two of Five) 1D format. */ + ITF, - /** MaxiCode 2D barcode format. */ - MAXICODE, + /** MaxiCode 2D barcode format. */ + MAXICODE, - /** PDF417 format. */ - PDF_417, + /** PDF417 format. */ + PDF_417, - /** QR Code 2D barcode format. */ - QR_CODE, + /** QR Code 2D barcode format. */ + QR_CODE, - /** RSS 14 */ - RSS_14, + /** RSS 14 */ + RSS_14, - /** RSS EXPANDED */ - RSS_EXPANDED, + /** RSS EXPANDED */ + RSS_EXPANDED, - /** UPC-A 1D format. */ - UPC_A, + /** UPC-A 1D format. */ + UPC_A, - /** UPC-E 1D format. */ - UPC_E, + /** UPC-E 1D format. */ + UPC_E, - /** UPC/EAN extension format. Not a stand-alone format. */ - UPC_EAN_EXTENSION + /** UPC/EAN extension format. Not a stand-alone format. */ + UPC_EAN_EXTENSION } diff --git a/src/core/Binarizer.ts b/src/core/Binarizer.ts index 54ba9a36..18431ea6 100644 --- a/src/core/Binarizer.ts +++ b/src/core/Binarizer.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ import LuminanceSource from './LuminanceSource'; import BitArray from './common/BitArray'; @@ -30,56 +30,56 @@ import BitMatrix from './common/BitMatrix'; */ abstract class Binarizer { - protected constructor(private source: LuminanceSource) { } + protected constructor(private source: LuminanceSource) { } - public getLuminanceSource(): LuminanceSource { - return this.source; - } + public getLuminanceSource(): LuminanceSource { + return this.source; + } - /** - * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return - * cached data. Callers should assume this method is expensive and call it as seldom as possible. - * This method is intended for decoding 1D barcodes and may choose to apply sharpening. - * For callers which only examine one row of pixels at a time, the same BitArray should be reused - * and passed in with each call for performance. However it is legal to keep more than one row - * at a time if needed. - * - * @param y The row to fetch, which must be in [0, bitmap height) - * @param row An optional preallocated array. If null or too small, it will be ignored. - * If used, the Binarizer will call BitArray.clear(). Always use the returned object. - * @return The array of bits for this row (true means black). - * @throws NotFoundException if row can't be binarized - */ - public abstract getBlackRow(y: number/*iny*/, row: BitArray): BitArray; /*throws NotFoundException*/ + /** + * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return + * cached data. Callers should assume this method is expensive and call it as seldom as possible. + * This method is intended for decoding 1D barcodes and may choose to apply sharpening. + * For callers which only examine one row of pixels at a time, the same BitArray should be reused + * and passed in with each call for performance. However it is legal to keep more than one row + * at a time if needed. + * + * @param y The row to fetch, which must be in [0, bitmap height) + * @param row An optional preallocated array. If null or too small, it will be ignored. + * If used, the Binarizer will call BitArray.clear(). Always use the returned object. + * @return The array of bits for this row (true means black). + * @throws NotFoundException if row can't be binarized + */ + public abstract getBlackRow(y: number/* iny */, row: BitArray): BitArray; /* throws NotFoundException */ - /** - * Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive - * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or - * may not apply sharpening. Therefore, a row from this matrix may not be identical to one - * fetched using getBlackRow(), so don't mix and match between them. - * - * @return The 2D array of bits for the image (true means black). - * @throws NotFoundException if image can't be binarized to make a matrix - */ - public abstract getBlackMatrix(): BitMatrix; /*throws NotFoundException*/ + /** + * Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive + * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or + * may not apply sharpening. Therefore, a row from this matrix may not be identical to one + * fetched using getBlackRow(), so don't mix and match between them. + * + * @return The 2D array of bits for the image (true means black). + * @throws NotFoundException if image can't be binarized to make a matrix + */ + public abstract getBlackMatrix(): BitMatrix; /* throws NotFoundException */ - /** - * Creates a new object with the same type as this Binarizer implementation, but with pristine - * state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache - * of 1 bit data. See Effective Java for why we can't use Java's clone() method. - * - * @param source The LuminanceSource this Binarizer will operate on. - * @return A new concrete Binarizer implementation object. - */ - public abstract createBinarizer(source: LuminanceSource): Binarizer; + /** + * Creates a new object with the same type as this Binarizer implementation, but with pristine + * state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache + * of 1 bit data. See Effective Java for why we can't use Java's clone() method. + * + * @param source The LuminanceSource this Binarizer will operate on. + * @return A new concrete Binarizer implementation object. + */ + public abstract createBinarizer(source: LuminanceSource): Binarizer; - public getWidth(): number /*int*/ { - return this.source.getWidth(); - } + public getWidth(): number /* int */ { + return this.source.getWidth(); + } - public getHeight(): number /*int*/ { - return this.source.getHeight(); - } + public getHeight(): number /* int */ { + return this.source.getHeight(); + } } export default Binarizer; diff --git a/src/core/BinaryBitmap.ts b/src/core/BinaryBitmap.ts index 009b54c7..bcd05aba 100644 --- a/src/core/BinaryBitmap.ts +++ b/src/core/BinaryBitmap.ts @@ -21,7 +21,7 @@ * @author dswitkin@google.com (Daniel Switkin) */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ import Binarizer from './Binarizer'; import BitArray from './common/BitArray'; @@ -30,122 +30,122 @@ import LuminanceSource from './LuminanceSource'; import IllegalArgumentException from './IllegalArgumentException'; export default class BinaryBitmap { - private matrix: BitMatrix; + private matrix: BitMatrix; - public constructor(private binarizer: Binarizer) { - if (binarizer === null) { - throw new IllegalArgumentException('Binarizer must be non-null.'); - } + public constructor(private binarizer: Binarizer) { + if (binarizer === null) { + throw new IllegalArgumentException('Binarizer must be non-null.'); } + } - /** - * @return The width of the bitmap. - */ - public getWidth(): number /*int*/ { - return this.binarizer.getWidth(); - } - - /** - * @return The height of the bitmap. - */ - public getHeight(): number /*int*/ { - return this.binarizer.getHeight(); - } - - /** - * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return - * cached data. Callers should assume this method is expensive and call it as seldom as possible. - * This method is intended for decoding 1D barcodes and may choose to apply sharpening. - * - * @param y The row to fetch, which must be in [0, bitmap height) - * @param row An optional preallocated array. If null or too small, it will be ignored. - * If used, the Binarizer will call BitArray.clear(). Always use the returned object. - * @return The array of bits for this row (true means black). - * @throws NotFoundException if row can't be binarized - */ - public getBlackRow(y: number /*int*/, row: BitArray): BitArray /*throws NotFoundException */ { - return this.binarizer.getBlackRow(y, row); - } - - /** - * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive - * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or - * may not apply sharpening. Therefore, a row from this matrix may not be identical to one - * fetched using getBlackRow(), so don't mix and match between them. - * - * @return The 2D array of bits for the image (true means black). - * @throws NotFoundException if image can't be binarized to make a matrix - */ - public getBlackMatrix(): BitMatrix /*throws NotFoundException*/ { - // The matrix is created on demand the first time it is requested, then cached. There are two - // reasons for this: - // 1. This work will never be done if the caller only installs 1D Reader objects, or if a - // 1D Reader finds a barcode before the 2D Readers run. - // 2. This work will only be done once even if the caller installs multiple 2D Readers. - if (this.matrix === null || this.matrix === undefined) { - this.matrix = this.binarizer.getBlackMatrix(); - } - return this.matrix; - } - - /** - * @return Whether this bitmap can be cropped. - */ - public isCropSupported(): boolean { - return this.binarizer.getLuminanceSource().isCropSupported(); - } - - /** - * Returns a new object with cropped image data. Implementations may keep a reference to the - * original data rather than a copy. Only callable if isCropSupported() is true. - * - * @param left The left coordinate, which must be in [0,getWidth()) - * @param top The top coordinate, which must be in [0,getHeight()) - * @param width The width of the rectangle to crop. - * @param height The height of the rectangle to crop. - * @return A cropped version of this object. - */ - public crop(left: number /*int*/, top: number /*int*/, width: number /*int*/, height: number /*int*/): BinaryBitmap { - const newSource: LuminanceSource = this.binarizer.getLuminanceSource().crop(left, top, width, height); - return new BinaryBitmap(this.binarizer.createBinarizer(newSource)); - } - - /** - * @return Whether this bitmap supports counter-clockwise rotation. - */ - public isRotateSupported(): boolean { - return this.binarizer.getLuminanceSource().isRotateSupported(); - } + /** + * @return The width of the bitmap. + */ + public getWidth(): number /* int */ { + return this.binarizer.getWidth(); + } - /** - * Returns a new object with rotated image data by 90 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - public rotateCounterClockwise(): BinaryBitmap { - const newSource: LuminanceSource = this.binarizer.getLuminanceSource().rotateCounterClockwise(); - return new BinaryBitmap(this.binarizer.createBinarizer(newSource)); + /** + * @return The height of the bitmap. + */ + public getHeight(): number /* int */ { + return this.binarizer.getHeight(); + } + + /** + * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return + * cached data. Callers should assume this method is expensive and call it as seldom as possible. + * This method is intended for decoding 1D barcodes and may choose to apply sharpening. + * + * @param y The row to fetch, which must be in [0, bitmap height) + * @param row An optional preallocated array. If null or too small, it will be ignored. + * If used, the Binarizer will call BitArray.clear(). Always use the returned object. + * @return The array of bits for this row (true means black). + * @throws NotFoundException if row can't be binarized + */ + public getBlackRow(y: number /* int */, row: BitArray): BitArray /* throws NotFoundException */ { + return this.binarizer.getBlackRow(y, row); + } + + /** + * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive + * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or + * may not apply sharpening. Therefore, a row from this matrix may not be identical to one + * fetched using getBlackRow(), so don't mix and match between them. + * + * @return The 2D array of bits for the image (true means black). + * @throws NotFoundException if image can't be binarized to make a matrix + */ + public getBlackMatrix(): BitMatrix /* throws NotFoundException */ { + // The matrix is created on demand the first time it is requested, then cached. There are two + // reasons for this: + // 1. This work will never be done if the caller only installs 1D Reader objects, or if a + // 1D Reader finds a barcode before the 2D Readers run. + // 2. This work will only be done once even if the caller installs multiple 2D Readers. + if (this.matrix === null || this.matrix === undefined) { + this.matrix = this.binarizer.getBlackMatrix(); } + return this.matrix; + } - /** - * Returns a new object with rotated image data by 45 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - public rotateCounterClockwise45(): BinaryBitmap { - const newSource: LuminanceSource = this.binarizer.getLuminanceSource().rotateCounterClockwise45(); - return new BinaryBitmap(this.binarizer.createBinarizer(newSource)); - } + /** + * @return Whether this bitmap can be cropped. + */ + public isCropSupported(): boolean { + return this.binarizer.getLuminanceSource().isCropSupported(); + } + + /** + * Returns a new object with cropped image data. Implementations may keep a reference to the + * original data rather than a copy. Only callable if isCropSupported() is true. + * + * @param left The left coordinate, which must be in [0,getWidth()) + * @param top The top coordinate, which must be in [0,getHeight()) + * @param width The width of the rectangle to crop. + * @param height The height of the rectangle to crop. + * @return A cropped version of this object. + */ + public crop(left: number /* int */, top: number /* int */, width: number /* int */, height: number /* int */): BinaryBitmap { + const newSource: LuminanceSource = this.binarizer.getLuminanceSource().crop(left, top, width, height); + return new BinaryBitmap(this.binarizer.createBinarizer(newSource)); + } - /*@Override*/ - public toString(): string { - try { - return this.getBlackMatrix().toString(); - } catch (e /*: NotFoundException*/) { - return ''; - } + /** + * @return Whether this bitmap supports counter-clockwise rotation. + */ + public isRotateSupported(): boolean { + return this.binarizer.getLuminanceSource().isRotateSupported(); + } + + /** + * Returns a new object with rotated image data by 90 degrees counterclockwise. + * Only callable if {@link #isRotateSupported()} is true. + * + * @return A rotated version of this object. + */ + public rotateCounterClockwise(): BinaryBitmap { + const newSource: LuminanceSource = this.binarizer.getLuminanceSource().rotateCounterClockwise(); + return new BinaryBitmap(this.binarizer.createBinarizer(newSource)); + } + + /** + * Returns a new object with rotated image data by 45 degrees counterclockwise. + * Only callable if {@link #isRotateSupported()} is true. + * + * @return A rotated version of this object. + */ + public rotateCounterClockwise45(): BinaryBitmap { + const newSource: LuminanceSource = this.binarizer.getLuminanceSource().rotateCounterClockwise45(); + return new BinaryBitmap(this.binarizer.createBinarizer(newSource)); + } + + /* @Override */ + public toString(): string { + try { + return this.getBlackMatrix().toString(); + } catch (e /* : NotFoundException */) { + return ''; } + } } diff --git a/src/core/DecodeHintType.ts b/src/core/DecodeHintType.ts index e07470fe..8eeda091 100644 --- a/src/core/DecodeHintType.ts +++ b/src/core/DecodeHintType.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ /** * Encapsulates a type of hint that a caller may pass to a barcode reader to help it @@ -27,95 +27,95 @@ */ enum DecodeHintType { - /** - * Unspecified, application-specific hint. Maps to an unspecified {@link Object}. - */ - OTHER/*(Object.class)*/, - - /** - * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - PURE_BARCODE/*(Void.class)*/, - - /** - * Image is known to be of one of a few possible formats. - * Maps to a {@link List} of {@link BarcodeFormat}s. - */ - POSSIBLE_FORMATS/*(List.class)*/, - - /** - * Spend more time to try to find a barcode; optimize for accuracy, not speed. - * Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - TRY_HARDER/*(Void.class)*/, - - /** - * Specifies what character encoding to use when decoding, where applicable (type String) - */ - CHARACTER_SET/*(String.class)*/, - - /** - * Allowed lengths of encoded data -- reject anything else. Maps to an {@code Int32Array}. - */ - ALLOWED_LENGTHS/*(Int32Array.class)*/, - - /** - * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - ASSUME_CODE_39_CHECK_DIGIT/*(Void.class)*/, - - /** - * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. - * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - ASSUME_GS1/*(Void.class)*/, - - /** - * If true, return the start and end digits in a Codabar barcode instead of stripping them. They - * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them - * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - RETURN_CODABAR_START_END/*(Void.class)*/, - - /** - * The caller needs to be notified via callback when a possible {@link ResultPoint} - * is found. Maps to a {@link ResultPointCallback}. - */ - NEED_RESULT_POINT_CALLBACK/*(ResultPointCallback.class)*/, - - - /** - * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. - * Maps to an {@code Int32Array} of the allowed extension lengths, for example [2], [5], or [2, 5]. - * If it is optional to have an extension, do not set this hint. If this is set, - * and a UPC or EAN barcode is found but an extension is not, then no result will be returned - * at all. - */ - ALLOWED_EAN_EXTENSIONS/*(Int32Array.class)*/, - - // End of enumeration values. - - - /** - * Data type the hint is expecting. - * Among the possible values the {@link Void} stands out as being used for - * hints that do not expect a value to be supplied (flag hints). Such hints - * will possibly have their value ignored, or replaced by a - * {@link Boolean#TRUE}. Hint suppliers should probably use - * {@link Boolean#TRUE} as directed by the actual hint documentation. - */ - // private valueType: Class - - // DecodeHintType(valueType: Class) { - // this.valueType = valueType - // } - - // public getValueType(): Class { - // return valueType - // } + /** + * Unspecified, application-specific hint. Maps to an unspecified {@link Object}. + */ + OTHER/* (Object.class) */, + + /** + * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + PURE_BARCODE/* (Void.class) */, + + /** + * Image is known to be of one of a few possible formats. + * Maps to a {@link List} of {@link BarcodeFormat}s. + */ + POSSIBLE_FORMATS/* (List.class) */, + + /** + * Spend more time to try to find a barcode; optimize for accuracy, not speed. + * Doesn't matter what it maps to; use {@link Boolean#TRUE}. + */ + TRY_HARDER/* (Void.class) */, + + /** + * Specifies what character encoding to use when decoding, where applicable (type String) + */ + CHARACTER_SET/* (String.class) */, + + /** + * Allowed lengths of encoded data -- reject anything else. Maps to an {@code Int32Array}. + */ + ALLOWED_LENGTHS/* (Int32Array.class) */, + + /** + * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + ASSUME_CODE_39_CHECK_DIGIT/* (Void.class) */, + + /** + * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. + * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to; + * use {@link Boolean#TRUE}. + */ + ASSUME_GS1/* (Void.class) */, + + /** + * If true, return the start and end digits in a Codabar barcode instead of stripping them. They + * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them + * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}. + */ + RETURN_CODABAR_START_END/* (Void.class) */, + + /** + * The caller needs to be notified via callback when a possible {@link ResultPoint} + * is found. Maps to a {@link ResultPointCallback}. + */ + NEED_RESULT_POINT_CALLBACK/* (ResultPointCallback.class) */, + + + /** + * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. + * Maps to an {@code Int32Array} of the allowed extension lengths, for example [2], [5], or [2, 5]. + * If it is optional to have an extension, do not set this hint. If this is set, + * and a UPC or EAN barcode is found but an extension is not, then no result will be returned + * at all. + */ + ALLOWED_EAN_EXTENSIONS/* (Int32Array.class) */, + + // End of enumeration values. + + + /** + * Data type the hint is expecting. + * Among the possible values the {@link Void} stands out as being used for + * hints that do not expect a value to be supplied (flag hints). Such hints + * will possibly have their value ignored, or replaced by a + * {@link Boolean#TRUE}. Hint suppliers should probably use + * {@link Boolean#TRUE} as directed by the actual hint documentation. + */ + // private valueType: Class + + // DecodeHintType(valueType: Class) { + // this.valueType = valueType + // } + + // public getValueType(): Class { + // return valueType + // } } diff --git a/src/core/Dimension.ts b/src/core/Dimension.ts index 581c2cc8..f0cbcf75 100644 --- a/src/core/Dimension.ts +++ b/src/core/Dimension.ts @@ -16,43 +16,43 @@ import IllegalArgumentException from './IllegalArgumentException'; -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ /** * Simply encapsulates a width and height. */ export default class Dimension { - public constructor(private width: number /*int*/, private height: number /*int*/) { - if (width < 0 || height < 0) { - throw new IllegalArgumentException(); - } + public constructor(private width: number /* int */, private height: number /* int */) { + if (width < 0 || height < 0) { + throw new IllegalArgumentException(); } + } - public getWidth(): number /*int*/ { - return this.width; - } - - public getHeight(): number /*int*/ { - return this.height; - } + public getWidth(): number /* int */ { + return this.width; + } - /*@Override*/ - public equals(other: any): boolean { - if (other instanceof Dimension) { - const d = other; - return this.width === d.width && this.height === d.height; - } - return false; - } - - /*@Override*/ - public hashCode(): number /*int*/ { - return this.width * 32713 + this.height; - } + public getHeight(): number /* int */ { + return this.height; + } - /*@Override*/ - public toString(): string { - return this.width + 'x' + this.height; + /* @Override */ + public equals(other: any): boolean { + if (other instanceof Dimension) { + const d = other; + return this.width === d.width && this.height === d.height; } + return false; + } + + /* @Override */ + public hashCode(): number /* int */ { + return this.width * 32713 + this.height; + } + + /* @Override */ + public toString(): string { + return this.width + 'x' + this.height; + } } diff --git a/src/core/EncodeHintType.ts b/src/core/EncodeHintType.ts index d50be2d3..007e4eca 100644 --- a/src/core/EncodeHintType.ts +++ b/src/core/EncodeHintType.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ /** * These are a set of hints that you may pass to Writers to specify their behavior. @@ -23,84 +23,84 @@ */ enum EncodeHintType { - /** - * Specifies what degree of error correction to use, for example in QR Codes. - * Type depends on the encoder. For example for QR codes it's type - * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}. - * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words. - * For PDF417 it is of type {@link Integer}, valid values being 0 to 8. - * In all cases, it can also be a {@link String} representation of the desired value as well. - * Note: an Aztec symbol should have a minimum of 25% EC words. - */ - ERROR_CORRECTION, + /** + * Specifies what degree of error correction to use, for example in QR Codes. + * Type depends on the encoder. For example for QR codes it's type + * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}. + * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words. + * For PDF417 it is of type {@link Integer}, valid values being 0 to 8. + * In all cases, it can also be a {@link String} representation of the desired value as well. + * Note: an Aztec symbol should have a minimum of 25% EC words. + */ + ERROR_CORRECTION, - /** - * Specifies what character encoding to use where applicable (type {@link String}) - */ - CHARACTER_SET, + /** + * Specifies what character encoding to use where applicable (type {@link String}) + */ + CHARACTER_SET, - /** - * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint}) - */ - DATA_MATRIX_SHAPE, + /** + * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint}) + */ + DATA_MATRIX_SHAPE, - /** - * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. - * - * @deprecated use width/height params in - * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)} - */ - /*@Deprecated*/ - MIN_SIZE, + /** + * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. + * + * @deprecated use width/height params in + * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)} + */ + /* @Deprecated */ + MIN_SIZE, - /** - * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. - * - * @deprecated without replacement - */ - /*@Deprecated*/ - MAX_SIZE, + /** + * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. + * + * @deprecated without replacement + */ + /* @Deprecated */ + MAX_SIZE, - /** - * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary - * by format; for example it controls margin before and after the barcode horizontally for - * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value). - */ - MARGIN, + /** + * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary + * by format; for example it controls margin before and after the barcode horizontally for + * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value). + */ + MARGIN, - /** - * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false" - * {@link String} value). - */ - PDF417_COMPACT, + /** + * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false" + * {@link String} value). + */ + PDF417_COMPACT, - /** - * Specifies what compaction mode to use for PDF417 (type - * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its - * enum values). - */ - PDF417_COMPACTION, + /** + * Specifies what compaction mode to use for PDF417 (type + * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its + * enum values). + */ + PDF417_COMPACTION, - /** - * Specifies the minimum and maximum number of rows and columns for PDF417 (type - * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}). - */ - PDF417_DIMENSIONS, + /** + * Specifies the minimum and maximum number of rows and columns for PDF417 (type + * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}). + */ + PDF417_DIMENSIONS, - /** - * Specifies the required number of layers for an Aztec code. - * A negative number (-1, -2, -3, -4) specifies a compact Aztec code. - * 0 indicates to use the minimum number of layers (the default). - * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code. - * (Type {@link Integer}, or {@link String} representation of the integer value). - */ - AZTEC_LAYERS, + /** + * Specifies the required number of layers for an Aztec code. + * A negative number (-1, -2, -3, -4) specifies a compact Aztec code. + * 0 indicates to use the minimum number of layers (the default). + * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code. + * (Type {@link Integer}, or {@link String} representation of the integer value). + */ + AZTEC_LAYERS, - /** - * Specifies the exact version of QR code to be encoded. - * (Type {@link Integer}, or {@link String} representation of the integer value). - */ - QR_VERSION, + /** + * Specifies the exact version of QR code to be encoded. + * (Type {@link Integer}, or {@link String} representation of the integer value). + */ + QR_VERSION, } export default EncodeHintType; diff --git a/src/core/Exception.ts b/src/core/Exception.ts index 965949fc..fce528f8 100644 --- a/src/core/Exception.ts +++ b/src/core/Exception.ts @@ -7,13 +7,13 @@ export default class Exception extends CustomError { /** * It's typed as string so it can be extended and overriden. - */ + */ static readonly kind: string = 'Exception'; /** * Allows Exception to be constructed directly * with some message and prototype definition. - */ + */ constructor( public message: string = undefined ) { diff --git a/src/core/FormatException.ts b/src/core/FormatException.ts index fb636b9a..2c24d277 100644 --- a/src/core/FormatException.ts +++ b/src/core/FormatException.ts @@ -7,7 +7,7 @@ export default class FormatException extends Exception { static readonly kind: string = 'FormatException'; - static getFormatInstance(): FormatException { - return new FormatException(); - } + static getFormatInstance(): FormatException { + return new FormatException(); + } } diff --git a/src/core/InvertedLuminanceSource.ts b/src/core/InvertedLuminanceSource.ts index d24caae4..74b4c373 100644 --- a/src/core/InvertedLuminanceSource.ts +++ b/src/core/InvertedLuminanceSource.ts @@ -16,7 +16,7 @@ import LuminanceSource from './LuminanceSource'; -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ /** * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes @@ -26,65 +26,65 @@ import LuminanceSource from './LuminanceSource'; */ export default class InvertedLuminanceSource extends LuminanceSource { - public constructor(private delegate: LuminanceSource) { - super(delegate.getWidth(), delegate.getHeight()); - } + public constructor(private delegate: LuminanceSource) { + super(delegate.getWidth(), delegate.getHeight()); + } - /*@Override*/ - public getRow(y: number /*int*/, row?: Uint8ClampedArray): Uint8ClampedArray { - const sourceRow = this.delegate.getRow(y, row); - const width: number /*int*/ = this.getWidth(); - for (let i = 0; i < width; i++) { - sourceRow[i] = /*(byte)*/ (255 - (sourceRow[i] & 0xFF)); - } - return sourceRow; + /* @Override */ + public getRow(y: number /* int */, row?: Uint8ClampedArray): Uint8ClampedArray { + const sourceRow = this.delegate.getRow(y, row); + const width: number /* int */ = this.getWidth(); + for (let i = 0; i < width; i++) { + sourceRow[i] = /* (byte) */ (255 - (sourceRow[i] & 0xFF)); } + return sourceRow; + } - /*@Override*/ - public getMatrix(): Uint8ClampedArray { - - const matrix: Uint8ClampedArray = this.delegate.getMatrix(); - const length: number /*int*/ = this.getWidth() * this.getHeight(); - const invertedMatrix = new Uint8ClampedArray(length); + /* @Override */ + public getMatrix(): Uint8ClampedArray { - for (let i = 0; i < length; i++) { - invertedMatrix[i] = /*(byte)*/ (255 - (matrix[i] & 0xFF)); - } + const matrix: Uint8ClampedArray = this.delegate.getMatrix(); + const length: number /* int */ = this.getWidth() * this.getHeight(); + const invertedMatrix = new Uint8ClampedArray(length); - return invertedMatrix; + for (let i = 0; i < length; i++) { + invertedMatrix[i] = /* (byte) */ (255 - (matrix[i] & 0xFF)); } - /*@Override*/ - public isCropSupported(): boolean { - return this.delegate.isCropSupported(); - } - - /*@Override*/ - public crop(left: number /*int*/, top: number /*int*/, width: number /*int*/, height: number /*int*/): LuminanceSource { - return new InvertedLuminanceSource(this.delegate.crop(left, top, width, height)); - } + return invertedMatrix; + } - /*@Override*/ - public isRotateSupported(): boolean { - return this.delegate.isRotateSupported(); - } + /* @Override */ + public isCropSupported(): boolean { + return this.delegate.isCropSupported(); + } - /** - * @return original delegate {@link LuminanceSource} since invert undoes itself - */ - /*@Override*/ - public invert(): LuminanceSource { - return this.delegate; - } + /* @Override */ + public crop(left: number /* int */, top: number /* int */, width: number /* int */, height: number /* int */): LuminanceSource { + return new InvertedLuminanceSource(this.delegate.crop(left, top, width, height)); + } - /*@Override*/ - public rotateCounterClockwise(): LuminanceSource { - return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise()); - } + /* @Override */ + public isRotateSupported(): boolean { + return this.delegate.isRotateSupported(); + } - /*@Override*/ - public rotateCounterClockwise45(): LuminanceSource { - return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise45()); - } + /** + * @return original delegate {@link LuminanceSource} since invert undoes itself + */ + /* @Override */ + public invert(): LuminanceSource { + return this.delegate; + } + + /* @Override */ + public rotateCounterClockwise(): LuminanceSource { + return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise()); + } + + /* @Override */ + public rotateCounterClockwise45(): LuminanceSource { + return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise45()); + } } diff --git a/src/core/LuminanceSource.ts b/src/core/LuminanceSource.ts index 842516d1..fe31aaa7 100644 --- a/src/core/LuminanceSource.ts +++ b/src/core/LuminanceSource.ts @@ -18,7 +18,7 @@ import StringBuilder from './util/StringBuilder'; import UnsupportedOperationException from './UnsupportedOperationException'; -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ /** * The purpose of this class hierarchy is to abstract different bitmap implementations across @@ -31,7 +31,7 @@ import UnsupportedOperationException from './UnsupportedOperationException'; */ abstract class LuminanceSource { - protected constructor(private width: number /*int*/, private height: number /*int*/) { } + protected constructor(private width: number /* int */, private height: number /* int */) { } /** * Fetches one row of luminance data from the underlying platform's bitmap. Values range from @@ -44,8 +44,8 @@ abstract class LuminanceSource { * @param row An optional preallocated array. If null or too small, it will be ignored. * Always use the returned object, and ignore the .length of the array. * @return An array containing the luminance data. - */ - public abstract getRow(y: number /*int*/, row?: Uint8ClampedArray): Uint8ClampedArray; + */ + public abstract getRow(y: number /* int */, row?: Uint8ClampedArray): Uint8ClampedArray; /** * Fetches luminance data for the underlying bitmap. Values should be fetched using: @@ -54,26 +54,26 @@ abstract class LuminanceSource { * @return A row-major 2D array of luminance values. Do not use result.length as it may be * larger than width * height bytes on some platforms. Do not modify the contents * of the result. - */ + */ public abstract getMatrix(): Uint8ClampedArray; /** * @return The width of the bitmap. - */ - public getWidth(): number /*int*/ { + */ + public getWidth(): number /* int */ { return this.width; } /** * @return The height of the bitmap. - */ - public getHeight(): number /*int*/ { + */ + public getHeight(): number /* int */ { return this.height; } /** * @return Whether this subclass supports cropping. - */ + */ public isCropSupported(): boolean { return false; } @@ -87,14 +87,14 @@ abstract class LuminanceSource { * @param width The width of the rectangle to crop. * @param height The height of the rectangle to crop. * @return A cropped version of this object. - */ - public crop(left: number /*int*/, top: number /*int*/, width: number /*int*/, height: number /*int*/): LuminanceSource { + */ + public crop(left: number /* int */, top: number /* int */, width: number /* int */, height: number /* int */): LuminanceSource { throw new UnsupportedOperationException('This luminance source does not support cropping.'); } /** * @return Whether this subclass supports counter-clockwise rotation. - */ + */ public isRotateSupported(): boolean { return false; } @@ -102,7 +102,7 @@ abstract class LuminanceSource { /** * @return a wrapper of this {@code LuminanceSource} which inverts the luminances it returns -- black becomes * white and vice versa, and each value becomes (255-value). - */ + */ public abstract invert(): LuminanceSource; /** @@ -110,7 +110,7 @@ abstract class LuminanceSource { * Only callable if {@link #isRotateSupported()} is true. * * @return A rotated version of this object. - */ + */ public rotateCounterClockwise(): LuminanceSource { throw new UnsupportedOperationException('This luminance source does not support rotation by 90 degrees.'); } @@ -120,12 +120,12 @@ abstract class LuminanceSource { * Only callable if {@link #isRotateSupported()} is true. * * @return A rotated version of this object. - */ + */ public rotateCounterClockwise45(): LuminanceSource { throw new UnsupportedOperationException('This luminance source does not support rotation by 45 degrees.'); } - /*@Override*/ + /* @Override */ public toString(): string { const row = new Uint8ClampedArray(this.width); let result = new StringBuilder(); diff --git a/src/core/MultiFormatReader.ts b/src/core/MultiFormatReader.ts index 3b0c1de4..bec8d421 100644 --- a/src/core/MultiFormatReader.ts +++ b/src/core/MultiFormatReader.ts @@ -28,7 +28,7 @@ import NotFoundException from './NotFoundException'; import PDF417Reader from './pdf417/PDF417Reader'; import ReaderException from './ReaderException'; -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ /** * MultiFormatReader is a convenience class and the main entry point into the library for most uses. @@ -40,8 +40,8 @@ import ReaderException from './ReaderException'; */ export default class MultiFormatReader implements Reader { - private hints: Map | null; - private readers: Reader[]; + private hints: Map | null; + private readers: Reader[]; /** * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it @@ -54,150 +54,147 @@ export default class MultiFormatReader implements Reader { * @throws NotFoundException Any errors which occurred */ /*@Override*/ - // public decode(image: BinaryBitmap): Result { - // setHints(null) - // return decodeInternal(image) - // } - - /** - * Decode an image using the hints provided. Does not honor existing state. - * - * @param image The pixel data to decode - * @param hints The hints to use, clearing the previous state. - * @return The contents of the image - * - * @throws NotFoundException Any errors which occurred - */ - /*@Override*/ - public decode(image: BinaryBitmap, hints?: Map): Result { - this.setHints(hints); - return this.decodeInternal(image); + public decode(image: BinaryBitmap): Result; + + /** + * Decode an image using the hints provided. Does not honor existing state. + * + * @param image The pixel data to decode + * @param hints The hints to use, clearing the previous state. + * @return The contents of the image + * + * @throws NotFoundException Any errors which occurred + */ + /* @Override */ + public decode(image: BinaryBitmap, hints?: Map | null): Result { + this.setHints(hints); + return this.decodeInternal(image); + } + + /** + * Decode an image using the state set up by calling setHints() previously. Continuous scan + * clients will get a large speed increase by using this instead of decode(). + * + * @param image The pixel data to decode + * @return The contents of the image + * + * @throws NotFoundException Any errors which occurred + */ + public decodeWithState(image: BinaryBitmap): Result { + // Make sure to set up the default state so we don't crash + if (this.readers === null || this.readers === undefined) { + this.setHints(null); } - - /** - * Decode an image using the state set up by calling setHints() previously. Continuous scan - * clients will get a large speed increase by using this instead of decode(). - * - * @param image The pixel data to decode - * @return The contents of the image - * - * @throws NotFoundException Any errors which occurred - */ - public decodeWithState(image: BinaryBitmap): Result { - // Make sure to set up the default state so we don't crash - if (this.readers === null || this.readers === undefined) { - this.setHints(null); - } - return this.decodeInternal(image); + return this.decodeInternal(image); + } + + /** + * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls + * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This + * is important for performance in continuous scan clients. + * + * @param hints The set of hints to use for subsequent calls to decode(image) + */ + public setHints(hints?: Map | null): void { + this.hints = hints; + + const tryHarder: boolean = hints !== null && hints !== undefined && undefined !== hints.get(DecodeHintType.TRY_HARDER); + /* @SuppressWarnings("unchecked") */ + const formats = hints === null || hints === undefined ? null : hints.get(DecodeHintType.POSSIBLE_FORMATS); + const readers = new Array(); + if (formats !== null && formats !== undefined) { + const addOneDReader: boolean = formats.some(f => + f === BarcodeFormat.UPC_A || + f === BarcodeFormat.UPC_E || + f === BarcodeFormat.EAN_13 || + f === BarcodeFormat.EAN_8 || + f === BarcodeFormat.CODABAR || + f === BarcodeFormat.CODE_39 || + f === BarcodeFormat.CODE_93 || + f === BarcodeFormat.CODE_128 || + f === BarcodeFormat.ITF || + f === BarcodeFormat.RSS_14 || + f === BarcodeFormat.RSS_EXPANDED + ); + // Put 1D readers upfront in "normal" mode + + // TYPESCRIPTPORT: TODO: uncomment below as they are ported + + if (addOneDReader && !tryHarder) { + readers.push(new MultiFormatOneDReader(hints)); + } + if (formats.includes(BarcodeFormat.QR_CODE)) { + readers.push(new QRCodeReader()); + } + if (formats.includes(BarcodeFormat.DATA_MATRIX)) { + readers.push(new DataMatrixReader()); + } + if (formats.includes(BarcodeFormat.AZTEC)) { + readers.push(new AztecReader()); + } + if (formats.includes(BarcodeFormat.PDF_417)) { + readers.push(new PDF417Reader()); + } + // if (formats.includes(BarcodeFormat.MAXICODE)) { + // readers.push(new MaxiCodeReader()) + // } + // At end in "try harder" mode + if (addOneDReader && tryHarder) { + readers.push(new MultiFormatOneDReader(hints)); + } } - - /** - * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls - * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This - * is important for performance in continuous scan clients. - * - * @param hints The set of hints to use for subsequent calls to decode(image) - */ - public setHints(hints?: Map | null): void { - this.hints = hints; - - const tryHarder: boolean = hints !== null && hints !== undefined && undefined !== hints.get(DecodeHintType.TRY_HARDER); - /*@SuppressWarnings("unchecked")*/ - const formats = hints === null || hints === undefined ? null : hints.get(DecodeHintType.POSSIBLE_FORMATS); - const readers = new Array(); - if (formats !== null && formats !== undefined) { - const addOneDReader: boolean = formats.some(f => - f === BarcodeFormat.UPC_A || - f === BarcodeFormat.UPC_E || - f === BarcodeFormat.EAN_13 || - f === BarcodeFormat.EAN_8 || - f === BarcodeFormat.CODABAR || - f === BarcodeFormat.CODE_39 || - f === BarcodeFormat.CODE_93 || - f === BarcodeFormat.CODE_128 || - f === BarcodeFormat.ITF || - f === BarcodeFormat.RSS_14 || - f === BarcodeFormat.RSS_EXPANDED - ); - // Put 1D readers upfront in "normal" mode - - // TYPESCRIPTPORT: TODO: uncomment below as they are ported - - if (addOneDReader && !tryHarder) { - readers.push(new MultiFormatOneDReader(hints)); - } - if (formats.includes(BarcodeFormat.QR_CODE)) { - readers.push(new QRCodeReader()); - } - if (formats.includes(BarcodeFormat.DATA_MATRIX)) { - readers.push(new DataMatrixReader()); - } - if (formats.includes(BarcodeFormat.AZTEC)) { - readers.push(new AztecReader()); - } - if (formats.includes(BarcodeFormat.PDF_417)) { - readers.push(new PDF417Reader()); - } - // if (formats.includes(BarcodeFormat.MAXICODE)) { - // readers.push(new MaxiCodeReader()) - // } - // At end in "try harder" mode - if (addOneDReader && tryHarder) { - readers.push(new MultiFormatOneDReader(hints)); - } - } - if (readers.length === 0) { - if (!tryHarder) { - readers.push(new MultiFormatOneDReader(hints)); - } - - readers.push(new QRCodeReader()); - readers.push(new DataMatrixReader()); - readers.push(new AztecReader()); - readers.push(new PDF417Reader()); - // readers.push(new MaxiCodeReader()) - - if (tryHarder) { - readers.push(new MultiFormatOneDReader(hints)); - } - } - this.readers = readers; // .toArray(new Reader[readers.size()]) + if (readers.length === 0) { + if (!tryHarder) { + readers.push(new MultiFormatOneDReader(hints)); + } + + readers.push(new QRCodeReader()); + readers.push(new DataMatrixReader()); + readers.push(new AztecReader()); + readers.push(new PDF417Reader()); + // readers.push(new MaxiCodeReader()) + + if (tryHarder) { + readers.push(new MultiFormatOneDReader(hints)); + } } - - /*@Override*/ - public reset(): void { - if (this.readers !== null) { - for (const reader of this.readers) { - reader.reset(); - } - } + this.readers = readers; // .toArray(new Reader[readers.size()]) + } + + /* @Override */ + public reset(): void { + if (this.readers !== null) { + for (const reader of this.readers) { + reader.reset(); + } } + } - /** - * @throws NotFoundException - */ - private decodeInternal(image: BinaryBitmap): Result { - - if (this.readers === null) { - throw new ReaderException('No readers where selected, nothing can be read.'); - } + /** + * @throws NotFoundException + */ + private decodeInternal(image: BinaryBitmap): Result { - for (const reader of this.readers) { + if (this.readers === null) { + throw new ReaderException('No readers where selected, nothing can be read.'); + } - // Trying to decode with ${reader} reader. + for (const reader of this.readers) { - try { - return reader.decode(image, this.hints); - } catch (ex) { - if (ex instanceof ReaderException) { - continue; - } + // Trying to decode with ${reader} reader. - // Bad Exception. - } + try { + return reader.decode(image, this.hints); + } catch (ex) { + if (ex instanceof ReaderException) { + continue; } - throw new NotFoundException('No MultiFormat Readers were able to detect the code.'); + // Bad Exception. + } } + throw new NotFoundException('No MultiFormat Readers were able to detect the code.'); + } + } diff --git a/src/core/MultiFormatWriter.ts b/src/core/MultiFormatWriter.ts index c551a6e8..6a43a0b0 100644 --- a/src/core/MultiFormatWriter.ts +++ b/src/core/MultiFormatWriter.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ import BitMatrix from './common/BitMatrix'; // import DataMatrixWriter from './datamatrix/DataMatrixWriter' @@ -35,7 +35,7 @@ import EncodeHintType from './EncodeHintType'; import IllegalArgumentException from './IllegalArgumentException'; -/*import java.util.Map;*/ +/* import java.util.Map; */ /** * This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat @@ -45,65 +45,65 @@ import IllegalArgumentException from './IllegalArgumentException'; */ export default class MultiFormatWriter implements Writer { - /*@Override*/ - // public encode(contents: string, - // format: BarcodeFormat, - // width: number /*int*/, - // height: number /*int*/): BitMatrix /*throws WriterException */ { - // return encode(contents, format, width, height, null) - // } + /* @Override */ + // public encode(contents: string, + // format: BarcodeFormat, + // width: number /*int */, + // height: number /*int */): BitMatrix /*throws WriterException */ { + // return encode(contents, format, width, height, null) + // } - /*@Override*/ - public encode(contents: string, - format: BarcodeFormat, - width: number /*int*/, height: number /*int*/, - hints: Map): BitMatrix /*throws WriterException */ { + /* @Override */ + public encode(contents: string, + format: BarcodeFormat, + width: number /* int */, height: number /* int */, + hints: Map): BitMatrix /* throws WriterException */ { - let writer: Writer; - switch (format) { - // case BarcodeFormat.EAN_8: - // writer = new EAN8Writer() - // break - // case BarcodeFormat.UPC_E: - // writer = new UPCEWriter() - // break - // case BarcodeFormat.EAN_13: - // writer = new EAN13Writer() - // break - // case BarcodeFormat.UPC_A: - // writer = new UPCAWriter() - // break - case BarcodeFormat.QR_CODE: - writer = new QRCodeWriter(); - break; - // case BarcodeFormat.CODE_39: - // writer = new Code39Writer() - // break - // case BarcodeFormat.CODE_93: - // writer = new Code93Writer() - // break - // case BarcodeFormat.CODE_128: - // writer = new Code128Writer() - // break - // case BarcodeFormat.ITF: - // writer = new ITFWriter() - // break - // case BarcodeFormat.PDF_417: - // writer = new PDF417Writer() - // break - // case BarcodeFormat.CODABAR: - // writer = new CodaBarWriter() - // break - // case BarcodeFormat.DATA_MATRIX: - // writer = new DataMatrixWriter() - // break - // case BarcodeFormat.AZTEC: - // writer = new AztecWriter() - // break - default: - throw new IllegalArgumentException('No encoder available for format ' + format); - } - return writer.encode(contents, format, width, height, hints); + let writer: Writer; + switch (format) { + // case BarcodeFormat.EAN_8: + // writer = new EAN8Writer() + // break + // case BarcodeFormat.UPC_E: + // writer = new UPCEWriter() + // break + // case BarcodeFormat.EAN_13: + // writer = new EAN13Writer() + // break + // case BarcodeFormat.UPC_A: + // writer = new UPCAWriter() + // break + case BarcodeFormat.QR_CODE: + writer = new QRCodeWriter(); + break; + // case BarcodeFormat.CODE_39: + // writer = new Code39Writer() + // break + // case BarcodeFormat.CODE_93: + // writer = new Code93Writer() + // break + // case BarcodeFormat.CODE_128: + // writer = new Code128Writer() + // break + // case BarcodeFormat.ITF: + // writer = new ITFWriter() + // break + // case BarcodeFormat.PDF_417: + // writer = new PDF417Writer() + // break + // case BarcodeFormat.CODABAR: + // writer = new CodaBarWriter() + // break + // case BarcodeFormat.DATA_MATRIX: + // writer = new DataMatrixWriter() + // break + // case BarcodeFormat.AZTEC: + // writer = new AztecWriter() + // break + default: + throw new IllegalArgumentException('No encoder available for format ' + format); } + return writer.encode(contents, format, width, height, hints); + } } diff --git a/src/core/OutOfMemoryError.ts b/src/core/OutOfMemoryError.ts index 210af964..6e3f6440 100644 --- a/src/core/OutOfMemoryError.ts +++ b/src/core/OutOfMemoryError.ts @@ -3,4 +3,4 @@ import Exception from './Exception'; /** * Custom Error class of type Exception. */ -export default class OutOfMemoryError extends Exception {} +export default class OutOfMemoryError extends Exception { } diff --git a/src/core/PlanarYUVLuminanceSource.ts b/src/core/PlanarYUVLuminanceSource.ts index 50106001..ca7e0957 100644 --- a/src/core/PlanarYUVLuminanceSource.ts +++ b/src/core/PlanarYUVLuminanceSource.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ import System from './util/System'; @@ -34,134 +34,134 @@ import IllegalArgumentException from './IllegalArgumentException'; */ export default class PlanarYUVLuminanceSource extends LuminanceSource { - private static THUMBNAIL_SCALE_FACTOR: number /*int*/ = 2; - - public constructor(private yuvData: Uint8ClampedArray, - private dataWidth: number /*int*/, - private dataHeight: number /*int*/, - private left: number /*int*/, - private top: number /*int*/, - width: number /*int*/, - height: number /*int*/, - reverseHorizontal: boolean) { - super(width, height); - - if (left + width > dataWidth || top + height > dataHeight) { - throw new IllegalArgumentException('Crop rectangle does not fit within image data.'); - } - - if (reverseHorizontal) { - this.reverseHorizontal(width, height); - } - } + private static THUMBNAIL_SCALE_FACTOR: number /* int */ = 2; - /*@Override*/ - public getRow(y: number /*int*/, row?: Uint8ClampedArray): Uint8ClampedArray { - if (y < 0 || y >= this.getHeight()) { - throw new IllegalArgumentException('Requested row is outside the image: ' + y); - } - const width: number /*int*/ = this.getWidth(); - if (row === null || row === undefined || row.length < width) { - row = new Uint8ClampedArray(width); - } - const offset = (y + this.top) * this.dataWidth + this.left; - System.arraycopy(this.yuvData, offset, row, 0, width); - return row; - } + public constructor(private yuvData: Uint8ClampedArray, + private dataWidth: number /* int */, + private dataHeight: number /* int */, + private left: number /* int */, + private top: number /* int */, + width: number /* int */, + height: number /* int */, + reverseHorizontal: boolean) { + super(width, height); - /*@Override*/ - public getMatrix(): Uint8ClampedArray { - const width: number /*int*/ = this.getWidth(); - const height: number /*int*/ = this.getHeight(); - - // If the caller asks for the entire underlying image, save the copy and give them the - // original data. The docs specifically warn that result.length must be ignored. - if (width === this.dataWidth && height === this.dataHeight) { - return this.yuvData; - } - - const area = width * height; - const matrix = new Uint8ClampedArray(area); - let inputOffset = this.top * this.dataWidth + this.left; - - // If the width matches the full width of the underlying data, perform a single copy. - if (width === this.dataWidth) { - System.arraycopy(this.yuvData, inputOffset, matrix, 0, area); - return matrix; - } - - // Otherwise copy one cropped row at a time. - for (let y = 0; y < height; y++) { - const outputOffset = y * width; - System.arraycopy(this.yuvData, inputOffset, matrix, outputOffset, width); - inputOffset += this.dataWidth; - } - return matrix; + if (left + width > dataWidth || top + height > dataHeight) { + throw new IllegalArgumentException('Crop rectangle does not fit within image data.'); } - /*@Override*/ - public isCropSupported(): boolean { - return true; + if (reverseHorizontal) { + this.reverseHorizontal(width, height); } + } - /*@Override*/ - public crop(left: number /*int*/, top: number /*int*/, width: number /*int*/, height: number /*int*/): LuminanceSource { - return new PlanarYUVLuminanceSource(this.yuvData, - this.dataWidth, - this.dataHeight, - this.left + left, - this.top + top, - width, - height, - false); + /* @Override */ + public getRow(y: number /* int */, row?: Uint8ClampedArray): Uint8ClampedArray { + if (y < 0 || y >= this.getHeight()) { + throw new IllegalArgumentException('Requested row is outside the image: ' + y); } - - public renderThumbnail(): Int32Array { - const width: number /*int*/ = this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; - const height: number /*int*/ = this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; - const pixels = new Int32Array(width * height); - const yuv = this.yuvData; - let inputOffset = this.top * this.dataWidth + this.left; - - for (let y = 0; y < height; y++) { - const outputOffset = y * width; - for (let x = 0; x < width; x++) { - const grey = yuv[inputOffset + x * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR] & 0xff; - pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101); - } - inputOffset += this.dataWidth * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; - } - return pixels; + const width: number /* int */ = this.getWidth(); + if (row === null || row === undefined || row.length < width) { + row = new Uint8ClampedArray(width); } - - /** - * @return width of image from {@link #renderThumbnail()} - */ - public getThumbnailWidth(): number /*int*/ { - return this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; + const offset = (y + this.top) * this.dataWidth + this.left; + System.arraycopy(this.yuvData, offset, row, 0, width); + return row; + } + + /* @Override */ + public getMatrix(): Uint8ClampedArray { + const width: number /* int */ = this.getWidth(); + const height: number /* int */ = this.getHeight(); + + // If the caller asks for the entire underlying image, save the copy and give them the + // original data. The docs specifically warn that result.length must be ignored. + if (width === this.dataWidth && height === this.dataHeight) { + return this.yuvData; } - /** - * @return height of image from {@link #renderThumbnail()} - */ - public getThumbnailHeight(): number /*int*/ { - return this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; + const area = width * height; + const matrix = new Uint8ClampedArray(area); + let inputOffset = this.top * this.dataWidth + this.left; + + // If the width matches the full width of the underlying data, perform a single copy. + if (width === this.dataWidth) { + System.arraycopy(this.yuvData, inputOffset, matrix, 0, area); + return matrix; } - private reverseHorizontal(width: number /*int*/, height: number /*int*/): void { - const yuvData = this.yuvData; - for (let y = 0, rowStart = this.top * this.dataWidth + this.left; y < height; y++ , rowStart += this.dataWidth) { - const middle = rowStart + width / 2; - for (let x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++ , x2--) { - const temp = yuvData[x1]; - yuvData[x1] = yuvData[x2]; - yuvData[x2] = temp; - } - } + // Otherwise copy one cropped row at a time. + for (let y = 0; y < height; y++) { + const outputOffset = y * width; + System.arraycopy(this.yuvData, inputOffset, matrix, outputOffset, width); + inputOffset += this.dataWidth; } + return matrix; + } + + /* @Override */ + public isCropSupported(): boolean { + return true; + } + + /* @Override */ + public crop(left: number /* int */, top: number /* int */, width: number /* int */, height: number /* int */): LuminanceSource { + return new PlanarYUVLuminanceSource(this.yuvData, + this.dataWidth, + this.dataHeight, + this.left + left, + this.top + top, + width, + height, + false); + } + + public renderThumbnail(): Int32Array { + const width: number /* int */ = this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; + const height: number /* int */ = this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; + const pixels = new Int32Array(width * height); + const yuv = this.yuvData; + let inputOffset = this.top * this.dataWidth + this.left; + + for (let y = 0; y < height; y++) { + const outputOffset = y * width; + for (let x = 0; x < width; x++) { + const grey = yuv[inputOffset + x * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR] & 0xff; + pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101); + } + inputOffset += this.dataWidth * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; + } + return pixels; + } + + /** + * @return width of image from {@link #renderThumbnail()} + */ + public getThumbnailWidth(): number /* int */ { + return this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; + } - public invert(): LuminanceSource { - return new InvertedLuminanceSource(this); + /** + * @return height of image from {@link #renderThumbnail()} + */ + public getThumbnailHeight(): number /* int */ { + return this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR; + } + + private reverseHorizontal(width: number /* int */, height: number /* int */): void { + const yuvData = this.yuvData; + for (let y = 0, rowStart = this.top * this.dataWidth + this.left; y < height; y++, rowStart += this.dataWidth) { + const middle = rowStart + width / 2; + for (let x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) { + const temp = yuvData[x1]; + yuvData[x1] = yuvData[x2]; + yuvData[x2] = temp; + } } + } + + public invert(): LuminanceSource { + return new InvertedLuminanceSource(this); + } } diff --git a/src/core/RGBLuminanceSource.ts b/src/core/RGBLuminanceSource.ts index fd63cacd..1a1b2ac5 100644 --- a/src/core/RGBLuminanceSource.ts +++ b/src/core/RGBLuminanceSource.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ import './InvertedLuminanceSource'; // required because of circular dependencies between LuminanceSource and InvertedLuminanceSource import InvertedLuminanceSource from './InvertedLuminanceSource'; @@ -32,136 +32,136 @@ import IllegalArgumentException from './IllegalArgumentException'; */ export default class RGBLuminanceSource extends LuminanceSource { - // public constructor(width: number /*int*/, height: number /*int*/, const pixels: Int32Array) { - // super(width, height) - - // dataWidth = width - // dataHeight = height - // left = 0 - // top = 0 - - // // In order to measure pure decoding speed, we convert the entire image to a greyscale array - // // up front, which is the same as the Y channel of the YUVLuminanceSource in the real app. - // // - // // Total number of pixels suffices, can ignore shape - // const size = width * height; - // luminances = new byte[size] - // for (let offset = 0; offset < size; offset++) { - // const pixel = pixels[offset] - // const r = (pixel >> 16) & 0xff; // red - // const g2 = (pixel >> 7) & 0x1fe; // 2 * green - // const b = pixel & 0xff; // blue - // // Calculate green-favouring average cheaply - // luminances[offset] = (byte) ((r + g2 + b) / 4) - // } - // } - - private luminances: Uint8ClampedArray; - - public constructor(luminances: Uint8ClampedArray | Int32Array, - width: number /*int*/, - height: number /*int*/, - private dataWidth?: number /*int*/, - private dataHeight?: number /*int*/, - private left?: number /*int*/, - private top?: number /*int*/) { - super(width, height); - - if (luminances.BYTES_PER_ELEMENT === 4) {// Int32Array - const size = width * height; - const luminancesUint8Array = new Uint8ClampedArray(size); - for (let offset = 0; offset < size; offset++) { - const pixel = luminances[offset]; - const r = (pixel >> 16) & 0xff; // red - const g2 = (pixel >> 7) & 0x1fe; // 2 * green - const b = pixel & 0xff; // blue - // Calculate green-favouring average cheaply - luminancesUint8Array[offset] = /*(byte) */((r + g2 + b) / 4) & 0xFF; - } - this.luminances = luminancesUint8Array; - } else { - this.luminances = luminances; - } - - if (undefined === dataWidth) { - this.dataWidth = width; - } - if (undefined === dataHeight) { - this.dataHeight = height; - } - if (undefined === left) { - this.left = 0; - } - if (undefined === top) { - this.top = 0; - } - if (this.left + width > this.dataWidth || this.top + height > this.dataHeight) { - throw new IllegalArgumentException('Crop rectangle does not fit within image data.'); - } + // public constructor(width: number /*int */, height: number /*int */, const pixels: Int32Array) { + // super(width, height) + + // dataWidth = width + // dataHeight = height + // left = 0 + // top = 0 + + // // In order to measure pure decoding speed, we convert the entire image to a greyscale array + // // up front, which is the same as the Y channel of the YUVLuminanceSource in the real app. + // // + // // Total number of pixels suffices, can ignore shape + // const size = width * height; + // luminances = new byte[size] + // for (let offset = 0; offset < size; offset++) { + // const pixel = pixels[offset] + // const r = (pixel >> 16) & 0xff; // red + // const g2 = (pixel >> 7) & 0x1fe; // 2 * green + // const b = pixel & 0xff; // blue + // // Calculate green-favouring average cheaply + // luminances[offset] = (byte) ((r + g2 + b) / 4) + // } + // } + + private luminances: Uint8ClampedArray; + + public constructor(luminances: Uint8ClampedArray | Int32Array, + width: number /* int */, + height: number /* int */, + private dataWidth?: number /* int */, + private dataHeight?: number /* int */, + private left?: number /* int */, + private top?: number /* int */) { + super(width, height); + + if (luminances.BYTES_PER_ELEMENT === 4) {// Int32Array + const size = width * height; + const luminancesUint8Array = new Uint8ClampedArray(size); + for (let offset = 0; offset < size; offset++) { + const pixel = luminances[offset]; + const r = (pixel >> 16) & 0xff; // red + const g2 = (pixel >> 7) & 0x1fe; // 2 * green + const b = pixel & 0xff; // blue + // Calculate green-favouring average cheaply + luminancesUint8Array[offset] = /* (byte) */((r + g2 + b) / 4) & 0xFF; + } + this.luminances = luminancesUint8Array; + } else { + this.luminances = luminances; } - /*@Override*/ - public getRow(y: number /*int*/, row?: Uint8ClampedArray): Uint8ClampedArray { - if (y < 0 || y >= this.getHeight()) { - throw new IllegalArgumentException('Requested row is outside the image: ' + y); - } - const width = this.getWidth(); - if (row === null || row === undefined || row.length < width) { - row = new Uint8ClampedArray(width); - } - const offset = (y + this.top) * this.dataWidth + this.left; - System.arraycopy(this.luminances, offset, row, 0, width); - return row; + if (undefined === dataWidth) { + this.dataWidth = width; } + if (undefined === dataHeight) { + this.dataHeight = height; + } + if (undefined === left) { + this.left = 0; + } + if (undefined === top) { + this.top = 0; + } + if (this.left + width > this.dataWidth || this.top + height > this.dataHeight) { + throw new IllegalArgumentException('Crop rectangle does not fit within image data.'); + } + } - /*@Override*/ - public getMatrix(): Uint8ClampedArray { - - const width = this.getWidth(); - const height = this.getHeight(); - - // If the caller asks for the entire underlying image, save the copy and give them the - // original data. The docs specifically warn that result.length must be ignored. - if (width === this.dataWidth && height === this.dataHeight) { - return this.luminances; - } - - const area = width * height; - const matrix = new Uint8ClampedArray(area); - let inputOffset = this.top * this.dataWidth + this.left; - - // If the width matches the full width of the underlying data, perform a single copy. - if (width === this.dataWidth) { - System.arraycopy(this.luminances, inputOffset, matrix, 0, area); - return matrix; - } - - // Otherwise copy one cropped row at a time. - for (let y = 0; y < height; y++) { - const outputOffset = y * width; - System.arraycopy(this.luminances, inputOffset, matrix, outputOffset, width); - inputOffset += this.dataWidth; - } - return matrix; + /* @Override */ + public getRow(y: number /* int */, row?: Uint8ClampedArray): Uint8ClampedArray { + if (y < 0 || y >= this.getHeight()) { + throw new IllegalArgumentException('Requested row is outside the image: ' + y); } + const width = this.getWidth(); + if (row === null || row === undefined || row.length < width) { + row = new Uint8ClampedArray(width); + } + const offset = (y + this.top) * this.dataWidth + this.left; + System.arraycopy(this.luminances, offset, row, 0, width); + return row; + } + + /* @Override */ + public getMatrix(): Uint8ClampedArray { - /*@Override*/ - public isCropSupported(): boolean { - return true; + const width = this.getWidth(); + const height = this.getHeight(); + + // If the caller asks for the entire underlying image, save the copy and give them the + // original data. The docs specifically warn that result.length must be ignored. + if (width === this.dataWidth && height === this.dataHeight) { + return this.luminances; } - /*@Override*/ - public crop(left: number /*int*/, top: number /*int*/, width: number /*int*/, height: number /*int*/): LuminanceSource { - return new RGBLuminanceSource(this.luminances, - width, - height, - this.dataWidth, - this.dataHeight, - this.left + left, - this.top + top, ); + const area = width * height; + const matrix = new Uint8ClampedArray(area); + let inputOffset = this.top * this.dataWidth + this.left; + + // If the width matches the full width of the underlying data, perform a single copy. + if (width === this.dataWidth) { + System.arraycopy(this.luminances, inputOffset, matrix, 0, area); + return matrix; } - public invert(): LuminanceSource { - return new InvertedLuminanceSource(this); + // Otherwise copy one cropped row at a time. + for (let y = 0; y < height; y++) { + const outputOffset = y * width; + System.arraycopy(this.luminances, inputOffset, matrix, outputOffset, width); + inputOffset += this.dataWidth; } + return matrix; + } + + /* @Override */ + public isCropSupported(): boolean { + return true; + } + + /* @Override */ + public crop(left: number /* int */, top: number /* int */, width: number /* int */, height: number /* int */): LuminanceSource { + return new RGBLuminanceSource(this.luminances, + width, + height, + this.dataWidth, + this.dataHeight, + this.left + left, + this.top + top); + } + + public invert(): LuminanceSource { + return new InvertedLuminanceSource(this); + } } diff --git a/src/core/Reader.ts b/src/core/Reader.ts index 0757759d..f4f9936c 100644 --- a/src/core/Reader.ts +++ b/src/core/Reader.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ -/*import java.util.Map;*/ +/* import java.util.Map; */ import BinaryBitmap from './BinaryBitmap'; import Result from './Result'; @@ -46,31 +46,32 @@ interface Reader { * @throws NotFoundException if no potential barcode is found * @throws ChecksumException if a potential barcode is found but does not pass its checksum * @throws FormatException if a potential barcode is found but format is invalid + * @override decode */ - // decode(image: BinaryBitmap): Result /*throws NotFoundException, ChecksumException, FormatException*/ + decode(image: BinaryBitmap): Result; - /** - * Locates and decodes a barcode in some format within an image. This method also accepts - * hints, each possibly associated to some data, which may help the implementation decode. - * - * @param image image of barcode to decode - * @param hints passed as a {@link Map} from {@link DecodeHintType} - * to arbitrary data. The - * meaning of the data depends upon the hint type. The implementation may or may not do - * anything with these hints. - * - * @return which: string the barcode encodes - * - * @throws NotFoundException if no potential barcode is found - * @throws ChecksumException if a potential barcode is found but does not pass its checksum - * @throws FormatException if a potential barcode is found but format is invalid - */ - decode(image: BinaryBitmap, hints?: Map | null): Result; + /** + * Locates and decodes a barcode in some format within an image. This method also accepts + * hints, each possibly associated to some data, which may help the implementation decode. + * + * @param image image of barcode to decode + * @param hints passed as a {@link Map} from {@link DecodeHintType} + * to arbitrary data. The + * meaning of the data depends upon the hint type. The implementation may or may not do + * anything with these hints. + * + * @return which: string the barcode encodes + * + * @throws NotFoundException if no potential barcode is found + * @throws ChecksumException if a potential barcode is found but does not pass its checksum + * @throws FormatException if a potential barcode is found but format is invalid + */ + decode(image: BinaryBitmap, hints?: Map | null): Result; - /** - * Resets any internal state the implementation has after a decode, to prepare it - * for reuse. - */ - reset(): void; + /** + * Resets any internal state the implementation has after a decode, to prepare it + * for reuse. + */ + reset(): void; } diff --git a/src/core/Result.ts b/src/core/Result.ts index 3af8b8e2..b199fe92 100644 --- a/src/core/Result.ts +++ b/src/core/Result.ts @@ -14,14 +14,16 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ -/*import java.util.EnumMap;*/ -/*import java.util.Map;*/ +/* import java.util.EnumMap; */ +/* import java.util.Map; */ import ResultPoint from './ResultPoint'; import BarcodeFormat from './BarcodeFormat'; import System from './util/System'; import ResultMetadataType from './ResultMetadataType'; +import { long } from '../customTypings'; +import { isBarcodeFormatValue } from './util/BarcodeFormaHelpers'; /** *

Encapsulates the result of decoding a barcode within an image.

@@ -30,130 +32,193 @@ import ResultMetadataType from './ResultMetadataType'; */ export default class Result { - private resultMetadata: Map; - - // public constructor(private text: string, - // Uint8Array rawBytes, - // ResultPoconst resultPoints: Int32Array, - // BarcodeFormat format) { - // this(text, rawBytes, resultPoints, format, System.currentTimeMillis()) - // } - - // public constructor(text: string, - // Uint8Array rawBytes, - // ResultPoconst resultPoints: Int32Array, - // BarcodeFormat format, - // long timestamp) { - // this(text, rawBytes, rawBytes == null ? 0 : 8 * rawBytes.length, - // resultPoints, format, timestamp) - // } - - public constructor(private text: string, - private rawBytes: Uint8Array, - private numBits: number /*int*/ = rawBytes == null ? 0 : 8 * rawBytes.length, - private resultPoints: ResultPoint[], - private format: BarcodeFormat, - private timestamp: number /*long*/ = System.currentTimeMillis()) { - this.text = text; - this.rawBytes = rawBytes; - if (undefined === numBits || null === numBits) { - this.numBits = (rawBytes === null || rawBytes === undefined) ? 0 : 8 * rawBytes.length; - } else { - this.numBits = numBits; - } - this.resultPoints = resultPoints; - this.format = format; - this.resultMetadata = null; - if (undefined === timestamp || null === timestamp) { - this.timestamp = System.currentTimeMillis(); - } else { - this.timestamp = timestamp; - } + private resultMetadata: Map; + private numBits: number; + private resultPoints: ResultPoint[]; + private format: BarcodeFormat; + + public constructor( + text: string, + rawBytes: Uint8Array, + resultPoints: ResultPoint[], + format: BarcodeFormat, + ); + public constructor( + text: string, + rawBytes: Uint8Array, + resultPoints: ResultPoint[], + format: BarcodeFormat, + timestamp: long, + ); + public constructor( + text: string, + rawBytes: Uint8Array, + numBits: number, + resultPoints: ResultPoint[], + format: BarcodeFormat, + timestamp: number + ); + public constructor( + private text: string, + private rawBytes: Uint8Array, + numBits_resultPoints: number | ResultPoint[], + resultPoints_format: ResultPoint[] | BarcodeFormat | any, + format_timestamp: BarcodeFormat | long | any = null, + private timestamp: long = System.currentTimeMillis() + ) { + // checks overloading order from most to least params + + // check overload 3 + if (numBits_resultPoints instanceof Number && Array.isArray(resultPoints_format) && isBarcodeFormatValue(format_timestamp)) { + numBits_resultPoints = rawBytes == null ? 0 : 8 * rawBytes.length; + this.constructorImpl(text, rawBytes, numBits_resultPoints, resultPoints_format, format_timestamp, timestamp); + return; } - /** - * @return raw text encoded by the barcode - */ - public getText(): string { - return this.text; + // check overload 2 + if (Array.isArray(resultPoints_format) && isBarcodeFormatValue(format_timestamp)) { + this.constructorOverload2(text, rawBytes, resultPoints_format, format_timestamp, timestamp); + return; } - /** - * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null} - */ - public getRawBytes(): Uint8Array { - return this.rawBytes; + // check overload 1 + if (typeof text === 'string' && rawBytes instanceof Uint8Array && Array.isArray(numBits_resultPoints) && isBarcodeFormatValue(resultPoints_format)) { + this.constructorOverload1(text, rawBytes, numBits_resultPoints, resultPoints_format); + return; } - /** - * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length - * @since 3.3.0 - */ - public getNumBits(): number /*int*/ { - return this.numBits; + // throw no supported overload exception + throw new Error('No supported overload for the given combination of parameters.'); + } + + private constructorOverload1( + text: string, + rawBytes: Uint8Array, + resultPoints: ResultPoint[], + format: BarcodeFormat, + ) { + return this.constructorOverload2(text, rawBytes, resultPoints, format, System.currentTimeMillis()); + } + + private constructorOverload2( + text: string, + rawBytes: Uint8Array, + resultPoints: ResultPoint[], + format: BarcodeFormat, + timestamp: number /* long */, + ) { + return this.constructorImpl(text, rawBytes, rawBytes == null ? 0 : 8 * rawBytes.length, + resultPoints, format, timestamp); + } + + private constructorImpl( + text: string, + rawBytes: Uint8Array, + numBits: number, + resultPoints: ResultPoint[], + format: BarcodeFormat, + timestamp: number + ) { + this.text = text; + this.rawBytes = rawBytes; + if (undefined === numBits || null === numBits) { + this.numBits = (rawBytes === null || rawBytes === undefined) ? 0 : 8 * rawBytes.length; + } else { + this.numBits = numBits; } - - /** - * @return points related to the barcode in the image. These are typically points - * identifying finder patterns or the corners of the barcode. The exact meaning is - * specific to the type of barcode that was decoded. - */ - public getResultPoints(): Array { - return this.resultPoints; - } - - /** - * @return {@link BarcodeFormat} representing the format of the barcode that was decoded - */ - public getBarcodeFormat(): BarcodeFormat { - return this.format; - } - - /** - * @return {@link Map} mapping {@link ResultMetadataType} keys to values. May be - * {@code null}. This contains optional metadata about what was detected about the barcode, - * like orientation. - */ - public getResultMetadata(): Map { - return this.resultMetadata; + this.resultPoints = resultPoints; + this.format = format; + this.resultMetadata = null; + if (undefined === timestamp || null === timestamp) { + this.timestamp = System.currentTimeMillis(); + } else { + this.timestamp = timestamp; } - - public putMetadata(type: ResultMetadataType, value: Object): void { - if (this.resultMetadata === null) { - this.resultMetadata = new Map(); - } - this.resultMetadata.set(type, value); + } + + /** + * @return raw text encoded by the barcode + */ + public getText(): string { + return this.text; + } + + /** + * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null} + */ + public getRawBytes(): Uint8Array { + return this.rawBytes; + } + + /** + * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length + * @since 3.3.0 + */ + public getNumBits(): number /* int */ { + return this.numBits; + } + + /** + * @return points related to the barcode in the image. These are typically points + * identifying finder patterns or the corners of the barcode. The exact meaning is + * specific to the type of barcode that was decoded. + */ + public getResultPoints(): Array { + return this.resultPoints; + } + + /** + * @return {@link BarcodeFormat} representing the format of the barcode that was decoded + */ + public getBarcodeFormat(): BarcodeFormat { + return this.format; + } + + /** + * @return {@link Map} mapping {@link ResultMetadataType} keys to values. May be + * {@code null}. This contains optional metadata about what was detected about the barcode, + * like orientation. + */ + public getResultMetadata(): Map { + return this.resultMetadata; + } + + public putMetadata(type: ResultMetadataType, value: Object): void { + if (this.resultMetadata === null) { + this.resultMetadata = new Map(); } - - public putAllMetadata(metadata: Map): void { - if (metadata !== null) { - if (this.resultMetadata === null) { - this.resultMetadata = metadata; - } else { - this.resultMetadata = new Map(metadata); - } - } + this.resultMetadata.set(type, value); + } + + public putAllMetadata(metadata: Map): void { + if (metadata !== null) { + if (this.resultMetadata === null) { + this.resultMetadata = metadata; + } else { + this.resultMetadata = new Map(metadata); + } } - - public addResultPoints(newPoints: Array): void { - const oldPoints = this.resultPoints; - if (oldPoints === null) { - this.resultPoints = newPoints; - } else if (newPoints !== null && newPoints.length > 0) { - const allPoints = new Array(oldPoints.length + newPoints.length); - System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length); - System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length); - this.resultPoints = allPoints; - } + } + + public addResultPoints(newPoints: Array): void { + const oldPoints = this.resultPoints; + if (oldPoints === null) { + this.resultPoints = newPoints; + } else if (newPoints !== null && newPoints.length > 0) { + const allPoints = new Array(oldPoints.length + newPoints.length); + System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length); + System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length); + this.resultPoints = allPoints; } + } - public getTimestamp(): number/*long*/ { - return this.timestamp; - } + public getTimestamp(): number/* long */ { + return this.timestamp; + } - /*@Override*/ - public toString(): string { - return this.text; - } + /* @Override */ + public toString(): string { + return this.text; + } } diff --git a/src/core/ResultMetadataType.ts b/src/core/ResultMetadataType.ts index 67921d40..cea3d1e5 100644 --- a/src/core/ResultMetadataType.ts +++ b/src/core/ResultMetadataType.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ /** * Represents some type of metadata about the result of the decoding that the decoder @@ -24,75 +24,75 @@ */ enum ResultMetadataType { - /** - * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. - */ - OTHER, + /** + * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. + */ + OTHER, - /** - * Denotes the likely approximate orientation of the barcode in the image. This value - * is given as degrees rotated clockwise from the normal, upright orientation. - * For example a 1D barcode which was found by reading top-to-bottom would be - * said to have orientation "90". This key maps to an {@link Integer} whose - * value is in the range [0,360). - */ - ORIENTATION, + /** + * Denotes the likely approximate orientation of the barcode in the image. This value + * is given as degrees rotated clockwise from the normal, upright orientation. + * For example a 1D barcode which was found by reading top-to-bottom would be + * said to have orientation "90". This key maps to an {@link Integer} whose + * value is in the range [0,360). + */ + ORIENTATION, - /** - *

2D barcode formats typically encode text, but allow for a sort of 'byte mode' - * which is sometimes used to encode binary data. While {@link Result} makes available - * the complete raw bytes in the barcode for these formats, it does not offer the bytes - * from the byte segments alone.

- * - *

This maps to a {@link java.util.List} of byte arrays corresponding to the - * raw bytes in the byte segments in the barcode, in order.

- */ - BYTE_SEGMENTS, + /** + *

2D barcode formats typically encode text, but allow for a sort of 'byte mode' + * which is sometimes used to encode binary data. While {@link Result} makes available + * the complete raw bytes in the barcode for these formats, it does not offer the bytes + * from the byte segments alone.

+ * + *

This maps to a {@link java.util.List} of byte arrays corresponding to the + * raw bytes in the byte segments in the barcode, in order.

+ */ + BYTE_SEGMENTS, - /** - * Error correction level used, if applicable. The value type depends on the - * format, but is typically a String. - */ - ERROR_CORRECTION_LEVEL, + /** + * Error correction level used, if applicable. The value type depends on the + * format, but is typically a String. + */ + ERROR_CORRECTION_LEVEL, - /** - * For some periodicals, indicates the issue number as an {@link Integer}. - */ - ISSUE_NUMBER, + /** + * For some periodicals, indicates the issue number as an {@link Integer}. + */ + ISSUE_NUMBER, - /** - * For some products, indicates the suggested retail price in the barcode as a - * formatted {@link String}. - */ - SUGGESTED_PRICE, + /** + * For some products, indicates the suggested retail price in the barcode as a + * formatted {@link String}. + */ + SUGGESTED_PRICE, - /** - * For some products, the possible country of manufacture as a {@link String} denoting the - * ISO country code. Some map to multiple possible countries, like "US/CA". - */ - POSSIBLE_COUNTRY, + /** + * For some products, the possible country of manufacture as a {@link String} denoting the + * ISO country code. Some map to multiple possible countries, like "US/CA". + */ + POSSIBLE_COUNTRY, - /** - * For some products, the extension text - */ - UPC_EAN_EXTENSION, + /** + * For some products, the extension text + */ + UPC_EAN_EXTENSION, - /** - * PDF417-specific metadata - */ - PDF417_EXTRA_METADATA, + /** + * PDF417-specific metadata + */ + PDF417_EXTRA_METADATA, - /** - * If the code format supports structured append and the current scanned code is part of one then the - * sequence number is given with it. - */ - STRUCTURED_APPEND_SEQUENCE, + /** + * If the code format supports structured append and the current scanned code is part of one then the + * sequence number is given with it. + */ + STRUCTURED_APPEND_SEQUENCE, - /** - * If the code format supports structured append and the current scanned code is part of one then the - * parity is given with it. - */ - STRUCTURED_APPEND_PARITY, + /** + * If the code format supports structured append and the current scanned code is part of one then the + * parity is given with it. + */ + STRUCTURED_APPEND_PARITY, } diff --git a/src/core/ResultPoint.ts b/src/core/ResultPoint.ts index 55578557..c7637219 100644 --- a/src/core/ResultPoint.ts +++ b/src/core/ResultPoint.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ import MathUtils from './common/detector/MathUtils'; import Float from './util/Float'; @@ -28,99 +28,99 @@ import { float, int } from '../customTypings'; */ export default class ResultPoint { - public constructor(private x: float, private y: float) { } + public constructor(private x: float, private y: float) { } - public getX(): float { - return this.x; - } + public getX(): float { + return this.x; + } - public getY(): float { - return this.y; - } + public getY(): float { + return this.y; + } - /*@Override*/ - public equals(other: Object): boolean { - if (other instanceof ResultPoint) { - const otherPoint = other; - return this.x === otherPoint.x && this.y === otherPoint.y; - } - return false; + /* @Override */ + public equals(other: Object): boolean { + if (other instanceof ResultPoint) { + const otherPoint = other; + return this.x === otherPoint.x && this.y === otherPoint.y; } - - /*@Override*/ - public hashCode(): int { - return 31 * Float.floatToIntBits(this.x) + Float.floatToIntBits(this.y); + return false; + } + + /* @Override */ + public hashCode(): int { + return 31 * Float.floatToIntBits(this.x) + Float.floatToIntBits(this.y); + } + + /* @Override */ + public toString(): string { + return '(' + this.x + ',' + this.y + ')'; + } + + /** + * Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC + * and BC is less than AC, and the angle between BC and BA is less than 180 degrees. + * + * @param patterns array of three {@code ResultPoint} to order + */ + public static orderBestPatterns(patterns: Array): void { + + // Find distances between pattern centers + const zeroOneDistance = this.distance(patterns[0], patterns[1]); + const oneTwoDistance = this.distance(patterns[1], patterns[2]); + const zeroTwoDistance = this.distance(patterns[0], patterns[2]); + + let pointA: ResultPoint; + let pointB: ResultPoint; + let pointC: ResultPoint; + // Assume one closest to other two is B; A and C will just be guesses at first + if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) { + pointB = patterns[0]; + pointA = patterns[1]; + pointC = patterns[2]; + } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) { + pointB = patterns[1]; + pointA = patterns[0]; + pointC = patterns[2]; + } else { + pointB = patterns[2]; + pointA = patterns[0]; + pointC = patterns[1]; } - /*@Override*/ - public toString(): string { - return '(' + this.x + ',' + this.y + ')'; + // Use cross product to figure out whether A and C are correct or flipped. + // This asks whether BC x BA has a positive z component, which is the arrangement + // we want for A, B, C. If it's negative, then we've got it flipped around and + // should swap A and C. + if (this.crossProductZ(pointA, pointB, pointC) < 0.0) { + const temp = pointA; + pointA = pointC; + pointC = temp; } - /** - * Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC - * and BC is less than AC, and the angle between BC and BA is less than 180 degrees. - * - * @param patterns array of three {@code ResultPoint} to order - */ - public static orderBestPatterns(patterns: Array): void { - - // Find distances between pattern centers - const zeroOneDistance = this.distance(patterns[0], patterns[1]); - const oneTwoDistance = this.distance(patterns[1], patterns[2]); - const zeroTwoDistance = this.distance(patterns[0], patterns[2]); - - let pointA: ResultPoint; - let pointB: ResultPoint; - let pointC: ResultPoint; - // Assume one closest to other two is B; A and C will just be guesses at first - if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) { - pointB = patterns[0]; - pointA = patterns[1]; - pointC = patterns[2]; - } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) { - pointB = patterns[1]; - pointA = patterns[0]; - pointC = patterns[2]; - } else { - pointB = patterns[2]; - pointA = patterns[0]; - pointC = patterns[1]; - } - - // Use cross product to figure out whether A and C are correct or flipped. - // This asks whether BC x BA has a positive z component, which is the arrangement - // we want for A, B, C. If it's negative, then we've got it flipped around and - // should swap A and C. - if (this.crossProductZ(pointA, pointB, pointC) < 0.0) { - const temp = pointA; - pointA = pointC; - pointC = temp; - } - - patterns[0] = pointA; - patterns[1] = pointB; - patterns[2] = pointC; - } + patterns[0] = pointA; + patterns[1] = pointB; + patterns[2] = pointC; + } - /** - * @param pattern1 first pattern - * @param pattern2 second pattern - * @return distance between two points - */ - public static distance(pattern1: ResultPoint, pattern2: ResultPoint): float { - return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y); - } + /** + * @param pattern1 first pattern + * @param pattern2 second pattern + * @return distance between two points + */ + public static distance(pattern1: ResultPoint, pattern2: ResultPoint): float { + return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y); + } - /** - * Returns the z component of the cross product between vectors BC and BA. - */ - private static crossProductZ(pointA: ResultPoint, - pointB: ResultPoint, - pointC: ResultPoint): float { - const bX = pointB.x; - const bY = pointB.y; - return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX)); - } + /** + * Returns the z component of the cross product between vectors BC and BA. + */ + private static crossProductZ(pointA: ResultPoint, + pointB: ResultPoint, + pointC: ResultPoint): float { + const bX = pointB.x; + const bY = pointB.y; + return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX)); + } } diff --git a/src/core/ResultPointCallback.ts b/src/core/ResultPointCallback.ts index 2d3c2e95..2d6d4094 100644 --- a/src/core/ResultPointCallback.ts +++ b/src/core/ResultPointCallback.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ import ResultPoint from './ResultPoint'; @@ -28,6 +28,6 @@ export default ResultPointCallback; */ interface ResultPointCallback { - foundPossibleResultPoint(point: ResultPoint): void; + foundPossibleResultPoint(point: ResultPoint): void; } diff --git a/src/core/Writer.ts b/src/core/Writer.ts index 03f20cd2..d3219a2e 100644 --- a/src/core/Writer.ts +++ b/src/core/Writer.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing {*/ +/* namespace com.google.zxing { */ import BitMatrix from './common/BitMatrix'; import BarcodeFormat from './BarcodeFormat'; @@ -22,7 +22,7 @@ import EncodeHintType from './EncodeHintType'; export default Writer; -/*import java.util.Map;*/ +/* import java.util.Map; */ /** * The base class for all objects which encode/generate a barcode image. @@ -31,33 +31,33 @@ export default Writer; */ interface Writer { - /** - * Encode a barcode using the default settings. - * - * @param contents The contents to encode in the barcode - * @param format The barcode format to generate - * @param width The preferred width in pixels - * @param height The preferred height in pixels - * @return {@link BitMatrix} representing encoded barcode image - * @throws WriterException if contents cannot be encoded legally in a format - */ - // encode(contents: string, format: BarcodeFormat, width: number /*int*/, height: number /*int*/): BitMatrix - - /** - * @param contents The contents to encode in the barcode - * @param format The barcode format to generate - * @param width The preferred width in pixels - * @param height The preferred height in pixels - * @param hints Additional parameters to supply to the encoder - * @return {@link BitMatrix} representing encoded barcode image - * @throws WriterException if contents cannot be encoded legally in a format - */ - encode( - contents: string, - format: BarcodeFormat, - width: number /*int*/, - height: number /*int*/, - hints: Map - ): BitMatrix; + /** + * Encode a barcode using the default settings. + * + * @param contents The contents to encode in the barcode + * @param format The barcode format to generate + * @param width The preferred width in pixels + * @param height The preferred height in pixels + * @return {@link BitMatrix} representing encoded barcode image + * @throws WriterException if contents cannot be encoded legally in a format + */ + // encode(contents: string, format: BarcodeFormat, width: number /*int */, height: number /*int */): BitMatrix + + /** + * @param contents The contents to encode in the barcode + * @param format The barcode format to generate + * @param width The preferred width in pixels + * @param height The preferred height in pixels + * @param hints Additional parameters to supply to the encoder + * @return {@link BitMatrix} representing encoded barcode image + * @throws WriterException if contents cannot be encoded legally in a format + */ + encode( + contents: string, + format: BarcodeFormat, + width: number /* int */, + height: number /* int */, + hints: Map + ): BitMatrix; } diff --git a/src/core/aztec/AztecDetectorResult.ts b/src/core/aztec/AztecDetectorResult.ts index 6a0c26ac..56e737fe 100644 --- a/src/core/aztec/AztecDetectorResult.ts +++ b/src/core/aztec/AztecDetectorResult.ts @@ -26,30 +26,30 @@ import DetectorResult from '../common/DetectorResult'; */ export default class AztecDetectorResult extends DetectorResult { - private compact: boolean; - private nbDatablocks: number; - private nbLayers: number; + private compact: boolean; + private nbDatablocks: number; + private nbLayers: number; - public constructor(bits: BitMatrix, - points: ResultPoint[], - compact: boolean, - nbDatablocks: number, - nbLayers: number) { - super(bits, points); - this.compact = compact; - this.nbDatablocks = nbDatablocks; - this.nbLayers = nbLayers; - } + public constructor(bits: BitMatrix, + points: ResultPoint[], + compact: boolean, + nbDatablocks: number, + nbLayers: number) { + super(bits, points); + this.compact = compact; + this.nbDatablocks = nbDatablocks; + this.nbLayers = nbLayers; + } - public getNbLayers(): number { - return this.nbLayers; - } + public getNbLayers(): number { + return this.nbLayers; + } - public getNbDatablocks(): number { - return this.nbDatablocks; - } + public getNbDatablocks(): number { + return this.nbDatablocks; + } - public isCompact(): boolean { - return this.compact; - } + public isCompact(): boolean { + return this.compact; + } } diff --git a/src/core/aztec/AztecReader.ts b/src/core/aztec/AztecReader.ts index e6352b57..ac061a01 100644 --- a/src/core/aztec/AztecReader.ts +++ b/src/core/aztec/AztecReader.ts @@ -40,75 +40,75 @@ import Exception from '../../core/Exception'; */ export default class AztecReader implements Reader { - /** - * Locates and decodes a Data Matrix code in an image. - * - * @return a String representing the content encoded by the Data Matrix code - * @throws NotFoundException if a Data Matrix code cannot be found - * @throws FormatException if a Data Matrix code cannot be decoded - */ - public decode(image: BinaryBitmap, hints: Map | null = null): Result { + /** + * Locates and decodes a Data Matrix code in an image. + * + * @return a String representing the content encoded by the Data Matrix code + * @throws NotFoundException if a Data Matrix code cannot be found + * @throws FormatException if a Data Matrix code cannot be decoded + */ + public decode(image: BinaryBitmap, hints: Map | null = null): Result { - let exception: Exception = null; - let detector = new Detector(image.getBlackMatrix()); - let points: ResultPoint[] = null; - let decoderResult: DecoderResult = null; + let exception: Exception = null; + let detector = new Detector(image.getBlackMatrix()); + let points: ResultPoint[] = null; + let decoderResult: DecoderResult = null; - try { - let detectorResult = detector.detectMirror(false); - points = detectorResult.getPoints(); - this.reportFoundResultPoints(hints, points); - decoderResult = new Decoder().decode(detectorResult); - } catch (e) { - exception = e; - } - if (decoderResult == null) { - try { - let detectorResult = detector.detectMirror(true); - points = detectorResult.getPoints(); - this.reportFoundResultPoints(hints, points); - decoderResult = new Decoder().decode(detectorResult); - } catch (e) { - if (exception != null) { - throw exception; - } - throw e; - } + try { + let detectorResult = detector.detectMirror(false); + points = detectorResult.getPoints(); + this.reportFoundResultPoints(hints, points); + decoderResult = new Decoder().decode(detectorResult); + } catch (e) { + exception = e; + } + if (decoderResult == null) { + try { + let detectorResult = detector.detectMirror(true); + points = detectorResult.getPoints(); + this.reportFoundResultPoints(hints, points); + decoderResult = new Decoder().decode(detectorResult); + } catch (e) { + if (exception != null) { + throw exception; } + throw e; + } + } - let result = new Result(decoderResult.getText(), - decoderResult.getRawBytes(), - decoderResult.getNumBits(), - points, - BarcodeFormat.AZTEC, - System.currentTimeMillis()); + let result = new Result(decoderResult.getText(), + decoderResult.getRawBytes(), + decoderResult.getNumBits(), + points, + BarcodeFormat.AZTEC, + System.currentTimeMillis()); - let byteSegments = decoderResult.getByteSegments(); - if (byteSegments != null) { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - let ecLevel = decoderResult.getECLevel(); - if (ecLevel != null) { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - - return result; + let byteSegments = decoderResult.getByteSegments(); + if (byteSegments != null) { + result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); } - - private reportFoundResultPoints(hints: Map, points: ResultPoint[]): void { - if (hints != null) { - let rpcb = hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - if (rpcb != null) { - points.forEach((point, idx, arr) => { - rpcb.foundPossibleResultPoint(point); - }); - } - } + let ecLevel = decoderResult.getECLevel(); + if (ecLevel != null) { + result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); } - // @Override - public reset(): void { - // do nothing + return result; + } + + private reportFoundResultPoints(hints: Map, points: ResultPoint[]): void { + if (hints != null) { + let rpcb = hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); + if (rpcb != null) { + points.forEach((point, idx, arr) => { + rpcb.foundPossibleResultPoint(point); + }); + } } + } + + // @Override + public reset(): void { + // do nothing + } } diff --git a/src/core/aztec/AztecWriter.ts b/src/core/aztec/AztecWriter.ts index b0a182a6..51706b57 100644 --- a/src/core/aztec/AztecWriter.ts +++ b/src/core/aztec/AztecWriter.ts @@ -45,7 +45,7 @@ import { int } from '../../customTypings'; /** * Renders an Aztec code as a {@link BitMatrix}. */ -export default /*public final*/ class AztecWriter implements Writer { +export default /* public final */ class AztecWriter implements Writer { // @Override public encode(contents: string, format: BarcodeFormat, width: int, height: int): BitMatrix { @@ -97,9 +97,9 @@ export default /*public final*/ class AztecWriter implements Writer { let output: BitMatrix = new BitMatrix(outputWidth, outputHeight); - for (let inputY /*int*/ = 0, outputY = topPadding; inputY < inputHeight; inputY++ , outputY += multiple) { + for (let inputY /* int */ = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) { // Write the contents of this row of the barcode - for (let inputX /*int*/ = 0, outputX = leftPadding; inputX < inputWidth; inputX++ , outputX += multiple) { + for (let inputX /* int */ = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) { if (input.get(inputX, inputY)) { output.setRegion(outputX, outputY, multiple, multiple); } diff --git a/src/core/aztec/decoder/Decoder.ts b/src/core/aztec/decoder/Decoder.ts index 7d891cae..5e95275f 100644 --- a/src/core/aztec/decoder/Decoder.ts +++ b/src/core/aztec/decoder/Decoder.ts @@ -29,12 +29,12 @@ import { int } from '../../../customTypings'; // import java.util.Arrays; enum Table { - UPPER, - LOWER, - MIXED, - DIGIT, - PUNCT, - BINARY + UPPER, + LOWER, + MIXED, + DIGIT, + PUNCT, + BINARY } /** @@ -45,327 +45,327 @@ enum Table { */ export default class Decoder { - private static UPPER_TABLE: string[] = [ - 'CTRL_PS', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'CTRL_LL', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS' - ]; + private static UPPER_TABLE: string[] = [ + 'CTRL_PS', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'CTRL_LL', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS' + ]; - private static LOWER_TABLE: string[] = [ - 'CTRL_PS', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'CTRL_US', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS' - ]; + private static LOWER_TABLE: string[] = [ + 'CTRL_PS', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'CTRL_US', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS' + ]; - private static MIXED_TABLE: string[] = [ - // Module parse failed: Octal literal in strict mode (50:29) - // so number string were scaped - 'CTRL_PS', ' ', '\\1', '\\2', '\\3', '\\4', '\\5', '\\6', '\\7', '\b', '\t', '\n', - '\\13', '\f', '\r', '\\33', '\\34', '\\35', '\\36', '\\37', '@', '\\', '^', '_', - '`', '|', '~', '\\177', 'CTRL_LL', 'CTRL_UL', 'CTRL_PL', 'CTRL_BS' - ]; + private static MIXED_TABLE: string[] = [ + // Module parse failed: Octal literal in strict mode (50:29) + // so number string were scaped + 'CTRL_PS', ' ', '\\1', '\\2', '\\3', '\\4', '\\5', '\\6', '\\7', '\b', '\t', '\n', + '\\13', '\f', '\r', '\\33', '\\34', '\\35', '\\36', '\\37', '@', '\\', '^', '_', + '`', '|', '~', '\\177', 'CTRL_LL', 'CTRL_UL', 'CTRL_PL', 'CTRL_BS' + ]; - private static PUNCT_TABLE: string[] = [ - '', '\r', '\r\n', '. ', ', ', ': ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', - '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', 'CTRL_UL' - ]; + private static PUNCT_TABLE: string[] = [ + '', '\r', '\r\n', '. ', ', ', ': ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', + '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', 'CTRL_UL' + ]; - private static DIGIT_TABLE: string[] = [ - 'CTRL_PS', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', 'CTRL_UL', 'CTRL_US' - ]; + private static DIGIT_TABLE: string[] = [ + 'CTRL_PS', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', 'CTRL_UL', 'CTRL_US' + ]; - private ddata: AztecDetectorResult; + private ddata: AztecDetectorResult; - public decode(detectorResult: AztecDetectorResult): DecoderResult { - this.ddata = detectorResult; - let matrix = detectorResult.getBits(); - let rawbits = this.extractBits(matrix); - let correctedBits = this.correctBits(rawbits); - let rawBytes = Decoder.convertBoolArrayToByteArray(correctedBits); - let result = Decoder.getEncodedData(correctedBits); - let decoderResult = new DecoderResult(rawBytes, result, null, null); - decoderResult.setNumBits(correctedBits.length); - return decoderResult; - } + public decode(detectorResult: AztecDetectorResult): DecoderResult { + this.ddata = detectorResult; + let matrix = detectorResult.getBits(); + let rawbits = this.extractBits(matrix); + let correctedBits = this.correctBits(rawbits); + let rawBytes = Decoder.convertBoolArrayToByteArray(correctedBits); + let result = Decoder.getEncodedData(correctedBits); + let decoderResult = new DecoderResult(rawBytes, result, null, null); + decoderResult.setNumBits(correctedBits.length); + return decoderResult; + } - // This method is used for testing the high-level encoder - public static highLevelDecode(correctedBits: boolean[]): string { - return this.getEncodedData(correctedBits); - } + // This method is used for testing the high-level encoder + public static highLevelDecode(correctedBits: boolean[]): string { + return this.getEncodedData(correctedBits); + } - /** - * Gets the string encoded in the aztec code bits - * - * @return the decoded string - */ - private static getEncodedData(correctedBits: boolean[]): string { - let endIndex: number = correctedBits.length; - let latchTable = Table.UPPER; // table most recently latched to - let shiftTable = Table.UPPER; // table to use for the next read - let result: string = ''; - let index = 0; - while (index < endIndex) { - if (shiftTable === Table.BINARY) { - if (endIndex - index < 5) { - break; - } - let length = Decoder.readCode(correctedBits, index, 5); - index += 5; - if (length === 0) { - if (endIndex - index < 11) { - break; - } - length = Decoder.readCode(correctedBits, index, 11) + 31; - index += 11; - } - for (let charCount = 0; charCount < length; charCount++) { - if (endIndex - index < 8) { - index = endIndex; // Force outer loop to exit - break; - } - const code: int = Decoder.readCode(correctedBits, index, 8); - result += /*(char)*/ StringUtils.castAsNonUtf8Char(code); - index += 8; - } - // Go back to whatever mode we had been in - shiftTable = latchTable; - } else { - let size = shiftTable === Table.DIGIT ? 4 : 5; - if (endIndex - index < size) { - break; - } - let code = Decoder.readCode(correctedBits, index, size); - index += size; - let str = Decoder.getCharacter(shiftTable, code); - if (str.startsWith('CTRL_')) { - // Table changes - // ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked. - // That's including when that mode is a shift. - // Our test case dlusbs.png for issue #642 exercises that. - latchTable = shiftTable; // Latch the current mode, so as to return to Upper after U/S B/S - shiftTable = Decoder.getTable(str.charAt(5)); - if (str.charAt(6) === 'L') { - latchTable = shiftTable; - } - } else { - result += str; - // Go back to whatever mode we had been in - shiftTable = latchTable; - } - } + /** + * Gets the string encoded in the aztec code bits + * + * @return the decoded string + */ + private static getEncodedData(correctedBits: boolean[]): string { + let endIndex: number = correctedBits.length; + let latchTable = Table.UPPER; // table most recently latched to + let shiftTable = Table.UPPER; // table to use for the next read + let result: string = ''; + let index = 0; + while (index < endIndex) { + if (shiftTable === Table.BINARY) { + if (endIndex - index < 5) { + break; + } + let length = Decoder.readCode(correctedBits, index, 5); + index += 5; + if (length === 0) { + if (endIndex - index < 11) { + break; + } + length = Decoder.readCode(correctedBits, index, 11) + 31; + index += 11; + } + for (let charCount = 0; charCount < length; charCount++) { + if (endIndex - index < 8) { + index = endIndex; // Force outer loop to exit + break; + } + const code: int = Decoder.readCode(correctedBits, index, 8); + result += /* (char) */ StringUtils.castAsNonUtf8Char(code); + index += 8; } - return result; + // Go back to whatever mode we had been in + shiftTable = latchTable; + } else { + let size = shiftTable === Table.DIGIT ? 4 : 5; + if (endIndex - index < size) { + break; + } + let code = Decoder.readCode(correctedBits, index, size); + index += size; + let str = Decoder.getCharacter(shiftTable, code); + if (str.startsWith('CTRL_')) { + // Table changes + // ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked. + // That's including when that mode is a shift. + // Our test case dlusbs.png for issue #642 exercises that. + latchTable = shiftTable; // Latch the current mode, so as to return to Upper after U/S B/S + shiftTable = Decoder.getTable(str.charAt(5)); + if (str.charAt(6) === 'L') { + latchTable = shiftTable; + } + } else { + result += str; + // Go back to whatever mode we had been in + shiftTable = latchTable; + } + } } + return result; + } - /** - * gets the table corresponding to the char passed - */ - private static getTable(t: string): Table { - switch (t) { - case 'L': - return Table.LOWER; - case 'P': - return Table.PUNCT; - case 'M': - return Table.MIXED; - case 'D': - return Table.DIGIT; - case 'B': - return Table.BINARY; - case 'U': - default: - return Table.UPPER; - } + /** + * gets the table corresponding to the char passed + */ + private static getTable(t: string): Table { + switch (t) { + case 'L': + return Table.LOWER; + case 'P': + return Table.PUNCT; + case 'M': + return Table.MIXED; + case 'D': + return Table.DIGIT; + case 'B': + return Table.BINARY; + case 'U': + default: + return Table.UPPER; } + } - /** - * Gets the character (or string) corresponding to the passed code in the given table - * - * @param table the table used - * @param code the code of the character - */ - private static getCharacter(table: Table, code: number): string { - switch (table) { - case Table.UPPER: - return Decoder.UPPER_TABLE[code]; - case Table.LOWER: - return Decoder.LOWER_TABLE[code]; - case Table.MIXED: - return Decoder.MIXED_TABLE[code]; - case Table.PUNCT: - return Decoder.PUNCT_TABLE[code]; - case Table.DIGIT: - return Decoder.DIGIT_TABLE[code]; - default: - // Should not reach here. - throw new IllegalStateException('Bad table'); - } + /** + * Gets the character (or string) corresponding to the passed code in the given table + * + * @param table the table used + * @param code the code of the character + */ + private static getCharacter(table: Table, code: number): string { + switch (table) { + case Table.UPPER: + return Decoder.UPPER_TABLE[code]; + case Table.LOWER: + return Decoder.LOWER_TABLE[code]; + case Table.MIXED: + return Decoder.MIXED_TABLE[code]; + case Table.PUNCT: + return Decoder.PUNCT_TABLE[code]; + case Table.DIGIT: + return Decoder.DIGIT_TABLE[code]; + default: + // Should not reach here. + throw new IllegalStateException('Bad table'); } + } - /** - *

Performs RS error correction on an array of bits.

- * - * @return the corrected array - * @throws FormatException if the input contains too many errors - */ - private correctBits(rawbits: boolean[]): boolean[] { - let gf: GenericGF; - let codewordSize: number; + /** + *

Performs RS error correction on an array of bits.

+ * + * @return the corrected array + * @throws FormatException if the input contains too many errors + */ + private correctBits(rawbits: boolean[]): boolean[] { + let gf: GenericGF; + let codewordSize: number; - if (this.ddata.getNbLayers() <= 2) { - codewordSize = 6; - gf = GenericGF.AZTEC_DATA_6; - } else if (this.ddata.getNbLayers() <= 8) { - codewordSize = 8; - gf = GenericGF.AZTEC_DATA_8; - } else if (this.ddata.getNbLayers() <= 22) { - codewordSize = 10; - gf = GenericGF.AZTEC_DATA_10; - } else { - codewordSize = 12; - gf = GenericGF.AZTEC_DATA_12; - } + if (this.ddata.getNbLayers() <= 2) { + codewordSize = 6; + gf = GenericGF.AZTEC_DATA_6; + } else if (this.ddata.getNbLayers() <= 8) { + codewordSize = 8; + gf = GenericGF.AZTEC_DATA_8; + } else if (this.ddata.getNbLayers() <= 22) { + codewordSize = 10; + gf = GenericGF.AZTEC_DATA_10; + } else { + codewordSize = 12; + gf = GenericGF.AZTEC_DATA_12; + } - let numDataCodewords = this.ddata.getNbDatablocks(); - let numCodewords = rawbits.length / codewordSize; - if (numCodewords < numDataCodewords) { - throw new FormatException(); - } - let offset = rawbits.length % codewordSize; + let numDataCodewords = this.ddata.getNbDatablocks(); + let numCodewords = rawbits.length / codewordSize; + if (numCodewords < numDataCodewords) { + throw new FormatException(); + } + let offset = rawbits.length % codewordSize; - let dataWords: Int32Array = new Int32Array(numCodewords); - for (let i = 0; i < numCodewords; i++ , offset += codewordSize) { - dataWords[i] = Decoder.readCode(rawbits, offset, codewordSize); - } + let dataWords: Int32Array = new Int32Array(numCodewords); + for (let i = 0; i < numCodewords; i++, offset += codewordSize) { + dataWords[i] = Decoder.readCode(rawbits, offset, codewordSize); + } - try { - let rsDecoder = new ReedSolomonDecoder(gf); - rsDecoder.decode(dataWords, numCodewords - numDataCodewords); - } catch (ex) { - throw new FormatException(ex); - } + try { + let rsDecoder = new ReedSolomonDecoder(gf); + rsDecoder.decode(dataWords, numCodewords - numDataCodewords); + } catch (ex) { + throw new FormatException(ex); + } - // Now perform the unstuffing operation. - // First, count how many bits are going to be thrown out as stuffing - let mask = (1 << codewordSize) - 1; - let stuffedBits = 0; - for (let i = 0; i < numDataCodewords; i++) { - let dataWord = dataWords[i]; - if (dataWord === 0 || dataWord === mask) { - throw new FormatException(); - } else if (dataWord === 1 || dataWord === mask - 1) { - stuffedBits++; - } - } - // Now, actually unpack the bits and remove the stuffing - let correctedBits: boolean[] = new Array(numDataCodewords * codewordSize - stuffedBits); - let index = 0; - for (let i = 0; i < numDataCodewords; i++) { - let dataWord = dataWords[i]; - if (dataWord === 1 || dataWord === mask - 1) { - // next codewordSize-1 bits are all zeros or all ones - correctedBits.fill(dataWord > 1, index, index + codewordSize - 1); - // Arrays.fill(correctedBits, index, index + codewordSize - 1, dataWord > 1); - index += codewordSize - 1; - } else { - for (let bit = codewordSize - 1; bit >= 0; --bit) { - correctedBits[index++] = (dataWord & (1 << bit)) !== 0; - } - } + // Now perform the unstuffing operation. + // First, count how many bits are going to be thrown out as stuffing + let mask = (1 << codewordSize) - 1; + let stuffedBits = 0; + for (let i = 0; i < numDataCodewords; i++) { + let dataWord = dataWords[i]; + if (dataWord === 0 || dataWord === mask) { + throw new FormatException(); + } else if (dataWord === 1 || dataWord === mask - 1) { + stuffedBits++; + } + } + // Now, actually unpack the bits and remove the stuffing + let correctedBits: boolean[] = new Array(numDataCodewords * codewordSize - stuffedBits); + let index = 0; + for (let i = 0; i < numDataCodewords; i++) { + let dataWord = dataWords[i]; + if (dataWord === 1 || dataWord === mask - 1) { + // next codewordSize-1 bits are all zeros or all ones + correctedBits.fill(dataWord > 1, index, index + codewordSize - 1); + // Arrays.fill(correctedBits, index, index + codewordSize - 1, dataWord > 1); + index += codewordSize - 1; + } else { + for (let bit = codewordSize - 1; bit >= 0; --bit) { + correctedBits[index++] = (dataWord & (1 << bit)) !== 0; } - return correctedBits; + } } + return correctedBits; + } - /** - * Gets the array of bits from an Aztec Code matrix - * - * @return the array of bits - */ - private extractBits(matrix: BitMatrix): boolean[] { - let compact = this.ddata.isCompact(); - let layers = this.ddata.getNbLayers(); - let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines - let alignmentMap = new Int32Array(baseMatrixSize); - let rawbits: boolean[] = new Array(this.totalBitsInLayer(layers, compact)); + /** + * Gets the array of bits from an Aztec Code matrix + * + * @return the array of bits + */ + private extractBits(matrix: BitMatrix): boolean[] { + let compact = this.ddata.isCompact(); + let layers = this.ddata.getNbLayers(); + let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines + let alignmentMap = new Int32Array(baseMatrixSize); + let rawbits: boolean[] = new Array(this.totalBitsInLayer(layers, compact)); - if (compact) { - for (let i = 0; i < alignmentMap.length; i++) { - alignmentMap[i] = i; - } - } else { - let matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15); - let origCenter = baseMatrixSize / 2; - let center = Integer.truncDivision(matrixSize, 2); - for (let i = 0; i < origCenter; i++) { - let newOffset = i + Integer.truncDivision(i, 15); - alignmentMap[origCenter - i - 1] = center - newOffset - 1; - alignmentMap[origCenter + i] = center + newOffset + 1; - } - } - for (let i = 0, rowOffset = 0; i < layers; i++) { - let rowSize = (layers - i) * 4 + (compact ? 9 : 12); - // The top-left most point of this layer is (not including alignment lines) - let low = i * 2; - // The bottom-right most point of this layer is (not including alignment lines) - let high = baseMatrixSize - 1 - low; - // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows - for (let j = 0; j < rowSize; j++) { - let columnOffset = j * 2; - for (let k = 0; k < 2; k++) { - // left column - rawbits[rowOffset + columnOffset + k] = - matrix.get(alignmentMap[low + k], alignmentMap[low + j]); - // bottom row - rawbits[rowOffset + 2 * rowSize + columnOffset + k] = - matrix.get(alignmentMap[low + j], alignmentMap[high - k]); - // right column - rawbits[rowOffset + 4 * rowSize + columnOffset + k] = - matrix.get(alignmentMap[high - k], alignmentMap[high - j]); - // top row - rawbits[rowOffset + 6 * rowSize + columnOffset + k] = - matrix.get(alignmentMap[high - j], alignmentMap[low + k]); - } - } - rowOffset += rowSize * 8; - } - return rawbits; + if (compact) { + for (let i = 0; i < alignmentMap.length; i++) { + alignmentMap[i] = i; + } + } else { + let matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15); + let origCenter = baseMatrixSize / 2; + let center = Integer.truncDivision(matrixSize, 2); + for (let i = 0; i < origCenter; i++) { + let newOffset = i + Integer.truncDivision(i, 15); + alignmentMap[origCenter - i - 1] = center - newOffset - 1; + alignmentMap[origCenter + i] = center + newOffset + 1; + } } - - /** - * Reads a code of given length and at given index in an array of bits - */ - private static readCode(rawbits: boolean[], startIndex: number, length: number): number { - let res = 0; - for (let i = startIndex; i < startIndex + length; i++) { - res <<= 1; - if (rawbits[i]) { - res |= 0x01; - } + for (let i = 0, rowOffset = 0; i < layers; i++) { + let rowSize = (layers - i) * 4 + (compact ? 9 : 12); + // The top-left most point of this layer is (not including alignment lines) + let low = i * 2; + // The bottom-right most point of this layer is (not including alignment lines) + let high = baseMatrixSize - 1 - low; + // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows + for (let j = 0; j < rowSize; j++) { + let columnOffset = j * 2; + for (let k = 0; k < 2; k++) { + // left column + rawbits[rowOffset + columnOffset + k] = + matrix.get(alignmentMap[low + k], alignmentMap[low + j]); + // bottom row + rawbits[rowOffset + 2 * rowSize + columnOffset + k] = + matrix.get(alignmentMap[low + j], alignmentMap[high - k]); + // right column + rawbits[rowOffset + 4 * rowSize + columnOffset + k] = + matrix.get(alignmentMap[high - k], alignmentMap[high - j]); + // top row + rawbits[rowOffset + 6 * rowSize + columnOffset + k] = + matrix.get(alignmentMap[high - j], alignmentMap[low + k]); } - return res; + } + rowOffset += rowSize * 8; } + return rawbits; + } - /** - * Reads a code of length 8 in an array of bits, padding with zeros - */ - private static readByte(rawbits: boolean[], startIndex: number): number { - let n = rawbits.length - startIndex; - if (n >= 8) { - return Decoder.readCode(rawbits, startIndex, 8); - } - return Decoder.readCode(rawbits, startIndex, n) << (8 - n); + /** + * Reads a code of given length and at given index in an array of bits + */ + private static readCode(rawbits: boolean[], startIndex: number, length: number): number { + let res = 0; + for (let i = startIndex; i < startIndex + length; i++) { + res <<= 1; + if (rawbits[i]) { + res |= 0x01; + } } + return res; + } - /** - * Packs a bit array into bytes, most significant bit first - */ - public static convertBoolArrayToByteArray(boolArr: boolean[]): Uint8Array { - let byteArr = new Uint8Array((boolArr.length + 7) / 8); - for (let i = 0; i < byteArr.length; i++) { - byteArr[i] = Decoder.readByte(boolArr, 8 * i); - } - return byteArr; + /** + * Reads a code of length 8 in an array of bits, padding with zeros + */ + private static readByte(rawbits: boolean[], startIndex: number): number { + let n = rawbits.length - startIndex; + if (n >= 8) { + return Decoder.readCode(rawbits, startIndex, 8); } + return Decoder.readCode(rawbits, startIndex, n) << (8 - n); + } - private totalBitsInLayer(layers: number, compact: boolean): number { - return ((compact ? 88 : 112) + 16 * layers) * layers; + /** + * Packs a bit array into bytes, most significant bit first + */ + public static convertBoolArrayToByteArray(boolArr: boolean[]): Uint8Array { + let byteArr = new Uint8Array((boolArr.length + 7) / 8); + for (let i = 0; i < byteArr.length; i++) { + byteArr[i] = Decoder.readByte(boolArr, 8 * i); } + return byteArr; + } + + private totalBitsInLayer(layers: number, compact: boolean): number { + return ((compact ? 88 : 112) + 16 * layers) * layers; + } } diff --git a/src/core/aztec/detector/Detector.ts b/src/core/aztec/detector/Detector.ts index 4e9b286a..ffecc9bc 100644 --- a/src/core/aztec/detector/Detector.ts +++ b/src/core/aztec/detector/Detector.ts @@ -28,30 +28,30 @@ import Integer from '../../util/Integer'; export class Point { - private x: number; - private y: number; - - public toResultPoint(): ResultPoint { - return new ResultPoint(this.getX(), this.getY()); - } - - public constructor(x: number, y: number) { - this.x = x; - this.y = y; - } - - public getX(): number { - return this.x; - } - - public getY(): number { - return this.y; - } - - // @Override - // public String toString() { - // return "<" + x + ' ' + y + '>'; - // } + private x: number; + private y: number; + + public toResultPoint(): ResultPoint { + return new ResultPoint(this.getX(), this.getY()); + } + + public constructor(x: number, y: number) { + this.x = x; + this.y = y; + } + + public getX(): number { + return this.x; + } + + public getY(): number { + return this.y; + } + + // @Override + // public String toString() { + // return "<" + x + ' ' + y + '>'; + // } } /** @@ -63,550 +63,550 @@ export class Point { */ export default class Detector { - private EXPECTED_CORNER_BITS = new Int32Array([ - 0xee0, // 07340 XXX .XX X.. ... - 0x1dc, // 00734 ... XXX .XX X.. - 0x83b, // 04073 X.. ... XXX .XX - 0x707, // 03407 .XX X.. ... XXX - ]); + private EXPECTED_CORNER_BITS = new Int32Array([ + 0xee0, // 07340 XXX .XX X.. ... + 0x1dc, // 00734 ... XXX .XX X.. + 0x83b, // 04073 X.. ... XXX .XX + 0x707, // 03407 .XX X.. ... XXX + ]); + + private image: BitMatrix; + + private compact: boolean; + private nbLayers: number; + private nbDataBlocks: number; + private nbCenterLayers: number; + private shift: number; + + public constructor(image: BitMatrix) { + this.image = image; + } + + public detect(): AztecDetectorResult { + return this.detectMirror(false); + } + + /** + * Detects an Aztec Code in an image. + * + * @param isMirror if true, image is a mirror-image of original + * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code + * @throws NotFoundException if no Aztec Code can be found + */ + public detectMirror(isMirror: boolean): AztecDetectorResult { - private image: BitMatrix; + // 1. Get the center of the aztec matrix + let pCenter = this.getMatrixCenter(); - private compact: boolean; - private nbLayers: number; - private nbDataBlocks: number; - private nbCenterLayers: number; - private shift: number; + // 2. Get the center points of the four diagonal points just outside the bull's eye + // [topRight, bottomRight, bottomLeft, topLeft] + let bullsEyeCorners = this.getBullsEyeCorners(pCenter); - public constructor(image: BitMatrix) { - this.image = image; + if (isMirror) { + let temp = bullsEyeCorners[0]; + bullsEyeCorners[0] = bullsEyeCorners[2]; + bullsEyeCorners[2] = temp; } - public detect(): AztecDetectorResult { - return this.detectMirror(false); - } + // 3. Get the size of the matrix and other parameters from the bull's eye + this.extractParameters(bullsEyeCorners); - /** - * Detects an Aztec Code in an image. - * - * @param isMirror if true, image is a mirror-image of original - * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code - * @throws NotFoundException if no Aztec Code can be found - */ - public detectMirror(isMirror: boolean): AztecDetectorResult { - - // 1. Get the center of the aztec matrix - let pCenter = this.getMatrixCenter(); - - // 2. Get the center points of the four diagonal points just outside the bull's eye - // [topRight, bottomRight, bottomLeft, topLeft] - let bullsEyeCorners = this.getBullsEyeCorners(pCenter); - - if (isMirror) { - let temp = bullsEyeCorners[0]; - bullsEyeCorners[0] = bullsEyeCorners[2]; - bullsEyeCorners[2] = temp; - } - // 3. Get the size of the matrix and other parameters from the bull's eye - this.extractParameters(bullsEyeCorners); + // 4. Sample the grid + let bits: BitMatrix = this.sampleGrid(this.image, + bullsEyeCorners[this.shift % 4], + bullsEyeCorners[(this.shift + 1) % 4], + bullsEyeCorners[(this.shift + 2) % 4], + bullsEyeCorners[(this.shift + 3) % 4] + ); + // 5. Get the corners of the matrix. + let corners: ResultPoint[] = this.getMatrixCornerPoints(bullsEyeCorners); - // 4. Sample the grid - let bits: BitMatrix = this.sampleGrid(this.image, - bullsEyeCorners[this.shift % 4], - bullsEyeCorners[(this.shift + 1) % 4], - bullsEyeCorners[(this.shift + 2) % 4], - bullsEyeCorners[(this.shift + 3) % 4] - ); + return new AztecDetectorResult(bits, corners, this.compact, this.nbDataBlocks, this.nbLayers); + } - // 5. Get the corners of the matrix. - let corners: ResultPoint[] = this.getMatrixCornerPoints(bullsEyeCorners); + /** + * Extracts the number of data layers and data blocks from the layer around the bull's eye. + * + * @param bullsEyeCorners the array of bull's eye corners + * @throws NotFoundException in case of too many errors or invalid parameters + */ + private extractParameters(bullsEyeCorners: ResultPoint[]): void { + if (!this.isValidPoint(bullsEyeCorners[0]) || !this.isValidPoint(bullsEyeCorners[1]) || + !this.isValidPoint(bullsEyeCorners[2]) || !this.isValidPoint(bullsEyeCorners[3])) { + throw new NotFoundException(); + } + let length = 2 * this.nbCenterLayers; + // Get the bits around the bull's eye + let sides = new Int32Array([ + this.sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length), // Right side + this.sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length), // Bottom + this.sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length), // Left side + this.sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top + ]); - return new AztecDetectorResult(bits, corners, this.compact, this.nbDataBlocks, this.nbLayers); + // bullsEyeCorners[shift] is the corner of the bulls'eye that has three + // orientation marks. + // sides[shift] is the row/column that goes from the corner with three + // orientation marks to the corner with two. + this.shift = this.getRotation(sides, length); + + // Flatten the parameter bits into a single 28- or 40-bit long + let parameterData = 0; + for (let i = 0; i < 4; i++) { + let side = sides[(this.shift + i) % 4]; + if (this.compact) { + // Each side of the form ..XXXXXXX. where Xs are parameter data + parameterData <<= 7; + parameterData += (side >> 1) & 0x7F; + } else { + // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data + parameterData <<= 10; + parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F); + } } - /** - * Extracts the number of data layers and data blocks from the layer around the bull's eye. - * - * @param bullsEyeCorners the array of bull's eye corners - * @throws NotFoundException in case of too many errors or invalid parameters - */ - private extractParameters(bullsEyeCorners: ResultPoint[]): void { - if (!this.isValidPoint(bullsEyeCorners[0]) || !this.isValidPoint(bullsEyeCorners[1]) || - !this.isValidPoint(bullsEyeCorners[2]) || !this.isValidPoint(bullsEyeCorners[3])) { - throw new NotFoundException(); - } - let length = 2 * this.nbCenterLayers; - // Get the bits around the bull's eye - let sides = new Int32Array([ - this.sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length), // Right side - this.sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length), // Bottom - this.sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length), // Left side - this.sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top - ]); - - // bullsEyeCorners[shift] is the corner of the bulls'eye that has three - // orientation marks. - // sides[shift] is the row/column that goes from the corner with three - // orientation marks to the corner with two. - this.shift = this.getRotation(sides, length); - - // Flatten the parameter bits into a single 28- or 40-bit long - let parameterData = 0; - for (let i = 0; i < 4; i++) { - let side = sides[(this.shift + i) % 4]; - if (this.compact) { - // Each side of the form ..XXXXXXX. where Xs are parameter data - parameterData <<= 7; - parameterData += (side >> 1) & 0x7F; - } else { - // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data - parameterData <<= 10; - parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F); - } - } + // Corrects parameter data using RS. Returns just the data portion + // without the error correction. + let correctedData = this.getCorrectedParameterData(parameterData, this.compact); + + if (this.compact) { + // 8 bits: 2 bits layers and 6 bits data blocks + this.nbLayers = (correctedData >> 6) + 1; + this.nbDataBlocks = (correctedData & 0x3F) + 1; + } else { + // 16 bits: 5 bits layers and 11 bits data blocks + this.nbLayers = (correctedData >> 11) + 1; + this.nbDataBlocks = (correctedData & 0x7FF) + 1; + } + } + + private getRotation(sides: Int32Array, length: number): number { + // In a normal pattern, we expect to See + // ** .* D A + // * * + // + // . * + // .. .. C B + // + // Grab the 3 bits from each of the sides the form the locator pattern and concatenate + // into a 12-bit integer. Start with the bit at A + let cornerBits = 0; + sides.forEach((side, idx, arr) => { + // XX......X where X's are orientation marks + let t = ((side >> (length - 2)) << 1) + (side & 1); + cornerBits = (cornerBits << 3) + t; + }); + // for (var side in sides) { + // // XX......X where X's are orientation marks + // var t = ((side >> (length - 2)) << 1) + (side & 1); + // cornerBits = (cornerBits << 3) + t; + // } - // Corrects parameter data using RS. Returns just the data portion - // without the error correction. - let correctedData = this.getCorrectedParameterData(parameterData, this.compact); - - if (this.compact) { - // 8 bits: 2 bits layers and 6 bits data blocks - this.nbLayers = (correctedData >> 6) + 1; - this.nbDataBlocks = (correctedData & 0x3F) + 1; - } else { - // 16 bits: 5 bits layers and 11 bits data blocks - this.nbLayers = (correctedData >> 11) + 1; - this.nbDataBlocks = (correctedData & 0x7FF) + 1; - } + // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are + // together. cornerBits is now: + // 3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D + cornerBits = ((cornerBits & 1) << 11) + (cornerBits >> 1); + // The result shift indicates which element of BullsEyeCorners[] goes into the top-left + // corner. Since the four rotation values have a Hamming distance of 8, we + // can easily tolerate two errors. + for (let shift = 0; shift < 4; shift++) { + if (Integer.bitCount(cornerBits ^ this.EXPECTED_CORNER_BITS[shift]) <= 2) { + return shift; + } + } + throw new NotFoundException(); + } + + /** + * Corrects the parameter bits using Reed-Solomon algorithm. + * + * @param parameterData parameter bits + * @param compact true if this is a compact Aztec code + * @throws NotFoundException if the array contains too many errors + */ + private getCorrectedParameterData(parameterData: number, compact: boolean): number { + let numCodewords; + let numDataCodewords; + + if (compact) { + numCodewords = 7; + numDataCodewords = 2; + } else { + numCodewords = 10; + numDataCodewords = 4; } - private getRotation(sides: Int32Array, length: number): number { - // In a normal pattern, we expect to See - // ** .* D A - // * * - // - // . * - // .. .. C B - // - // Grab the 3 bits from each of the sides the form the locator pattern and concatenate - // into a 12-bit integer. Start with the bit at A - let cornerBits = 0; - sides.forEach((side, idx, arr) => { - // XX......X where X's are orientation marks - let t = ((side >> (length - 2)) << 1) + (side & 1); - cornerBits = (cornerBits << 3) + t; - }); - // for (var side in sides) { - // // XX......X where X's are orientation marks - // var t = ((side >> (length - 2)) << 1) + (side & 1); - // cornerBits = (cornerBits << 3) + t; - // } - - // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are - // together. cornerBits is now: - // 3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D - cornerBits = ((cornerBits & 1) << 11) + (cornerBits >> 1); - // The result shift indicates which element of BullsEyeCorners[] goes into the top-left - // corner. Since the four rotation values have a Hamming distance of 8, we - // can easily tolerate two errors. - for (let shift = 0; shift < 4; shift++) { - if (Integer.bitCount(cornerBits ^ this.EXPECTED_CORNER_BITS[shift]) <= 2) { - return shift; - } - } - throw new NotFoundException(); + let numECCodewords = numCodewords - numDataCodewords; + let parameterWords: Int32Array = new Int32Array(numCodewords); + for (let i = numCodewords - 1; i >= 0; --i) { + parameterWords[i] = parameterData & 0xF; + parameterData >>= 4; + } + try { + let rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM); + rsDecoder.decode(parameterWords, numECCodewords); + } catch (ignored) { + throw new NotFoundException(); + } + // Toss the error correction. Just return the data as an integer + let result = 0; + for (let i = 0; i < numDataCodewords; i++) { + result = (result << 4) + parameterWords[i]; } + return result; + } + + /** + * Finds the corners of a bull-eye centered on the passed point. + * This returns the centers of the diagonal points just outside the bull's eye + * Returns [topRight, bottomRight, bottomLeft, topLeft] + * + * @param pCenter Center point + * @return The corners of the bull-eye + * @throws NotFoundException If no valid bull-eye can be found + */ + private getBullsEyeCorners(pCenter: Point): ResultPoint[] { - /** - * Corrects the parameter bits using Reed-Solomon algorithm. - * - * @param parameterData parameter bits - * @param compact true if this is a compact Aztec code - * @throws NotFoundException if the array contains too many errors - */ - private getCorrectedParameterData(parameterData: number, compact: boolean): number { - let numCodewords; - let numDataCodewords; - - if (compact) { - numCodewords = 7; - numDataCodewords = 2; - } else { - numCodewords = 10; - numDataCodewords = 4; - } - let numECCodewords = numCodewords - numDataCodewords; - let parameterWords: Int32Array = new Int32Array(numCodewords); - for (let i = numCodewords - 1; i >= 0; --i) { - parameterWords[i] = parameterData & 0xF; - parameterData >>= 4; - } - try { - let rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM); - rsDecoder.decode(parameterWords, numECCodewords); - } catch (ignored) { - throw new NotFoundException(); - } - // Toss the error correction. Just return the data as an integer - let result = 0; - for (let i = 0; i < numDataCodewords; i++) { - result = (result << 4) + parameterWords[i]; - } - return result; - } + let pina = pCenter; + let pinb = pCenter; + let pinc = pCenter; + let pind = pCenter; - /** - * Finds the corners of a bull-eye centered on the passed point. - * This returns the centers of the diagonal points just outside the bull's eye - * Returns [topRight, bottomRight, bottomLeft, topLeft] - * - * @param pCenter Center point - * @return The corners of the bull-eye - * @throws NotFoundException If no valid bull-eye can be found - */ - private getBullsEyeCorners(pCenter: Point): ResultPoint[] { - - - let pina = pCenter; - let pinb = pCenter; - let pinc = pCenter; - let pind = pCenter; - - let color = true; - - for (this.nbCenterLayers = 1; this.nbCenterLayers < 9; this.nbCenterLayers++) { - - let pouta = this.getFirstDifferent(pina, color, 1, -1); - let poutb = this.getFirstDifferent(pinb, color, 1, 1); - let poutc = this.getFirstDifferent(pinc, color, -1, 1); - let poutd = this.getFirstDifferent(pind, color, -1, -1); - - // d a - // - // c b - - if (this.nbCenterLayers > 2) { - let q = (this.distancePoint(poutd, pouta) * this.nbCenterLayers) / (this.distancePoint(pind, pina) * (this.nbCenterLayers + 2)); - if (q < 0.75 || q > 1.25 || !this.isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) { - break; - } - } - - pina = pouta; - pinb = poutb; - pinc = poutc; - pind = poutd; - - color = !color; - } + let color = true; + + for (this.nbCenterLayers = 1; this.nbCenterLayers < 9; this.nbCenterLayers++) { - if (this.nbCenterLayers !== 5 && this.nbCenterLayers !== 7) { - throw new NotFoundException(); + let pouta = this.getFirstDifferent(pina, color, 1, -1); + let poutb = this.getFirstDifferent(pinb, color, 1, 1); + let poutc = this.getFirstDifferent(pinc, color, -1, 1); + let poutd = this.getFirstDifferent(pind, color, -1, -1); + + // d a + // + // c b + + if (this.nbCenterLayers > 2) { + let q = (this.distancePoint(poutd, pouta) * this.nbCenterLayers) / (this.distancePoint(pind, pina) * (this.nbCenterLayers + 2)); + if (q < 0.75 || q > 1.25 || !this.isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) { + break; } + } - this.compact = this.nbCenterLayers === 5; + pina = pouta; + pinb = poutb; + pinc = poutc; + pind = poutd; - // Expand the square by .5 pixel in each direction so that we're on the border - // between the white square and the black square - let pinax = new ResultPoint(pina.getX() + 0.5, pina.getY() - 0.5); - let pinbx = new ResultPoint(pinb.getX() + 0.5, pinb.getY() + 0.5); - let pincx = new ResultPoint(pinc.getX() - 0.5, pinc.getY() + 0.5); - let pindx = new ResultPoint(pind.getX() - 0.5, pind.getY() - 0.5); + color = !color; + } - // Expand the square so that its corners are the centers of the points - // just outside the bull's eye. - return this.expandSquare([pinax, pinbx, pincx, pindx], - 2 * this.nbCenterLayers - 3, - 2 * this.nbCenterLayers); + if (this.nbCenterLayers !== 5 && this.nbCenterLayers !== 7) { + throw new NotFoundException(); } - /** - * Finds a candidate center point of an Aztec code from an image - * - * @return the center point - */ - private getMatrixCenter(): Point { - - let pointA: ResultPoint; - let pointB: ResultPoint; - let pointC: ResultPoint; - let pointD: ResultPoint; - - // Get a white rectangle that can be the border of the matrix in center bull's eye or - try { - - let cornerPoints = new WhiteRectangleDetector(this.image).detect(); - pointA = cornerPoints[0]; - pointB = cornerPoints[1]; - pointC = cornerPoints[2]; - pointD = cornerPoints[3]; - - } catch (e) { - - // This exception can be in case the initial rectangle is white - // In that case, surely in the bull's eye, we try to expand the rectangle. - let cx = this.image.getWidth() / 2; - let cy = this.image.getHeight() / 2; - pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint(); - pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint(); - pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint(); - pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint(); + this.compact = this.nbCenterLayers === 5; + + // Expand the square by .5 pixel in each direction so that we're on the border + // between the white square and the black square + let pinax = new ResultPoint(pina.getX() + 0.5, pina.getY() - 0.5); + let pinbx = new ResultPoint(pinb.getX() + 0.5, pinb.getY() + 0.5); + let pincx = new ResultPoint(pinc.getX() - 0.5, pinc.getY() + 0.5); + let pindx = new ResultPoint(pind.getX() - 0.5, pind.getY() - 0.5); + + // Expand the square so that its corners are the centers of the points + // just outside the bull's eye. + return this.expandSquare([pinax, pinbx, pincx, pindx], + 2 * this.nbCenterLayers - 3, + 2 * this.nbCenterLayers); + } + + /** + * Finds a candidate center point of an Aztec code from an image + * + * @return the center point + */ + private getMatrixCenter(): Point { - } + let pointA: ResultPoint; + let pointB: ResultPoint; + let pointC: ResultPoint; + let pointD: ResultPoint; - // Compute the center of the rectangle - let cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0); - let cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0); - - // Redetermine the white rectangle starting from previously computed center. - // This will ensure that we end up with a white rectangle in center bull's eye - // in order to compute a more accurate center. - try { - let cornerPoints = new WhiteRectangleDetector(this.image, 15, cx, cy).detect(); - pointA = cornerPoints[0]; - pointB = cornerPoints[1]; - pointC = cornerPoints[2]; - pointD = cornerPoints[3]; - } catch (e) { - // This exception can be in case the initial rectangle is white - // In that case we try to expand the rectangle. - pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint(); - pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint(); - pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint(); - pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint(); - } + // Get a white rectangle that can be the border of the matrix in center bull's eye or + try { - // Recompute the center of the rectangle - cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0); - cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0); + let cornerPoints = new WhiteRectangleDetector(this.image).detect(); + pointA = cornerPoints[0]; + pointB = cornerPoints[1]; + pointC = cornerPoints[2]; + pointD = cornerPoints[3]; - return new Point(cx, cy); - } + } catch (e) { - /** - * Gets the Aztec code corners from the bull's eye corners and the parameters. - * - * @param bullsEyeCorners the array of bull's eye corners - * @return the array of aztec code corners - */ - private getMatrixCornerPoints(bullsEyeCorners: ResultPoint[]): ResultPoint[] { - return this.expandSquare(bullsEyeCorners, 2 * this.nbCenterLayers, this.getDimension()); - } + // This exception can be in case the initial rectangle is white + // In that case, surely in the bull's eye, we try to expand the rectangle. + let cx = this.image.getWidth() / 2; + let cy = this.image.getHeight() / 2; + pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint(); + pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint(); + pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint(); + pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint(); - /** - * Creates a BitMatrix by sampling the provided image. - * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the - * diagonal just outside the bull's eye. - */ - private sampleGrid(image: BitMatrix, - topLeft: ResultPoint, - topRight: ResultPoint, - bottomRight: ResultPoint, - bottomLeft: ResultPoint): BitMatrix { - - let sampler = GridSamplerInstance.getInstance(); - let dimension = this.getDimension(); - - let low = dimension / 2 - this.nbCenterLayers; - let high = dimension / 2 + this.nbCenterLayers; - - return sampler.sampleGrid(image, - dimension, - dimension, - low, low, // topleft - high, low, // topright - high, high, // bottomright - low, high, // bottomleft - topLeft.getX(), topLeft.getY(), - topRight.getX(), topRight.getY(), - bottomRight.getX(), bottomRight.getY(), - bottomLeft.getX(), bottomLeft.getY()); } - /** - * Samples a line. - * - * @param p1 start point (inclusive) - * @param p2 end point (exclusive) - * @param size number of bits - * @return the array of bits as an int (first bit is high-order bit of result) - */ - private sampleLine(p1: ResultPoint, p2: ResultPoint, size: number): number { - let result = 0; - - let d = this.distanceResultPoint(p1, p2); - let moduleSize = d / size; - let px = p1.getX(); - let py = p1.getY(); - let dx = moduleSize * (p2.getX() - p1.getX()) / d; - let dy = moduleSize * (p2.getY() - p1.getY()) / d; - for (let i = 0; i < size; i++) { - if (this.image.get(MathUtils.round(px + i * dx), MathUtils.round(py + i * dy))) { - result |= 1 << (size - i - 1); - } - } - return result; + // Compute the center of the rectangle + let cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0); + let cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0); + + // Redetermine the white rectangle starting from previously computed center. + // This will ensure that we end up with a white rectangle in center bull's eye + // in order to compute a more accurate center. + try { + let cornerPoints = new WhiteRectangleDetector(this.image, 15, cx, cy).detect(); + pointA = cornerPoints[0]; + pointB = cornerPoints[1]; + pointC = cornerPoints[2]; + pointD = cornerPoints[3]; + } catch (e) { + // This exception can be in case the initial rectangle is white + // In that case we try to expand the rectangle. + pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint(); + pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint(); + pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint(); + pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint(); } - /** - * @return true if the border of the rectangle passed in parameter is compound of white points only - * or black points only - */ - private isWhiteOrBlackRectangle(p1: Point, - p2: Point, - p3: Point, - p4: Point): boolean { - - let corr = 3; - p1 = new Point(p1.getX() - corr, p1.getY() + corr); - p2 = new Point(p2.getX() - corr, p2.getY() - corr); - p3 = new Point(p3.getX() + corr, p3.getY() - corr); - p4 = new Point(p4.getX() + corr, p4.getY() + corr); - - let cInit = this.getColor(p4, p1); - - if (cInit === 0) { - return false; - } - - let c = this.getColor(p1, p2); + // Recompute the center of the rectangle + cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0); + cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0); - if (c !== cInit) { - return false; - } + return new Point(cx, cy); + } - c = this.getColor(p2, p3); + /** + * Gets the Aztec code corners from the bull's eye corners and the parameters. + * + * @param bullsEyeCorners the array of bull's eye corners + * @return the array of aztec code corners + */ + private getMatrixCornerPoints(bullsEyeCorners: ResultPoint[]): ResultPoint[] { + return this.expandSquare(bullsEyeCorners, 2 * this.nbCenterLayers, this.getDimension()); + } + + /** + * Creates a BitMatrix by sampling the provided image. + * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the + * diagonal just outside the bull's eye. + */ + private sampleGrid(image: BitMatrix, + topLeft: ResultPoint, + topRight: ResultPoint, + bottomRight: ResultPoint, + bottomLeft: ResultPoint): BitMatrix { + + let sampler = GridSamplerInstance.getInstance(); + let dimension = this.getDimension(); + + let low = dimension / 2 - this.nbCenterLayers; + let high = dimension / 2 + this.nbCenterLayers; + + return sampler.sampleGrid(image, + dimension, + dimension, + low, low, // topleft + high, low, // topright + high, high, // bottomright + low, high, // bottomleft + topLeft.getX(), topLeft.getY(), + topRight.getX(), topRight.getY(), + bottomRight.getX(), bottomRight.getY(), + bottomLeft.getX(), bottomLeft.getY()); + } + + /** + * Samples a line. + * + * @param p1 start point (inclusive) + * @param p2 end point (exclusive) + * @param size number of bits + * @return the array of bits as an int (first bit is high-order bit of result) + */ + private sampleLine(p1: ResultPoint, p2: ResultPoint, size: number): number { + let result = 0; + + let d = this.distanceResultPoint(p1, p2); + let moduleSize = d / size; + let px = p1.getX(); + let py = p1.getY(); + let dx = moduleSize * (p2.getX() - p1.getX()) / d; + let dy = moduleSize * (p2.getY() - p1.getY()) / d; + for (let i = 0; i < size; i++) { + if (this.image.get(MathUtils.round(px + i * dx), MathUtils.round(py + i * dy))) { + result |= 1 << (size - i - 1); + } + } + return result; + } - if (c !== cInit) { - return false; - } + /** + * @return true if the border of the rectangle passed in parameter is compound of white points only + * or black points only + */ + private isWhiteOrBlackRectangle(p1: Point, + p2: Point, + p3: Point, + p4: Point): boolean { - c = this.getColor(p3, p4); + let corr = 3; + p1 = new Point(p1.getX() - corr, p1.getY() + corr); + p2 = new Point(p2.getX() - corr, p2.getY() - corr); + p3 = new Point(p3.getX() + corr, p3.getY() - corr); + p4 = new Point(p4.getX() + corr, p4.getY() + corr); - return c === cInit; + let cInit = this.getColor(p4, p1); + if (cInit === 0) { + return false; } - /** - * Gets the color of a segment - * - * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else - */ - private getColor(p1: Point, p2: Point): number { - let d = this.distancePoint(p1, p2); - let dx = (p2.getX() - p1.getX()) / d; - let dy = (p2.getY() - p1.getY()) / d; - let error = 0; - - let px = p1.getX(); - let py = p1.getY(); - - let colorModel = this.image.get(p1.getX(), p1.getY()); - - let iMax = Math.ceil(d); - for (let i = 0; i < iMax; i++) { - px += dx; - py += dy; - if (this.image.get(MathUtils.round(px), MathUtils.round(py)) !== colorModel) { - error++; - } - } + let c = this.getColor(p1, p2); - let errRatio = error / d; + if (c !== cInit) { + return false; + } - if (errRatio > 0.1 && errRatio < 0.9) { - return 0; - } + c = this.getColor(p2, p3); - return (errRatio <= 0.1) === colorModel ? 1 : -1; + if (c !== cInit) { + return false; } - /** - * Gets the coordinate of the first point with a different color in the given direction - */ - private getFirstDifferent(init: Point, color: boolean, dx: number, dy: number): Point { - let x = init.getX() + dx; - let y = init.getY() + dy; + c = this.getColor(p3, p4); - while (this.isValid(x, y) && this.image.get(x, y) === color) { - x += dx; - y += dy; - } + return c === cInit; - x -= dx; - y -= dy; + } - while (this.isValid(x, y) && this.image.get(x, y) === color) { - x += dx; - } - x -= dx; + /** + * Gets the color of a segment + * + * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else + */ + private getColor(p1: Point, p2: Point): number { + let d = this.distancePoint(p1, p2); + let dx = (p2.getX() - p1.getX()) / d; + let dy = (p2.getY() - p1.getY()) / d; + let error = 0; + + let px = p1.getX(); + let py = p1.getY(); + + let colorModel = this.image.get(p1.getX(), p1.getY()); + + let iMax = Math.ceil(d); + for (let i = 0; i < iMax; i++) { + px += dx; + py += dy; + if (this.image.get(MathUtils.round(px), MathUtils.round(py)) !== colorModel) { + error++; + } + } - while (this.isValid(x, y) && this.image.get(x, y) === color) { - y += dy; - } - y -= dy; + let errRatio = error / d; - return new Point(x, y); + if (errRatio > 0.1 && errRatio < 0.9) { + return 0; } - /** - * Expand the square represented by the corner points by pushing out equally in all directions - * - * @param cornerPoints the corners of the square, which has the bull's eye at its center - * @param oldSide the original length of the side of the square in the target bit matrix - * @param newSide the new length of the size of the square in the target bit matrix - * @return the corners of the expanded square - */ - private expandSquare(cornerPoints: ResultPoint[], oldSide: number, newSide: number): ResultPoint[] { - let ratio = newSide / (2.0 * oldSide); - let dx = cornerPoints[0].getX() - cornerPoints[2].getX(); - let dy = cornerPoints[0].getY() - cornerPoints[2].getY(); - let centerx = (cornerPoints[0].getX() + cornerPoints[2].getX()) / 2.0; - let centery = (cornerPoints[0].getY() + cornerPoints[2].getY()) / 2.0; - - let result0 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy); - let result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy); - - dx = cornerPoints[1].getX() - cornerPoints[3].getX(); - dy = cornerPoints[1].getY() - cornerPoints[3].getY(); - centerx = (cornerPoints[1].getX() + cornerPoints[3].getX()) / 2.0; - centery = (cornerPoints[1].getY() + cornerPoints[3].getY()) / 2.0; - let result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy); - let result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy); - - let results: ResultPoint[] = [result0, result1, result2, result3]; - return results; - } + return (errRatio <= 0.1) === colorModel ? 1 : -1; + } - private isValid(x: number, y: number): boolean { - return x >= 0 && x < this.image.getWidth() && y > 0 && y < this.image.getHeight(); - } + /** + * Gets the coordinate of the first point with a different color in the given direction + */ + private getFirstDifferent(init: Point, color: boolean, dx: number, dy: number): Point { + let x = init.getX() + dx; + let y = init.getY() + dy; - private isValidPoint(point: ResultPoint): boolean { - let x = MathUtils.round(point.getX()); - let y = MathUtils.round(point.getY()); - return this.isValid(x, y); + while (this.isValid(x, y) && this.image.get(x, y) === color) { + x += dx; + y += dy; } - private distancePoint(a: Point, b: Point): number { - return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY()); - } + x -= dx; + y -= dy; - private distanceResultPoint(a: ResultPoint, b: ResultPoint): number { - return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY()); + while (this.isValid(x, y) && this.image.get(x, y) === color) { + x += dx; } + x -= dx; - private getDimension(): number { - if (this.compact) { - return 4 * this.nbLayers + 11; - } - if (this.nbLayers <= 4) { - return 4 * this.nbLayers + 15; - } - return 4 * this.nbLayers + 2 * (Integer.truncDivision((this.nbLayers - 4), 8) + 1) + 15; + while (this.isValid(x, y) && this.image.get(x, y) === color) { + y += dy; + } + y -= dy; + + return new Point(x, y); + } + + /** + * Expand the square represented by the corner points by pushing out equally in all directions + * + * @param cornerPoints the corners of the square, which has the bull's eye at its center + * @param oldSide the original length of the side of the square in the target bit matrix + * @param newSide the new length of the size of the square in the target bit matrix + * @return the corners of the expanded square + */ + private expandSquare(cornerPoints: ResultPoint[], oldSide: number, newSide: number): ResultPoint[] { + let ratio = newSide / (2.0 * oldSide); + let dx = cornerPoints[0].getX() - cornerPoints[2].getX(); + let dy = cornerPoints[0].getY() - cornerPoints[2].getY(); + let centerx = (cornerPoints[0].getX() + cornerPoints[2].getX()) / 2.0; + let centery = (cornerPoints[0].getY() + cornerPoints[2].getY()) / 2.0; + + let result0 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy); + let result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy); + + dx = cornerPoints[1].getX() - cornerPoints[3].getX(); + dy = cornerPoints[1].getY() - cornerPoints[3].getY(); + centerx = (cornerPoints[1].getX() + cornerPoints[3].getX()) / 2.0; + centery = (cornerPoints[1].getY() + cornerPoints[3].getY()) / 2.0; + let result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy); + let result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy); + + let results: ResultPoint[] = [result0, result1, result2, result3]; + return results; + } + + private isValid(x: number, y: number): boolean { + return x >= 0 && x < this.image.getWidth() && y > 0 && y < this.image.getHeight(); + } + + private isValidPoint(point: ResultPoint): boolean { + let x = MathUtils.round(point.getX()); + let y = MathUtils.round(point.getY()); + return this.isValid(x, y); + } + + private distancePoint(a: Point, b: Point): number { + return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY()); + } + + private distanceResultPoint(a: ResultPoint, b: ResultPoint): number { + return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY()); + } + + private getDimension(): number { + if (this.compact) { + return 4 * this.nbLayers + 11; + } + if (this.nbLayers <= 4) { + return 4 * this.nbLayers + 15; } + return 4 * this.nbLayers + 2 * (Integer.truncDivision((this.nbLayers - 4), 8) + 1) + 15; + } } diff --git a/src/core/aztec/encoder/AztecCode.ts b/src/core/aztec/encoder/AztecCode.ts index 4fa38c80..0c887883 100644 --- a/src/core/aztec/encoder/AztecCode.ts +++ b/src/core/aztec/encoder/AztecCode.ts @@ -26,7 +26,7 @@ import { int } from '../../../customTypings'; * * @author Rustam Abdullaev */ -export default /*public final*/ class AztecCode { +export default /* public final */ class AztecCode { private compact: boolean; private size: int; @@ -36,7 +36,7 @@ export default /*public final*/ class AztecCode { /** * @return {@code true} if compact instead of full mode - */ + */ public isCompact(): boolean { return this.compact; } @@ -47,7 +47,7 @@ export default /*public final*/ class AztecCode { /** * @return size in pixels (width and height) - */ + */ public getSize(): int { return this.size; } @@ -58,7 +58,7 @@ export default /*public final*/ class AztecCode { /** * @return number of levels - */ + */ public getLayers(): int { return this.layers; } @@ -69,7 +69,7 @@ export default /*public final*/ class AztecCode { /** * @return number of data codewords - */ + */ public getCodeWords(): int { return this.codeWords; } @@ -80,7 +80,7 @@ export default /*public final*/ class AztecCode { /** * @return the symbol image - */ + */ public getMatrix(): BitMatrix { return this.matrix; } diff --git a/src/core/aztec/encoder/BinaryShiftToken.ts b/src/core/aztec/encoder/BinaryShiftToken.ts index 0a4189dc..17c21e2f 100644 --- a/src/core/aztec/encoder/BinaryShiftToken.ts +++ b/src/core/aztec/encoder/BinaryShiftToken.ts @@ -24,10 +24,10 @@ import SimpleToken from './SimpleToken'; import { short, int } from '../../../customTypings'; -export default /*final*/ class BinaryShiftToken extends SimpleToken { +export default /* final */ class BinaryShiftToken extends SimpleToken { - private /*final*/ binaryShiftStart: short; - private /*final*/ binaryShiftByteCount: short; + private /* final */ binaryShiftStart: short; + private /* final */ binaryShiftByteCount: short; constructor( previous: Token, @@ -41,8 +41,8 @@ export default /*final*/ class BinaryShiftToken extends SimpleToken { /** * @Override - */ - public appendTo(bitArray: BitArray, text: /*byte[]*/ Uint8Array): void { + */ + public appendTo(bitArray: BitArray, text: /* byte[] */ Uint8Array): void { for (let i = 0; i < this.binaryShiftByteCount; i++) { if (i === 0 || (i === 31 && this.binaryShiftByteCount <= 62)) { // We need a header before the first character, and before @@ -62,14 +62,14 @@ export default /*final*/ class BinaryShiftToken extends SimpleToken { } } - public /*final*/ addBinaryShift(start: int, byteCount: int): Token { + public /* final */ addBinaryShift(start: int, byteCount: int): Token { // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21); return new BinaryShiftToken(this, start, byteCount); } /** * @Override - */ + */ public toString(): string { return '<' + this.binaryShiftStart + '::' + (this.binaryShiftStart + this.binaryShiftByteCount - 1) + '>'; } diff --git a/src/core/aztec/encoder/Encoder.ts b/src/core/aztec/encoder/Encoder.ts index 84d740e2..231d162a 100644 --- a/src/core/aztec/encoder/Encoder.ts +++ b/src/core/aztec/encoder/Encoder.ts @@ -38,14 +38,14 @@ import Integer from '../../util/Integer'; * * @author Rustam Abdullaev */ -export default /*public final*/ class Encoder { +export default /* public final */ class Encoder { - public static /*final*/ DEFAULT_EC_PERCENT: int = 33; // default minimal percentage of error check words - public static /*final*/ DEFAULT_AZTEC_LAYERS: int = 0; - private static /*final*/ MAX_NB_BITS: int = 32; - private static /*final*/ MAX_NB_BITS_COMPACT: int = 4; + public static /* final */ DEFAULT_EC_PERCENT: int = 33; // default minimal percentage of error check words + public static /* final */ DEFAULT_AZTEC_LAYERS: int = 0; + private static /* final */ MAX_NB_BITS: int = 32; + private static /* final */ MAX_NB_BITS_COMPACT: int = 4; - private static /*final*/ WORD_SIZE: Int32Array = Int32Array.from([ + private static /* final */ WORD_SIZE: Int32Array = Int32Array.from([ 4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ]); @@ -58,7 +58,7 @@ export default /*public final*/ class Encoder { * * @param data input data string * @return Aztec symbol matrix with metadata - */ + */ public static encodeBytes(data: Uint8Array): AztecCode { return Encoder.encode(data, Encoder.DEFAULT_EC_PERCENT, Encoder.DEFAULT_AZTEC_LAYERS); } @@ -71,7 +71,7 @@ export default /*public final*/ class Encoder { * a minimum of 23% + 3 words is recommended) * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers * @return Aztec symbol matrix with metadata - */ + */ public static encode(data: Uint8Array, minECCPercent: int, userSpecifiedLayers: int): AztecCode { // High-level encode let bits: BitArray = new HighLevelEncoder(data).encode(); @@ -89,7 +89,7 @@ export default /*public final*/ class Encoder { layers = Math.abs(userSpecifiedLayers); if (layers > (compact ? Encoder.MAX_NB_BITS_COMPACT : Encoder.MAX_NB_BITS)) { throw new IllegalArgumentException( - StringUtils.format('Illegal value %s for layers', userSpecifiedLayers)); + StringUtils.format('Illegal value %s for layers', userSpecifiedLayers)); } totalBitsInLayer = Encoder.totalBitsInLayer(layers, compact); wordSize = Encoder.WORD_SIZE[layers]; @@ -108,7 +108,7 @@ export default /*public final*/ class Encoder { // We look at the possible table sizes in the order Compact1, Compact2, Compact3, // Compact4, Normal4,... Normal(i) for i < 4 isn't typically used since Compact(i+1) // is the same size, but has more data. - for (let i /*int*/ = 0; ; i++) { + for (let i /* int */ = 0; ; i++) { if (i > Encoder.MAX_NB_BITS) { throw new IllegalArgumentException('Data too large for an Aztec code'); } @@ -147,14 +147,14 @@ export default /*public final*/ class Encoder { if (compact) { // no alignment marks in compact mode, alignmentMap is a no-op matrixSize = baseMatrixSize; - for (let i /*int*/ = 0; i < alignmentMap.length; i++) { + for (let i /* int */ = 0; i < alignmentMap.length; i++) { alignmentMap[i] = i; } } else { matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15); let origCenter: int = Integer.truncDivision(baseMatrixSize, 2); let center: int = Integer.truncDivision(matrixSize, 2); - for (let i /*int*/ = 0; i < origCenter; i++) { + for (let i /* int */ = 0; i < origCenter; i++) { let newOffset: int = i + Integer.truncDivision(i, 15); alignmentMap[origCenter - i - 1] = center - newOffset - 1; alignmentMap[origCenter + i] = center + newOffset + 1; @@ -163,11 +163,11 @@ export default /*public final*/ class Encoder { let matrix: BitMatrix = new BitMatrix(matrixSize); // draw data bits - for (let i /*int*/ = 0, rowOffset = 0; i < layers; i++) { + for (let i /* int */ = 0, rowOffset = 0; i < layers; i++) { let rowSize: int = (layers - i) * 4 + (compact ? 9 : 12); - for (let j /*int*/ = 0; j < rowSize; j++) { + for (let j /* int */ = 0; j < rowSize; j++) { let columnOffset: int = j * 2; - for (let k /*int*/ = 0; k < 2; k++) { + for (let k /* int */ = 0; k < 2; k++) { if (messageBits.get(rowOffset + columnOffset + k)) { matrix.set(alignmentMap[i * 2 + k], alignmentMap[i * 2 + j]); } @@ -193,8 +193,8 @@ export default /*public final*/ class Encoder { Encoder.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 5); } else { Encoder.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 7); - for (let i /*int*/ = 0, j = 0; i < Integer.truncDivision(baseMatrixSize, 2) - 1; i += 15, j += 16) { - for (let k /*int*/ = Integer.truncDivision(matrixSize, 2) & 1; k < matrixSize; k += 2) { + for (let i /* int */ = 0, j = 0; i < Integer.truncDivision(baseMatrixSize, 2) - 1; i += 15, j += 16) { + for (let k /* int */ = Integer.truncDivision(matrixSize, 2) & 1; k < matrixSize; k += 2) { matrix.set(Integer.truncDivision(matrixSize, 2) - j, k); matrix.set(Integer.truncDivision(matrixSize, 2) + j, k); matrix.set(k, Integer.truncDivision(matrixSize, 2) - j); @@ -213,8 +213,8 @@ export default /*public final*/ class Encoder { } private static drawBullsEye(matrix: BitMatrix, center: int, size: int): void { - for (let i /*int*/ = 0; i < size; i += 2) { - for (let j /*int*/ = center - i; j <= center + i; j++) { + for (let i /* int */ = 0; i < size; i += 2) { + for (let j /* int */ = center - i; j <= center + i; j++) { matrix.set(j, center - i); matrix.set(j, center + i); matrix.set(center - i, j); @@ -246,7 +246,7 @@ export default /*public final*/ class Encoder { private static drawModeMessage(matrix: BitMatrix, compact: boolean, matrixSize: int, modeMessage: BitArray): void { let center: int = Integer.truncDivision(matrixSize, 2); if (compact) { - for (let i /*int*/ = 0; i < 7; i++) { + for (let i /* int */ = 0; i < 7; i++) { let offset: int = center - 3 + i; if (modeMessage.get(i)) { matrix.set(offset, center - 5); @@ -262,7 +262,7 @@ export default /*public final*/ class Encoder { } } } else { - for (let i /*int*/ = 0; i < 10; i++) { + for (let i /* int */ = 0; i < 10; i++) { let offset: int = center - 5 + i + Integer.truncDivision(i, 5); if (modeMessage.get(i)) { matrix.set(offset, center - 7); @@ -290,7 +290,7 @@ export default /*public final*/ class Encoder { let startPad: int = totalBits % wordSize; let messageBits: BitArray = new BitArray(); messageBits.appendBits(0, startPad); - for (const messageWord/*: int*/ of Array.from(messageWords)) { + for (const messageWord/* : int */ of Array.from(messageWords)) { messageBits.appendBits(messageWord, wordSize); } return messageBits; @@ -302,7 +302,7 @@ export default /*public final*/ class Encoder { let n: int; for (i = 0, n = stuffedBits.getSize() / wordSize; i < n; i++) { let value: int = 0; - for (let j /*int*/ = 0; j < wordSize; j++) { + for (let j /* int */ = 0; j < wordSize; j++) { value |= stuffedBits.get(i * wordSize + j) ? (1 << wordSize - j - 1) : 0; } message[i] = value; @@ -332,9 +332,9 @@ export default /*public final*/ class Encoder { let n: int = bits.getSize(); let mask: int = (1 << wordSize) - 2; - for (let i /*int*/ = 0; i < n; i += wordSize) { + for (let i /* int */ = 0; i < n; i += wordSize) { let word: int = 0; - for (let j /*int*/ = 0; j < wordSize; j++) { + for (let j /* int */ = 0; j < wordSize; j++) { if (i + j >= n || bits.get(i + j)) { word |= 1 << (wordSize - 1 - j); } diff --git a/src/core/aztec/encoder/EncoderConstants.ts b/src/core/aztec/encoder/EncoderConstants.ts index 5106e012..8932b9e8 100644 --- a/src/core/aztec/encoder/EncoderConstants.ts +++ b/src/core/aztec/encoder/EncoderConstants.ts @@ -3,18 +3,18 @@ import SimpleToken from './SimpleToken'; import { int } from '../../../customTypings'; -export const /*final*/ MODE_NAMES: String[] = [ - 'UPPER', - 'LOWER', - 'DIGIT', - 'MIXED', - 'PUNCT' - ]; +export const /* final */ MODE_NAMES: String[] = [ + 'UPPER', + 'LOWER', + 'DIGIT', + 'MIXED', + 'PUNCT' +]; -export const /*final*/ MODE_UPPER: int = 0; // 5 bits -export const /*final*/ MODE_LOWER: int = 1; // 5 bits -export const /*final*/ MODE_DIGIT: int = 2; // 4 bits -export const /*final*/ MODE_MIXED: int = 3; // 5 bits -export const /*final*/ MODE_PUNCT: int = 4; // 5 bits +export const /* final */ MODE_UPPER: int = 0; // 5 bits +export const /* final */ MODE_LOWER: int = 1; // 5 bits +export const /* final */ MODE_DIGIT: int = 2; // 4 bits +export const /* final */ MODE_MIXED: int = 3; // 5 bits +export const /* final */ MODE_PUNCT: int = 4; // 5 bits export const EMPTY_TOKEN: Token = new SimpleToken(null, 0, 0); diff --git a/src/core/aztec/encoder/HighLevelEncoder.ts b/src/core/aztec/encoder/HighLevelEncoder.ts index 6493b29f..8804bcb7 100644 --- a/src/core/aztec/encoder/HighLevelEncoder.ts +++ b/src/core/aztec/encoder/HighLevelEncoder.ts @@ -49,16 +49,16 @@ import { int, Collection, char } from '../../../customTypings'; * @author Frank Yellin * @author Rustam Abdullaev */ -export default /*public final*/ class HighLevelEncoder { +export default /* public final */ class HighLevelEncoder { // A reverse mapping from [mode][char] to the encoding for that character // in that mode. An entry of 0 indicates no mapping exists. - // private static /*final*/ CHAR_MAP: Int32Array[] = static_CHAR_MAP(Arrays.createInt32Array(5, 256)); + // private static /*final */ CHAR_MAP: Int32Array[] = static_CHAR_MAP(Arrays.createInt32Array(5, 256)); // A map showing the available shift codes. (The shifts to BINARY are not // shown - // static /*final*/ SHIFT_TABLE: Int32Array[] = ShiftTable.static_SHIFT_TABLE(Arrays.createInt32Array(6, 6)); // mode shift codes, per table - private /*final*/ text: Uint8Array; + // static /*final */ SHIFT_TABLE: Int32Array[] = ShiftTable.static_SHIFT_TABLE(Arrays.createInt32Array(6, 6)); // mode shift codes, per table + private /* final */ text: Uint8Array; public constructor(text: Uint8Array) { this.text = text; @@ -66,7 +66,7 @@ export default /*public final*/ class HighLevelEncoder { /** * @return text represented by this encoder encoded as a {@link BitArray} - */ + */ public encode(): BitArray { const spaceCharCode = StringUtils.getCharCode(' '); @@ -124,7 +124,7 @@ export default /*public final*/ class HighLevelEncoder { index: int ): Collection { const result: State[] = []; - for (let state /*State*/ of states) { + for (let state /* State */ of states) { this.updateStateForChar(state, index, result); } return HighLevelEncoder.simplifyStates(result); @@ -141,7 +141,7 @@ export default /*public final*/ class HighLevelEncoder { let ch: char = (this.text[index] & 0xff); let charInCurrentTable: boolean = CharMap.CHAR_MAP[state.getMode()][ch] > 0; let stateNoBinary: State = null; - for (let mode /*int*/ = 0; mode <= C.MODE_PUNCT; mode++) { + for (let mode /* int */ = 0; mode <= C.MODE_PUNCT; mode++) { let charInMode: int = CharMap.CHAR_MAP[mode][ch]; if (charInMode > 0) { if (stateNoBinary == null) { @@ -197,7 +197,7 @@ export default /*public final*/ class HighLevelEncoder { pairCode: int ): Collection { const result: State[] = []; - for (let state /*State*/ of states) { + for (let state /* State */ of states) { this.updateStateForPair(state, index, pairCode, result); } return this.simplifyStates(result); diff --git a/src/core/aztec/encoder/ShiftTable.ts b/src/core/aztec/encoder/ShiftTable.ts index b17a5baa..c44762de 100644 --- a/src/core/aztec/encoder/ShiftTable.ts +++ b/src/core/aztec/encoder/ShiftTable.ts @@ -2,7 +2,7 @@ import Arrays from '../../util/Arrays'; import * as C from './EncoderConstants'; export function static_SHIFT_TABLE(SHIFT_TABLE: Int32Array[]): Int32Array[] { - for (let table /*Int32Array*/ of SHIFT_TABLE) { + for (let table /* Int32Array */ of SHIFT_TABLE) { Arrays.fill(table, -1); } SHIFT_TABLE[C.MODE_UPPER][C.MODE_PUNCT] = 0; @@ -14,4 +14,4 @@ export function static_SHIFT_TABLE(SHIFT_TABLE: Int32Array[]): Int32Array[] { return SHIFT_TABLE; } -export const /*final*/ SHIFT_TABLE: Int32Array[] = static_SHIFT_TABLE(Arrays.createInt32Array(6, 6)); // mode shift codes, per table \ No newline at end of file +export const /* final */ SHIFT_TABLE: Int32Array[] = static_SHIFT_TABLE(Arrays.createInt32Array(6, 6)); // mode shift codes, per table diff --git a/src/core/aztec/encoder/SimpleToken.ts b/src/core/aztec/encoder/SimpleToken.ts index 78b521bd..7b8a205b 100644 --- a/src/core/aztec/encoder/SimpleToken.ts +++ b/src/core/aztec/encoder/SimpleToken.ts @@ -24,11 +24,11 @@ import Integer from '../../util/Integer'; import { short, int } from '../../../customTypings'; -export default /*final*/ class SimpleToken extends Token { +export default /* final */ class SimpleToken extends Token { // For normal words, indicates value and bitCount - private /*final*/ value: short; - private /*final*/ bitCount: short; + private /* final */ value: short; + private /* final */ bitCount: short; constructor(previous: Token, value: int, bitCount: int) { super(previous); @@ -38,16 +38,16 @@ export default /*final*/ class SimpleToken extends Token { /** * @Override - */ - appendTo(bitArray: BitArray, text: /*byte[]*/Uint8Array): void { + */ + appendTo(bitArray: BitArray, text: /* byte[] */Uint8Array): void { bitArray.appendBits(this.value, this.bitCount); } - public /*final*/ add(value: int, bitCount: int): Token { + public /* final */ add(value: int, bitCount: int): Token { return new SimpleToken(this, value, bitCount); } - public /*final*/ addBinaryShift(start: int, byteCount: int): Token { + public /* final */ addBinaryShift(start: int, byteCount: int): Token { // no-op can't binary shift a simple token console.warn('addBinaryShift on SimpleToken, this simply returns a copy of this token'); return new SimpleToken(this, start, byteCount); @@ -55,7 +55,7 @@ export default /*final*/ class SimpleToken extends Token { /** * @Override - */ + */ public toString(): String { let value: int = this.value & ((1 << this.bitCount) - 1); value |= 1 << this.bitCount; diff --git a/src/core/aztec/encoder/State.ts b/src/core/aztec/encoder/State.ts index 66a0b4d5..a721b0a5 100644 --- a/src/core/aztec/encoder/State.ts +++ b/src/core/aztec/encoder/State.ts @@ -35,8 +35,8 @@ import { int, Deque } from '../../../customTypings'; * State represents all information about a sequence necessary to generate the current output. * Note that a state is immutable. */ -export default /*final*/ class State { - static /*final*/ INITIAL_STATE: State = new State( +export default /* final */ class State { + static /* final */ INITIAL_STATE: State = new State( C.EMPTY_TOKEN, C.MODE_UPPER, 0, @@ -45,15 +45,15 @@ export default /*final*/ class State { // The current mode of the encoding (or the mode to which we'll return if // we're in Binary Shift mode. - private /*final*/ mode: int; + private /* final */ mode: int; // The list of tokens that we output. If we are in Binary Shift mode, this // token list does *not* yet included the token for those bytes - private /*final*/ token: Token; + private /* final */ token: Token; // If non-zero, the number of most recent bytes that should be output // in Binary Shift mode. - private /*final*/ binaryShiftByteCount: int; + private /* final */ binaryShiftByteCount: int; // The total number of bits generated (Shift: y). - private /*final*/ bitCount: int; + private /* final */ bitCount: int; private constructor( token: Token, @@ -137,8 +137,8 @@ export default /*final*/ class State { this.binaryShiftByteCount === 0 || this.binaryShiftByteCount === 31 ? 18 : this.binaryShiftByteCount === 62 - ? 9 - : 8; + ? 9 + : 8; let result: State = new State( token, mode, @@ -209,7 +209,7 @@ export default /*final*/ class State { /** * @Override - */ + */ public toString(): String { return StringUtils.format( '%s bits=%d bytes=%d', diff --git a/src/core/aztec/encoder/Token.ts b/src/core/aztec/encoder/Token.ts index 8ceab81a..3609a94c 100644 --- a/src/core/aztec/encoder/Token.ts +++ b/src/core/aztec/encoder/Token.ts @@ -23,20 +23,20 @@ import { int } from '../../../customTypings'; export default abstract class Token { - private /*final*/ previous: Token; + private /* final */ previous: Token; constructor(previous: Token) { this.previous = previous; } - public /*final*/ getPrevious(): Token { + public /* final */ getPrevious(): Token { return this.previous; } - public /*final*/ abstract add(value: int, bitCount: int): Token; + public /* final */ abstract add(value: int, bitCount: int): Token; - public /*final*/ abstract addBinaryShift(start: int, byteCount: int): Token; + public /* final */ abstract addBinaryShift(start: int, byteCount: int): Token; - public abstract appendTo(bitArray: BitArray, text: /*byte[]*/Uint8Array): void; + public abstract appendTo(bitArray: BitArray, text: /* byte[] */Uint8Array): void; } diff --git a/src/core/common/BitArray.ts b/src/core/common/BitArray.ts index e61b80a5..980f2ca4 100644 --- a/src/core/common/BitArray.ts +++ b/src/core/common/BitArray.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ -/*import java.util.Arrays;*/ +/* import java.util.Arrays; */ import IllegalArgumentException from '../IllegalArgumentException'; import Arrays from '../util/Arrays'; @@ -29,7 +29,7 @@ import System from '../util/System'; * * @author Sean Owen */ -export default class BitArray /*implements Cloneable*/ { +export default class BitArray /* implements Cloneable */ { private size: number; private bits: Int32Array; @@ -39,7 +39,7 @@ export default class BitArray /*implements Cloneable*/ { // this.bits = new Int32Array(1) // } - // public constructor(size?: number /*int*/) { + // public constructor(size?: number /*int */) { // if (undefined === size) { // this.size = 0 // } else { @@ -49,7 +49,7 @@ export default class BitArray /*implements Cloneable*/ { // } // For testing only - public constructor(size?: number /*int*/, bits?: Int32Array) { + public constructor(size?: number /* int */, bits?: Int32Array) { if (undefined === size) { this.size = 0; this.bits = new Int32Array(1); @@ -63,15 +63,15 @@ export default class BitArray /*implements Cloneable*/ { } } - public getSize(): number /*int*/ { + public getSize(): number /* int */ { return this.size; } - public getSizeInBytes(): number /*int*/ { + public getSizeInBytes(): number /* int */ { return Math.floor((this.size + 7) / 8); } - private ensureCapacity(size: number /*int*/): void { + private ensureCapacity(size: number /* int */): void { if (size > this.bits.length * 32) { const newBits = BitArray.makeArray(size); System.arraycopy(this.bits, 0, newBits, 0, this.bits.length); @@ -82,8 +82,8 @@ export default class BitArray /*implements Cloneable*/ { /** * @param i bit to get * @return true iff bit i is set - */ - public get(i: number /*int*/): boolean { + */ + public get(i: number /* int */): boolean { return (this.bits[Math.floor(i / 32)] & (1 << (i & 0x1F))) !== 0; } @@ -91,8 +91,8 @@ export default class BitArray /*implements Cloneable*/ { * Sets bit i. * * @param i bit to set - */ - public set(i: number /*int*/): void { + */ + public set(i: number /* int */): void { this.bits[Math.floor(i / 32)] |= 1 << (i & 0x1F); } @@ -100,8 +100,8 @@ export default class BitArray /*implements Cloneable*/ { * Flips bit i. * * @param i bit to set - */ - public flip(i: number /*int*/): void { + */ + public flip(i: number /* int */): void { this.bits[Math.floor(i / 32)] ^= 1 << (i & 0x1F); } @@ -110,8 +110,8 @@ export default class BitArray /*implements Cloneable*/ { * @return index of first bit that is set, starting from the given index, or size if none are set * at or beyond this given index * @see #getNextUnset(int) - */ - public getNextSet(from: number /*int*/): number /*int*/ { + */ + public getNextSet(from: number /* int */): number /* int */ { const size = this.size; if (from >= size) { return size; @@ -136,8 +136,8 @@ export default class BitArray /*implements Cloneable*/ { * @param from index to start looking for unset bit * @return index of next unset bit, or {@code size} if none are unset until the end * @see #getNextSet(int) - */ - public getNextUnset(from: number /*int*/): number /*int*/ { + */ + public getNextUnset(from: number /* int */): number /* int */ { const size = this.size; if (from >= size) { return size; @@ -164,8 +164,8 @@ export default class BitArray /*implements Cloneable*/ { * @param i first bit to set * @param newBits the new value of the next 32 bits. Note again that the least-significant bit * corresponds to bit i, the next-least-significant to i+1, and so on. - */ - public setBulk(i: number /*int*/, newBits: number /*int*/): void { + */ + public setBulk(i: number /* int */, newBits: number /* int */): void { this.bits[Math.floor(i / 32)] = newBits; } @@ -174,8 +174,8 @@ export default class BitArray /*implements Cloneable*/ { * * @param start start of range, inclusive. * @param end end of range, exclusive - */ - public setRange(start: number /*int*/, end: number /*int*/): void { + */ + public setRange(start: number /* int */, end: number /* int */): void { if (end < start || start < 0 || end > this.size) { throw new IllegalArgumentException(); } @@ -197,7 +197,7 @@ export default class BitArray /*implements Cloneable*/ { /** * Clears all bits (sets to false). - */ + */ public clear(): void { const max = this.bits.length; const bits = this.bits; @@ -214,8 +214,8 @@ export default class BitArray /*implements Cloneable*/ { * @param value if true, checks that bits in range are set, otherwise checks that they are not set * @return true iff all bits are set or not set in range, according to value argument * @throws IllegalArgumentException if end is less than start or the range is not contained in the array - */ - public isRange(start: number /*int*/, end: number /*int*/, value: boolean): boolean { + */ + public isRange(start: number /* int */, end: number /* int */, value: boolean): boolean { if (end < start || start < 0 || end > this.size) { throw new IllegalArgumentException(); } @@ -256,8 +256,8 @@ export default class BitArray /*implements Cloneable*/ { * * @param value {@code int} containing bits to append * @param numBits bits from value to append - */ - public appendBits(value: number /*int*/, numBits: number /*int*/): void { + */ + public appendBits(value: number /* int */, numBits: number /* int */): void { if (numBits < 0 || numBits > 32) { throw new IllegalArgumentException('Num bits must be between 0 and 32'); } @@ -296,8 +296,8 @@ export default class BitArray /*implements Cloneable*/ { * of the internal representation, which is exposed by {@link #getBitArray()} * @param offset position in array to start writing * @param numBytes how many bytes to write - */ - public toBytes(bitOffset: number /*int*/, array: Uint8Array, offset: number /*int*/, numBytes: number /*int*/): void { + */ + public toBytes(bitOffset: number /* int */, array: Uint8Array, offset: number /* int */, numBytes: number /* int */): void { for (let i = 0; i < numBytes; i++) { let theByte = 0; for (let j = 0; j < 8; j++) { @@ -306,21 +306,21 @@ export default class BitArray /*implements Cloneable*/ { } bitOffset++; } - array[offset + i] = /*(byte)*/ theByte; + array[offset + i] = /* (byte) */ theByte; } } /** * @return underlying array of ints. The first element holds the first 32 bits, and the least * significant bit is bit 0. - */ + */ public getBitArray(): Int32Array { return this.bits; } /** * Reverses all bits in the array. - */ + */ public reverse(): void { const newBits = new Int32Array(this.bits.length); // reverse all int's first @@ -334,7 +334,7 @@ export default class BitArray /*implements Cloneable*/ { x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4); x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8); x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16); - newBits[len - i] = /*(int)*/ x; + newBits[len - i] = /* (int) */ x; } // now correct the int's if the bit size isn't a multiple of 32 if (this.size !== oldBitsLen * 32) { @@ -351,11 +351,11 @@ export default class BitArray /*implements Cloneable*/ { this.bits = newBits; } - private static makeArray(size: number /*int*/): Int32Array { + private static makeArray(size: number /* int */): Int32Array { return new Int32Array(Math.floor((size + 31) / 32)); } - /*@Override*/ + /* @Override */ public equals(o: any): boolean { if (!(o instanceof BitArray)) { return false; @@ -364,12 +364,12 @@ export default class BitArray /*implements Cloneable*/ { return this.size === other.size && Arrays.equals(this.bits, other.bits); } - /*@Override*/ - public hashCode(): number /*int*/ { + /* @Override */ + public hashCode(): number /* int */ { return 31 * this.size + Arrays.hashCode(this.bits); } - /*@Override*/ + /* @Override */ public toString(): string { let result = ''; for (let i = 0, size = this.size; i < size; i++) { @@ -381,7 +381,7 @@ export default class BitArray /*implements Cloneable*/ { return result; } - /*@Override*/ + /* @Override */ public clone(): BitArray { return new BitArray(this.size, this.bits.slice()); } diff --git a/src/core/common/BitMatrix.ts b/src/core/common/BitMatrix.ts index d1499c41..a38d27ff 100644 --- a/src/core/common/BitMatrix.ts +++ b/src/core/common/BitMatrix.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ -/*import java.util.Arrays;*/ +/* import java.util.Arrays; */ import BitArray from './BitArray'; import System from '../util/System'; @@ -41,482 +41,482 @@ import { int } from '../../customTypings'; * @author Sean Owen * @author dswitkin@google.com (Daniel Switkin) */ -export default class BitMatrix /*implements Cloneable*/ { - - /** - * Creates an empty square {@link BitMatrix}. - * - * @param dimension height and width - */ - // public constructor(dimension: number /*int*/) { - // this(dimension, dimension) - // } - - /** - * Creates an empty {@link BitMatrix}. - * - * @param width bit matrix width - * @param height bit matrix height - */ - // public constructor(width: number /*int*/, height: number /*int*/) { - // if (width < 1 || height < 1) { - // throw new IllegalArgumentException("Both dimensions must be greater than 0") - // } - // this.width = width - // this.height = height - // this.rowSize = (width + 31) / 32 - // bits = new int[rowSize * height]; - // } - - public constructor(private width: number /*int*/, private height?: number /*int*/, - private rowSize?: number /*int*/, private bits?: Int32Array) { - if (undefined === height || null === height) { - height = width; - } - this.height = height; - if (width < 1 || height < 1) { - throw new IllegalArgumentException('Both dimensions must be greater than 0'); - } - if (undefined === rowSize || null === rowSize) { - rowSize = Math.floor((width + 31) / 32); - } - this.rowSize = rowSize; - if (undefined === bits || null === bits) { - this.bits = new Int32Array(this.rowSize * this.height); - } - } +export default class BitMatrix /* implements Cloneable */ { - /** - * Interprets a 2D array of booleans as a {@link BitMatrix}, where "true" means an "on" bit. - * - * @function parse - * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows - * @return {@link BitMatrix} representation of image - */ - public static parseFromBooleanArray(image: boolean[][]): BitMatrix { - const height = image.length; - const width = image[0].length; - const bits = new BitMatrix(width, height); - for (let i = 0; i < height; i++) { - const imageI = image[i]; - for (let j = 0; j < width; j++) { - if (imageI[j]) { - bits.set(j, i); - } - } - } - return bits; + /** + * Creates an empty square {@link BitMatrix}. + * + * @param dimension height and width + */ + // public constructor(dimension: number /*int */) { + // this(dimension, dimension) + // } + + /** + * Creates an empty {@link BitMatrix}. + * + * @param width bit matrix width + * @param height bit matrix height + */ + // public constructor(width: number /*int */, height: number /*int */) { + // if (width < 1 || height < 1) { + // throw new IllegalArgumentException("Both dimensions must be greater than 0") + // } + // this.width = width + // this.height = height + // this.rowSize = (width + 31) / 32 + // bits = new int[rowSize * height]; + // } + + public constructor(private width: number /* int */, private height?: number /* int */, + private rowSize?: number /* int */, private bits?: Int32Array) { + if (undefined === height || null === height) { + height = width; } - - /** - * - * @function parse - * @param stringRepresentation - * @param setString - * @param unsetString - */ - public static parseFromString(stringRepresentation: string, setString: string, unsetString: string): BitMatrix { - if (stringRepresentation === null) { - throw new IllegalArgumentException('stringRepresentation cannot be null'); - } - - const bits = new Array(stringRepresentation.length); - let bitsPos = 0; - let rowStartPos = 0; - let rowLength = -1; - let nRows = 0; - let pos = 0; - while (pos < stringRepresentation.length) { - if (stringRepresentation.charAt(pos) === '\n' || - stringRepresentation.charAt(pos) === '\r') { - if (bitsPos > rowStartPos) { - if (rowLength === -1) { - rowLength = bitsPos - rowStartPos; - } else if (bitsPos - rowStartPos !== rowLength) { - throw new IllegalArgumentException('row lengths do not match'); - } - rowStartPos = bitsPos; - nRows++; - } - pos++; - } else if (stringRepresentation.substring(pos, pos + setString.length) === setString) { - pos += setString.length; - bits[bitsPos] = true; - bitsPos++; - } else if (stringRepresentation.substring(pos, pos + unsetString.length) === unsetString) { - pos += unsetString.length; - bits[bitsPos] = false; - bitsPos++; - } else { - throw new IllegalArgumentException( - 'illegal character encountered: ' + stringRepresentation.substring(pos)); - } + this.height = height; + if (width < 1 || height < 1) { + throw new IllegalArgumentException('Both dimensions must be greater than 0'); + } + if (undefined === rowSize || null === rowSize) { + rowSize = Math.floor((width + 31) / 32); + } + this.rowSize = rowSize; + if (undefined === bits || null === bits) { + this.bits = new Int32Array(this.rowSize * this.height); + } + } + + /** + * Interprets a 2D array of booleans as a {@link BitMatrix}, where "true" means an "on" bit. + * + * @function parse + * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows + * @return {@link BitMatrix} representation of image + */ + public static parseFromBooleanArray(image: boolean[][]): BitMatrix { + const height = image.length; + const width = image[0].length; + const bits = new BitMatrix(width, height); + for (let i = 0; i < height; i++) { + const imageI = image[i]; + for (let j = 0; j < width; j++) { + if (imageI[j]) { + bits.set(j, i); } + } + } + return bits; + } + + /** + * + * @function parse + * @param stringRepresentation + * @param setString + * @param unsetString + */ + public static parseFromString(stringRepresentation: string, setString: string, unsetString: string): BitMatrix { + if (stringRepresentation === null) { + throw new IllegalArgumentException('stringRepresentation cannot be null'); + } - // no EOL at end? + const bits = new Array(stringRepresentation.length); + let bitsPos = 0; + let rowStartPos = 0; + let rowLength = -1; + let nRows = 0; + let pos = 0; + while (pos < stringRepresentation.length) { + if (stringRepresentation.charAt(pos) === '\n' || + stringRepresentation.charAt(pos) === '\r') { if (bitsPos > rowStartPos) { - if (rowLength === -1) { - rowLength = bitsPos - rowStartPos; - } else if (bitsPos - rowStartPos !== rowLength) { - throw new IllegalArgumentException('row lengths do not match'); - } - nRows++; + if (rowLength === -1) { + rowLength = bitsPos - rowStartPos; + } else if (bitsPos - rowStartPos !== rowLength) { + throw new IllegalArgumentException('row lengths do not match'); + } + rowStartPos = bitsPos; + nRows++; } - - const matrix = new BitMatrix(rowLength, nRows); - for (let i = 0; i < bitsPos; i++) { - if (bits[i]) { - matrix.set(Math.floor(i % rowLength), Math.floor(i / rowLength)); - } - } - return matrix; + pos++; + } else if (stringRepresentation.substring(pos, pos + setString.length) === setString) { + pos += setString.length; + bits[bitsPos] = true; + bitsPos++; + } else if (stringRepresentation.substring(pos, pos + unsetString.length) === unsetString) { + pos += unsetString.length; + bits[bitsPos] = false; + bitsPos++; + } else { + throw new IllegalArgumentException( + 'illegal character encountered: ' + stringRepresentation.substring(pos)); + } } - /** - *

Gets the requested bit, where true means black.

- * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - * @return value of given bit in matrix - */ - public get(x: number /*int*/, y: number /*int*/): boolean { - const offset = y * this.rowSize + Math.floor(x / 32); - return ((this.bits[offset] >>> (x & 0x1f)) & 1) !== 0; + // no EOL at end? + if (bitsPos > rowStartPos) { + if (rowLength === -1) { + rowLength = bitsPos - rowStartPos; + } else if (bitsPos - rowStartPos !== rowLength) { + throw new IllegalArgumentException('row lengths do not match'); + } + nRows++; } - /** - *

Sets the given bit to true.

- * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - */ - public set(x: number /*int*/, y: number /*int*/): void { - const offset = y * this.rowSize + Math.floor(x / 32); - this.bits[offset] |= (1 << (x & 0x1f)) & 0xFFFFFFFF; + const matrix = new BitMatrix(rowLength, nRows); + for (let i = 0; i < bitsPos; i++) { + if (bits[i]) { + matrix.set(Math.floor(i % rowLength), Math.floor(i / rowLength)); + } } - - public unset(x: number /*int*/, y: number /*int*/): void { - const offset = y * this.rowSize + Math.floor(x / 32); - this.bits[offset] &= ~((1 << (x & 0x1f)) & 0xFFFFFFFF); + return matrix; + } + + /** + *

Gets the requested bit, where true means black.

+ * + * @param x The horizontal component (i.e. which column) + * @param y The vertical component (i.e. which row) + * @return value of given bit in matrix + */ + public get(x: number /* int */, y: number /* int */): boolean { + const offset = y * this.rowSize + Math.floor(x / 32); + return ((this.bits[offset] >>> (x & 0x1f)) & 1) !== 0; + } + + /** + *

Sets the given bit to true.

+ * + * @param x The horizontal component (i.e. which column) + * @param y The vertical component (i.e. which row) + */ + public set(x: number /* int */, y: number /* int */): void { + const offset = y * this.rowSize + Math.floor(x / 32); + this.bits[offset] |= (1 << (x & 0x1f)) & 0xFFFFFFFF; + } + + public unset(x: number /* int */, y: number /* int */): void { + const offset = y * this.rowSize + Math.floor(x / 32); + this.bits[offset] &= ~((1 << (x & 0x1f)) & 0xFFFFFFFF); + } + + /** + *

Flips the given bit.

+ * + * @param x The horizontal component (i.e. which column) + * @param y The vertical component (i.e. which row) + */ + public flip(x: number /* int */, y: number /* int */): void { + const offset = y * this.rowSize + Math.floor(x / 32); + this.bits[offset] ^= ((1 << (x & 0x1f)) & 0xFFFFFFFF); + } + + /** + * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding + * mask bit is set. + * + * @param mask XOR mask + */ + public xor(mask: BitMatrix): void { + if (this.width !== mask.getWidth() || this.height !== mask.getHeight() + || this.rowSize !== mask.getRowSize()) { + throw new IllegalArgumentException('input matrix dimensions do not match'); } - - /** - *

Flips the given bit.

- * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - */ - public flip(x: number /*int*/, y: number /*int*/): void { - const offset = y * this.rowSize + Math.floor(x / 32); - this.bits[offset] ^= ((1 << (x & 0x1f)) & 0xFFFFFFFF); + const rowArray = new BitArray(Math.floor(this.width / 32) + 1); + const rowSize = this.rowSize; + const bits = this.bits; + for (let y = 0, height = this.height; y < height; y++) { + const offset = y * rowSize; + const row = mask.getRow(y, rowArray).getBitArray(); + for (let x = 0; x < rowSize; x++) { + bits[offset + x] ^= row[x]; + } } + } - /** - * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding - * mask bit is set. - * - * @param mask XOR mask - */ - public xor(mask: BitMatrix): void { - if (this.width !== mask.getWidth() || this.height !== mask.getHeight() - || this.rowSize !== mask.getRowSize()) { - throw new IllegalArgumentException('input matrix dimensions do not match'); - } - const rowArray = new BitArray(Math.floor(this.width / 32) + 1); - const rowSize = this.rowSize; - const bits = this.bits; - for (let y = 0, height = this.height; y < height; y++) { - const offset = y * rowSize; - const row = mask.getRow(y, rowArray).getBitArray(); - for (let x = 0; x < rowSize; x++) { - bits[offset + x] ^= row[x]; - } - } + /** + * Clears all bits (sets to false). + */ + public clear(): void { + const bits = this.bits; + const max = bits.length; + for (let i = 0; i < max; i++) { + bits[i] = 0; } - - /** - * Clears all bits (sets to false). - */ - public clear(): void { - const bits = this.bits; - const max = bits.length; - for (let i = 0; i < max; i++) { - bits[i] = 0; - } + } + + /** + *

Sets a square region of the bit matrix to true.

+ * + * @param left The horizontal position to begin at (inclusive) + * @param top The vertical position to begin at (inclusive) + * @param width The width of the region + * @param height The height of the region + */ + public setRegion(left: number /* int */, top: number /* int */, width: number /* int */, height: number /* int */): void { + if (top < 0 || left < 0) { + throw new IllegalArgumentException('Left and top must be nonnegative'); } - - /** - *

Sets a square region of the bit matrix to true.

- * - * @param left The horizontal position to begin at (inclusive) - * @param top The vertical position to begin at (inclusive) - * @param width The width of the region - * @param height The height of the region - */ - public setRegion(left: number /*int*/, top: number /*int*/, width: number /*int*/, height: number /*int*/): void { - if (top < 0 || left < 0) { - throw new IllegalArgumentException('Left and top must be nonnegative'); - } - if (height < 1 || width < 1) { - throw new IllegalArgumentException('Height and width must be at least 1'); - } - const right = left + width; - const bottom = top + height; - if (bottom > this.height || right > this.width) { - throw new IllegalArgumentException('The region must fit inside the matrix'); - } - const rowSize = this.rowSize; - const bits = this.bits; - for (let y = top; y < bottom; y++) { - const offset = y * rowSize; - for (let x = left; x < right; x++) { - bits[offset + Math.floor(x / 32)] |= ((1 << (x & 0x1f)) & 0xFFFFFFFF); - } - } + if (height < 1 || width < 1) { + throw new IllegalArgumentException('Height and width must be at least 1'); } - - /** - * A fast method to retrieve one row of data from the matrix as a BitArray. - * - * @param y The row to retrieve - * @param row An optional caller-allocated BitArray, will be allocated if null or too small - * @return The resulting BitArray - this reference should always be used even when passing - * your own row - */ - public getRow(y: number /*int*/, row?: BitArray): BitArray { - if (row === null || row === undefined || row.getSize() < this.width) { - row = new BitArray(this.width); - } else { - row.clear(); - } - const rowSize = this.rowSize; - const bits = this.bits; - const offset = y * rowSize; - for (let x = 0; x < rowSize; x++) { - row.setBulk(x * 32, bits[offset + x]); - } - return row; + const right = left + width; + const bottom = top + height; + if (bottom > this.height || right > this.width) { + throw new IllegalArgumentException('The region must fit inside the matrix'); } - - /** - * @param y row to set - * @param row {@link BitArray} to copy from - */ - public setRow(y: number /*int*/, row: BitArray): void { - System.arraycopy(row.getBitArray(), 0, this.bits, y * this.rowSize, this.rowSize); + const rowSize = this.rowSize; + const bits = this.bits; + for (let y = top; y < bottom; y++) { + const offset = y * rowSize; + for (let x = left; x < right; x++) { + bits[offset + Math.floor(x / 32)] |= ((1 << (x & 0x1f)) & 0xFFFFFFFF); + } } - - /** - * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees - */ - public rotate180(): void { - const width = this.getWidth(); - const height = this.getHeight(); - let topRow = new BitArray(width); - let bottomRow = new BitArray(width); - for (let i = 0, length = Math.floor((height + 1) / 2); i < length; i++) { - topRow = this.getRow(i, topRow); - bottomRow = this.getRow(height - 1 - i, bottomRow); - topRow.reverse(); - bottomRow.reverse(); - this.setRow(i, bottomRow); - this.setRow(height - 1 - i, topRow); - } + } + + /** + * A fast method to retrieve one row of data from the matrix as a BitArray. + * + * @param y The row to retrieve + * @param row An optional caller-allocated BitArray, will be allocated if null or too small + * @return The resulting BitArray - this reference should always be used even when passing + * your own row + */ + public getRow(y: number /* int */, row?: BitArray): BitArray { + if (row === null || row === undefined || row.getSize() < this.width) { + row = new BitArray(this.width); + } else { + row.clear(); } + const rowSize = this.rowSize; + const bits = this.bits; + const offset = y * rowSize; + for (let x = 0; x < rowSize; x++) { + row.setBulk(x * 32, bits[offset + x]); + } + return row; + } - /** - * This is useful in detecting the enclosing rectangle of a 'pure' barcode. - * - * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white - */ - public getEnclosingRectangle(): Int32Array { - const width = this.width; - const height = this.height; - const rowSize = this.rowSize; - const bits = this.bits; - - let left = width; - let top = height; - let right = -1; - let bottom = -1; - - for (let y = 0; y < height; y++) { - for (let x32 = 0; x32 < rowSize; x32++) { - const theBits = bits[y * rowSize + x32]; - if (theBits !== 0) { - if (y < top) { - top = y; - } - if (y > bottom) { - bottom = y; - } - if (x32 * 32 < left) { - let bit = 0; - while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) { - bit++; - } - if ((x32 * 32 + bit) < left) { - left = x32 * 32 + bit; - } - } - if (x32 * 32 + 31 > right) { - let bit = 31; - while ((theBits >>> bit) === 0) { - bit--; - } - if ((x32 * 32 + bit) > right) { - right = x32 * 32 + bit; - } - } - } - } - } - - if (right < left || bottom < top) { - return null; - } + /** + * @param y row to set + * @param row {@link BitArray} to copy from + */ + public setRow(y: number /* int */, row: BitArray): void { + System.arraycopy(row.getBitArray(), 0, this.bits, y * this.rowSize, this.rowSize); + } - return Int32Array.from([left, top, right - left + 1, bottom - top + 1]); + /** + * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees + */ + public rotate180(): void { + const width = this.getWidth(); + const height = this.getHeight(); + let topRow = new BitArray(width); + let bottomRow = new BitArray(width); + for (let i = 0, length = Math.floor((height + 1) / 2); i < length; i++) { + topRow = this.getRow(i, topRow); + bottomRow = this.getRow(height - 1 - i, bottomRow); + topRow.reverse(); + bottomRow.reverse(); + this.setRow(i, bottomRow); + this.setRow(height - 1 - i, topRow); } + } - /** - * This is useful in detecting a corner of a 'pure' barcode. - * - * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white - */ - public getTopLeftOnBit(): Int32Array { - const rowSize = this.rowSize; - const bits = this.bits; - - let bitsOffset = 0; - while (bitsOffset < bits.length && bits[bitsOffset] === 0) { - bitsOffset++; - } - if (bitsOffset === bits.length) { - return null; - } - const y = bitsOffset / rowSize; - let x = (bitsOffset % rowSize) * 32; - - const theBits = bits[bitsOffset]; - let bit = 0; - while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) { - bit++; + /** + * This is useful in detecting the enclosing rectangle of a 'pure' barcode. + * + * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white + */ + public getEnclosingRectangle(): Int32Array { + const width = this.width; + const height = this.height; + const rowSize = this.rowSize; + const bits = this.bits; + + let left = width; + let top = height; + let right = -1; + let bottom = -1; + + for (let y = 0; y < height; y++) { + for (let x32 = 0; x32 < rowSize; x32++) { + const theBits = bits[y * rowSize + x32]; + if (theBits !== 0) { + if (y < top) { + top = y; + } + if (y > bottom) { + bottom = y; + } + if (x32 * 32 < left) { + let bit = 0; + while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) { + bit++; + } + if ((x32 * 32 + bit) < left) { + left = x32 * 32 + bit; + } + } + if (x32 * 32 + 31 > right) { + let bit = 31; + while ((theBits >>> bit) === 0) { + bit--; + } + if ((x32 * 32 + bit) > right) { + right = x32 * 32 + bit; + } + } } - x += bit; - return Int32Array.from([x, y]); + } } - public getBottomRightOnBit(): Int32Array { - const rowSize = this.rowSize; - const bits = this.bits; - - let bitsOffset = bits.length - 1; - while (bitsOffset >= 0 && bits[bitsOffset] === 0) { - bitsOffset--; - } - if (bitsOffset < 0) { - return null; - } + if (right < left || bottom < top) { + return null; + } - const y = Math.floor(bitsOffset / rowSize); - let x = Math.floor(bitsOffset % rowSize) * 32; + return Int32Array.from([left, top, right - left + 1, bottom - top + 1]); + } - const theBits = bits[bitsOffset]; - let bit = 31; - while ((theBits >>> bit) === 0) { - bit--; - } - x += bit; + /** + * This is useful in detecting a corner of a 'pure' barcode. + * + * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white + */ + public getTopLeftOnBit(): Int32Array { + const rowSize = this.rowSize; + const bits = this.bits; - return Int32Array.from([x, y]); + let bitsOffset = 0; + while (bitsOffset < bits.length && bits[bitsOffset] === 0) { + bitsOffset++; } - - /** - * @return The width of the matrix - */ - public getWidth(): number /*int*/ { - return this.width; + if (bitsOffset === bits.length) { + return null; } + const y = bitsOffset / rowSize; + let x = (bitsOffset % rowSize) * 32; - /** - * @return The height of the matrix - */ - public getHeight(): number /*int*/ { - return this.height; + const theBits = bits[bitsOffset]; + let bit = 0; + while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) { + bit++; } + x += bit; + return Int32Array.from([x, y]); + } - /** - * @return The row size of the matrix - */ - public getRowSize(): number /*int*/ { - return this.rowSize; - } + public getBottomRightOnBit(): Int32Array { + const rowSize = this.rowSize; + const bits = this.bits; - /*@Override*/ - public equals(o: Object): boolean { - if (!(o instanceof BitMatrix)) { - return false; - } - const other = o; - return this.width === other.width && this.height === other.height && this.rowSize === other.rowSize && - Arrays.equals(this.bits, other.bits); + let bitsOffset = bits.length - 1; + while (bitsOffset >= 0 && bits[bitsOffset] === 0) { + bitsOffset--; } - - /*@Override*/ - public hashCode(): int { - let hash = this.width; - hash = 31 * hash + this.width; - hash = 31 * hash + this.height; - hash = 31 * hash + this.rowSize; - hash = 31 * hash + Arrays.hashCode(this.bits); - return hash; + if (bitsOffset < 0) { + return null; } - /** - * @return string representation using "X" for set and " " for unset bits - */ - /*@Override*/ - // public toString(): string { - // return toString(": "X, " ") - // } - - /** - * @param setString representation of a set bit - * @param unsetString representation of an unset bit - * @return string representation of entire matrix utilizing given strings - */ - // public toString(setString: string = "X ", unsetString: string = " "): string { - // return this.buildToString(setString, unsetString, "\n") - // } - - /** - * @param setString representation of a set bit - * @param unsetString representation of an unset bit - * @param lineSeparator newline character in string representation - * @return string representation of entire matrix utilizing given strings and line separator - * @deprecated call {@link #toString(String,String)} only, which uses \n line separator always - */ - // @Deprecated - public toString(setString: string = 'X ', unsetString: string = ' ', lineSeparator: string = '\n'): string { - return this.buildToString(setString, unsetString, lineSeparator); - } + const y = Math.floor(bitsOffset / rowSize); + let x = Math.floor(bitsOffset % rowSize) * 32; - private buildToString(setString: string, unsetString: string, lineSeparator: string) { - let result = new StringBuilder(); - // result.append(lineSeparator); - for (let y = 0, height = this.height; y < height; y++) { - for (let x = 0, width = this.width; x < width; x++) { - result.append(this.get(x, y) ? setString : unsetString); - } - result.append(lineSeparator); - } - return result.toString(); + const theBits = bits[bitsOffset]; + let bit = 31; + while ((theBits >>> bit) === 0) { + bit--; } + x += bit; - /*@Override*/ - public clone(): BitMatrix { - return new BitMatrix(this.width, this.height, this.rowSize, this.bits.slice()); + return Int32Array.from([x, y]); + } + + /** + * @return The width of the matrix + */ + public getWidth(): number /* int */ { + return this.width; + } + + /** + * @return The height of the matrix + */ + public getHeight(): number /* int */ { + return this.height; + } + + /** + * @return The row size of the matrix + */ + public getRowSize(): number /* int */ { + return this.rowSize; + } + + /* @Override */ + public equals(o: Object): boolean { + if (!(o instanceof BitMatrix)) { + return false; } + const other = o; + return this.width === other.width && this.height === other.height && this.rowSize === other.rowSize && + Arrays.equals(this.bits, other.bits); + } + + /* @Override */ + public hashCode(): int { + let hash = this.width; + hash = 31 * hash + this.width; + hash = 31 * hash + this.height; + hash = 31 * hash + this.rowSize; + hash = 31 * hash + Arrays.hashCode(this.bits); + return hash; + } + + /** + * @return string representation using "X" for set and " " for unset bits + */ + /* @Override */ + // public toString(): string { + // return toString(": "X, " ") + // } + + /** + * @param setString representation of a set bit + * @param unsetString representation of an unset bit + * @return string representation of entire matrix utilizing given strings + */ + // public toString(setString: string = "X ", unsetString: string = " "): string { + // return this.buildToString(setString, unsetString, "\n") + // } + + /** + * @param setString representation of a set bit + * @param unsetString representation of an unset bit + * @param lineSeparator newline character in string representation + * @return string representation of entire matrix utilizing given strings and line separator + * @deprecated call {@link #toString(String,String)} only, which uses \n line separator always + */ + // @Deprecated + public toString(setString: string = 'X ', unsetString: string = ' ', lineSeparator: string = '\n'): string { + return this.buildToString(setString, unsetString, lineSeparator); + } + + private buildToString(setString: string, unsetString: string, lineSeparator: string) { + let result = new StringBuilder(); + // result.append(lineSeparator); + for (let y = 0, height = this.height; y < height; y++) { + for (let x = 0, width = this.width; x < width; x++) { + result.append(this.get(x, y) ? setString : unsetString); + } + result.append(lineSeparator); + } + return result.toString(); + } + + /* @Override */ + public clone(): BitMatrix { + return new BitMatrix(this.width, this.height, this.rowSize, this.bits.slice()); + } } diff --git a/src/core/common/BitSource.ts b/src/core/common/BitSource.ts index bbfb9bb9..4b321e9d 100644 --- a/src/core/common/BitSource.ts +++ b/src/core/common/BitSource.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ import IllegalArgumentException from '../IllegalArgumentException'; @@ -30,96 +30,96 @@ import IllegalArgumentException from '../IllegalArgumentException'; */ export default class BitSource { - private byteOffset: number; /*int*/ - private bitOffset: number; /*int*/ + private byteOffset: number; /* int */ + private bitOffset: number; /* int */ - /** - * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. - * Bits are read within a byte from most-significant to least-significant bit. - */ - public constructor(private bytes: Uint8Array) { - this.byteOffset = 0; - this.bitOffset = 0; - } + /** + * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. + * Bits are read within a byte from most-significant to least-significant bit. + */ + public constructor(private bytes: Uint8Array) { + this.byteOffset = 0; + this.bitOffset = 0; + } - /** - * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. - */ - public getBitOffset(): number /*int*/ { - return this.bitOffset; - } + /** + * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. + */ + public getBitOffset(): number /* int */ { + return this.bitOffset; + } - /** - * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. - */ - public getByteOffset(): number /*int*/ { - return this.byteOffset; + /** + * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. + */ + public getByteOffset(): number /* int */ { + return this.byteOffset; + } + + /** + * @param numBits number of bits to read + * @return int representing the bits read. The bits will appear as the least-significant + * bits of the int + * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available + */ + public readBits(numBits: number /* int */): number /* int */ { + if (numBits < 1 || numBits > 32 || numBits > this.available()) { + throw new IllegalArgumentException('' + numBits); } - /** - * @param numBits number of bits to read - * @return int representing the bits read. The bits will appear as the least-significant - * bits of the int - * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available - */ - public readBits(numBits: number /*int*/): number /*int*/ { - if (numBits < 1 || numBits > 32 || numBits > this.available()) { - throw new IllegalArgumentException('' + numBits); - } - - let result = 0; - - let bitOffset = this.bitOffset; - let byteOffset = this.byteOffset; - - const bytes = this.bytes; - // First, read remainder from current byte - if (bitOffset > 0) { - const bitsLeft = 8 - bitOffset; - const toRead = numBits < bitsLeft ? numBits : bitsLeft; - const bitsToNotRead = bitsLeft - toRead; - const mask = (0xFF >> (8 - toRead)) << bitsToNotRead; - - result = (bytes[byteOffset] & mask) >> bitsToNotRead; - numBits -= toRead; - bitOffset += toRead; - - if (bitOffset === 8) { - bitOffset = 0; - byteOffset++; - } - } - - // Next read whole bytes - if (numBits > 0) { - - while (numBits >= 8) { - result = (result << 8) | (bytes[byteOffset] & 0xFF); - byteOffset++; - numBits -= 8; - } - - // Finally read a partial byte - if (numBits > 0) { - const bitsToNotRead = 8 - numBits; - const mask = (0xFF >> bitsToNotRead) << bitsToNotRead; - - result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead); - bitOffset += numBits; - } - } - - this.bitOffset = bitOffset; - this.byteOffset = byteOffset; - - return result; + let result = 0; + + let bitOffset = this.bitOffset; + let byteOffset = this.byteOffset; + + const bytes = this.bytes; + // First, read remainder from current byte + if (bitOffset > 0) { + const bitsLeft = 8 - bitOffset; + const toRead = numBits < bitsLeft ? numBits : bitsLeft; + const bitsToNotRead = bitsLeft - toRead; + const mask = (0xFF >> (8 - toRead)) << bitsToNotRead; + + result = (bytes[byteOffset] & mask) >> bitsToNotRead; + numBits -= toRead; + bitOffset += toRead; + + if (bitOffset === 8) { + bitOffset = 0; + byteOffset++; + } } - /** - * @return number of bits that can be read successfully - */ - public available(): number /*int*/ { - return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset; + // Next read whole bytes + if (numBits > 0) { + + while (numBits >= 8) { + result = (result << 8) | (bytes[byteOffset] & 0xFF); + byteOffset++; + numBits -= 8; + } + + // Finally read a partial byte + if (numBits > 0) { + const bitsToNotRead = 8 - numBits; + const mask = (0xFF >> bitsToNotRead) << bitsToNotRead; + + result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead); + bitOffset += numBits; + } } + this.bitOffset = bitOffset; + this.byteOffset = byteOffset; + + return result; + } + + /** + * @return number of bits that can be read successfully + */ + public available(): number /* int */ { + return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset; + } + } diff --git a/src/core/common/CharacterSetECI.ts b/src/core/common/CharacterSetECI.ts index 3b521e76..2fc516f8 100644 --- a/src/core/common/CharacterSetECI.ts +++ b/src/core/common/CharacterSetECI.ts @@ -14,42 +14,42 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ import FormatException from '../FormatException'; -/*import java.util.HashMap;*/ -/*import java.util.Map;*/ +/* import java.util.HashMap; */ +/* import java.util.Map; */ export enum CharacterSetValueIdentifiers { - Cp437, - ISO8859_1, - ISO8859_2, - ISO8859_3, - ISO8859_4, - ISO8859_5, - ISO8859_6, - ISO8859_7, - ISO8859_8, - ISO8859_9, - ISO8859_10, - ISO8859_11, - ISO8859_13, - ISO8859_14, - ISO8859_15, - ISO8859_16, - SJIS, - Cp1250, - Cp1251, - Cp1252, - Cp1256, - UnicodeBigUnmarked, - UTF8, - ASCII, - Big5, - GB18030, - EUC_KR, + Cp437, + ISO8859_1, + ISO8859_2, + ISO8859_3, + ISO8859_4, + ISO8859_5, + ISO8859_6, + ISO8859_7, + ISO8859_8, + ISO8859_9, + ISO8859_10, + ISO8859_11, + ISO8859_13, + ISO8859_14, + ISO8859_15, + ISO8859_16, + SJIS, + Cp1250, + Cp1251, + Cp1252, + Cp1256, + UnicodeBigUnmarked, + UTF8, + ASCII, + Big5, + GB18030, + EUC_KR, } /** @@ -61,198 +61,198 @@ export enum CharacterSetValueIdentifiers { export default class CharacterSetECI { - private static VALUE_IDENTIFIER_TO_ECI = new Map(); - private static VALUES_TO_ECI = new Map(); - private static NAME_TO_ECI = new Map(); + private static VALUE_IDENTIFIER_TO_ECI = new Map(); + private static VALUES_TO_ECI = new Map(); + private static NAME_TO_ECI = new Map(); - // Enum name is a Java encoding valid for java.lang and java.io - // TYPESCRIPTPORT: changed the main label for ISO as the TextEncoder did not recognized them in the form from java - // (eg ISO8859_1 must be ISO88591 or ISO8859-1 or ISO-8859-1) - // later on: well, except 16 wich does not work with ISO885916 so used ISO-8859-1 form for default - public static readonly Cp437 = new CharacterSetECI( - CharacterSetValueIdentifiers.Cp437, Int32Array.from([0, 2]), 'Cp437'); + // Enum name is a Java encoding valid for java.lang and java.io + // TYPESCRIPTPORT: changed the main label for ISO as the TextEncoder did not recognized them in the form from java + // (eg ISO8859_1 must be ISO88591 or ISO8859-1 or ISO-8859-1) + // later on: well, except 16 wich does not work with ISO885916 so used ISO-8859-1 form for default + public static readonly Cp437 = new CharacterSetECI( + CharacterSetValueIdentifiers.Cp437, Int32Array.from([0, 2]), 'Cp437'); - public static readonly ISO8859_1 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_1, Int32Array.from([1, 3]), 'ISO-8859-1', 'ISO88591', 'ISO8859_1'); + public static readonly ISO8859_1 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_1, Int32Array.from([1, 3]), 'ISO-8859-1', 'ISO88591', 'ISO8859_1'); - public static readonly ISO8859_2 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_2, 4, 'ISO-8859-2', 'ISO88592', 'ISO8859_2'); + public static readonly ISO8859_2 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_2, 4, 'ISO-8859-2', 'ISO88592', 'ISO8859_2'); - public static readonly ISO8859_3 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_3, 5, 'ISO-8859-3', 'ISO88593', 'ISO8859_3'); + public static readonly ISO8859_3 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_3, 5, 'ISO-8859-3', 'ISO88593', 'ISO8859_3'); - public static readonly ISO8859_4 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_4, 6, 'ISO-8859-4', 'ISO88594', 'ISO8859_4'); + public static readonly ISO8859_4 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_4, 6, 'ISO-8859-4', 'ISO88594', 'ISO8859_4'); - public static readonly ISO8859_5 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_5, 7, 'ISO-8859-5', 'ISO88595', 'ISO8859_5'); + public static readonly ISO8859_5 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_5, 7, 'ISO-8859-5', 'ISO88595', 'ISO8859_5'); - public static readonly ISO8859_6 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_6, 8, 'ISO-8859-6', 'ISO88596', 'ISO8859_6'); + public static readonly ISO8859_6 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_6, 8, 'ISO-8859-6', 'ISO88596', 'ISO8859_6'); - public static readonly ISO8859_7 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_7, 9, 'ISO-8859-7', 'ISO88597', 'ISO8859_7'); + public static readonly ISO8859_7 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_7, 9, 'ISO-8859-7', 'ISO88597', 'ISO8859_7'); - public static readonly ISO8859_8 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_8, 10, 'ISO-8859-8', 'ISO88598', 'ISO8859_8'); + public static readonly ISO8859_8 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_8, 10, 'ISO-8859-8', 'ISO88598', 'ISO8859_8'); - public static readonly ISO8859_9 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_9, 11, 'ISO-8859-9', 'ISO88599', 'ISO8859_9'); + public static readonly ISO8859_9 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_9, 11, 'ISO-8859-9', 'ISO88599', 'ISO8859_9'); - public static readonly ISO8859_10 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_10, 12, 'ISO-8859-10', 'ISO885910', 'ISO8859_10'); + public static readonly ISO8859_10 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_10, 12, 'ISO-8859-10', 'ISO885910', 'ISO8859_10'); - public static readonly ISO8859_11 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_11, 13, 'ISO-8859-11', 'ISO885911', 'ISO8859_11'); + public static readonly ISO8859_11 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_11, 13, 'ISO-8859-11', 'ISO885911', 'ISO8859_11'); - public static readonly ISO8859_13 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_13, 15, 'ISO-8859-13', 'ISO885913', 'ISO8859_13'); + public static readonly ISO8859_13 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_13, 15, 'ISO-8859-13', 'ISO885913', 'ISO8859_13'); - public static readonly ISO8859_14 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_14, 16, 'ISO-8859-14', 'ISO885914', 'ISO8859_14'); + public static readonly ISO8859_14 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_14, 16, 'ISO-8859-14', 'ISO885914', 'ISO8859_14'); - public static readonly ISO8859_15 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_15, 17, 'ISO-8859-15', 'ISO885915', 'ISO8859_15'); + public static readonly ISO8859_15 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_15, 17, 'ISO-8859-15', 'ISO885915', 'ISO8859_15'); - public static readonly ISO8859_16 = new CharacterSetECI( - CharacterSetValueIdentifiers.ISO8859_16, 18, 'ISO-8859-16', 'ISO885916', 'ISO8859_16'); + public static readonly ISO8859_16 = new CharacterSetECI( + CharacterSetValueIdentifiers.ISO8859_16, 18, 'ISO-8859-16', 'ISO885916', 'ISO8859_16'); - public static readonly SJIS = new CharacterSetECI( - CharacterSetValueIdentifiers.SJIS, 20, 'SJIS', 'Shift_JIS'); + public static readonly SJIS = new CharacterSetECI( + CharacterSetValueIdentifiers.SJIS, 20, 'SJIS', 'Shift_JIS'); - public static readonly Cp1250 = new CharacterSetECI( - CharacterSetValueIdentifiers.Cp1250, 21, 'Cp1250', 'windows-1250'); + public static readonly Cp1250 = new CharacterSetECI( + CharacterSetValueIdentifiers.Cp1250, 21, 'Cp1250', 'windows-1250'); - public static readonly Cp1251 = new CharacterSetECI( - CharacterSetValueIdentifiers.Cp1251, 22, 'Cp1251', 'windows-1251'); + public static readonly Cp1251 = new CharacterSetECI( + CharacterSetValueIdentifiers.Cp1251, 22, 'Cp1251', 'windows-1251'); - public static readonly Cp1252 = new CharacterSetECI( - CharacterSetValueIdentifiers.Cp1252, 23, 'Cp1252', 'windows-1252'); + public static readonly Cp1252 = new CharacterSetECI( + CharacterSetValueIdentifiers.Cp1252, 23, 'Cp1252', 'windows-1252'); - public static readonly Cp1256 = new CharacterSetECI( - CharacterSetValueIdentifiers.Cp1256, 24, 'Cp1256', 'windows-1256'); + public static readonly Cp1256 = new CharacterSetECI( + CharacterSetValueIdentifiers.Cp1256, 24, 'Cp1256', 'windows-1256'); - public static readonly UnicodeBigUnmarked = new CharacterSetECI( - CharacterSetValueIdentifiers.UnicodeBigUnmarked, 25, 'UnicodeBigUnmarked', 'UTF-16BE', 'UnicodeBig'); + public static readonly UnicodeBigUnmarked = new CharacterSetECI( + CharacterSetValueIdentifiers.UnicodeBigUnmarked, 25, 'UnicodeBigUnmarked', 'UTF-16BE', 'UnicodeBig'); - public static readonly UTF8 = new CharacterSetECI( - CharacterSetValueIdentifiers.UTF8, 26, 'UTF8', 'UTF-8'); + public static readonly UTF8 = new CharacterSetECI( + CharacterSetValueIdentifiers.UTF8, 26, 'UTF8', 'UTF-8'); - public static readonly ASCII = new CharacterSetECI( - CharacterSetValueIdentifiers.ASCII, Int32Array.from([27, 170]), 'ASCII', 'US-ASCII'); + public static readonly ASCII = new CharacterSetECI( + CharacterSetValueIdentifiers.ASCII, Int32Array.from([27, 170]), 'ASCII', 'US-ASCII'); - public static readonly Big5 = new CharacterSetECI( - CharacterSetValueIdentifiers.Big5, 28, 'Big5'); + public static readonly Big5 = new CharacterSetECI( + CharacterSetValueIdentifiers.Big5, 28, 'Big5'); - public static readonly GB18030 = new CharacterSetECI( - CharacterSetValueIdentifiers.GB18030, 29, 'GB18030', 'GB2312', 'EUC_CN', 'GBK'); + public static readonly GB18030 = new CharacterSetECI( + CharacterSetValueIdentifiers.GB18030, 29, 'GB18030', 'GB2312', 'EUC_CN', 'GBK'); - public static readonly EUC_KR = new CharacterSetECI( - CharacterSetValueIdentifiers.EUC_KR, 30, 'EUC_KR', 'EUC-KR'); + public static readonly EUC_KR = new CharacterSetECI( + CharacterSetValueIdentifiers.EUC_KR, 30, 'EUC_KR', 'EUC-KR'); - public values: Int32Array; - public otherEncodingNames: string[]; + public values: Int32Array; + public otherEncodingNames: string[]; - public constructor( - public valueIdentifier: CharacterSetValueIdentifiers, - valuesParam: Int32Array | number, - public name: string, ...otherEncodingNames: string[] - ) { + public constructor( + public valueIdentifier: CharacterSetValueIdentifiers, + valuesParam: Int32Array | number, + public name: string, ...otherEncodingNames: string[] + ) { - if (typeof valuesParam === 'number') { - this.values = Int32Array.from([valuesParam]); - } else { - this.values = valuesParam; - } - - this.otherEncodingNames = otherEncodingNames; - - CharacterSetECI.VALUE_IDENTIFIER_TO_ECI.set(valueIdentifier, this); - CharacterSetECI.NAME_TO_ECI.set(name, this); - - const values = this.values; - - for (let i = 0, length = values.length; i !== length; i++) { - const v = values[i]; - CharacterSetECI.VALUES_TO_ECI.set(v, this); - } - for (const otherName of otherEncodingNames) { - CharacterSetECI.NAME_TO_ECI.set(otherName, this); - } + if (typeof valuesParam === 'number') { + this.values = Int32Array.from([valuesParam]); + } else { + this.values = valuesParam; } - // CharacterSetECI(value: number /*int*/) { - // this(new Int32Array {value}) - // } + this.otherEncodingNames = otherEncodingNames; - // CharacterSetECI(value: number /*int*/, String... otherEncodingNames) { - // this.values = new Int32Array {value} - // this.otherEncodingNames = otherEncodingNames - // } + CharacterSetECI.VALUE_IDENTIFIER_TO_ECI.set(valueIdentifier, this); + CharacterSetECI.NAME_TO_ECI.set(name, this); - // CharacterSetECI(values: Int32Array, String... otherEncodingNames) { - // this.values = values - // this.otherEncodingNames = otherEncodingNames - // } + const values = this.values; - public getValueIdentifier(): CharacterSetValueIdentifiers/*int*/ { - return this.valueIdentifier; + for (let i = 0, length = values.length; i !== length; i++) { + const v = values[i]; + CharacterSetECI.VALUES_TO_ECI.set(v, this); } - - public getName(): string { - return this.name; + for (const otherName of otherEncodingNames) { + CharacterSetECI.NAME_TO_ECI.set(otherName, this); } + } + + // CharacterSetECI(value: number /*int */) { + // this(new Int32Array {value}) + // } + + // CharacterSetECI(value: number /*int */, String... otherEncodingNames) { + // this.values = new Int32Array {value} + // this.otherEncodingNames = otherEncodingNames + // } + + // CharacterSetECI(values: Int32Array, String... otherEncodingNames) { + // this.values = values + // this.otherEncodingNames = otherEncodingNames + // } + + public getValueIdentifier(): CharacterSetValueIdentifiers/* int */ { + return this.valueIdentifier; + } + + public getName(): string { + return this.name; + } + + public getValue(): number /* int */ { + return this.values[0]; + } + + /** + * @param value character set ECI value + * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but + * unsupported + * @throws FormatException if ECI value is invalid + */ + public static getCharacterSetECIByValue(value: number /* int */): CharacterSetECI /* throws FormatException */ { - public getValue(): number /*int*/ { - return this.values[0]; + if (value < 0 || value >= 900) { + throw new FormatException('incorect value'); } - /** - * @param value character set ECI value - * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but - * unsupported - * @throws FormatException if ECI value is invalid - */ - public static getCharacterSetECIByValue(value: number /*int*/): CharacterSetECI /*throws FormatException*/ { - - if (value < 0 || value >= 900) { - throw new FormatException('incorect value'); - } + const characterSet = CharacterSetECI.VALUES_TO_ECI.get(value); - const characterSet = CharacterSetECI.VALUES_TO_ECI.get(value); - - if (undefined === characterSet) { - throw new FormatException('incorect value'); - } - - return characterSet; + if (undefined === characterSet) { + throw new FormatException('incorect value'); } - /** - * @param name character set ECI encoding name - * @return CharacterSetECI representing ECI for character encoding, or null if it is legal - * but unsupported - */ - public static getCharacterSetECIByName(name: string): CharacterSetECI { + return characterSet; + } - const characterSet = CharacterSetECI.NAME_TO_ECI.get(name); + /** + * @param name character set ECI encoding name + * @return CharacterSetECI representing ECI for character encoding, or null if it is legal + * but unsupported + */ + public static getCharacterSetECIByName(name: string): CharacterSetECI { - if (undefined === characterSet) { - throw new FormatException('incorect value'); - } + const characterSet = CharacterSetECI.NAME_TO_ECI.get(name); - return characterSet; + if (undefined === characterSet) { + throw new FormatException('incorect value'); } - public equals(o: CharacterSetECI) { + return characterSet; + } - if (!(o instanceof CharacterSetECI)) { - return false; - } + public equals(o: CharacterSetECI) { - const other = o as CharacterSetECI; - - return this.getName() === other.getName(); + if (!(o instanceof CharacterSetECI)) { + return false; } + const other = o as CharacterSetECI; + + return this.getName() === other.getName(); + } + } diff --git a/src/core/common/DecoderResult.ts b/src/core/common/DecoderResult.ts index dadb9d59..4976d494 100644 --- a/src/core/common/DecoderResult.ts +++ b/src/core/common/DecoderResult.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ -/*import java.util.List;*/ +/* import java.util.List; */ /** *

Encapsulates the result of decoding a matrix of bits. This typically @@ -27,114 +27,114 @@ */ export default class DecoderResult { - private numBits: number; /*int*/ - private errorsCorrected: number; /*Integer*/ - private erasures: number; /*Integer*/ - private other: any; - - // public constructor(rawBytes: Uint8Array, - // text: string, - // List byteSegments, - // String ecLevel) { - // this(rawBytes, text, byteSegments, ecLevel, -1, -1) - // } - - public constructor(private rawBytes: Uint8Array, - private text: string, - private byteSegments: Uint8Array[], - private ecLevel: string, - private structuredAppendSequenceNumber: number /*int*/ = -1, - private structuredAppendParity: number /*int*/ = -1) { - this.numBits = (rawBytes === undefined || rawBytes === null) ? 0 : 8 * rawBytes.length; - } - - /** - * @return raw bytes representing the result, or {@code null} if not applicable - */ - public getRawBytes(): Uint8Array { - return this.rawBytes; - } - - /** - * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length - * @since 3.3.0 - */ - public getNumBits(): number /*int*/ { - return this.numBits; - } - - /** - * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()} - * @since 3.3.0 - */ - public setNumBits(numBits: number /*int*/): void { - this.numBits = numBits; - } - - /** - * @return text representation of the result - */ - public getText(): string { - return this.text; - } - - /** - * @return list of byte segments in the result, or {@code null} if not applicable - */ - public getByteSegments(): Uint8Array[] { - return this.byteSegments; - } - - /** - * @return name of error correction level used, or {@code null} if not applicable - */ - public getECLevel(): string { - return this.ecLevel; - } - - /** - * @return number of errors corrected, or {@code null} if not applicable - */ - public getErrorsCorrected(): number/*Integer*/ { - return this.errorsCorrected; - } - - public setErrorsCorrected(errorsCorrected: number/*Integer*/): void { - this.errorsCorrected = errorsCorrected; - } - - /** - * @return number of erasures corrected, or {@code null} if not applicable - */ - public getErasures(): number/*Integer*/ { - return this.erasures; - } - - public setErasures(erasures: number/*Integer*/): void { - this.erasures = erasures; - } - - /** - * @return arbitrary additional metadata - */ - public getOther(): any { - return this.other; - } - - public setOther(other: any): void { - this.other = other; - } - - public hasStructuredAppend(): boolean { - return this.structuredAppendParity >= 0 && this.structuredAppendSequenceNumber >= 0; - } - - public getStructuredAppendParity(): number /*int*/ { - return this.structuredAppendParity; - } - - public getStructuredAppendSequenceNumber(): number /*int*/ { - return this.structuredAppendSequenceNumber; - } + private numBits: number; /* int */ + private errorsCorrected: number; /* Integer */ + private erasures: number; /* Integer */ + private other: any; + + // public constructor(rawBytes: Uint8Array, + // text: string, + // List byteSegments, + // String ecLevel) { + // this(rawBytes, text, byteSegments, ecLevel, -1, -1) + // } + + public constructor(private rawBytes: Uint8Array, + private text: string, + private byteSegments: Uint8Array[], + private ecLevel: string, + private structuredAppendSequenceNumber: number /* int */ = -1, + private structuredAppendParity: number /* int */ = -1) { + this.numBits = (rawBytes === undefined || rawBytes === null) ? 0 : 8 * rawBytes.length; + } + + /** + * @return raw bytes representing the result, or {@code null} if not applicable + */ + public getRawBytes(): Uint8Array { + return this.rawBytes; + } + + /** + * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length + * @since 3.3.0 + */ + public getNumBits(): number /* int */ { + return this.numBits; + } + + /** + * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()} + * @since 3.3.0 + */ + public setNumBits(numBits: number /* int */): void { + this.numBits = numBits; + } + + /** + * @return text representation of the result + */ + public getText(): string { + return this.text; + } + + /** + * @return list of byte segments in the result, or {@code null} if not applicable + */ + public getByteSegments(): Uint8Array[] { + return this.byteSegments; + } + + /** + * @return name of error correction level used, or {@code null} if not applicable + */ + public getECLevel(): string { + return this.ecLevel; + } + + /** + * @return number of errors corrected, or {@code null} if not applicable + */ + public getErrorsCorrected(): number/* Integer */ { + return this.errorsCorrected; + } + + public setErrorsCorrected(errorsCorrected: number/* Integer */): void { + this.errorsCorrected = errorsCorrected; + } + + /** + * @return number of erasures corrected, or {@code null} if not applicable + */ + public getErasures(): number/* Integer */ { + return this.erasures; + } + + public setErasures(erasures: number/* Integer */): void { + this.erasures = erasures; + } + + /** + * @return arbitrary additional metadata + */ + public getOther(): any { + return this.other; + } + + public setOther(other: any): void { + this.other = other; + } + + public hasStructuredAppend(): boolean { + return this.structuredAppendParity >= 0 && this.structuredAppendSequenceNumber >= 0; + } + + public getStructuredAppendParity(): number /* int */ { + return this.structuredAppendParity; + } + + public getStructuredAppendSequenceNumber(): number /* int */ { + return this.structuredAppendSequenceNumber; + } } diff --git a/src/core/common/DefaultGridSampler.ts b/src/core/common/DefaultGridSampler.ts index 35c8189c..06239449 100644 --- a/src/core/common/DefaultGridSampler.ts +++ b/src/core/common/DefaultGridSampler.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ import GridSampler from './GridSampler'; import BitMatrix from './BitMatrix'; @@ -29,66 +29,66 @@ import { float } from '../../customTypings'; */ export default class DefaultGridSampler extends GridSampler { - /*@Override*/ - public sampleGrid(image: BitMatrix, - dimensionX: number /*int*/, - dimensionY: number /*int*/, - p1ToX: number/*float*/, p1ToY: number/*float*/, - p2ToX: number/*float*/, p2ToY: number/*float*/, - p3ToX: number/*float*/, p3ToY: number/*float*/, - p4ToX: number/*float*/, p4ToY: number/*float*/, - p1FromX: number/*float*/, p1FromY: number/*float*/, - p2FromX: number/*float*/, p2FromY: number/*float*/, - p3FromX: number/*float*/, p3FromY: number/*float*/, - p4FromX: number/*float*/, p4FromY: number/*float*/): BitMatrix /*throws NotFoundException*/ { + /* @Override */ + public sampleGrid(image: BitMatrix, + dimensionX: number /* int */, + dimensionY: number /* int */, + p1ToX: number/* float */, p1ToY: number/* float */, + p2ToX: number/* float */, p2ToY: number/* float */, + p3ToX: number/* float */, p3ToY: number/* float */, + p4ToX: number/* float */, p4ToY: number/* float */, + p1FromX: number/* float */, p1FromY: number/* float */, + p2FromX: number/* float */, p2FromY: number/* float */, + p3FromX: number/* float */, p3FromY: number/* float */, + p4FromX: number/* float */, p4FromY: number/* float */): BitMatrix /* throws NotFoundException */ { - const transform = PerspectiveTransform.quadrilateralToQuadrilateral( - p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, - p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY); + const transform = PerspectiveTransform.quadrilateralToQuadrilateral( + p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, + p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY); - return this.sampleGridWithTransform(image, dimensionX, dimensionY, transform); - } + return this.sampleGridWithTransform(image, dimensionX, dimensionY, transform); + } - /*@Override*/ - public sampleGridWithTransform(image: BitMatrix, - dimensionX: number /*int*/, - dimensionY: number /*int*/, - transform: PerspectiveTransform): BitMatrix /*throws NotFoundException*/ { - if (dimensionX <= 0 || dimensionY <= 0) { - throw new NotFoundException(); - } - const bits = new BitMatrix(dimensionX, dimensionY); - const points = new Float32Array(2 * dimensionX); - for (let y = 0; y < dimensionY; y++) { - const max = points.length; - const iValue: number /*float*/ = y + 0.5; - for (let x = 0; x < max; x += 2) { - points[x] = (x / 2) + 0.5; - points[x + 1] = iValue; - } - transform.transformPoints(points); - // Quick check to see if points transformed to something inside the image - // sufficient to check the endpoints - GridSampler.checkAndNudgePoints(image, points); - try { - for (let x = 0; x < max; x += 2) { - if (image.get(Math.floor(points[x]), Math.floor(points[x + 1]))) { - // Black(-ish) pixel - bits.set(x / 2, y); - } - } - } catch (aioobe/*: ArrayIndexOutOfBoundsException*/) { - // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting - // transform gets "twisted" such that it maps a straight line of points to a set of points - // whose endpoints are in bounds, but others are not. There is probably some mathematical - // way to detect this about the transformation that I don't know yet. - // This results in an ugly runtime exception despite our clever checks above -- can't have - // that. We could check each point's coordinates but that feels duplicative. We settle for - // catching and wrapping ArrayIndexOutOfBoundsException. - throw new NotFoundException(); - } + /* @Override */ + public sampleGridWithTransform(image: BitMatrix, + dimensionX: number /* int */, + dimensionY: number /* int */, + transform: PerspectiveTransform): BitMatrix /* throws NotFoundException */ { + if (dimensionX <= 0 || dimensionY <= 0) { + throw new NotFoundException(); + } + const bits = new BitMatrix(dimensionX, dimensionY); + const points = new Float32Array(2 * dimensionX); + for (let y = 0; y < dimensionY; y++) { + const max = points.length; + const iValue: number /* float */ = y + 0.5; + for (let x = 0; x < max; x += 2) { + points[x] = (x / 2) + 0.5; + points[x + 1] = iValue; + } + transform.transformPoints(points); + // Quick check to see if points transformed to something inside the image + // sufficient to check the endpoints + GridSampler.checkAndNudgePoints(image, points); + try { + for (let x = 0; x < max; x += 2) { + if (image.get(Math.floor(points[x]), Math.floor(points[x + 1]))) { + // Black(-ish) pixel + bits.set(x / 2, y); + } } - return bits; + } catch (aioobe/* : ArrayIndexOutOfBoundsException */) { + // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting + // transform gets "twisted" such that it maps a straight line of points to a set of points + // whose endpoints are in bounds, but others are not. There is probably some mathematical + // way to detect this about the transformation that I don't know yet. + // This results in an ugly runtime exception despite our clever checks above -- can't have + // that. We could check each point's coordinates but that feels duplicative. We settle for + // catching and wrapping ArrayIndexOutOfBoundsException. + throw new NotFoundException(); + } } + return bits; + } } diff --git a/src/core/common/DetectorResult.ts b/src/core/common/DetectorResult.ts index ceb696b1..5cda6778 100644 --- a/src/core/common/DetectorResult.ts +++ b/src/core/common/DetectorResult.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ import ResultPoint from '../ResultPoint'; import BitMatrix from './BitMatrix'; @@ -28,20 +28,20 @@ import BitMatrix from './BitMatrix'; */ export default class DetectorResult { - private bits: BitMatrix; - private points: Array; + private bits: BitMatrix; + private points: Array; - public constructor(bits: BitMatrix, points: Array) { - this.bits = bits; - this.points = points; - } + public constructor(bits: BitMatrix, points: Array) { + this.bits = bits; + this.points = points; + } - public getBits(): BitMatrix { - return this.bits; - } + public getBits(): BitMatrix { + return this.bits; + } - public getPoints(): Array { - return this.points; - } + public getPoints(): Array { + return this.points; + } } diff --git a/src/core/common/GlobalHistogramBinarizer.ts b/src/core/common/GlobalHistogramBinarizer.ts index b59f0528..8339b4a4 100644 --- a/src/core/common/GlobalHistogramBinarizer.ts +++ b/src/core/common/GlobalHistogramBinarizer.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ import Binarizer from '../Binarizer'; import LuminanceSource from '../LuminanceSource'; @@ -36,173 +36,173 @@ import NotFoundException from '../NotFoundException'; */ export default class GlobalHistogramBinarizer extends Binarizer { - private static LUMINANCE_BITS = 5; - private static LUMINANCE_SHIFT = 8 - GlobalHistogramBinarizer.LUMINANCE_BITS; - private static LUMINANCE_BUCKETS = 1 << GlobalHistogramBinarizer.LUMINANCE_BITS; - private static EMPTY = Uint8ClampedArray.from([0]); - - private luminances: Uint8ClampedArray; - private buckets: Int32Array; - - public constructor(source: LuminanceSource) { - super(source); - this.luminances = GlobalHistogramBinarizer.EMPTY; - this.buckets = new Int32Array(GlobalHistogramBinarizer.LUMINANCE_BUCKETS); + private static LUMINANCE_BITS = 5; + private static LUMINANCE_SHIFT = 8 - GlobalHistogramBinarizer.LUMINANCE_BITS; + private static LUMINANCE_BUCKETS = 1 << GlobalHistogramBinarizer.LUMINANCE_BITS; + private static EMPTY = Uint8ClampedArray.from([0]); + + private luminances: Uint8ClampedArray; + private buckets: Int32Array; + + public constructor(source: LuminanceSource) { + super(source); + this.luminances = GlobalHistogramBinarizer.EMPTY; + this.buckets = new Int32Array(GlobalHistogramBinarizer.LUMINANCE_BUCKETS); + } + + // Applies simple sharpening to the row data to improve performance of the 1D Readers. + /* @Override */ + public getBlackRow(y: number /* int */, row: BitArray): BitArray /* throws NotFoundException */ { + const source = this.getLuminanceSource(); + const width = source.getWidth(); + if (row === undefined || row === null || row.getSize() < width) { + row = new BitArray(width); + } else { + row.clear(); } - // Applies simple sharpening to the row data to improve performance of the 1D Readers. - /*@Override*/ - public getBlackRow(y: number /*int*/, row: BitArray): BitArray /*throws NotFoundException*/ { - const source = this.getLuminanceSource(); - const width = source.getWidth(); - if (row === undefined || row === null || row.getSize() < width) { - row = new BitArray(width); - } else { - row.clear(); - } - - this.initArrays(width); - const localLuminances = source.getRow(y, this.luminances); - const localBuckets = this.buckets; - for (let x = 0; x < width; x++) { - localBuckets[(localLuminances[x] & 0xff) >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++; - } - const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets); - - if (width < 3) { - // Special case for very small images - for (let x = 0; x < width; x++) { - if ((localLuminances[x] & 0xff) < blackPoint) { - row.set(x); - } - } - } else { - let left = localLuminances[0] & 0xff; - let center = localLuminances[1] & 0xff; - for (let x = 1; x < width - 1; x++) { - const right = localLuminances[x + 1] & 0xff; - // A simple -1 4 -1 box filter with a weight of 2. - if (((center * 4) - left - right) / 2 < blackPoint) { - row.set(x); - } - left = center; - center = right; - } - } - return row; + this.initArrays(width); + const localLuminances = source.getRow(y, this.luminances); + const localBuckets = this.buckets; + for (let x = 0; x < width; x++) { + localBuckets[(localLuminances[x] & 0xff) >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++; } + const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets); - // Does not sharpen the data, as this call is intended to only be used by 2D Readers. - /*@Override*/ - public getBlackMatrix(): BitMatrix /*throws NotFoundException*/ { - const source = this.getLuminanceSource(); - const width = source.getWidth(); - const height = source.getHeight(); - const matrix = new BitMatrix(width, height); - - // Quickly calculates the histogram by sampling four rows from the image. This proved to be - // more robust on the blackbox tests than sampling a diagonal as we used to do. - this.initArrays(width); - const localBuckets = this.buckets; - for (let y = 1; y < 5; y++) { - const row = Math.floor((height * y) / 5); - const localLuminances = source.getRow(row, this.luminances); - const right = Math.floor((width * 4) / 5); - for (let x = Math.floor(width / 5); x < right; x++) { - const pixel = localLuminances[x] & 0xff; - localBuckets[pixel >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++; - } + if (width < 3) { + // Special case for very small images + for (let x = 0; x < width; x++) { + if ((localLuminances[x] & 0xff) < blackPoint) { + row.set(x); } - const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets); - - // We delay reading the entire image luminance until the black point estimation succeeds. - // Although we end up reading four rows twice, it is consistent with our motto of - // "fail quickly" which is necessary for continuous scanning. - const localLuminances = source.getMatrix(); - for (let y = 0; y < height; y++) { - const offset = y * width; - for (let x = 0; x < width; x++) { - const pixel = localLuminances[offset + x] & 0xff; - if (pixel < blackPoint) { - matrix.set(x, y); - } - } + } + } else { + let left = localLuminances[0] & 0xff; + let center = localLuminances[1] & 0xff; + for (let x = 1; x < width - 1; x++) { + const right = localLuminances[x + 1] & 0xff; + // A simple -1 4 -1 box filter with a weight of 2. + if (((center * 4) - left - right) / 2 < blackPoint) { + row.set(x); } - - return matrix; + left = center; + center = right; + } } - - /*@Override*/ - public createBinarizer(source: LuminanceSource): Binarizer { - return new GlobalHistogramBinarizer(source); + return row; + } + + // Does not sharpen the data, as this call is intended to only be used by 2D Readers. + /* @Override */ + public getBlackMatrix(): BitMatrix /* throws NotFoundException */ { + const source = this.getLuminanceSource(); + const width = source.getWidth(); + const height = source.getHeight(); + const matrix = new BitMatrix(width, height); + + // Quickly calculates the histogram by sampling four rows from the image. This proved to be + // more robust on the blackbox tests than sampling a diagonal as we used to do. + this.initArrays(width); + const localBuckets = this.buckets; + for (let y = 1; y < 5; y++) { + const row = Math.floor((height * y) / 5); + const localLuminances = source.getRow(row, this.luminances); + const right = Math.floor((width * 4) / 5); + for (let x = Math.floor(width / 5); x < right; x++) { + const pixel = localLuminances[x] & 0xff; + localBuckets[pixel >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++; + } } - - private initArrays(luminanceSize: number /*int*/): void { - if (this.luminances.length < luminanceSize) { - this.luminances = new Uint8ClampedArray(luminanceSize); - } - const buckets = this.buckets; - for (let x = 0; x < GlobalHistogramBinarizer.LUMINANCE_BUCKETS; x++) { - buckets[x] = 0; + const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets); + + // We delay reading the entire image luminance until the black point estimation succeeds. + // Although we end up reading four rows twice, it is consistent with our motto of + // "fail quickly" which is necessary for continuous scanning. + const localLuminances = source.getMatrix(); + for (let y = 0; y < height; y++) { + const offset = y * width; + for (let x = 0; x < width; x++) { + const pixel = localLuminances[offset + x] & 0xff; + if (pixel < blackPoint) { + matrix.set(x, y); } + } } - private static estimateBlackPoint(buckets: Int32Array): number /*int*/ /*throws NotFoundException*/ { - // Find the tallest peak in the histogram. - const numBuckets = buckets.length; - let maxBucketCount = 0; - let firstPeak = 0; - let firstPeakSize = 0; - for (let x = 0; x < numBuckets; x++) { - if (buckets[x] > firstPeakSize) { - firstPeak = x; - firstPeakSize = buckets[x]; - } - if (buckets[x] > maxBucketCount) { - maxBucketCount = buckets[x]; - } - } + return matrix; + } - // Find the second-tallest peak which is somewhat far from the tallest peak. - let secondPeak = 0; - let secondPeakScore = 0; - - for (let x = 0; x < numBuckets; x++) { - const distanceToBiggest = x - firstPeak; - // Encourage more distant second peaks by multiplying by square of distance. - const score = buckets[x] * distanceToBiggest * distanceToBiggest; - if (score > secondPeakScore) { - secondPeak = x; - secondPeakScore = score; - } - } + /* @Override */ + public createBinarizer(source: LuminanceSource): Binarizer { + return new GlobalHistogramBinarizer(source); + } - // Make sure firstPeak corresponds to the black peak. - if (firstPeak > secondPeak) { - const temp = firstPeak; - firstPeak = secondPeak; - secondPeak = temp; - } + private initArrays(luminanceSize: number /* int */): void { + if (this.luminances.length < luminanceSize) { + this.luminances = new Uint8ClampedArray(luminanceSize); + } + const buckets = this.buckets; + for (let x = 0; x < GlobalHistogramBinarizer.LUMINANCE_BUCKETS; x++) { + buckets[x] = 0; + } + } + + private static estimateBlackPoint(buckets: Int32Array): number /* int */ /* throws NotFoundException */ { + // Find the tallest peak in the histogram. + const numBuckets = buckets.length; + let maxBucketCount = 0; + let firstPeak = 0; + let firstPeakSize = 0; + for (let x = 0; x < numBuckets; x++) { + if (buckets[x] > firstPeakSize) { + firstPeak = x; + firstPeakSize = buckets[x]; + } + if (buckets[x] > maxBucketCount) { + maxBucketCount = buckets[x]; + } + } - // If there is too little contrast in the image to pick a meaningful black point, throw rather - // than waste time trying to decode the image, and risk false positives. - if (secondPeak - firstPeak <= numBuckets / 16) { - throw new NotFoundException(); - } + // Find the second-tallest peak which is somewhat far from the tallest peak. + let secondPeak = 0; + let secondPeakScore = 0; + + for (let x = 0; x < numBuckets; x++) { + const distanceToBiggest = x - firstPeak; + // Encourage more distant second peaks by multiplying by square of distance. + const score = buckets[x] * distanceToBiggest * distanceToBiggest; + if (score > secondPeakScore) { + secondPeak = x; + secondPeakScore = score; + } + } - // Find a valley between them that is low and closer to the white peak. - let bestValley = secondPeak - 1; - let bestValleyScore = -1; - for (let x = secondPeak - 1; x > firstPeak; x--) { - const fromFirst = x - firstPeak; - const score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]); - if (score > bestValleyScore) { - bestValley = x; - bestValleyScore = score; - } - } + // Make sure firstPeak corresponds to the black peak. + if (firstPeak > secondPeak) { + const temp = firstPeak; + firstPeak = secondPeak; + secondPeak = temp; + } - return bestValley << GlobalHistogramBinarizer.LUMINANCE_SHIFT; + // If there is too little contrast in the image to pick a meaningful black point, throw rather + // than waste time trying to decode the image, and risk false positives. + if (secondPeak - firstPeak <= numBuckets / 16) { + throw new NotFoundException(); } + // Find a valley between them that is low and closer to the white peak. + let bestValley = secondPeak - 1; + let bestValleyScore = -1; + for (let x = secondPeak - 1; x > firstPeak; x--) { + const fromFirst = x - firstPeak; + const score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]); + if (score > bestValleyScore) { + bestValley = x; + bestValleyScore = score; + } + } + + return bestValley << GlobalHistogramBinarizer.LUMINANCE_SHIFT; + } + } diff --git a/src/core/common/GridSampler.ts b/src/core/common/GridSampler.ts index 7d9c7b1d..8304e5db 100644 --- a/src/core/common/GridSampler.ts +++ b/src/core/common/GridSampler.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ import BitMatrix from './BitMatrix'; import PerspectiveTransform from './PerspectiveTransform'; @@ -36,143 +36,143 @@ import NotFoundException from '../NotFoundException'; */ abstract class GridSampler { - /** - * Samples an image for a rectangular matrix of bits of the given dimension. The sampling - * transformation is determined by the coordinates of 4 points, in the original and transformed - * image space. - * - * @param image image to sample - * @param dimensionX width of {@link BitMatrix} to sample from image - * @param dimensionY height of {@link BitMatrix} to sample from image - * @param p1ToX point 1 preimage X - * @param p1ToY point 1 preimage Y - * @param p2ToX point 2 preimage X - * @param p2ToY point 2 preimage Y - * @param p3ToX point 3 preimage X - * @param p3ToY point 3 preimage Y - * @param p4ToX point 4 preimage X - * @param p4ToY point 4 preimage Y - * @param p1FromX point 1 image X - * @param p1FromY point 1 image Y - * @param p2FromX point 2 image X - * @param p2FromY point 2 image Y - * @param p3FromX point 3 image X - * @param p3FromY point 3 image Y - * @param p4FromX point 4 image X - * @param p4FromY point 4 image Y - * - * @return {@link BitMatrix} representing a grid of points sampled from the image within a region - * defined by the "from" parameters - * - * @throws NotFoundException if image can't be sampled, for example, if the transformation defined - * by the given points is invalid or results in sampling outside the image boundaries - */ - public abstract sampleGrid( - image: BitMatrix, - dimensionX: number /*int*/, - dimensionY: number /*int*/, - p1ToX: number/*float*/, p1ToY: number/*float*/, - p2ToX: number/*float*/, p2ToY: number/*float*/, - p3ToX: number/*float*/, p3ToY: number/*float*/, - p4ToX: number/*float*/, p4ToY: number/*float*/, - p1FromX: number/*float*/, p1FromY: number/*float*/, - p2FromX: number/*float*/, p2FromY: number/*float*/, - p3FromX: number/*float*/, p3FromY: number/*float*/, - p4FromX: number/*float*/, p4FromY: number/*float*/ - ): BitMatrix; /*throws NotFoundException*/ - - public abstract sampleGridWithTransform( - image: BitMatrix, - dimensionX: number /*int*/, - dimensionY: number /*int*/, - transform: PerspectiveTransform - ): BitMatrix; /*throws NotFoundException*/ - - /** - *

Checks a set of points that have been transformed to sample points on an image against - * the image's dimensions to see if the point are even within the image.

- * - *

This method will actually "nudge" the endpoints back onto the image if they are found to be - * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder - * patterns in an image where the QR Code runs all the way to the image border.

- * - *

For efficiency, the method will check points from either end of the line until one is found - * to be within the image. Because the set of points are assumed to be linear, this is valid.

- * - * @param image image into which the points should map - * @param points actual points in x1,y1,...,xn,yn form - * @throws NotFoundException if an endpoint is lies outside the image boundaries - */ - protected static checkAndNudgePoints( - image: BitMatrix, - points: Float32Array - ): void /*throws NotFoundException*/ { - - const width: number /*int*/ = image.getWidth(); - const height: number /*int*/ = image.getHeight(); - - // Check and nudge points from start until we see some that are OK: - let nudged: boolean = true; - - for (let offset = 0; offset < points.length && nudged; offset += 2) { - - const x = Math.floor(points[offset]); - const y = Math.floor(points[offset + 1]); - - if (x < -1 || x > width || y < -1 || y > height) { - throw new NotFoundException(); - } - - nudged = false; - - if (x === -1) { - points[offset] = 0.0; - nudged = true; - } else if (x === width) { - points[offset] = width - 1; - nudged = true; - } - - if (y === -1) { - points[offset + 1] = 0.0; - nudged = true; - } else if (y === height) { - points[offset + 1] = height - 1; - nudged = true; - } - } - - // Check and nudge points from end: + /** + * Samples an image for a rectangular matrix of bits of the given dimension. The sampling + * transformation is determined by the coordinates of 4 points, in the original and transformed + * image space. + * + * @param image image to sample + * @param dimensionX width of {@link BitMatrix} to sample from image + * @param dimensionY height of {@link BitMatrix} to sample from image + * @param p1ToX point 1 preimage X + * @param p1ToY point 1 preimage Y + * @param p2ToX point 2 preimage X + * @param p2ToY point 2 preimage Y + * @param p3ToX point 3 preimage X + * @param p3ToY point 3 preimage Y + * @param p4ToX point 4 preimage X + * @param p4ToY point 4 preimage Y + * @param p1FromX point 1 image X + * @param p1FromY point 1 image Y + * @param p2FromX point 2 image X + * @param p2FromY point 2 image Y + * @param p3FromX point 3 image X + * @param p3FromY point 3 image Y + * @param p4FromX point 4 image X + * @param p4FromY point 4 image Y + * + * @return {@link BitMatrix} representing a grid of points sampled from the image within a region + * defined by the "from" parameters + * + * @throws NotFoundException if image can't be sampled, for example, if the transformation defined + * by the given points is invalid or results in sampling outside the image boundaries + */ + public abstract sampleGrid( + image: BitMatrix, + dimensionX: number /* int */, + dimensionY: number /* int */, + p1ToX: number/* float */, p1ToY: number/* float */, + p2ToX: number/* float */, p2ToY: number/* float */, + p3ToX: number/* float */, p3ToY: number/* float */, + p4ToX: number/* float */, p4ToY: number/* float */, + p1FromX: number/* float */, p1FromY: number/* float */, + p2FromX: number/* float */, p2FromY: number/* float */, + p3FromX: number/* float */, p3FromY: number/* float */, + p4FromX: number/* float */, p4FromY: number/* float */ + ): BitMatrix; /* throws NotFoundException */ + + public abstract sampleGridWithTransform( + image: BitMatrix, + dimensionX: number /* int */, + dimensionY: number /* int */, + transform: PerspectiveTransform + ): BitMatrix; /* throws NotFoundException */ + + /** + *

Checks a set of points that have been transformed to sample points on an image against + * the image's dimensions to see if the point are even within the image.

+ * + *

This method will actually "nudge" the endpoints back onto the image if they are found to be + * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder + * patterns in an image where the QR Code runs all the way to the image border.

+ * + *

For efficiency, the method will check points from either end of the line until one is found + * to be within the image. Because the set of points are assumed to be linear, this is valid.

+ * + * @param image image into which the points should map + * @param points actual points in x1,y1,...,xn,yn form + * @throws NotFoundException if an endpoint is lies outside the image boundaries + */ + protected static checkAndNudgePoints( + image: BitMatrix, + points: Float32Array + ): void /* throws NotFoundException */ { + + const width: number /* int */ = image.getWidth(); + const height: number /* int */ = image.getHeight(); + + // Check and nudge points from start until we see some that are OK: + let nudged: boolean = true; + + for (let offset = 0; offset < points.length && nudged; offset += 2) { + + const x = Math.floor(points[offset]); + const y = Math.floor(points[offset + 1]); + + if (x < -1 || x > width || y < -1 || y > height) { + throw new NotFoundException(); + } + + nudged = false; + + if (x === -1) { + points[offset] = 0.0; + nudged = true; + } else if (x === width) { + points[offset] = width - 1; + nudged = true; + } + + if (y === -1) { + points[offset + 1] = 0.0; nudged = true; + } else if (y === height) { + points[offset + 1] = height - 1; + nudged = true; + } + } + + // Check and nudge points from end: + nudged = true; + + for (let offset = points.length - 2; offset >= 0 && nudged; offset -= 2) { + + const x = Math.floor(points[offset]); + const y = Math.floor(points[offset + 1]); + + if (x < -1 || x > width || y < -1 || y > height) { + throw new NotFoundException(); + } - for (let offset = points.length - 2; offset >= 0 && nudged; offset -= 2) { - - const x = Math.floor(points[offset]); - const y = Math.floor(points[offset + 1]); - - if (x < -1 || x > width || y < -1 || y > height) { - throw new NotFoundException(); - } - - nudged = false; - - if (x === -1) { - points[offset] = 0.0; - nudged = true; - } else if (x === width) { - points[offset] = width - 1; - nudged = true; - } - - if (y === -1) { - points[offset + 1] = 0.0; - nudged = true; - } else if (y === height) { - points[offset + 1] = height - 1; - nudged = true; - } - } + nudged = false; + + if (x === -1) { + points[offset] = 0.0; + nudged = true; + } else if (x === width) { + points[offset] = width - 1; + nudged = true; + } + + if (y === -1) { + points[offset + 1] = 0.0; + nudged = true; + } else if (y === height) { + points[offset + 1] = height - 1; + nudged = true; + } } + } } diff --git a/src/core/common/GridSamplerInstance.ts b/src/core/common/GridSamplerInstance.ts index 288afd46..fba54aaa 100644 --- a/src/core/common/GridSamplerInstance.ts +++ b/src/core/common/GridSamplerInstance.ts @@ -3,26 +3,26 @@ import DefaultGridSampler from './DefaultGridSampler'; export default class GridSamplerInstance { - private static gridSampler: GridSampler = new DefaultGridSampler(); + private static gridSampler: GridSampler = new DefaultGridSampler(); - /** - * Sets the implementation of GridSampler used by the library. One global - * instance is stored, which may sound problematic. But, the implementation provided - * ought to be appropriate for the entire platform, and all uses of this library - * in the whole lifetime of the JVM. For instance, an Android activity can swap in - * an implementation that takes advantage of native platform libraries. - * - * @param newGridSampler The platform-specific object to install. - */ - public static setGridSampler(newGridSampler: GridSampler): void { - GridSamplerInstance.gridSampler = newGridSampler; - } + /** + * Sets the implementation of GridSampler used by the library. One global + * instance is stored, which may sound problematic. But, the implementation provided + * ought to be appropriate for the entire platform, and all uses of this library + * in the whole lifetime of the JVM. For instance, an Android activity can swap in + * an implementation that takes advantage of native platform libraries. + * + * @param newGridSampler The platform-specific object to install. + */ + public static setGridSampler(newGridSampler: GridSampler): void { + GridSamplerInstance.gridSampler = newGridSampler; + } - /** - * @return the current implementation of GridSampler - */ - public static getInstance(): GridSampler { - return GridSamplerInstance.gridSampler; - } + /** + * @return the current implementation of GridSampler + */ + public static getInstance(): GridSampler { + return GridSamplerInstance.gridSampler; + } } diff --git a/src/core/common/HybridBinarizer.ts b/src/core/common/HybridBinarizer.ts index 11688a3e..ccfd88d9 100644 --- a/src/core/common/HybridBinarizer.ts +++ b/src/core/common/HybridBinarizer.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ import Binarizer from '../Binarizer'; import LuminanceSource from '../LuminanceSource'; @@ -40,202 +40,202 @@ import BitMatrix from './BitMatrix'; */ export default class HybridBinarizer extends GlobalHistogramBinarizer { - // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels. - // So this is the smallest dimension in each axis we can accept. - private static BLOCK_SIZE_POWER = 3; - private static BLOCK_SIZE = 1 << HybridBinarizer.BLOCK_SIZE_POWER; // ...0100...00 - private static BLOCK_SIZE_MASK = HybridBinarizer.BLOCK_SIZE - 1; // ...0011...11 - private static MINIMUM_DIMENSION = HybridBinarizer.BLOCK_SIZE * 5; - private static MIN_DYNAMIC_RANGE = 24; + // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels. + // So this is the smallest dimension in each axis we can accept. + private static BLOCK_SIZE_POWER = 3; + private static BLOCK_SIZE = 1 << HybridBinarizer.BLOCK_SIZE_POWER; // ...0100...00 + private static BLOCK_SIZE_MASK = HybridBinarizer.BLOCK_SIZE - 1; // ...0011...11 + private static MINIMUM_DIMENSION = HybridBinarizer.BLOCK_SIZE * 5; + private static MIN_DYNAMIC_RANGE = 24; - private matrix: BitMatrix | null = null; + private matrix: BitMatrix | null = null; - public constructor(source: LuminanceSource) { - super(source); - } + public constructor(source: LuminanceSource) { + super(source); + } - /** - * Calculates the final BitMatrix once for all requests. This could be called once from the - * constructor instead, but there are some advantages to doing it lazily, such as making - * profiling easier, and not doing heavy lifting when callers don't expect it. - */ - /*@Override*/ - public getBlackMatrix(): BitMatrix /*throws NotFoundException*/ { - if (this.matrix !== null) { - return this.matrix; + /** + * Calculates the final BitMatrix once for all requests. This could be called once from the + * constructor instead, but there are some advantages to doing it lazily, such as making + * profiling easier, and not doing heavy lifting when callers don't expect it. + */ + /* @Override */ + public getBlackMatrix(): BitMatrix /* throws NotFoundException */ { + if (this.matrix !== null) { + return this.matrix; + } + const source = this.getLuminanceSource(); + const width = source.getWidth(); + const height = source.getHeight(); + if (width >= HybridBinarizer.MINIMUM_DIMENSION && height >= HybridBinarizer.MINIMUM_DIMENSION) { + const luminances = source.getMatrix(); + let subWidth = width >> HybridBinarizer.BLOCK_SIZE_POWER; + if ((width & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) { + subWidth++; + } + let subHeight = height >> HybridBinarizer.BLOCK_SIZE_POWER; + if ((height & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) { + subHeight++; + } + const blackPoints = HybridBinarizer.calculateBlackPoints(luminances, subWidth, subHeight, width, height); + + const newMatrix = new BitMatrix(width, height); + HybridBinarizer.calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix); + this.matrix = newMatrix; + } else { + // If the image is too small, fall back to the global histogram approach. + this.matrix = super.getBlackMatrix(); + } + return this.matrix; + } + + /* @Override */ + public createBinarizer(source: LuminanceSource): Binarizer { + return new HybridBinarizer(source); + } + + /** + * For each block in the image, calculate the average black point using a 5x5 grid + * of the blocks around it. Also handles the corner cases (fractional blocks are computed based + * on the last pixels in the row/column which are also used in the previous block). + */ + private static calculateThresholdForBlock(luminances: Uint8ClampedArray, + subWidth: number /* int */, + subHeight: number /* int */, + width: number /* int */, + height: number /* int */, + blackPoints: Int32Array[], + matrix: BitMatrix): void { + const maxYOffset = height - HybridBinarizer.BLOCK_SIZE; + const maxXOffset = width - HybridBinarizer.BLOCK_SIZE; + for (let y = 0; y < subHeight; y++) { + let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER; + if (yoffset > maxYOffset) { + yoffset = maxYOffset; + } + const top = HybridBinarizer.cap(y, 2, subHeight - 3); + for (let x = 0; x < subWidth; x++) { + let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER; + if (xoffset > maxXOffset) { + xoffset = maxXOffset; } - const source = this.getLuminanceSource(); - const width = source.getWidth(); - const height = source.getHeight(); - if (width >= HybridBinarizer.MINIMUM_DIMENSION && height >= HybridBinarizer.MINIMUM_DIMENSION) { - const luminances = source.getMatrix(); - let subWidth = width >> HybridBinarizer.BLOCK_SIZE_POWER; - if ((width & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) { - subWidth++; - } - let subHeight = height >> HybridBinarizer.BLOCK_SIZE_POWER; - if ((height & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) { - subHeight++; - } - const blackPoints = HybridBinarizer.calculateBlackPoints(luminances, subWidth, subHeight, width, height); - - const newMatrix = new BitMatrix(width, height); - HybridBinarizer.calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix); - this.matrix = newMatrix; - } else { - // If the image is too small, fall back to the global histogram approach. - this.matrix = super.getBlackMatrix(); + const left = HybridBinarizer.cap(x, 2, subWidth - 3); + let sum = 0; + for (let z = -2; z <= 2; z++) { + const blackRow = blackPoints[top + z]; + sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2]; } - return this.matrix; + const average = sum / 25; + HybridBinarizer.thresholdBlock(luminances, xoffset, yoffset, average, width, matrix); + } } + } - /*@Override*/ - public createBinarizer(source: LuminanceSource): Binarizer { - return new HybridBinarizer(source); - } + private static cap(value: number /* int */, min: number /* int */, max: number /* int */): number /* int */ { + return value < min ? min : value > max ? max : value; + } - /** - * For each block in the image, calculate the average black point using a 5x5 grid - * of the blocks around it. Also handles the corner cases (fractional blocks are computed based - * on the last pixels in the row/column which are also used in the previous block). - */ - private static calculateThresholdForBlock(luminances: Uint8ClampedArray, - subWidth: number /*int*/, - subHeight: number /*int*/, - width: number /*int*/, - height: number /*int*/, - blackPoints: Int32Array[], - matrix: BitMatrix): void { - const maxYOffset = height - HybridBinarizer.BLOCK_SIZE; - const maxXOffset = width - HybridBinarizer.BLOCK_SIZE; - for (let y = 0; y < subHeight; y++) { - let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER; - if (yoffset > maxYOffset) { - yoffset = maxYOffset; - } - const top = HybridBinarizer.cap(y, 2, subHeight - 3); - for (let x = 0; x < subWidth; x++) { - let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER; - if (xoffset > maxXOffset) { - xoffset = maxXOffset; - } - const left = HybridBinarizer.cap(x, 2, subWidth - 3); - let sum = 0; - for (let z = -2; z <= 2; z++) { - const blackRow = blackPoints[top + z]; - sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2]; - } - const average = sum / 25; - HybridBinarizer.thresholdBlock(luminances, xoffset, yoffset, average, width, matrix); - } + /** + * Applies a single threshold to a block of pixels. + */ + private static thresholdBlock(luminances: Uint8ClampedArray, + xoffset: number /* int */, + yoffset: number /* int */, + threshold: number /* int */, + stride: number /* int */, + matrix: BitMatrix): void { + for (let y = 0, offset = yoffset * stride + xoffset; y < HybridBinarizer.BLOCK_SIZE; y++, offset += stride) { + for (let x = 0; x < HybridBinarizer.BLOCK_SIZE; x++) { + // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0. + if ((luminances[offset + x] & 0xFF) <= threshold) { + matrix.set(xoffset + x, yoffset + y); } + } } + } - private static cap(value: number /*int*/, min: number /*int*/, max: number /*int*/): number /*int*/ { - return value < min ? min : value > max ? max : value; - } - - /** - * Applies a single threshold to a block of pixels. - */ - private static thresholdBlock(luminances: Uint8ClampedArray, - xoffset: number /*int*/, - yoffset: number /*int*/, - threshold: number /*int*/, - stride: number /*int*/, - matrix: BitMatrix): void { - for (let y = 0, offset = yoffset * stride + xoffset; y < HybridBinarizer.BLOCK_SIZE; y++ , offset += stride) { - for (let x = 0; x < HybridBinarizer.BLOCK_SIZE; x++) { - // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0. - if ((luminances[offset + x] & 0xFF) <= threshold) { - matrix.set(xoffset + x, yoffset + y); - } + /** + * Calculates a single black point for each block of pixels and saves it away. + * See the following thread for a discussion of this algorithm: + * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 + */ + private static calculateBlackPoints(luminances: Uint8ClampedArray, + subWidth: number /* int */, + subHeight: number /* int */, + width: number /* int */, + height: number /* int */): Int32Array[] { + const maxYOffset = height - HybridBinarizer.BLOCK_SIZE; + const maxXOffset = width - HybridBinarizer.BLOCK_SIZE; + // tslint:disable-next-line:whitespace + const blackPoints = new Array(subHeight);// subWidth + + for (let y = 0; y < subHeight; y++) { + blackPoints[y] = new Int32Array(subWidth); + let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER; + if (yoffset > maxYOffset) { + yoffset = maxYOffset; + } + for (let x = 0; x < subWidth; x++) { + let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER; + if (xoffset > maxXOffset) { + xoffset = maxXOffset; + } + let sum = 0; + let min = 0xFF; + let max = 0; + for (let yy = 0, offset = yoffset * width + xoffset; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) { + for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) { + const pixel = luminances[offset + xx] & 0xFF; + sum += pixel; + // still looking for good contrast + if (pixel < min) { + min = pixel; } + if (pixel > max) { + max = pixel; + } + } + // short-circuit min/max tests once dynamic range is met + if (max - min > HybridBinarizer.MIN_DYNAMIC_RANGE) { + // finish the rest of the rows quickly + for (yy++, offset += width; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) { + for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) { + sum += luminances[offset + xx] & 0xFF; + } + } + } } - } - /** - * Calculates a single black point for each block of pixels and saves it away. - * See the following thread for a discussion of this algorithm: - * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 - */ - private static calculateBlackPoints(luminances: Uint8ClampedArray, - subWidth: number /*int*/, - subHeight: number /*int*/, - width: number /*int*/, - height: number /*int*/): Int32Array[] { - const maxYOffset = height - HybridBinarizer.BLOCK_SIZE; - const maxXOffset = width - HybridBinarizer.BLOCK_SIZE; - // tslint:disable-next-line:whitespace - const blackPoints = new Array(subHeight);// subWidth - - for (let y = 0; y < subHeight; y++) { - blackPoints[y] = new Int32Array(subWidth); - let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER; - if (yoffset > maxYOffset) { - yoffset = maxYOffset; - } - for (let x = 0; x < subWidth; x++) { - let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER; - if (xoffset > maxXOffset) { - xoffset = maxXOffset; - } - let sum = 0; - let min = 0xFF; - let max = 0; - for (let yy = 0, offset = yoffset * width + xoffset; yy < HybridBinarizer.BLOCK_SIZE; yy++ , offset += width) { - for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) { - const pixel = luminances[offset + xx] & 0xFF; - sum += pixel; - // still looking for good contrast - if (pixel < min) { - min = pixel; - } - if (pixel > max) { - max = pixel; - } - } - // short-circuit min/max tests once dynamic range is met - if (max - min > HybridBinarizer.MIN_DYNAMIC_RANGE) { - // finish the rest of the rows quickly - for (yy++ , offset += width; yy < HybridBinarizer.BLOCK_SIZE; yy++ , offset += width) { - for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) { - sum += luminances[offset + xx] & 0xFF; - } - } - } - } - - // The default estimate is the average of the values in the block. - let average = sum >> (HybridBinarizer.BLOCK_SIZE_POWER * 2); - if (max - min <= HybridBinarizer.MIN_DYNAMIC_RANGE) { - // If variation within the block is low, assume this is a block with only light or only - // dark pixels. In that case we do not want to use the average, as it would divide this - // low contrast area into black and white pixels, essentially creating data out of noise. - // - // The default assumption is that the block is light/background. Since no estimate for - // the level of dark pixels exists locally, use half the min for the block. - average = min / 2; - - if (y > 0 && x > 0) { - // Correct the "white background" assumption for blocks that have neighbors by comparing - // the pixels in this block to the previously calculated black points. This is based on - // the fact that dark barcode symbology is always surrounded by some amount of light - // background for which reasonable black point estimates were made. The bp estimated at - // the boundaries is used for the interior. - - // The (min < bp) is arbitrary but works better than other heuristics that were tried. - const averageNeighborBlackPoint = - (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4; - if (min < averageNeighborBlackPoint) { - average = averageNeighborBlackPoint; - } - } - } - blackPoints[y][x] = average; + // The default estimate is the average of the values in the block. + let average = sum >> (HybridBinarizer.BLOCK_SIZE_POWER * 2); + if (max - min <= HybridBinarizer.MIN_DYNAMIC_RANGE) { + // If variation within the block is low, assume this is a block with only light or only + // dark pixels. In that case we do not want to use the average, as it would divide this + // low contrast area into black and white pixels, essentially creating data out of noise. + // + // The default assumption is that the block is light/background. Since no estimate for + // the level of dark pixels exists locally, use half the min for the block. + average = min / 2; + + if (y > 0 && x > 0) { + // Correct the "white background" assumption for blocks that have neighbors by comparing + // the pixels in this block to the previously calculated black points. This is based on + // the fact that dark barcode symbology is always surrounded by some amount of light + // background for which reasonable black point estimates were made. The bp estimated at + // the boundaries is used for the interior. + + // The (min < bp) is arbitrary but works better than other heuristics that were tried. + const averageNeighborBlackPoint = + (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4; + if (min < averageNeighborBlackPoint) { + average = averageNeighborBlackPoint; } + } } - return blackPoints; + blackPoints[y][x] = average; + } } + return blackPoints; + } } diff --git a/src/core/common/PerspectiveTransform.ts b/src/core/common/PerspectiveTransform.ts index 8f110e61..1ed3a641 100644 --- a/src/core/common/PerspectiveTransform.ts +++ b/src/core/common/PerspectiveTransform.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ /** *

This class implements a perspective transform in two dimensions. Given four source and four @@ -25,145 +25,145 @@ */ export default class PerspectiveTransform { - private constructor(private a11: number/*float*/, private a21: number/*float*/, private a31: number/*float*/, - private a12: number/*float*/, private a22: number/*float*/, private a32: number/*float*/, - private a13: number/*float*/, private a23: number/*float*/, private a33: number/*float*/) { } - - public static quadrilateralToQuadrilateral( - x0: number/*float*/, y0: number/*float*/, - x1: number/*float*/, y1: number/*float*/, - x2: number/*float*/, y2: number/*float*/, - x3: number/*float*/, y3: number/*float*/, - x0p: number/*float*/, y0p: number/*float*/, - x1p: number/*float*/, y1p: number/*float*/, - x2p: number/*float*/, y2p: number/*float*/, - x3p: number/*float*/, y3p: number/*float*/ - ): PerspectiveTransform { - - const qToS = PerspectiveTransform.quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3); - const sToQ = PerspectiveTransform.squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); - - return sToQ.times(qToS); + private constructor(private a11: number/* float */, private a21: number/* float */, private a31: number/* float */, + private a12: number/* float */, private a22: number/* float */, private a32: number/* float */, + private a13: number/* float */, private a23: number/* float */, private a33: number/* float */) { } + + public static quadrilateralToQuadrilateral( + x0: number/* float */, y0: number/* float */, + x1: number/* float */, y1: number/* float */, + x2: number/* float */, y2: number/* float */, + x3: number/* float */, y3: number/* float */, + x0p: number/* float */, y0p: number/* float */, + x1p: number/* float */, y1p: number/* float */, + x2p: number/* float */, y2p: number/* float */, + x3p: number/* float */, y3p: number/* float */ + ): PerspectiveTransform { + + const qToS = PerspectiveTransform.quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3); + const sToQ = PerspectiveTransform.squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); + + return sToQ.times(qToS); + } + + public transformPoints(points: Float32Array): void { + + const max = points.length; + + const a11 = this.a11; + const a12 = this.a12; + const a13 = this.a13; + const a21 = this.a21; + const a22 = this.a22; + const a23 = this.a23; + const a31 = this.a31; + const a32 = this.a32; + const a33 = this.a33; + + for (let i = 0; i < max; i += 2) { + const x = points[i]; + const y = points[i + 1]; + const denominator = a13 * x + a23 * y + a33; + points[i] = (a11 * x + a21 * y + a31) / denominator; + points[i + 1] = (a12 * x + a22 * y + a32) / denominator; } + } - public transformPoints(points: Float32Array): void { - - const max = points.length; - - const a11 = this.a11; - const a12 = this.a12; - const a13 = this.a13; - const a21 = this.a21; - const a22 = this.a22; - const a23 = this.a23; - const a31 = this.a31; - const a32 = this.a32; - const a33 = this.a33; - - for (let i = 0; i < max; i += 2) { - const x = points[i]; - const y = points[i + 1]; - const denominator = a13 * x + a23 * y + a33; - points[i] = (a11 * x + a21 * y + a31) / denominator; - points[i + 1] = (a12 * x + a22 * y + a32) / denominator; - } - } - - public transformPointsWithValues(xValues: Float32Array, yValues: Float32Array): void { + public transformPointsWithValues(xValues: Float32Array, yValues: Float32Array): void { - const a11 = this.a11; - const a12 = this.a12; - const a13 = this.a13; - const a21 = this.a21; - const a22 = this.a22; - const a23 = this.a23; - const a31 = this.a31; - const a32 = this.a32; - const a33 = this.a33; + const a11 = this.a11; + const a12 = this.a12; + const a13 = this.a13; + const a21 = this.a21; + const a22 = this.a22; + const a23 = this.a23; + const a31 = this.a31; + const a32 = this.a32; + const a33 = this.a33; - const n = xValues.length; + const n = xValues.length; - for (let i = 0; i < n; i++) { - const x = xValues[i]; - const y = yValues[i]; - const denominator = a13 * x + a23 * y + a33; + for (let i = 0; i < n; i++) { + const x = xValues[i]; + const y = yValues[i]; + const denominator = a13 * x + a23 * y + a33; - xValues[i] = (a11 * x + a21 * y + a31) / denominator; - yValues[i] = (a12 * x + a22 * y + a32) / denominator; - } + xValues[i] = (a11 * x + a21 * y + a31) / denominator; + yValues[i] = (a12 * x + a22 * y + a32) / denominator; } - - public static squareToQuadrilateral( - x0: number/*float*/, y0: number/*float*/, - x1: number/*float*/, y1: number/*float*/, - x2: number/*float*/, y2: number/*float*/, - x3: number/*float*/, y3: number/*float*/ - ): PerspectiveTransform { - - const dx3 = x0 - x1 + x2 - x3; - const dy3 = y0 - y1 + y2 - y3; - - if (dx3 === 0.0 && dy3 === 0.0) { - // Affine - return new PerspectiveTransform(x1 - x0, x2 - x1, x0, - y1 - y0, y2 - y1, y0, - 0.0, 0.0, 1.0); - } else { - const dx1 = x1 - x2; - const dx2 = x3 - x2; - const dy1 = y1 - y2; - const dy2 = y3 - y2; - - const denominator = dx1 * dy2 - dx2 * dy1; - - const a13 = (dx3 * dy2 - dx2 * dy3) / denominator; - const a23 = (dx1 * dy3 - dx3 * dy1) / denominator; - - return new PerspectiveTransform( - x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, - y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, - a13, a23, 1.0 - ); - } - } - - public static quadrilateralToSquare( - x0: number/*float*/, y0: number/*float*/, - x1: number/*float*/, y1: number/*float*/, - x2: number/*float*/, y2: number/*float*/, - x3: number/*float*/, y3: number/*float*/ - ): PerspectiveTransform { - // Here, the adjoint serves as the inverse: - return PerspectiveTransform.squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint(); - } - - protected buildAdjoint(): PerspectiveTransform { - // Adjoint is the transpose of the cofactor matrix: - return new PerspectiveTransform( - this.a22 * this.a33 - this.a23 * this.a32, - this.a23 * this.a31 - this.a21 * this.a33, - this.a21 * this.a32 - this.a22 * this.a31, - this.a13 * this.a32 - this.a12 * this.a33, - this.a11 * this.a33 - this.a13 * this.a31, - this.a12 * this.a31 - this.a11 * this.a32, - this.a12 * this.a23 - this.a13 * this.a22, - this.a13 * this.a21 - this.a11 * this.a23, - this.a11 * this.a22 - this.a12 * this.a21 - ); - } - - protected times(other: PerspectiveTransform): PerspectiveTransform { - return new PerspectiveTransform( - this.a11 * other.a11 + this.a21 * other.a12 + this.a31 * other.a13, - this.a11 * other.a21 + this.a21 * other.a22 + this.a31 * other.a23, - this.a11 * other.a31 + this.a21 * other.a32 + this.a31 * other.a33, - this.a12 * other.a11 + this.a22 * other.a12 + this.a32 * other.a13, - this.a12 * other.a21 + this.a22 * other.a22 + this.a32 * other.a23, - this.a12 * other.a31 + this.a22 * other.a32 + this.a32 * other.a33, - this.a13 * other.a11 + this.a23 * other.a12 + this.a33 * other.a13, - this.a13 * other.a21 + this.a23 * other.a22 + this.a33 * other.a23, - this.a13 * other.a31 + this.a23 * other.a32 + this.a33 * other.a33 - ); + } + + public static squareToQuadrilateral( + x0: number/* float */, y0: number/* float */, + x1: number/* float */, y1: number/* float */, + x2: number/* float */, y2: number/* float */, + x3: number/* float */, y3: number/* float */ + ): PerspectiveTransform { + + const dx3 = x0 - x1 + x2 - x3; + const dy3 = y0 - y1 + y2 - y3; + + if (dx3 === 0.0 && dy3 === 0.0) { + // Affine + return new PerspectiveTransform(x1 - x0, x2 - x1, x0, + y1 - y0, y2 - y1, y0, + 0.0, 0.0, 1.0); + } else { + const dx1 = x1 - x2; + const dx2 = x3 - x2; + const dy1 = y1 - y2; + const dy2 = y3 - y2; + + const denominator = dx1 * dy2 - dx2 * dy1; + + const a13 = (dx3 * dy2 - dx2 * dy3) / denominator; + const a23 = (dx1 * dy3 - dx3 * dy1) / denominator; + + return new PerspectiveTransform( + x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, + y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, + a13, a23, 1.0 + ); } + } + + public static quadrilateralToSquare( + x0: number/* float */, y0: number/* float */, + x1: number/* float */, y1: number/* float */, + x2: number/* float */, y2: number/* float */, + x3: number/* float */, y3: number/* float */ + ): PerspectiveTransform { + // Here, the adjoint serves as the inverse: + return PerspectiveTransform.squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint(); + } + + protected buildAdjoint(): PerspectiveTransform { + // Adjoint is the transpose of the cofactor matrix: + return new PerspectiveTransform( + this.a22 * this.a33 - this.a23 * this.a32, + this.a23 * this.a31 - this.a21 * this.a33, + this.a21 * this.a32 - this.a22 * this.a31, + this.a13 * this.a32 - this.a12 * this.a33, + this.a11 * this.a33 - this.a13 * this.a31, + this.a12 * this.a31 - this.a11 * this.a32, + this.a12 * this.a23 - this.a13 * this.a22, + this.a13 * this.a21 - this.a11 * this.a23, + this.a11 * this.a22 - this.a12 * this.a21 + ); + } + + protected times(other: PerspectiveTransform): PerspectiveTransform { + return new PerspectiveTransform( + this.a11 * other.a11 + this.a21 * other.a12 + this.a31 * other.a13, + this.a11 * other.a21 + this.a21 * other.a22 + this.a31 * other.a23, + this.a11 * other.a31 + this.a21 * other.a32 + this.a31 * other.a33, + this.a12 * other.a11 + this.a22 * other.a12 + this.a32 * other.a13, + this.a12 * other.a21 + this.a22 * other.a22 + this.a32 * other.a23, + this.a12 * other.a31 + this.a22 * other.a32 + this.a32 * other.a33, + this.a13 * other.a11 + this.a23 * other.a12 + this.a33 * other.a13, + this.a13 * other.a21 + this.a23 * other.a22 + this.a33 * other.a23, + this.a13 * other.a31 + this.a23 * other.a32 + this.a33 * other.a33 + ); + } } diff --git a/src/core/common/StringUtils.ts b/src/core/common/StringUtils.ts index 70bff9e5..40cb481b 100644 --- a/src/core/common/StringUtils.ts +++ b/src/core/common/StringUtils.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -/*namespace com.google.zxing.common {*/ +/* namespace com.google.zxing.common { */ -/*import java.nio.charset.Charset;*/ -/*import java.util.Map;*/ +/* import java.nio.charset.Charset; */ +/* import java.util.Map; */ import DecodeHintType from '../DecodeHintType'; import CharacterSetECI from './CharacterSetECI'; @@ -57,7 +57,7 @@ export default class StringUtils { * @return name of guessed encoding; at the moment will only guess one of: * {@link #SHIFT_JIS}, {@link #UTF8}, {@link #ISO88591}, or the platform * default encoding if none of these can possibly be correct - */ + */ public static guessEncoding(bytes: Uint8Array, hints: Map): string { if (hints !== null && hints !== undefined && undefined !== hints.get(DecodeHintType.CHARACTER_SET)) { return hints.get(DecodeHintType.CHARACTER_SET).toString(); @@ -86,9 +86,9 @@ export default class StringUtils { let isoHighOther = 0; const utf8bom = bytes.length > 3 && - bytes[0] === /*(byte) */0xEF && - bytes[1] === /*(byte) */0xBB && - bytes[2] === /*(byte) */0xBF; + bytes[0] === /* (byte) */0xEF && + bytes[1] === /* (byte) */0xBB && + bytes[2] === /* (byte) */0xBF; for (let i = 0; i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8); @@ -224,7 +224,7 @@ export default class StringUtils { * * @param append The new string to append. * @param args Argumets values to be formated. - */ + */ public static format(append: string, ...args: any[]) { let i = -1; @@ -265,21 +265,21 @@ export default class StringUtils { /** * - */ + */ public static getBytes(str: string, encoding: CharacterSetECI): Uint8Array { return StringEncoding.encode(str, encoding); } /** * Returns the charcode at the specified index or at index zero. - */ + */ public static getCharCode(str: string, index = 0): int { return str.charCodeAt(index); } /** * Returns char for given charcode - */ + */ public static getCharAt(charCode: number): string { return String.fromCharCode(charCode); } diff --git a/src/core/common/detector/CornerDetector.ts b/src/core/common/detector/CornerDetector.ts index b7e1da7b..9ca22a88 100644 --- a/src/core/common/detector/CornerDetector.ts +++ b/src/core/common/detector/CornerDetector.ts @@ -23,269 +23,269 @@ import NotFoundException from '../../NotFoundException'; */ export default class CornerDetector { - private image: BitMatrix; - private height: number; - private width: number; - private leftInit: number; - private rightInit: number; - private downInit: number; - private upInit: number; - private targetMatrixSize: number; - - - /** - * @throws NotFoundException if image is too small to accommodate {@code initSize} - */ - public constructor(image: BitMatrix, initSize: number, x: number, y: number, targetMatrixSize: number) { - this.image = image; - this.height = image.getHeight(); - this.width = image.getWidth(); - const halfsize = initSize / 2; - this.leftInit = x - halfsize; - this.rightInit = x + halfsize; - this.upInit = y - halfsize; - this.downInit = y + halfsize; - this.targetMatrixSize = targetMatrixSize * 2; - if (this.upInit < 0 || this.leftInit < 0 || this.downInit >= this.height || this.rightInit >= this.width) { - throw new NotFoundException(); - } + private image: BitMatrix; + private height: number; + private width: number; + private leftInit: number; + private rightInit: number; + private downInit: number; + private upInit: number; + private targetMatrixSize: number; + + + /** + * @throws NotFoundException if image is too small to accommodate {@code initSize} + */ + public constructor(image: BitMatrix, initSize: number, x: number, y: number, targetMatrixSize: number) { + this.image = image; + this.height = image.getHeight(); + this.width = image.getWidth(); + const halfsize = initSize / 2; + this.leftInit = x - halfsize; + this.rightInit = x + halfsize; + this.upInit = y - halfsize; + this.downInit = y + halfsize; + this.targetMatrixSize = targetMatrixSize * 2; + if (this.upInit < 0 || this.leftInit < 0 || this.downInit >= this.height || this.rightInit >= this.width) { + throw new NotFoundException(); } + } - /** - * @throws NotFoundException if no Data Matrix Code can be found - */ - public detect(): ResultPoint[] { - - let left = this.leftInit; - let right = this.rightInit; - let up = this.upInit; - let down = this.downInit; - let sizeExceeded = false; - let aBlackPointFoundOnBorder = true; - let atLeastOneBlackPointFoundOnBorder = false; - - let atLeastOneBlackPointFoundOnRight = false; - let atLeastOneBlackPointFoundOnBottom = false; - let atLeastOneBlackPointFoundOnLeft = false; - let atLeastOneBlackPointFoundOnTop = false; - - while (aBlackPointFoundOnBorder) { - - aBlackPointFoundOnBorder = false; - - // ..... - // . | - // ..... - let rightBorderNotWhite = true; - while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < this.width) { - rightBorderNotWhite = this.containsBlackPoint(up, down, right, false); - if (rightBorderNotWhite) { - right++; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnRight = true; - } else if (!atLeastOneBlackPointFoundOnRight) { - right++; - } - } - - if (right >= this.width) { - sizeExceeded = true; - break; - } - - // ..... - // . . - // .___. - let bottomBorderNotWhite = true; - while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < this.height) { - bottomBorderNotWhite = this.containsBlackPoint(left, right, down, true); - if (bottomBorderNotWhite) { - down++; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnBottom = true; - } else if (!atLeastOneBlackPointFoundOnBottom) { - down++; - } - } - - if (down >= this.height) { - sizeExceeded = true; - break; - } - - // ..... - // | . - // ..... - let leftBorderNotWhite = true; - while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) { - leftBorderNotWhite = this.containsBlackPoint(up, down, left, false); - if (leftBorderNotWhite) { - left--; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnLeft = true; - } else if (!atLeastOneBlackPointFoundOnLeft) { - left--; - } - } + /** + * @throws NotFoundException if no Data Matrix Code can be found + */ + public detect(): ResultPoint[] { + + let left = this.leftInit; + let right = this.rightInit; + let up = this.upInit; + let down = this.downInit; + let sizeExceeded = false; + let aBlackPointFoundOnBorder = true; + let atLeastOneBlackPointFoundOnBorder = false; + + let atLeastOneBlackPointFoundOnRight = false; + let atLeastOneBlackPointFoundOnBottom = false; + let atLeastOneBlackPointFoundOnLeft = false; + let atLeastOneBlackPointFoundOnTop = false; + + while (aBlackPointFoundOnBorder) { + + aBlackPointFoundOnBorder = false; + + // ..... + // . | + // ..... + let rightBorderNotWhite = true; + while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < this.width) { + rightBorderNotWhite = this.containsBlackPoint(up, down, right, false); + if (rightBorderNotWhite) { + right++; + aBlackPointFoundOnBorder = true; + atLeastOneBlackPointFoundOnRight = true; + } else if (!atLeastOneBlackPointFoundOnRight) { + right++; + } + } + + if (right >= this.width) { + sizeExceeded = true; + break; + } + + // ..... + // . . + // .___. + let bottomBorderNotWhite = true; + while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < this.height) { + bottomBorderNotWhite = this.containsBlackPoint(left, right, down, true); + if (bottomBorderNotWhite) { + down++; + aBlackPointFoundOnBorder = true; + atLeastOneBlackPointFoundOnBottom = true; + } else if (!atLeastOneBlackPointFoundOnBottom) { + down++; + } + } + + if (down >= this.height) { + sizeExceeded = true; + break; + } + + // ..... + // | . + // ..... + let leftBorderNotWhite = true; + while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) { + leftBorderNotWhite = this.containsBlackPoint(up, down, left, false); + if (leftBorderNotWhite) { + left--; + aBlackPointFoundOnBorder = true; + atLeastOneBlackPointFoundOnLeft = true; + } else if (!atLeastOneBlackPointFoundOnLeft) { + left--; + } + } + + if (left < 0) { + sizeExceeded = true; + break; + } + + // .___. + // . . + // ..... + let topBorderNotWhite = true; + while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) { + topBorderNotWhite = this.containsBlackPoint(left, right, up, true); + if (topBorderNotWhite) { + up--; + aBlackPointFoundOnBorder = true; + atLeastOneBlackPointFoundOnTop = true; + } else if (!atLeastOneBlackPointFoundOnTop) { + up--; + } + } - if (left < 0) { - sizeExceeded = true; - break; - } + if (up < 0) { + sizeExceeded = true; + break; + } - // .___. - // . . - // ..... - let topBorderNotWhite = true; - while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) { - topBorderNotWhite = this.containsBlackPoint(left, right, up, true); - if (topBorderNotWhite) { - up--; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnTop = true; - } else if (!atLeastOneBlackPointFoundOnTop) { - up--; - } - } + if (aBlackPointFoundOnBorder) { + atLeastOneBlackPointFoundOnBorder = true; + } + } - if (up < 0) { - sizeExceeded = true; - break; + if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) { + return this.findCorners(right, left, down, up); + } else { + throw new NotFoundException(); + } + } + + private findCorners(right: number, left: number, down: number, up: number): ResultPoint[] { + // + // A------------ ------------B + // | | up | | + // | -------|--------------|------- | + // | | | | | | + // | | | | | | + // ------------AP BP------------ + // | | + // | | + // left | | right + // | | + // | | + // ------------DP CP------------ + // | | | | | | + // | | | down | | | + // | -------|-------------|-------- | + // | | | | + // D-----------| |------------C + // + + + const width = right - left; + const height = down - up; + const sampler = 16 / this.targetMatrixSize; + const sampler2 = 4 / this.targetMatrixSize; + const deltaX = width * sampler2; + const deltaY = height * sampler2; + const areaWidth = deltaX + (right - left) * sampler; + const areaHeight = deltaY + (down - up) * sampler; + + const a = new ResultPoint(left - deltaX, up - deltaY); + const b = new ResultPoint(right + deltaX, up - deltaY); + const c = new ResultPoint(right + deltaX, down + deltaY); + const d = new ResultPoint(left - deltaX, down + deltaY); + + const ap = new ResultPoint(a.getX() + areaWidth, a.getY() + areaHeight); + const bp = new ResultPoint(b.getX() - areaWidth, b.getY() + areaHeight); + const cp = new ResultPoint(c.getX() - areaWidth, c.getY() - areaHeight); + const dp = new ResultPoint(d.getX() + areaWidth, d.getY() - areaHeight); + + const topLeftCorner = this.getCornerFromArea(a.getX(), ap.getX(), a.getY(), ap.getY(), false, false); + const topRightCorner = this.getCornerFromArea(bp.getX(), b.getX(), b.getY(), bp.getY(), true, false); + const bottomRightCorner = this.getCornerFromArea(cp.getX(), c.getX(), cp.getY(), c.getY(), true, true); + const bottomLeftCorner = this.getCornerFromArea(d.getX(), dp.getX(), dp.getY(), d.getY(), false, true); + + const xCorrection = (topRightCorner.getX() - topLeftCorner.getX()) / this.targetMatrixSize; + const yCorrection = (bottomRightCorner.getY() - topRightCorner.getY()) / this.targetMatrixSize; + + const topLeftCornerCenter = new ResultPoint(topLeftCorner.getX() + xCorrection, topLeftCorner.getY() + yCorrection); + const topRightCornerCenter = new ResultPoint(topRightCorner.getX() - xCorrection, topRightCorner.getY() + yCorrection); + const bottomRightCornerCenter = new ResultPoint(bottomRightCorner.getX() - xCorrection, bottomRightCorner.getY() - yCorrection); + const bottomLeftCornerCenter = new ResultPoint(bottomLeftCorner.getX() + xCorrection, bottomLeftCorner.getY() - yCorrection); + + const result: ResultPoint[] = [topLeftCornerCenter, topRightCornerCenter, bottomRightCornerCenter, bottomLeftCornerCenter]; + return result; + } + + private getCornerFromArea(left: number, right: number, top: number, bottom: number, maximizeX: boolean, maximizeY: boolean): ResultPoint { + let resX = maximizeX ? 0 : Number.MAX_VALUE; + let resY = maximizeY ? 0 : Number.MAX_VALUE; + for (let x = left; x < right; x++) { + for (let y = top; y < bottom; y++) { + if (x > 0 && y > 0 && x < this.image.getWidth() && y < this.image.getHeight()) { + if (this.image.get(x, y)) { + if (maximizeX) { + if (x > resX) { + resX = x; + } + } else { + if (x < resX) { + resX = x; + } } - - if (aBlackPointFoundOnBorder) { - atLeastOneBlackPointFoundOnBorder = true; + if (maximizeY) { + if (y > resY) { + resY = y; + } + } else { + if (y < resY) { + resY = y; + } } + } } - - if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) { - return this.findCorners(right, left, down, up); - } else { - throw new NotFoundException(); - } + } } - - private findCorners(right: number, left: number, down: number, up: number): ResultPoint[] { - // - // A------------ ------------B - // | | up | | - // | -------|--------------|------- | - // | | | | | | - // | | | | | | - // ------------AP BP------------ - // | | - // | | - // left | | right - // | | - // | | - // ------------DP CP------------ - // | | | | | | - // | | | down | | | - // | -------|-------------|-------- | - // | | | | - // D-----------| |------------C - // - - - const width = right - left; - const height = down - up; - const sampler = 16 / this.targetMatrixSize; - const sampler2 = 4 / this.targetMatrixSize; - const deltaX = width * sampler2; - const deltaY = height * sampler2; - const areaWidth = deltaX + (right - left) * sampler; - const areaHeight = deltaY + (down - up) * sampler; - - const a = new ResultPoint(left - deltaX, up - deltaY); - const b = new ResultPoint(right + deltaX, up - deltaY); - const c = new ResultPoint(right + deltaX, down + deltaY); - const d = new ResultPoint(left - deltaX, down + deltaY); - - const ap = new ResultPoint(a.getX() + areaWidth, a.getY() + areaHeight); - const bp = new ResultPoint(b.getX() - areaWidth, b.getY() + areaHeight); - const cp = new ResultPoint(c.getX() - areaWidth, c.getY() - areaHeight); - const dp = new ResultPoint(d.getX() + areaWidth, d.getY() - areaHeight); - - const topLeftCorner = this.getCornerFromArea(a.getX(), ap.getX(), a.getY(), ap.getY(), false, false); - const topRightCorner = this.getCornerFromArea(bp.getX(), b.getX(), b.getY(), bp.getY(), true, false); - const bottomRightCorner = this.getCornerFromArea(cp.getX(), c.getX(), cp.getY(), c.getY(), true, true); - const bottomLeftCorner = this.getCornerFromArea(d.getX(), dp.getX(), dp.getY(), d.getY(), false, true); - - const xCorrection = (topRightCorner.getX() - topLeftCorner.getX()) / this.targetMatrixSize; - const yCorrection = (bottomRightCorner.getY() - topRightCorner.getY()) / this.targetMatrixSize; - - const topLeftCornerCenter = new ResultPoint(topLeftCorner.getX() + xCorrection, topLeftCorner.getY() + yCorrection); - const topRightCornerCenter = new ResultPoint(topRightCorner.getX() - xCorrection, topRightCorner.getY() + yCorrection); - const bottomRightCornerCenter = new ResultPoint(bottomRightCorner.getX() - xCorrection, bottomRightCorner.getY() - yCorrection); - const bottomLeftCornerCenter = new ResultPoint(bottomLeftCorner.getX() + xCorrection, bottomLeftCorner.getY() - yCorrection); - - const result: ResultPoint[] = [topLeftCornerCenter, topRightCornerCenter, bottomRightCornerCenter, bottomLeftCornerCenter]; - return result; + if (resX === 0 || resY === 0) { + throw new NotFoundException(); + } else { + return new ResultPoint(resX, resY); } + } - private getCornerFromArea(left: number, right: number, top: number, bottom: number, maximizeX: boolean, maximizeY: boolean): ResultPoint { - let resX = maximizeX ? 0 : Number.MAX_VALUE; - let resY = maximizeY ? 0 : Number.MAX_VALUE; - for (let x = left; x < right; x++) { - for (let y = top; y < bottom; y++) { - if (x > 0 && y > 0 && x < this.image.getWidth() && y < this.image.getHeight()) { - if (this.image.get(x, y)) { - if (maximizeX) { - if (x > resX) { - resX = x; - } - } else { - if (x < resX) { - resX = x; - } - } - if (maximizeY) { - if (y > resY) { - resY = y; - } - } else { - if (y < resY) { - resY = y; - } - } - } - } - } - } - if (resX === 0 || resY === 0) { - throw new NotFoundException(); - } else { - return new ResultPoint(resX, resY); - } - } + /** + * Determines whether a segment contains a black point + * + * @param a min value of the scanned coordinate + * @param b max value of the scanned coordinate + * @param fixed value of fixed coordinate + * @param horizontal set to true if scan must be horizontal, false if vertical + * @return true if a black point has been found, else false. + */ + private containsBlackPoint(a: number, b: number, fixed: number, horizontal: boolean): boolean { - /** - * Determines whether a segment contains a black point - * - * @param a min value of the scanned coordinate - * @param b max value of the scanned coordinate - * @param fixed value of fixed coordinate - * @param horizontal set to true if scan must be horizontal, false if vertical - * @return true if a black point has been found, else false. - */ - private containsBlackPoint(a: number, b: number, fixed: number, horizontal: boolean): boolean { - - if (horizontal) { - for (let x = a; x <= b; x++) { - if (this.image.get(x, fixed)) { - return true; - } - } - } else { - for (let y = a; y <= b; y++) { - if (this.image.get(fixed, y)) { - return true; - } - } + if (horizontal) { + for (let x = a; x <= b; x++) { + if (this.image.get(x, fixed)) { + return true; } - - return false; + } + } else { + for (let y = a; y <= b; y++) { + if (this.image.get(fixed, y)) { + return true; + } + } } + return false; + } + } diff --git a/src/core/common/detector/MathUtils.ts b/src/core/common/detector/MathUtils.ts index bf167c13..ebd47451 100644 --- a/src/core/common/detector/MathUtils.ts +++ b/src/core/common/detector/MathUtils.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common.detector {*/ +/* namespace com.google.zxing.common.detector { */ /** * General math-related and numeric utility functions. @@ -31,12 +31,12 @@ export default class MathUtils { * * @param d real value to round * @return nearest {@code int} - */ - public static round(d: number/*float*/): number /*int*/ { + */ + public static round(d: number/* float */): number /* int */ { if (NaN === d) return 0; if (d <= Number.MIN_SAFE_INTEGER) return Number.MIN_SAFE_INTEGER; if (d >= Number.MAX_SAFE_INTEGER) return Number.MAX_SAFE_INTEGER; - return /*(int) */(d + (d < 0.0 ? -0.5 : 0.5)) | 0; + return /* (int) */(d + (d < 0.0 ? -0.5 : 0.5)) | 0; } // TYPESCRIPTPORT: maybe remove round method and call directly Math.round, it looks like it doesn't make sense for js @@ -46,11 +46,11 @@ export default class MathUtils { * @param bX point B x coordinate * @param bY point B y coordinate * @return Euclidean distance between points A and B - */ - public static distance(aX: number/*float|int*/, aY: number/*float|int*/, bX: number/*float|int*/, bY: number/*float|int*/): number/*float*/ { + */ + public static distance(aX: number/* float|int */, aY: number/* float|int */, bX: number/* float|int */, bY: number/* float|int */): number/* float */ { const xDiff = aX - bX; const yDiff = aY - bY; - return /*(float) */Math.sqrt(xDiff * xDiff + yDiff * yDiff); + return /* (float) */Math.sqrt(xDiff * xDiff + yDiff * yDiff); } /** @@ -59,8 +59,8 @@ export default class MathUtils { * @param bX point B x coordinate * @param bY point B y coordinate * @return Euclidean distance between points A and B - */ - // public static distance(aX: number /*int*/, aY: number /*int*/, bX: number /*int*/, bY: number /*int*/): float { + */ + // public static distance(aX: number /*int */, aY: number /*int */, bX: number /*int */, bY: number /*int */): float { // const xDiff = aX - bX // const yDiff = aY - bY // return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff); @@ -69,8 +69,8 @@ export default class MathUtils { /** * @param array values to sum * @return sum of values in array - */ - public static sum(array: Int32Array): number /*int*/ { + */ + public static sum(array: Int32Array): number /* int */ { let count = 0; for (let i = 0, length = array.length; i !== length; i++) { const a = array[i]; diff --git a/src/core/common/detector/MonochromeRectangleDetector.ts b/src/core/common/detector/MonochromeRectangleDetector.ts index c6d68e0b..0b87bb72 100644 --- a/src/core/common/detector/MonochromeRectangleDetector.ts +++ b/src/core/common/detector/MonochromeRectangleDetector.ts @@ -12,9 +12,9 @@ // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * See the License for the specific language governing permissions and // * limitations under the License. -// */ +// */ -// /*namespace com.google.zxing.common.detector {*/ +// /*namespace com.google.zxing.common.detector { */ // import ResultPoint from '../../ResultPoint' // import BitMatrix from '../BitMatrix' @@ -26,7 +26,7 @@ // * // * @author Sean Owen // * @deprecated without replacement since 3.3.0 -// */ +// */ // @Deprecated // export default class MonochromeRectangleDetector { @@ -47,10 +47,10 @@ // * the topmost point and the last, the bottommost. The second point will be leftmost and the // * third, the rightmost // * @throws NotFoundException if no Data Matrix Code can be found -// */ -// public detect(): ResultPoInt32Array /*throws NotFoundException*/ { -// height: number /*int*/ = image.getHeight(); -// width: number /*int*/ = image.getWidth(); +// */ +// public detect(): ResultPoInt32Array /*throws NotFoundException */ { +// height: number /*int */ = image.getHeight(); +// width: number /*int */ = image.getWidth(); // const halfHeight = height / 2 // const halfWidth = width / 2 // const deltaY = Math.max(1, height / (MAX_MODULES * 8)); @@ -97,16 +97,16 @@ // * the barcode // * @return a {@link ResultPoint} encapsulating the corner that was found // * @throws NotFoundException if such a point cannot be found -// */ -// private ResultPoint findCornerFromCenter(centerX: number /*int*/, -// deltaX: number /*int*/, -// left: number /*int*/, -// right: number /*int*/, -// centerY: number /*int*/, -// deltaY: number /*int*/, -// top: number /*int*/, -// bottom: number /*int*/, -// maxWhiteRun: number /*int*/) /*throws NotFoundException*/ { +// */ +// private ResultPoint findCornerFromCenter(centerX: number /*int */, +// deltaX: number /*int */, +// left: number /*int */, +// right: number /*int */, +// centerY: number /*int */, +// deltaY: number /*int */, +// top: number /*int */, +// bottom: number /*int */, +// maxWhiteRun: number /*int */) /*throws NotFoundException */ { // const lastRange: Int32Array = null // for (let y = centerY, x = centerX // y < bottom && y >= top && x < right && x >= left @@ -165,8 +165,8 @@ // * @param horizontal if true, we're scanning left-right, instead of up-down // * @return const with: Int32Array start and end of found range, or null if no such range is found // * (e.g. only white was found) -// */ -// private const blackWhiteRange: Int32Array(fixedDimension: number /*int*/, maxWhiteRun: number /*int*/, minDim: number /*int*/, maxDim: number /*int*/, boolean horizontal) { +// */ +// private const blackWhiteRange: Int32Array(fixedDimension: number /*int */, maxWhiteRun: number /*int */, minDim: number /*int */, maxDim: number /*int */, boolean horizontal) { // const center = (minDim + maxDim) / 2 @@ -213,4 +213,4 @@ // return end > start ? new Int32Array{start, end} : null // } -// } \ No newline at end of file +// } diff --git a/src/core/common/detector/WhiteRectangleDetector.ts b/src/core/common/detector/WhiteRectangleDetector.ts index 8e675379..274c6c08 100644 --- a/src/core/common/detector/WhiteRectangleDetector.ts +++ b/src/core/common/detector/WhiteRectangleDetector.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common.detector {*/ +/* namespace com.google.zxing.common.detector { */ import ResultPoint from '../../ResultPoint'; import BitMatrix from '../BitMatrix'; @@ -34,314 +34,314 @@ import NotFoundException from '../../NotFoundException'; */ export default class WhiteRectangleDetector { - private static INIT_SIZE = 10; - private static CORR = 1; - - private height: number; /*int*/ - private width: number; /*int*/ - private leftInit: number; /*int*/ - private rightInit: number; /*int*/ - private downInit: number; /*int*/ - private upInit: number; /*int*/ - - // public constructor(private image: BitMatrix) /*throws NotFoundException*/ { - // this(image, INIT_SIZE, image.getWidth() / 2, image.getHeight() / 2) - // } - - /** - * @param image barcode image to find a rectangle in - * @param initSize initial size of search area around center - * @param x x position of search center - * @param y y position of search center - * @throws NotFoundException if image is too small to accommodate {@code initSize} - */ - public constructor(private image: BitMatrix, initSize?: number /*int*/, x?: number /*int*/, y?: number /*int*/) /*throws NotFoundException*/ { - this.height = image.getHeight(); - this.width = image.getWidth(); - if (undefined === initSize || null === initSize) { - initSize = WhiteRectangleDetector.INIT_SIZE; + private static INIT_SIZE = 10; + private static CORR = 1; + + private height: number; /* int */ + private width: number; /* int */ + private leftInit: number; /* int */ + private rightInit: number; /* int */ + private downInit: number; /* int */ + private upInit: number; /* int */ + + // public constructor(private image: BitMatrix) /*throws NotFoundException */ { + // this(image, INIT_SIZE, image.getWidth() / 2, image.getHeight() / 2) + // } + + /** + * @param image barcode image to find a rectangle in + * @param initSize initial size of search area around center + * @param x x position of search center + * @param y y position of search center + * @throws NotFoundException if image is too small to accommodate {@code initSize} + */ + public constructor(private image: BitMatrix, initSize?: number /* int */, x?: number /* int */, y?: number /* int */) /* throws NotFoundException */ { + this.height = image.getHeight(); + this.width = image.getWidth(); + if (undefined === initSize || null === initSize) { + initSize = WhiteRectangleDetector.INIT_SIZE; + } + if (undefined === x || null === x) { + x = image.getWidth() / 2 | 0; + } + if (undefined === y || null === y) { + y = image.getHeight() / 2 | 0; + } + const halfsize = initSize / 2 | 0; + this.leftInit = x - halfsize; + this.rightInit = x + halfsize; + this.upInit = y - halfsize; + this.downInit = y + halfsize; + if (this.upInit < 0 || this.leftInit < 0 || this.downInit >= this.height || this.rightInit >= this.width) { + throw new NotFoundException(); + } + } + + /** + *

+ * Detects a candidate barcode-like rectangular region within an image. It + * starts around the center of the image, increases the size of the candidate + * region until it finds a white rectangular region. + *

+ * + * @return {@link ResultPoint}[] describing the corners of the rectangular + * region. The first and last points are opposed on the diagonal, as + * are the second and third. The first point will be the topmost + * point and the last, the bottommost. The second point will be + * leftmost and the third, the rightmost + * @throws NotFoundException if no Data Matrix Code can be found + */ + public detect(): Array /* throws NotFoundException */ { + let left = this.leftInit; + let right = this.rightInit; + let up = this.upInit; + let down = this.downInit; + let sizeExceeded: boolean = false; + let aBlackPointFoundOnBorder: boolean = true; + let atLeastOneBlackPointFoundOnBorder: boolean = false; + + let atLeastOneBlackPointFoundOnRight: boolean = false; + let atLeastOneBlackPointFoundOnBottom: boolean = false; + let atLeastOneBlackPointFoundOnLeft: boolean = false; + let atLeastOneBlackPointFoundOnTop: boolean = false; + + const width = this.width; + const height = this.height; + + while (aBlackPointFoundOnBorder) { + + aBlackPointFoundOnBorder = false; + + // ..... + // . | + // ..... + let rightBorderNotWhite: boolean = true; + while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) { + rightBorderNotWhite = this.containsBlackPoint(up, down, right, false); + if (rightBorderNotWhite) { + right++; + aBlackPointFoundOnBorder = true; + atLeastOneBlackPointFoundOnRight = true; + } else if (!atLeastOneBlackPointFoundOnRight) { + right++; } - if (undefined === x || null === x) { - x = image.getWidth() / 2 | 0; + } + + if (right >= width) { + sizeExceeded = true; + break; + } + + // ..... + // . . + // .___. + let bottomBorderNotWhite: boolean = true; + while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) { + bottomBorderNotWhite = this.containsBlackPoint(left, right, down, true); + if (bottomBorderNotWhite) { + down++; + aBlackPointFoundOnBorder = true; + atLeastOneBlackPointFoundOnBottom = true; + } else if (!atLeastOneBlackPointFoundOnBottom) { + down++; } - if (undefined === y || null === y) { - y = image.getHeight() / 2 | 0; + } + + if (down >= height) { + sizeExceeded = true; + break; + } + + // ..... + // | . + // ..... + let leftBorderNotWhite: boolean = true; + while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) { + leftBorderNotWhite = this.containsBlackPoint(up, down, left, false); + if (leftBorderNotWhite) { + left--; + aBlackPointFoundOnBorder = true; + atLeastOneBlackPointFoundOnLeft = true; + } else if (!atLeastOneBlackPointFoundOnLeft) { + left--; } - const halfsize = initSize / 2 | 0; - this.leftInit = x - halfsize; - this.rightInit = x + halfsize; - this.upInit = y - halfsize; - this.downInit = y + halfsize; - if (this.upInit < 0 || this.leftInit < 0 || this.downInit >= this.height || this.rightInit >= this.width) { - throw new NotFoundException(); + } + + if (left < 0) { + sizeExceeded = true; + break; + } + + // .___. + // . . + // ..... + let topBorderNotWhite: boolean = true; + while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) { + topBorderNotWhite = this.containsBlackPoint(left, right, up, true); + if (topBorderNotWhite) { + up--; + aBlackPointFoundOnBorder = true; + atLeastOneBlackPointFoundOnTop = true; + } else if (!atLeastOneBlackPointFoundOnTop) { + up--; } - } + } - /** - *

- * Detects a candidate barcode-like rectangular region within an image. It - * starts around the center of the image, increases the size of the candidate - * region until it finds a white rectangular region. - *

- * - * @return {@link ResultPoint}[] describing the corners of the rectangular - * region. The first and last points are opposed on the diagonal, as - * are the second and third. The first point will be the topmost - * point and the last, the bottommost. The second point will be - * leftmost and the third, the rightmost - * @throws NotFoundException if no Data Matrix Code can be found - */ - public detect(): Array /*throws NotFoundException*/ { - let left = this.leftInit; - let right = this.rightInit; - let up = this.upInit; - let down = this.downInit; - let sizeExceeded: boolean = false; - let aBlackPointFoundOnBorder: boolean = true; - let atLeastOneBlackPointFoundOnBorder: boolean = false; - - let atLeastOneBlackPointFoundOnRight: boolean = false; - let atLeastOneBlackPointFoundOnBottom: boolean = false; - let atLeastOneBlackPointFoundOnLeft: boolean = false; - let atLeastOneBlackPointFoundOnTop: boolean = false; - - const width = this.width; - const height = this.height; - - while (aBlackPointFoundOnBorder) { - - aBlackPointFoundOnBorder = false; - - // ..... - // . | - // ..... - let rightBorderNotWhite: boolean = true; - while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) { - rightBorderNotWhite = this.containsBlackPoint(up, down, right, false); - if (rightBorderNotWhite) { - right++; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnRight = true; - } else if (!atLeastOneBlackPointFoundOnRight) { - right++; - } - } - - if (right >= width) { - sizeExceeded = true; - break; - } - - // ..... - // . . - // .___. - let bottomBorderNotWhite: boolean = true; - while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) { - bottomBorderNotWhite = this.containsBlackPoint(left, right, down, true); - if (bottomBorderNotWhite) { - down++; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnBottom = true; - } else if (!atLeastOneBlackPointFoundOnBottom) { - down++; - } - } - - if (down >= height) { - sizeExceeded = true; - break; - } - - // ..... - // | . - // ..... - let leftBorderNotWhite: boolean = true; - while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) { - leftBorderNotWhite = this.containsBlackPoint(up, down, left, false); - if (leftBorderNotWhite) { - left--; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnLeft = true; - } else if (!atLeastOneBlackPointFoundOnLeft) { - left--; - } - } - - if (left < 0) { - sizeExceeded = true; - break; - } - - // .___. - // . . - // ..... - let topBorderNotWhite: boolean = true; - while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) { - topBorderNotWhite = this.containsBlackPoint(left, right, up, true); - if (topBorderNotWhite) { - up--; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnTop = true; - } else if (!atLeastOneBlackPointFoundOnTop) { - up--; - } - } - - if (up < 0) { - sizeExceeded = true; - break; - } - - if (aBlackPointFoundOnBorder) { - atLeastOneBlackPointFoundOnBorder = true; - } + if (up < 0) { + sizeExceeded = true; + break; + } - } + if (aBlackPointFoundOnBorder) { + atLeastOneBlackPointFoundOnBorder = true; + } - if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) { + } - const maxSize = right - left; + if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) { - let z: ResultPoint | null = null; - for (let i = 1; z === null && i < maxSize; i++) { - z = this.getBlackPointOnSegment(left, down - i, left + i, down); - } + const maxSize = right - left; - if (z == null) { - throw new NotFoundException(); - } + let z: ResultPoint | null = null; + for (let i = 1; z === null && i < maxSize; i++) { + z = this.getBlackPointOnSegment(left, down - i, left + i, down); + } - let t: ResultPoint | null = null; - // go down right - for (let i = 1; t === null && i < maxSize; i++) { - t = this.getBlackPointOnSegment(left, up + i, left + i, up); - } + if (z == null) { + throw new NotFoundException(); + } - if (t == null) { - throw new NotFoundException(); - } + let t: ResultPoint | null = null; + // go down right + for (let i = 1; t === null && i < maxSize; i++) { + t = this.getBlackPointOnSegment(left, up + i, left + i, up); + } - let x: ResultPoint | null = null; - // go down left - for (let i = 1; x === null && i < maxSize; i++) { - x = this.getBlackPointOnSegment(right, up + i, right - i, up); - } + if (t == null) { + throw new NotFoundException(); + } - if (x == null) { - throw new NotFoundException(); - } + let x: ResultPoint | null = null; + // go down left + for (let i = 1; x === null && i < maxSize; i++) { + x = this.getBlackPointOnSegment(right, up + i, right - i, up); + } - let y: ResultPoint | null = null; - // go up left - for (let i = 1; y === null && i < maxSize; i++) { - y = this.getBlackPointOnSegment(right, down - i, right - i, down); - } + if (x == null) { + throw new NotFoundException(); + } - if (y == null) { - throw new NotFoundException(); - } + let y: ResultPoint | null = null; + // go up left + for (let i = 1; y === null && i < maxSize; i++) { + y = this.getBlackPointOnSegment(right, down - i, right - i, down); + } - return this.centerEdges(y, z, x, t); + if (y == null) { + throw new NotFoundException(); + } - } else { - throw new NotFoundException(); - } + return this.centerEdges(y, z, x, t); + + } else { + throw new NotFoundException(); } + } - private getBlackPointOnSegment(aX: number/*float*/, aY: number/*float*/, bX: number/*float*/, bY: number/*float*/): ResultPoint | null { - const dist = MathUtils.round(MathUtils.distance(aX, aY, bX, bY)); - const xStep: number /*float*/ = (bX - aX) / dist; - const yStep: number /*float*/ = (bY - aY) / dist; + private getBlackPointOnSegment(aX: number/* float */, aY: number/* float */, bX: number/* float */, bY: number/* float */): ResultPoint | null { + const dist = MathUtils.round(MathUtils.distance(aX, aY, bX, bY)); + const xStep: number /* float */ = (bX - aX) / dist; + const yStep: number /* float */ = (bY - aY) / dist; - const image = this.image; + const image = this.image; - for (let i = 0; i < dist; i++) { - const x = MathUtils.round(aX + i * xStep); - const y = MathUtils.round(aY + i * yStep); - if (image.get(x, y)) { - return new ResultPoint(x, y); - } - } - return null; + for (let i = 0; i < dist; i++) { + const x = MathUtils.round(aX + i * xStep); + const y = MathUtils.round(aY + i * yStep); + if (image.get(x, y)) { + return new ResultPoint(x, y); + } } - - /** - * recenters the points of a constant distance towards the center - * - * @param y bottom most point - * @param z left most point - * @param x right most point - * @param t top most point - * @return {@link ResultPoint}[] describing the corners of the rectangular - * region. The first and last points are opposed on the diagonal, as - * are the second and third. The first point will be the topmost - * point and the last, the bottommost. The second point will be - * leftmost and the third, the rightmost - */ - private centerEdges(y: ResultPoint, z: ResultPoint, - x: ResultPoint, t: ResultPoint): Array { - - // - // t t - // z x - // x OR z - // y y - // - - const yi: number /*float*/ = y.getX(); - const yj: number /*float*/ = y.getY(); - const zi: number /*float*/ = z.getX(); - const zj: number /*float*/ = z.getY(); - const xi: number /*float*/ = x.getX(); - const xj: number /*float*/ = x.getY(); - const ti: number /*float*/ = t.getX(); - const tj: number /*float*/ = t.getY(); - - const CORR = WhiteRectangleDetector.CORR; - - if (yi < this.width / 2.0) { - return [ - new ResultPoint(ti - CORR, tj + CORR), - new ResultPoint(zi + CORR, zj + CORR), - new ResultPoint(xi - CORR, xj - CORR), - new ResultPoint(yi + CORR, yj - CORR)]; - } else { - return [ - new ResultPoint(ti + CORR, tj + CORR), - new ResultPoint(zi + CORR, zj - CORR), - new ResultPoint(xi - CORR, xj + CORR), - new ResultPoint(yi - CORR, yj - CORR)]; - } + return null; + } + + /** + * recenters the points of a constant distance towards the center + * + * @param y bottom most point + * @param z left most point + * @param x right most point + * @param t top most point + * @return {@link ResultPoint}[] describing the corners of the rectangular + * region. The first and last points are opposed on the diagonal, as + * are the second and third. The first point will be the topmost + * point and the last, the bottommost. The second point will be + * leftmost and the third, the rightmost + */ + private centerEdges(y: ResultPoint, z: ResultPoint, + x: ResultPoint, t: ResultPoint): Array { + + // + // t t + // z x + // x OR z + // y y + // + + const yi: number /* float */ = y.getX(); + const yj: number /* float */ = y.getY(); + const zi: number /* float */ = z.getX(); + const zj: number /* float */ = z.getY(); + const xi: number /* float */ = x.getX(); + const xj: number /* float */ = x.getY(); + const ti: number /* float */ = t.getX(); + const tj: number /* float */ = t.getY(); + + const CORR = WhiteRectangleDetector.CORR; + + if (yi < this.width / 2.0) { + return [ + new ResultPoint(ti - CORR, tj + CORR), + new ResultPoint(zi + CORR, zj + CORR), + new ResultPoint(xi - CORR, xj - CORR), + new ResultPoint(yi + CORR, yj - CORR)]; + } else { + return [ + new ResultPoint(ti + CORR, tj + CORR), + new ResultPoint(zi + CORR, zj - CORR), + new ResultPoint(xi - CORR, xj + CORR), + new ResultPoint(yi - CORR, yj - CORR)]; } + } + + /** + * Determines whether a segment contains a black point + * + * @param a min value of the scanned coordinate + * @param b max value of the scanned coordinate + * @param fixed value of fixed coordinate + * @param horizontal set to true if scan must be horizontal, false if vertical + * @return true if a black point has been found, else false. + */ + private containsBlackPoint(a: number /* int */, b: number /* int */, fixed: number /* int */, horizontal: boolean): boolean { - /** - * Determines whether a segment contains a black point - * - * @param a min value of the scanned coordinate - * @param b max value of the scanned coordinate - * @param fixed value of fixed coordinate - * @param horizontal set to true if scan must be horizontal, false if vertical - * @return true if a black point has been found, else false. - */ - private containsBlackPoint(a: number /*int*/, b: number /*int*/, fixed: number /*int*/, horizontal: boolean): boolean { - - const image = this.image; - - if (horizontal) { - for (let x = a; x <= b; x++) { - if (image.get(x, fixed)) { - return true; - } - } - } else { - for (let y = a; y <= b; y++) { - if (image.get(fixed, y)) { - return true; - } - } - } + const image = this.image; - return false; + if (horizontal) { + for (let x = a; x <= b; x++) { + if (image.get(x, fixed)) { + return true; + } + } + } else { + for (let y = a; y <= b; y++) { + if (image.get(fixed, y)) { + return true; + } + } } + return false; + } + } diff --git a/src/core/common/reedsolomon/AbstractGenericGF.ts b/src/core/common/reedsolomon/AbstractGenericGF.ts index bca4a82e..3087493e 100644 --- a/src/core/common/reedsolomon/AbstractGenericGF.ts +++ b/src/core/common/reedsolomon/AbstractGenericGF.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common.reedsolomon {*/ +/* namespace com.google.zxing.common.reedsolomon { */ // import GenericGFPoly from './GenericGFPoly'; @@ -39,24 +39,24 @@ export default abstract class AbstractGenericGF { public abstract getZero(): any; // GenericGFPoly public abstract buildMonomial( - degree: number /*int*/, - coefficient: number /*int*/ + degree: number /* int */, + coefficient: number /* int */ ): any; // GenericGFPoly public abstract equals(o: Object): boolean; - public abstract multiply(a: number /*int*/, b: number /*int*/): number; - public abstract inverse(a: number /*int*/): number; + public abstract multiply(a: number /* int */, b: number /* int */): number; + public abstract inverse(a: number /* int */): number; /** * @return 2 to the power of a in GF(size) - */ - public exp(a: number): number /*int*/ { + */ + public exp(a: number): number /* int */ { return this.expTable[a]; } /** * @return base 2 log of a in GF(size) - */ - public log(a: number /*int*/): number /*int*/ { + */ + public log(a: number /* int */): number /* int */ { if (a === 0) { throw new IllegalArgumentException(); } @@ -67,11 +67,11 @@ export default abstract class AbstractGenericGF { * Implements both addition and subtraction -- they are the same in GF(size). * * @return sum/difference of a and b - */ + */ public static addOrSubtract( - a: number /*int*/, - b: number /*int*/ - ): number /*int*/ { + a: number /* int */, + b: number /* int */ + ): number /* int */ { return a ^ b; } } diff --git a/src/core/common/reedsolomon/AbstractGenericGFPoly.ts b/src/core/common/reedsolomon/AbstractGenericGFPoly.ts index fb575e6a..cf1142b8 100644 --- a/src/core/common/reedsolomon/AbstractGenericGFPoly.ts +++ b/src/core/common/reedsolomon/AbstractGenericGFPoly.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common.reedsolomon {*/ +/* namespace com.google.zxing.common.reedsolomon { */ // import GenericGF from './GenericGF'; import AbstractGenericGF from './AbstractGenericGF'; @@ -30,108 +30,108 @@ import AbstractGenericGF from './AbstractGenericGF'; */ export default abstract class AbstractGenericGFPoly { - protected field: AbstractGenericGF; - protected coefficients: Int32Array; + protected field: AbstractGenericGF; + protected coefficients: Int32Array; - public getCoefficients(): Int32Array { - return this.coefficients; - } + public getCoefficients(): Int32Array { + return this.coefficients; + } - /** - * @return degree of this polynomial - */ - public getDegree(): number { - return this.coefficients.length - 1; - } + /** + * @return degree of this polynomial + */ + public getDegree(): number { + return this.coefficients.length - 1; + } - /** - * @return true iff this polynomial is the monomial "0" - */ - public isZero(): boolean { - return this.coefficients[0] === 0; - } + /** + * @return true iff this polynomial is the monomial "0" + */ + public isZero(): boolean { + return this.coefficients[0] === 0; + } - /** - * @return coefficient of x^degree term in this polynomial - */ - public getCoefficient(degree: number /*int*/): number { - return this.coefficients[this.coefficients.length - 1 - degree]; + /** + * @return coefficient of x^degree term in this polynomial + */ + public getCoefficient(degree: number /* int */): number { + return this.coefficients[this.coefficients.length - 1 - degree]; + } + + /** + * @return evaluation of this polynomial at a given point + */ + public evaluateAt(a: number /* int */): number { + if (a === 0) { + // Just return the x^0 coefficient + return this.getCoefficient(0); + } + const coefficients = this.coefficients; + let result: number; + if (a === 1) { + // Just the sum of the coefficients + result = 0; + for (let i = 0, length = coefficients.length; i !== length; i++) { + const coefficient = coefficients[i]; + result = AbstractGenericGF.addOrSubtract(result, coefficient); + } + return result; } + result = coefficients[0]; + const size = coefficients.length; + const field = this.field; + for (let i = 1; i < size; i++) { + result = AbstractGenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]); + } + return result; + } - /** - * @return evaluation of this polynomial at a given point - */ - public evaluateAt(a: number /*int*/): number { - if (a === 0) { - // Just return the x^0 coefficient - return this.getCoefficient(0); - } - const coefficients = this.coefficients; - let result: number; - if (a === 1) { - // Just the sum of the coefficients - result = 0; - for (let i = 0, length = coefficients.length; i !== length; i++) { - const coefficient = coefficients[i]; - result = AbstractGenericGF.addOrSubtract(result, coefficient); - } - return result; + public abstract addOrSubtract(other: AbstractGenericGFPoly): AbstractGenericGFPoly; + + public abstract multiply(other: AbstractGenericGFPoly): AbstractGenericGFPoly; + + public abstract multiplyScalar(scalar: number /* int */): AbstractGenericGFPoly; + + public abstract multiplyByMonomial(degree: number /* int */, coefficient: number /* int */): AbstractGenericGFPoly; + + public abstract divide(other: AbstractGenericGFPoly): AbstractGenericGFPoly[]; + + /* @Override */ + public toString(): string { + let result = ''; + for (let degree = this.getDegree(); degree >= 0; degree--) { + let coefficient = this.getCoefficient(degree); + if (coefficient !== 0) { + if (coefficient < 0) { + result += ' - '; + coefficient = -coefficient; + } else { + if (result.length > 0) { + result += ' + '; + } } - result = coefficients[0]; - const size = coefficients.length; - const field = this.field; - for (let i = 1; i < size; i++) { - result = AbstractGenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]); + if (degree === 0 || coefficient !== 1) { + const alphaPower = this.field.log(coefficient); + if (alphaPower === 0) { + result += '1'; + } else if (alphaPower === 1) { + result += 'a'; + } else { + result += 'a^'; + result += alphaPower; + } } - return result; - } - - public abstract addOrSubtract(other: AbstractGenericGFPoly): AbstractGenericGFPoly; - - public abstract multiply(other: AbstractGenericGFPoly): AbstractGenericGFPoly; - - public abstract multiplyScalar(scalar: number /*int*/): AbstractGenericGFPoly; - - public abstract multiplyByMonomial(degree: number /*int*/, coefficient: number /*int*/): AbstractGenericGFPoly; - - public abstract divide(other: AbstractGenericGFPoly): AbstractGenericGFPoly[]; - - /*@Override*/ - public toString(): string { - let result = ''; - for (let degree = this.getDegree(); degree >= 0; degree--) { - let coefficient = this.getCoefficient(degree); - if (coefficient !== 0) { - if (coefficient < 0) { - result += ' - '; - coefficient = -coefficient; - } else { - if (result.length > 0) { - result += ' + '; - } - } - if (degree === 0 || coefficient !== 1) { - const alphaPower = this.field.log(coefficient); - if (alphaPower === 0) { - result += '1'; - } else if (alphaPower === 1) { - result += 'a'; - } else { - result += 'a^'; - result += alphaPower; - } - } - if (degree !== 0) { - if (degree === 1) { - result += 'x'; - } else { - result += 'x^'; - result += degree; - } - } - } + if (degree !== 0) { + if (degree === 1) { + result += 'x'; + } else { + result += 'x^'; + result += degree; + } } - return result; + } } + return result; + } } diff --git a/src/core/common/reedsolomon/GenericGF.ts b/src/core/common/reedsolomon/GenericGF.ts index af7318e3..b9bcb45a 100644 --- a/src/core/common/reedsolomon/GenericGF.ts +++ b/src/core/common/reedsolomon/GenericGF.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common.reedsolomon {*/ +/* namespace com.google.zxing.common.reedsolomon { */ import GenericGFPoly from './GenericGFPoly'; import AbstractGenericGF from './AbstractGenericGF'; @@ -57,11 +57,11 @@ export default class GenericGF extends AbstractGenericGF { * @param b the factor b in the generator polynomial can be 0- or 1-based * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))). * In most cases it should be 1, but for QR code it is 0. - */ + */ public constructor( - private primitive: number /*int*/, - private size: number /*int*/, - private generatorBase: number /*int*/ + private primitive: number /* int */, + private size: number /* int */, + private generatorBase: number /* int */ ) { super(); const expTable = new Int32Array(size); @@ -97,10 +97,10 @@ export default class GenericGF extends AbstractGenericGF { /** * @return the monomial representing coefficient * x^degree - */ + */ public buildMonomial( - degree: number /*int*/, - coefficient: number /*int*/ + degree: number /* int */, + coefficient: number /* int */ ): GenericGFPoly { if (degree < 0) { throw new IllegalArgumentException(); @@ -115,8 +115,8 @@ export default class GenericGF extends AbstractGenericGF { /** * @return multiplicative inverse of a - */ - public inverse(a: number /*int*/): number /*int*/ { + */ + public inverse(a: number /* int */): number /* int */ { if (a === 0) { throw new ArithmeticException(); } @@ -125,8 +125,8 @@ export default class GenericGF extends AbstractGenericGF { /** * @return product of a and b in GF(size) - */ - public multiply(a: number /*int*/, b: number /*int*/): number /*int*/ { + */ + public multiply(a: number /* int */, b: number /* int */): number /* int */ { if (a === 0 || b === 0) { return 0; } @@ -135,15 +135,15 @@ export default class GenericGF extends AbstractGenericGF { ]; } - public getSize(): number /*int*/ { + public getSize(): number /* int */ { return this.size; } - public getGeneratorBase(): number /*int*/ { + public getGeneratorBase(): number /* int */ { return this.generatorBase; } - /*@Override*/ + /* @Override */ public toString(): string { return ( 'GF(0x' + Integer.toHexString(this.primitive) + ',' + this.size + ')' diff --git a/src/core/common/reedsolomon/GenericGFPoly.ts b/src/core/common/reedsolomon/GenericGFPoly.ts index 9de5e245..e79cf492 100644 --- a/src/core/common/reedsolomon/GenericGFPoly.ts +++ b/src/core/common/reedsolomon/GenericGFPoly.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common.reedsolomon {*/ +/* namespace com.google.zxing.common.reedsolomon { */ import AbstractGenericGF from './AbstractGenericGF'; @@ -32,249 +32,249 @@ import IllegalArgumentException from '../../IllegalArgumentException'; */ export default class GenericGFPoly { - private field: AbstractGenericGF; - private coefficients: Int32Array; + private field: AbstractGenericGF; + private coefficients: Int32Array; - /** - * @param field the {@link GenericGF} instance representing the field to use - * to perform computations - * @param coefficients coefficients as ints representing elements of GF(size), arranged - * from most significant (highest-power term) coefficient to least significant - * @throws IllegalArgumentException if argument is null or empty, - * or if leading coefficient is 0 and this is not a - * constant polynomial (that is, it is not the monomial "0") - */ - public constructor(field: AbstractGenericGF, coefficients: Int32Array) { - if (coefficients.length === 0) { - throw new IllegalArgumentException(); - } - this.field = field; - const coefficientsLength = coefficients.length; - if (coefficientsLength > 1 && coefficients[0] === 0) { - // Leading term must be non-zero for anything except the constant polynomial "0" - let firstNonZero = 1; - while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) { - firstNonZero++; - } - if (firstNonZero === coefficientsLength) { - this.coefficients = Int32Array.from([0]); - } else { - this.coefficients = new Int32Array(coefficientsLength - firstNonZero); - System.arraycopy(coefficients, - firstNonZero, - this.coefficients, - 0, - this.coefficients.length); - } - } else { - this.coefficients = coefficients; - } + /** + * @param field the {@link GenericGF} instance representing the field to use + * to perform computations + * @param coefficients coefficients as ints representing elements of GF(size), arranged + * from most significant (highest-power term) coefficient to least significant + * @throws IllegalArgumentException if argument is null or empty, + * or if leading coefficient is 0 and this is not a + * constant polynomial (that is, it is not the monomial "0") + */ + public constructor(field: AbstractGenericGF, coefficients: Int32Array) { + if (coefficients.length === 0) { + throw new IllegalArgumentException(); } - - public getCoefficients(): Int32Array { - return this.coefficients; + this.field = field; + const coefficientsLength = coefficients.length; + if (coefficientsLength > 1 && coefficients[0] === 0) { + // Leading term must be non-zero for anything except the constant polynomial "0" + let firstNonZero = 1; + while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) { + firstNonZero++; + } + if (firstNonZero === coefficientsLength) { + this.coefficients = Int32Array.from([0]); + } else { + this.coefficients = new Int32Array(coefficientsLength - firstNonZero); + System.arraycopy(coefficients, + firstNonZero, + this.coefficients, + 0, + this.coefficients.length); + } + } else { + this.coefficients = coefficients; } + } - /** - * @return degree of this polynomial - */ - public getDegree(): number { - return this.coefficients.length - 1; - } + public getCoefficients(): Int32Array { + return this.coefficients; + } - /** - * @return true iff this polynomial is the monomial "0" - */ - public isZero(): boolean { - return this.coefficients[0] === 0; - } + /** + * @return degree of this polynomial + */ + public getDegree(): number { + return this.coefficients.length - 1; + } + + /** + * @return true iff this polynomial is the monomial "0" + */ + public isZero(): boolean { + return this.coefficients[0] === 0; + } - /** - * @return coefficient of x^degree term in this polynomial - */ - public getCoefficient(degree: number /*int*/): number { - return this.coefficients[this.coefficients.length - 1 - degree]; + /** + * @return coefficient of x^degree term in this polynomial + */ + public getCoefficient(degree: number /* int */): number { + return this.coefficients[this.coefficients.length - 1 - degree]; + } + + /** + * @return evaluation of this polynomial at a given point + */ + public evaluateAt(a: number /* int */): number { + if (a === 0) { + // Just return the x^0 coefficient + return this.getCoefficient(0); } + const coefficients = this.coefficients; + let result: number; + if (a === 1) { + // Just the sum of the coefficients + result = 0; + for (let i = 0, length = coefficients.length; i !== length; i++) { + const coefficient = coefficients[i]; + result = AbstractGenericGF.addOrSubtract(result, coefficient); + } + return result; + } + result = coefficients[0]; + const size = coefficients.length; + const field = this.field; + for (let i = 1; i < size; i++) { + result = AbstractGenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]); + } + return result; + } - /** - * @return evaluation of this polynomial at a given point - */ - public evaluateAt(a: number /*int*/): number { - if (a === 0) { - // Just return the x^0 coefficient - return this.getCoefficient(0); - } - const coefficients = this.coefficients; - let result: number; - if (a === 1) { - // Just the sum of the coefficients - result = 0; - for (let i = 0, length = coefficients.length; i !== length; i++) { - const coefficient = coefficients[i]; - result = AbstractGenericGF.addOrSubtract(result, coefficient); - } - return result; - } - result = coefficients[0]; - const size = coefficients.length; - const field = this.field; - for (let i = 1; i < size; i++) { - result = AbstractGenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]); - } - return result; + public addOrSubtract(other: GenericGFPoly): GenericGFPoly { + if (!this.field.equals(other.field)) { + throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field'); + } + if (this.isZero()) { + return other; + } + if (other.isZero()) { + return this; } - public addOrSubtract(other: GenericGFPoly): GenericGFPoly { - if (!this.field.equals(other.field)) { - throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field'); - } - if (this.isZero()) { - return other; - } - if (other.isZero()) { - return this; - } + let smallerCoefficients = this.coefficients; + let largerCoefficients = other.coefficients; + if (smallerCoefficients.length > largerCoefficients.length) { + const temp = smallerCoefficients; + smallerCoefficients = largerCoefficients; + largerCoefficients = temp; + } + let sumDiff = new Int32Array(largerCoefficients.length); + const lengthDiff = largerCoefficients.length - smallerCoefficients.length; + // Copy high-order terms only found in higher-degree polynomial's coefficients + System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff); - let smallerCoefficients = this.coefficients; - let largerCoefficients = other.coefficients; - if (smallerCoefficients.length > largerCoefficients.length) { - const temp = smallerCoefficients; - smallerCoefficients = largerCoefficients; - largerCoefficients = temp; - } - let sumDiff = new Int32Array(largerCoefficients.length); - const lengthDiff = largerCoefficients.length - smallerCoefficients.length; - // Copy high-order terms only found in higher-degree polynomial's coefficients - System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff); + for (let i = lengthDiff; i < largerCoefficients.length; i++) { + sumDiff[i] = AbstractGenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); + } - for (let i = lengthDiff; i < largerCoefficients.length; i++) { - sumDiff[i] = AbstractGenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); - } + return new GenericGFPoly(this.field, sumDiff); + } - return new GenericGFPoly(this.field, sumDiff); + public multiply(other: GenericGFPoly): GenericGFPoly { + if (!this.field.equals(other.field)) { + throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field'); } - - public multiply(other: GenericGFPoly): GenericGFPoly { - if (!this.field.equals(other.field)) { - throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field'); - } - if (this.isZero() || other.isZero()) { - return this.field.getZero(); - } - const aCoefficients = this.coefficients; - const aLength = aCoefficients.length; - const bCoefficients = other.coefficients; - const bLength = bCoefficients.length; - const product = new Int32Array(aLength + bLength - 1); - const field = this.field; - for (let i = 0; i < aLength; i++) { - const aCoeff = aCoefficients[i]; - for (let j = 0; j < bLength; j++) { - product[i + j] = AbstractGenericGF.addOrSubtract(product[i + j], - field.multiply(aCoeff, bCoefficients[j])); - } - } - return new GenericGFPoly(field, product); + if (this.isZero() || other.isZero()) { + return this.field.getZero(); } - - public multiplyScalar(scalar: number /*int*/): GenericGFPoly { - if (scalar === 0) { - return this.field.getZero(); - } - if (scalar === 1) { - return this; - } - const size = this.coefficients.length; - const field = this.field; - const product = new Int32Array(size); - const coefficients = this.coefficients; - for (let i = 0; i < size; i++) { - product[i] = field.multiply(coefficients[i], scalar); - } - return new GenericGFPoly(field, product); + const aCoefficients = this.coefficients; + const aLength = aCoefficients.length; + const bCoefficients = other.coefficients; + const bLength = bCoefficients.length; + const product = new Int32Array(aLength + bLength - 1); + const field = this.field; + for (let i = 0; i < aLength; i++) { + const aCoeff = aCoefficients[i]; + for (let j = 0; j < bLength; j++) { + product[i + j] = AbstractGenericGF.addOrSubtract(product[i + j], + field.multiply(aCoeff, bCoefficients[j])); + } } + return new GenericGFPoly(field, product); + } - public multiplyByMonomial(degree: number /*int*/, coefficient: number /*int*/): GenericGFPoly { - if (degree < 0) { - throw new IllegalArgumentException(); - } - if (coefficient === 0) { - return this.field.getZero(); - } - const coefficients = this.coefficients; - const size = coefficients.length; - const product = new Int32Array(size + degree); - const field = this.field; - for (let i = 0; i < size; i++) { - product[i] = field.multiply(coefficients[i], coefficient); - } - return new GenericGFPoly(field, product); + public multiplyScalar(scalar: number /* int */): GenericGFPoly { + if (scalar === 0) { + return this.field.getZero(); + } + if (scalar === 1) { + return this; } + const size = this.coefficients.length; + const field = this.field; + const product = new Int32Array(size); + const coefficients = this.coefficients; + for (let i = 0; i < size; i++) { + product[i] = field.multiply(coefficients[i], scalar); + } + return new GenericGFPoly(field, product); + } - public divide(other: GenericGFPoly): GenericGFPoly[] { - if (!this.field.equals(other.field)) { - throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field'); - } - if (other.isZero()) { - throw new IllegalArgumentException('Divide by 0'); - } + public multiplyByMonomial(degree: number /* int */, coefficient: number /* int */): GenericGFPoly { + if (degree < 0) { + throw new IllegalArgumentException(); + } + if (coefficient === 0) { + return this.field.getZero(); + } + const coefficients = this.coefficients; + const size = coefficients.length; + const product = new Int32Array(size + degree); + const field = this.field; + for (let i = 0; i < size; i++) { + product[i] = field.multiply(coefficients[i], coefficient); + } + return new GenericGFPoly(field, product); + } - const field = this.field; + public divide(other: GenericGFPoly): GenericGFPoly[] { + if (!this.field.equals(other.field)) { + throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field'); + } + if (other.isZero()) { + throw new IllegalArgumentException('Divide by 0'); + } - let quotient: GenericGFPoly = field.getZero(); - let remainder: GenericGFPoly = this; + const field = this.field; - const denominatorLeadingTerm = other.getCoefficient(other.getDegree()); - const inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm); + let quotient: GenericGFPoly = field.getZero(); + let remainder: GenericGFPoly = this; - while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) { - const degreeDifference = remainder.getDegree() - other.getDegree(); - const scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm); - const term = other.multiplyByMonomial(degreeDifference, scale); - const iterationQuotient = field.buildMonomial(degreeDifference, scale); - quotient = quotient.addOrSubtract(iterationQuotient); - remainder = remainder.addOrSubtract(term); - } + const denominatorLeadingTerm = other.getCoefficient(other.getDegree()); + const inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm); - return [quotient, remainder]; + while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) { + const degreeDifference = remainder.getDegree() - other.getDegree(); + const scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm); + const term = other.multiplyByMonomial(degreeDifference, scale); + const iterationQuotient = field.buildMonomial(degreeDifference, scale); + quotient = quotient.addOrSubtract(iterationQuotient); + remainder = remainder.addOrSubtract(term); } - /*@Override*/ - public toString(): string { - let result = ''; - for (let degree = this.getDegree(); degree >= 0; degree--) { - let coefficient = this.getCoefficient(degree); - if (coefficient !== 0) { - if (coefficient < 0) { - result += ' - '; - coefficient = -coefficient; - } else { - if (result.length > 0) { - result += ' + '; - } - } - if (degree === 0 || coefficient !== 1) { - const alphaPower = this.field.log(coefficient); - if (alphaPower === 0) { - result += '1'; - } else if (alphaPower === 1) { - result += 'a'; - } else { - result += 'a^'; - result += alphaPower; - } - } - if (degree !== 0) { - if (degree === 1) { - result += 'x'; - } else { - result += 'x^'; - result += degree; - } - } - } + return [quotient, remainder]; + } + + /* @Override */ + public toString(): string { + let result = ''; + for (let degree = this.getDegree(); degree >= 0; degree--) { + let coefficient = this.getCoefficient(degree); + if (coefficient !== 0) { + if (coefficient < 0) { + result += ' - '; + coefficient = -coefficient; + } else { + if (result.length > 0) { + result += ' + '; + } + } + if (degree === 0 || coefficient !== 1) { + const alphaPower = this.field.log(coefficient); + if (alphaPower === 0) { + result += '1'; + } else if (alphaPower === 1) { + result += 'a'; + } else { + result += 'a^'; + result += alphaPower; + } + } + if (degree !== 0) { + if (degree === 1) { + result += 'x'; + } else { + result += 'x^'; + result += degree; + } } - return result; + } } + return result; + } } diff --git a/src/core/common/reedsolomon/ReedSolomonDecoder.ts b/src/core/common/reedsolomon/ReedSolomonDecoder.ts index 1f2a5de8..1a2fb218 100644 --- a/src/core/common/reedsolomon/ReedSolomonDecoder.ts +++ b/src/core/common/reedsolomon/ReedSolomonDecoder.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.common.reedsolomon {*/ +/* namespace com.google.zxing.common.reedsolomon { */ import GenericGF from './GenericGF'; import GenericGFPoly from './GenericGFPoly'; @@ -46,150 +46,150 @@ import IllegalStateException from '../../IllegalStateException'; */ export default class ReedSolomonDecoder { - public constructor(private field: GenericGF) { } - - /** - *

Decodes given set of received codewords, which include both data and error-correction - * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, - * in the input.

- * - * @param received data and error-correction codewords - * @param twoS number of error-correction codewords available - * @throws ReedSolomonException if decoding fails for any reason - */ - public decode(received: Int32Array, twoS: number /*int*/): void /*throws ReedSolomonException*/ { - const field = this.field; - const poly = new GenericGFPoly(field, received); - const syndromeCoefficients = new Int32Array(twoS); - let noError: boolean = true; - for (let i = 0; i < twoS; i++) { - const evalResult = poly.evaluateAt(field.exp(i + field.getGeneratorBase())); - syndromeCoefficients[syndromeCoefficients.length - 1 - i] = evalResult; - if (evalResult !== 0) { - noError = false; - } - } - if (noError) { - return; - } - const syndrome = new GenericGFPoly(field, syndromeCoefficients); - const sigmaOmega = this.runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS); - const sigma = sigmaOmega[0]; - const omega = sigmaOmega[1]; - const errorLocations = this.findErrorLocations(sigma); - const errorMagnitudes = this.findErrorMagnitudes(omega, errorLocations); - for (let i = 0; i < errorLocations.length; i++) { - const position = received.length - 1 - field.log(errorLocations[i]); - if (position < 0) { - throw new ReedSolomonException('Bad error location'); - } - received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]); - } - } - - private runEuclideanAlgorithm(a: GenericGFPoly, b: GenericGFPoly, R: number /*int*/): GenericGFPoly[] { - // Assume a's degree is >= b's - if (a.getDegree() < b.getDegree()) { - const temp = a; - a = b; - b = temp; - } - - const field = this.field; - - let rLast = a; - let r = b; - let tLast = field.getZero(); - let t = field.getOne(); - - // Run Euclidean algorithm until r's degree is less than R/2 - while (r.getDegree() >= (R / 2 | 0)) { - let rLastLast = rLast; - let tLastLast = tLast; - rLast = r; - tLast = t; - - // Divide rLastLast by rLast, with quotient in q and remainder in r - if (rLast.isZero()) { - // Oops, Euclidean algorithm already terminated? - throw new ReedSolomonException('r_{i-1} was zero'); - } - r = rLastLast; - let q = field.getZero(); - const denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree()); - const dltInverse = field.inverse(denominatorLeadingTerm); - while (r.getDegree() >= rLast.getDegree() && !r.isZero()) { - const degreeDiff = r.getDegree() - rLast.getDegree(); - const scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse); - q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale)); - r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale)); - } - - t = q.multiply(tLast).addOrSubtract(tLastLast); - - if (r.getDegree() >= rLast.getDegree()) { - throw new IllegalStateException('Division algorithm failed to reduce polynomial?'); - } - } + public constructor(private field: GenericGF) { } - const sigmaTildeAtZero = t.getCoefficient(0); - if (sigmaTildeAtZero === 0) { - throw new ReedSolomonException('sigmaTilde(0) was zero'); - } + /** + *

Decodes given set of received codewords, which include both data and error-correction + * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, + * in the input.

+ * + * @param received data and error-correction codewords + * @param twoS number of error-correction codewords available + * @throws ReedSolomonException if decoding fails for any reason + */ + public decode(received: Int32Array, twoS: number /* int */): void /* throws ReedSolomonException */ { + const field = this.field; + const poly = new GenericGFPoly(field, received); + const syndromeCoefficients = new Int32Array(twoS); + let noError: boolean = true; + for (let i = 0; i < twoS; i++) { + const evalResult = poly.evaluateAt(field.exp(i + field.getGeneratorBase())); + syndromeCoefficients[syndromeCoefficients.length - 1 - i] = evalResult; + if (evalResult !== 0) { + noError = false; + } + } + if (noError) { + return; + } + const syndrome = new GenericGFPoly(field, syndromeCoefficients); + const sigmaOmega = this.runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS); + const sigma = sigmaOmega[0]; + const omega = sigmaOmega[1]; + const errorLocations = this.findErrorLocations(sigma); + const errorMagnitudes = this.findErrorMagnitudes(omega, errorLocations); + for (let i = 0; i < errorLocations.length; i++) { + const position = received.length - 1 - field.log(errorLocations[i]); + if (position < 0) { + throw new ReedSolomonException('Bad error location'); + } + received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]); + } + } + + private runEuclideanAlgorithm(a: GenericGFPoly, b: GenericGFPoly, R: number /* int */): GenericGFPoly[] { + // Assume a's degree is >= b's + if (a.getDegree() < b.getDegree()) { + const temp = a; + a = b; + b = temp; + } - const inverse = field.inverse(sigmaTildeAtZero); - const sigma = t.multiplyScalar(inverse); - const omega = r.multiplyScalar(inverse); - return [sigma, omega]; + const field = this.field; + + let rLast = a; + let r = b; + let tLast = field.getZero(); + let t = field.getOne(); + + // Run Euclidean algorithm until r's degree is less than R/2 + while (r.getDegree() >= (R / 2 | 0)) { + let rLastLast = rLast; + let tLastLast = tLast; + rLast = r; + tLast = t; + + // Divide rLastLast by rLast, with quotient in q and remainder in r + if (rLast.isZero()) { + // Oops, Euclidean algorithm already terminated? + throw new ReedSolomonException('r_{i-1} was zero'); + } + r = rLastLast; + let q = field.getZero(); + const denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree()); + const dltInverse = field.inverse(denominatorLeadingTerm); + while (r.getDegree() >= rLast.getDegree() && !r.isZero()) { + const degreeDiff = r.getDegree() - rLast.getDegree(); + const scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse); + q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale)); + r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale)); + } + + t = q.multiply(tLast).addOrSubtract(tLastLast); + + if (r.getDegree() >= rLast.getDegree()) { + throw new IllegalStateException('Division algorithm failed to reduce polynomial?'); + } } - private findErrorLocations(errorLocator: GenericGFPoly): Int32Array /*throws ReedSolomonException*/ { - // This is a direct application of Chien's search - const numErrors = errorLocator.getDegree(); - if (numErrors === 1) { // shortcut - return Int32Array.from([errorLocator.getCoefficient(1)]); - } - const result = new Int32Array(numErrors); - let e = 0; - const field = this.field; - for (let i = 1; i < field.getSize() && e < numErrors; i++) { - if (errorLocator.evaluateAt(i) === 0) { - result[e] = field.inverse(i); - e++; - } - } - if (e !== numErrors) { - throw new ReedSolomonException('Error locator degree does not match number of roots'); - } - return result; + const sigmaTildeAtZero = t.getCoefficient(0); + if (sigmaTildeAtZero === 0) { + throw new ReedSolomonException('sigmaTilde(0) was zero'); } - private findErrorMagnitudes(errorEvaluator: GenericGFPoly, errorLocations: Int32Array): Int32Array { - // This is directly applying Forney's Formula - const s = errorLocations.length; - const result = new Int32Array(s); - const field = this.field; - for (let i = 0; i < s; i++) { - const xiInverse = field.inverse(errorLocations[i]); - let denominator = 1; - for (let j = 0; j < s; j++) { - if (i !== j) { - // denominator = field.multiply(denominator, - // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))) - // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug. - // Below is a funny-looking workaround from Steven Parkes - const term = field.multiply(errorLocations[j], xiInverse); - const termPlus1 = (term & 0x1) === 0 ? term | 1 : term & ~1; - denominator = field.multiply(denominator, termPlus1); - } - } - result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), - field.inverse(denominator)); - if (field.getGeneratorBase() !== 0) { - result[i] = field.multiply(result[i], xiInverse); - } + const inverse = field.inverse(sigmaTildeAtZero); + const sigma = t.multiplyScalar(inverse); + const omega = r.multiplyScalar(inverse); + return [sigma, omega]; + } + + private findErrorLocations(errorLocator: GenericGFPoly): Int32Array /* throws ReedSolomonException */ { + // This is a direct application of Chien's search + const numErrors = errorLocator.getDegree(); + if (numErrors === 1) { // shortcut + return Int32Array.from([errorLocator.getCoefficient(1)]); + } + const result = new Int32Array(numErrors); + let e = 0; + const field = this.field; + for (let i = 1; i < field.getSize() && e < numErrors; i++) { + if (errorLocator.evaluateAt(i) === 0) { + result[e] = field.inverse(i); + e++; + } + } + if (e !== numErrors) { + throw new ReedSolomonException('Error locator degree does not match number of roots'); + } + return result; + } + + private findErrorMagnitudes(errorEvaluator: GenericGFPoly, errorLocations: Int32Array): Int32Array { + // This is directly applying Forney's Formula + const s = errorLocations.length; + const result = new Int32Array(s); + const field = this.field; + for (let i = 0; i < s; i++) { + const xiInverse = field.inverse(errorLocations[i]); + let denominator = 1; + for (let j = 0; j < s; j++) { + if (i !== j) { + // denominator = field.multiply(denominator, + // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))) + // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug. + // Below is a funny-looking workaround from Steven Parkes + const term = field.multiply(errorLocations[j], xiInverse); + const termPlus1 = (term & 0x1) === 0 ? term | 1 : term & ~1; + denominator = field.multiply(denominator, termPlus1); } - return result; + } + result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), + field.inverse(denominator)); + if (field.getGeneratorBase() !== 0) { + result[i] = field.multiply(result[i], xiInverse); + } } + return result; + } } diff --git a/src/core/common/reedsolomon/ReedSolomonEncoder.ts b/src/core/common/reedsolomon/ReedSolomonEncoder.ts index a97eec14..52e3db89 100644 --- a/src/core/common/reedsolomon/ReedSolomonEncoder.ts +++ b/src/core/common/reedsolomon/ReedSolomonEncoder.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -/*namespace com.google.zxing.common.reedsolomon {*/ +/* namespace com.google.zxing.common.reedsolomon { */ -/*import java.util.ArrayList;*/ -/*import java.util.List;*/ +/* import java.util.ArrayList; */ +/* import java.util.List; */ import GenericGF from './GenericGF'; import GenericGFPoly from './GenericGFPoly'; @@ -33,77 +33,77 @@ import IllegalArgumentException from '../../IllegalArgumentException'; */ export default class ReedSolomonEncoder { - private field: GenericGF; - private cachedGenerators: GenericGFPoly[]; + private field: GenericGF; + private cachedGenerators: GenericGFPoly[]; - /** - * A reed solomon error-correcting encoding constructor is created by - * passing as Galois Field with of size equal to the number of code - * words (symbols) in the alphabet (the number of values in each - * element of arrays that are encoded/decoded). - * @param field A galois field with a number of elements equal to the size - * of the alphabet of symbols to encode. - */ - public constructor(field: GenericGF) { - this.field = field; - this.cachedGenerators = []; - this.cachedGenerators.push(new GenericGFPoly(field, Int32Array.from([1]))); - } + /** + * A reed solomon error-correcting encoding constructor is created by + * passing as Galois Field with of size equal to the number of code + * words (symbols) in the alphabet (the number of values in each + * element of arrays that are encoded/decoded). + * @param field A galois field with a number of elements equal to the size + * of the alphabet of symbols to encode. + */ + public constructor(field: GenericGF) { + this.field = field; + this.cachedGenerators = []; + this.cachedGenerators.push(new GenericGFPoly(field, Int32Array.from([1]))); + } - private buildGenerator(degree: number /*int*/): GenericGFPoly { - const cachedGenerators = this.cachedGenerators; - if (degree >= cachedGenerators.length) { - let lastGenerator = cachedGenerators[cachedGenerators.length - 1]; - const field = this.field; - for (let d = cachedGenerators.length; d <= degree; d++) { - const nextGenerator = lastGenerator.multiply( - new GenericGFPoly(field, Int32Array.from([1, field.exp(d - 1 + field.getGeneratorBase())]))); - cachedGenerators.push(nextGenerator); - lastGenerator = nextGenerator; - } - } - return cachedGenerators[degree]; + private buildGenerator(degree: number /* int */): GenericGFPoly { + const cachedGenerators = this.cachedGenerators; + if (degree >= cachedGenerators.length) { + let lastGenerator = cachedGenerators[cachedGenerators.length - 1]; + const field = this.field; + for (let d = cachedGenerators.length; d <= degree; d++) { + const nextGenerator = lastGenerator.multiply( + new GenericGFPoly(field, Int32Array.from([1, field.exp(d - 1 + field.getGeneratorBase())]))); + cachedGenerators.push(nextGenerator); + lastGenerator = nextGenerator; + } } + return cachedGenerators[degree]; + } - /** - *

Encode a sequence of code words (symbols) using Reed-Solomon to allow decoders - * to detect and correct errors that may have been introduced when the resulting - * data is stored or transmitted.

- * - * @param toEncode array used for both and output. Caller initializes the array with - * the code words (symbols) to be encoded followed by empty elements allocated to make - * space for error-correction code words in the encoded output. The array contains - * the encdoded output when encode returns. Code words are encoded as numbers from - * 0 to n-1, where n is the number of possible code words (symbols), as determined - * by the size of the Galois Field passed in the constructor of this object. - * @param ecBytes the number of elements reserved in the array (first parameter) - * to store error-correction code words. Thus, the number of code words (symbols) - * to encode in the first parameter is thus toEncode.length - ecBytes. - * Note, the use of "bytes" in the name of this parameter is misleading, as there may - * be more or fewer than 256 symbols being encoded, as determined by the number of - * elements in the Galois Field passed as a constructor to this object. - * @throws IllegalArgumentException thrown in response to validation errros. - */ - public encode(toEncode: Int32Array, ecBytes: number /*int*/): void { - if (ecBytes === 0) { - throw new IllegalArgumentException('No error correction bytes'); - } - const dataBytes = toEncode.length - ecBytes; - if (dataBytes <= 0) { - throw new IllegalArgumentException('No data bytes provided'); - } - const generator = this.buildGenerator(ecBytes); - const infoCoefficients: Int32Array = new Int32Array(dataBytes); - System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes); - let info = new GenericGFPoly(this.field, infoCoefficients); - info = info.multiplyByMonomial(ecBytes, 1); - const remainder = info.divide(generator)[1]; - const coefficients = remainder.getCoefficients(); - const numZeroCoefficients = ecBytes - coefficients.length; - for (let i = 0; i < numZeroCoefficients; i++) { - toEncode[dataBytes + i] = 0; - } - System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length); + /** + *

Encode a sequence of code words (symbols) using Reed-Solomon to allow decoders + * to detect and correct errors that may have been introduced when the resulting + * data is stored or transmitted.

+ * + * @param toEncode array used for both and output. Caller initializes the array with + * the code words (symbols) to be encoded followed by empty elements allocated to make + * space for error-correction code words in the encoded output. The array contains + * the encdoded output when encode returns. Code words are encoded as numbers from + * 0 to n-1, where n is the number of possible code words (symbols), as determined + * by the size of the Galois Field passed in the constructor of this object. + * @param ecBytes the number of elements reserved in the array (first parameter) + * to store error-correction code words. Thus, the number of code words (symbols) + * to encode in the first parameter is thus toEncode.length - ecBytes. + * Note, the use of "bytes" in the name of this parameter is misleading, as there may + * be more or fewer than 256 symbols being encoded, as determined by the number of + * elements in the Galois Field passed as a constructor to this object. + * @throws IllegalArgumentException thrown in response to validation errros. + */ + public encode(toEncode: Int32Array, ecBytes: number /* int */): void { + if (ecBytes === 0) { + throw new IllegalArgumentException('No error correction bytes'); + } + const dataBytes = toEncode.length - ecBytes; + if (dataBytes <= 0) { + throw new IllegalArgumentException('No data bytes provided'); + } + const generator = this.buildGenerator(ecBytes); + const infoCoefficients: Int32Array = new Int32Array(dataBytes); + System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes); + let info = new GenericGFPoly(this.field, infoCoefficients); + info = info.multiplyByMonomial(ecBytes, 1); + const remainder = info.divide(generator)[1]; + const coefficients = remainder.getCoefficients(); + const numZeroCoefficients = ecBytes - coefficients.length; + for (let i = 0; i < numZeroCoefficients; i++) { + toEncode[dataBytes + i] = 0; } + System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length); + } } diff --git a/src/core/datamatrix/DataMatrixReader.ts b/src/core/datamatrix/DataMatrixReader.ts index 90d45997..9f1c5ef7 100644 --- a/src/core/datamatrix/DataMatrixReader.ts +++ b/src/core/datamatrix/DataMatrixReader.ts @@ -47,7 +47,7 @@ export default class DataMatrixReader implements Reader { * @throws NotFoundException if a Data Matrix code cannot be found * @throws FormatException if a Data Matrix code cannot be decoded * @throws ChecksumException if error correction fails - */ + */ // @Override // public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException { // return decode(image, null); @@ -100,7 +100,7 @@ export default class DataMatrixReader implements Reader { * case. * * @see com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix) - */ + */ private static extractPureBits(image: BitMatrix): BitMatrix { const leftTopBlack = image.getTopLeftOnBit(); diff --git a/src/core/datamatrix/decoder/BitMatrixParser.ts b/src/core/datamatrix/decoder/BitMatrixParser.ts index ea235a0d..eadb901f 100644 --- a/src/core/datamatrix/decoder/BitMatrixParser.ts +++ b/src/core/datamatrix/decoder/BitMatrixParser.ts @@ -32,7 +32,7 @@ export default class BitMatrixParser { /** * @param bitMatrix {@link BitMatrix} to parse * @throws FormatException if dimension is < 8 or > 144 or not 0 mod 2 - */ + */ constructor(bitMatrix: BitMatrix) { const dimension = bitMatrix.getHeight(); if (dimension < 8 || dimension > 144 || (dimension & 0x01) !== 0) { @@ -58,7 +58,7 @@ export default class BitMatrixParser { * @return {@link Version} encapsulating the Data Matrix Code's "version" * @throws FormatException if the dimensions of the mapping matrix are not valid * Data Matrix dimensions. - */ + */ public static readVersion(bitMatrix: BitMatrix): Version { const numRows = bitMatrix.getHeight(); const numColumns = bitMatrix.getWidth(); @@ -72,7 +72,7 @@ export default class BitMatrixParser { * * @return bytes encoded within the Data Matrix Code * @throws FormatException if the exact number of bytes expected is not read - */ + */ readCodewords(): Int8Array { const result = new Int8Array(this.version.getTotalCodewords()); @@ -127,7 +127,7 @@ export default class BitMatrixParser { // Sweep downward diagonally to the left do { if ((row >= 0) && (column < numColumns) && !this.readMappingMatrix.get(column, row)) { - result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff; + result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff; } row += 2; column -= 2; @@ -151,7 +151,7 @@ export default class BitMatrixParser { * @param numRows Number of rows in the mapping matrix * @param numColumns Number of columns in the mapping matrix * @return value of the given bit in the mapping matrix - */ + */ private readModule(row: number, column: number, numRows: number, numColumns: number): boolean { // Adjust the row and column indices based on boundary wrapping if (row < 0) { @@ -176,7 +176,7 @@ export default class BitMatrixParser { * @param numRows Number of rows in the mapping matrix * @param numColumns Number of columns in the mapping matrix * @return byte from the utah shape - */ + */ private readUtah(row: number, column: number, numRows: number, numColumns: number): number { let currentByte = 0; if (this.readModule(row - 2, column - 2, numRows, numColumns)) { @@ -221,7 +221,7 @@ export default class BitMatrixParser { * @param numRows Number of rows in the mapping matrix * @param numColumns Number of columns in the mapping matrix * @return byte from the Corner condition 1 - */ + */ private readCorner1(numRows: number, numColumns: number): number { let currentByte = 0; if (this.readModule(numRows - 1, 0, numRows, numColumns)) { @@ -266,7 +266,7 @@ export default class BitMatrixParser { * @param numRows Number of rows in the mapping matrix * @param numColumns Number of columns in the mapping matrix * @return byte from the Corner condition 2 - */ + */ private readCorner2(numRows: number, numColumns: number): number { let currentByte = 0; if (this.readModule(numRows - 3, 0, numRows, numColumns)) { @@ -311,7 +311,7 @@ export default class BitMatrixParser { * @param numRows Number of rows in the mapping matrix * @param numColumns Number of columns in the mapping matrix * @return byte from the Corner condition 3 - */ + */ private readCorner3(numRows: number, numColumns: number): number { let currentByte = 0; if (this.readModule(numRows - 1, 0, numRows, numColumns)) { @@ -356,7 +356,7 @@ export default class BitMatrixParser { * @param numRows Number of rows in the mapping matrix * @param numColumns Number of columns in the mapping matrix * @return byte from the Corner condition 4 - */ + */ private readCorner4(numRows: number, numColumns: number): number { let currentByte = 0; if (this.readModule(numRows - 3, 0, numRows, numColumns)) { @@ -399,7 +399,7 @@ export default class BitMatrixParser { * * @param bitMatrix Original {@link BitMatrix} with alignment patterns * @return BitMatrix that has the alignment patterns removed - */ + */ private extractDataRegion(bitMatrix: BitMatrix): BitMatrix { const symbolSizeRows = this.version.getSymbolSizeRows(); const symbolSizeColumns = this.version.getSymbolSizeColumns(); diff --git a/src/core/datamatrix/decoder/DataBlock.ts b/src/core/datamatrix/decoder/DataBlock.ts index 9e686fee..f27ea6a2 100644 --- a/src/core/datamatrix/decoder/DataBlock.ts +++ b/src/core/datamatrix/decoder/DataBlock.ts @@ -44,9 +44,9 @@ export default class DataBlock { * @param version version of the Data Matrix Code * @return DataBlocks containing original bytes, "de-interleaved" from representation in the * Data Matrix Code - */ + */ static getDataBlocks(rawCodewords: Int8Array, - version: Version): DataBlock[] { + version: Version): DataBlock[] { // Figure out the number and size of data blocks used by this version const ecBlocks = version.getECBlocks(); @@ -54,7 +54,7 @@ export default class DataBlock { let totalBlocks = 0; const ecBlockArray = ecBlocks.getECBlocks(); for (let ecBlock of ecBlockArray) { - totalBlocks += ecBlock.getCount(); + totalBlocks += ecBlock.getCount(); } // Now establish DataBlocks of the appropriate size and number of data codewords diff --git a/src/core/datamatrix/decoder/DecodedBitStreamParser.ts b/src/core/datamatrix/decoder/DecodedBitStreamParser.ts index 9f801292..edecf16c 100644 --- a/src/core/datamatrix/decoder/DecodedBitStreamParser.ts +++ b/src/core/datamatrix/decoder/DecodedBitStreamParser.ts @@ -47,7 +47,7 @@ export default class DecodedBitStreamParser { /** * See ISO 16022:2006, Annex C Table C.1 * The C40 Basic Character Set (*'s used for placeholders for the shift values) - */ + */ private static C40_BASIC_SET_CHARS: string[] = [ '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', @@ -55,14 +55,14 @@ export default class DecodedBitStreamParser { ]; private static C40_SHIFT2_SET_CHARS: string[] = [ - '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', - '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_' + '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', + '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_' ]; /** * See ISO 16022:2006, Annex C Table C.2 * The Text Basic Character Set (*'s used for placeholders for the shift values) - */ + */ private static TEXT_BASIC_SET_CHARS: string[] = [ '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', @@ -74,10 +74,10 @@ export default class DecodedBitStreamParser { private static TEXT_SHIFT3_SET_CHARS: string[] = [ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', String.fromCharCode(127) + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', String.fromCharCode(127) ]; - static decode(bytes: Uint8Array): DecoderResult { + static decode(bytes: Uint8Array): DecoderResult { const bits = new BitSource(bytes); const result = new StringBuilder(); const resultTrailer = new StringBuilder(); @@ -117,10 +117,10 @@ export default class DecodedBitStreamParser { /** * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2 - */ + */ private static decodeAsciiSegment(bits: BitSource, - result: StringBuilder, - resultTrailer: StringBuilder): Mode { + result: StringBuilder, + resultTrailer: StringBuilder): Mode { let upperShift = false; do { let oneByte = bits.readBits(8); @@ -160,11 +160,11 @@ export default class DecodedBitStreamParser { break; case 236: // 05 Macro result.append('[)>\u001E05\u001D'); - resultTrailer.insert(0, '\u001E\u0004'); + resultTrailer.insert(0, '\u001E\u0004', 2); // Replacing two characters break; case 237: // 06 Macro result.append('[)>\u001E06\u001D'); - resultTrailer.insert(0, '\u001E\u0004'); + resultTrailer.insert(0, '\u001E\u0004', 2); // Replacing two characters break; case 238: // Latch to ANSI X12 encodation return Mode.ANSIX12_ENCODE; @@ -192,7 +192,7 @@ export default class DecodedBitStreamParser { /** * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1 - */ + */ private static decodeC40Segment(bits: BitSource, result: StringBuilder): void { // Three C40 values are encoded in a 16-bit value as // (1600 * C1) + (40 * C2) + C3 + 1 @@ -258,7 +258,7 @@ export default class DecodedBitStreamParser { upperShift = true; break; default: - throw new FormatException(); + throw new FormatException(); } } shift = 0; @@ -281,7 +281,7 @@ export default class DecodedBitStreamParser { /** * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2 - */ + */ private static decodeTextSegment(bits: BitSource, result: StringBuilder): void { // Three Text values are encoded in a 16-bit value as // (1600 * C1) + (40 * C2) + C3 + 1 @@ -348,7 +348,7 @@ export default class DecodedBitStreamParser { upperShift = true; break; default: - throw new FormatException(); + throw new FormatException(); } } shift = 0; @@ -368,7 +368,7 @@ export default class DecodedBitStreamParser { } break; default: - throw new FormatException(); + throw new FormatException(); } } } while (bits.available() > 0); @@ -376,9 +376,9 @@ export default class DecodedBitStreamParser { /** * See ISO 16022:2006, 5.2.7 - */ + */ private static decodeAnsiX12Segment(bits: BitSource, - result: StringBuilder): void { + result: StringBuilder): void { // Three ANSI X12 values are encoded in a 16-bit value as // (1600 * C1) + (40 * C2) + C3 + 1 @@ -436,7 +436,7 @@ export default class DecodedBitStreamParser { /** * See ISO 16022:2006, 5.2.8 and Annex C Table C.3 - */ + */ private static decodeEdifactSegment(bits: BitSource, result: StringBuilder): void { do { // If there is only two or less bytes left then it will be encoded as ASCII @@ -467,10 +467,10 @@ export default class DecodedBitStreamParser { /** * See ISO 16022:2006, 5.2.9 and Annex B, B.2 - */ + */ private static decodeBase256Segment(bits: BitSource, - result: StringBuilder, - byteSegments: Uint8Array[]): void { + result: StringBuilder, + byteSegments: Uint8Array[]): void { // Figure out how long the Base 256 Segment is. let codewordPosition = 1 + bits.getByteOffset(); // position is 1-indexed const d1 = this.unrandomize255State(bits.readBits(8), codewordPosition++); @@ -507,9 +507,9 @@ export default class DecodedBitStreamParser { /** * See ISO 16022:2006, Annex B, B.2 - */ + */ private static unrandomize255State(randomizedBase256Codeword: number, - base256CodewordPosition: number): number { + base256CodewordPosition: number): number { const pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1; const tempVariable = randomizedBase256Codeword - pseudoRandomNumber; return tempVariable >= 0 ? tempVariable : tempVariable + 256; diff --git a/src/core/datamatrix/decoder/Decoder.ts b/src/core/datamatrix/decoder/Decoder.ts index e2b933d9..c22c690d 100644 --- a/src/core/datamatrix/decoder/Decoder.ts +++ b/src/core/datamatrix/decoder/Decoder.ts @@ -45,7 +45,7 @@ export default class Decoder { * @return text and bytes encoded within the Data Matrix Code * @throws FormatException if the Data Matrix Code cannot be decoded * @throws ChecksumException if error correction fails - */ + */ public decode(bits: BitMatrix): DecoderResult { // Construct a parser and read version, error-correction level const parser = new BitMatrixParser(bits); @@ -87,7 +87,7 @@ export default class Decoder { * @param codewordBytes data and error correction codewords * @param numDataCodewords number of codewords that are data bytes * @throws ChecksumException if error correction fails - */ + */ private correctErrors(codewordBytes: Uint8Array, numDataCodewords: number): void { // const numCodewords = codewordBytes.length; // First read into an array of ints diff --git a/src/core/datamatrix/decoder/Version.ts b/src/core/datamatrix/decoder/Version.ts index 7c413249..9aa86e7f 100644 --- a/src/core/datamatrix/decoder/Version.ts +++ b/src/core/datamatrix/decoder/Version.ts @@ -18,53 +18,53 @@ import FormatException from '../../FormatException'; */ - /** - *

Encapsulates a set of error-correction blocks in one symbol version. Most versions will - * use blocks of differing sizes within one version, so, this encapsulates the parameters for - * each set of blocks. It also holds the number of error-correction codewords per block since it - * will be the same across all blocks within one version.

- */ - export class ECBlocks { - private ecCodewords: number; - private ecBlocks: ECB[]; - - constructor(ecCodewords: number, ecBlocks1: ECB, ecBlocks2?: ECB) { - this.ecCodewords = ecCodewords; - this.ecBlocks = [ ecBlocks1 ]; - ecBlocks2 && this.ecBlocks.push(ecBlocks2); - } +/** + *

Encapsulates a set of error-correction blocks in one symbol version. Most versions will + * use blocks of differing sizes within one version, so, this encapsulates the parameters for + * each set of blocks. It also holds the number of error-correction codewords per block since it + * will be the same across all blocks within one version.

+ */ +export class ECBlocks { + private ecCodewords: number; + private ecBlocks: ECB[]; + + constructor(ecCodewords: number, ecBlocks1: ECB, ecBlocks2?: ECB) { + this.ecCodewords = ecCodewords; + this.ecBlocks = [ecBlocks1]; + ecBlocks2 && this.ecBlocks.push(ecBlocks2); + } - getECCodewords(): number { - return this.ecCodewords; - } + getECCodewords(): number { + return this.ecCodewords; + } - getECBlocks(): ECB[] { - return this.ecBlocks; - } + getECBlocks(): ECB[] { + return this.ecBlocks; } +} - /** - *

Encapsulates the parameters for one error-correction block in one symbol version. - * This includes the number of data codewords, and the number of times a block with these - * parameters is used consecutively in the Data Matrix code version's format.

- */ +/** + *

Encapsulates the parameters for one error-correction block in one symbol version. + * This includes the number of data codewords, and the number of times a block with these + * parameters is used consecutively in the Data Matrix code version's format.

+ */ export class ECB { - private count: number; - private dataCodewords: number; + private count: number; + private dataCodewords: number; - constructor(count: number, dataCodewords: number) { - this.count = count; - this.dataCodewords = dataCodewords; - } + constructor(count: number, dataCodewords: number) { + this.count = count; + this.dataCodewords = dataCodewords; + } - getCount(): number { - return this.count; - } + getCount(): number { + return this.count; + } - getDataCodewords(): number { - return this.dataCodewords; - } + getDataCodewords(): number { + return this.dataCodewords; } +} /** * The Version object encapsulates attributes about a particular @@ -85,11 +85,11 @@ export default class Version { private totalCodewords: number; constructor(versionNumber, - symbolSizeRows, - symbolSizeColumns, - dataRegionSizeRows, - dataRegionSizeColumns, - ecBlocks: ECBlocks) { + symbolSizeRows, + symbolSizeColumns, + dataRegionSizeRows, + dataRegionSizeColumns, + ecBlocks: ECBlocks) { this.versionNumber = versionNumber; this.symbolSizeRows = symbolSizeRows; this.symbolSizeColumns = symbolSizeColumns; @@ -142,7 +142,7 @@ export default class Version { * @param numColumns Number of columns in modules * @return Version for a Data Matrix Code of those dimensions * @throws FormatException if dimensions do correspond to a valid Data Matrix size - */ + */ public static getVersionForDimensions(numRows: number, numColumns: number): Version { if ((numRows & 0x01) !== 0 || (numColumns & 0x01) !== 0) { throw new FormatException(); @@ -157,77 +157,77 @@ export default class Version { throw new FormatException(); } -// @Override + // @Override public toString(): string { return '' + this.versionNumber; } /** * See ISO 16022:2006 5.5.1 Table 7 - */ + */ private static buildVersions(): Version[] { return [ - new Version(1, 10, 10, 8, 8, - new ECBlocks(5, new ECB(1, 3))), - new Version(2, 12, 12, 10, 10, - new ECBlocks(7, new ECB(1, 5))), - new Version(3, 14, 14, 12, 12, - new ECBlocks(10, new ECB(1, 8))), - new Version(4, 16, 16, 14, 14, - new ECBlocks(12, new ECB(1, 12))), - new Version(5, 18, 18, 16, 16, - new ECBlocks(14, new ECB(1, 18))), - new Version(6, 20, 20, 18, 18, - new ECBlocks(18, new ECB(1, 22))), - new Version(7, 22, 22, 20, 20, - new ECBlocks(20, new ECB(1, 30))), - new Version(8, 24, 24, 22, 22, - new ECBlocks(24, new ECB(1, 36))), - new Version(9, 26, 26, 24, 24, - new ECBlocks(28, new ECB(1, 44))), - new Version(10, 32, 32, 14, 14, - new ECBlocks(36, new ECB(1, 62))), - new Version(11, 36, 36, 16, 16, - new ECBlocks(42, new ECB(1, 86))), - new Version(12, 40, 40, 18, 18, - new ECBlocks(48, new ECB(1, 114))), - new Version(13, 44, 44, 20, 20, - new ECBlocks(56, new ECB(1, 144))), - new Version(14, 48, 48, 22, 22, - new ECBlocks(68, new ECB(1, 174))), - new Version(15, 52, 52, 24, 24, - new ECBlocks(42, new ECB(2, 102))), - new Version(16, 64, 64, 14, 14, - new ECBlocks(56, new ECB(2, 140))), - new Version(17, 72, 72, 16, 16, - new ECBlocks(36, new ECB(4, 92))), - new Version(18, 80, 80, 18, 18, - new ECBlocks(48, new ECB(4, 114))), - new Version(19, 88, 88, 20, 20, - new ECBlocks(56, new ECB(4, 144))), - new Version(20, 96, 96, 22, 22, - new ECBlocks(68, new ECB(4, 174))), - new Version(21, 104, 104, 24, 24, - new ECBlocks(56, new ECB(6, 136))), - new Version(22, 120, 120, 18, 18, - new ECBlocks(68, new ECB(6, 175))), - new Version(23, 132, 132, 20, 20, - new ECBlocks(62, new ECB(8, 163))), - new Version(24, 144, 144, 22, 22, - new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))), - new Version(25, 8, 18, 6, 16, - new ECBlocks(7, new ECB(1, 5))), - new Version(26, 8, 32, 6, 14, - new ECBlocks(11, new ECB(1, 10))), - new Version(27, 12, 26, 10, 24, - new ECBlocks(14, new ECB(1, 16))), - new Version(28, 12, 36, 10, 16, - new ECBlocks(18, new ECB(1, 22))), - new Version(29, 16, 36, 14, 16, - new ECBlocks(24, new ECB(1, 32))), - new Version(30, 16, 48, 14, 22, - new ECBlocks(28, new ECB(1, 49))) - ]; + new Version(1, 10, 10, 8, 8, + new ECBlocks(5, new ECB(1, 3))), + new Version(2, 12, 12, 10, 10, + new ECBlocks(7, new ECB(1, 5))), + new Version(3, 14, 14, 12, 12, + new ECBlocks(10, new ECB(1, 8))), + new Version(4, 16, 16, 14, 14, + new ECBlocks(12, new ECB(1, 12))), + new Version(5, 18, 18, 16, 16, + new ECBlocks(14, new ECB(1, 18))), + new Version(6, 20, 20, 18, 18, + new ECBlocks(18, new ECB(1, 22))), + new Version(7, 22, 22, 20, 20, + new ECBlocks(20, new ECB(1, 30))), + new Version(8, 24, 24, 22, 22, + new ECBlocks(24, new ECB(1, 36))), + new Version(9, 26, 26, 24, 24, + new ECBlocks(28, new ECB(1, 44))), + new Version(10, 32, 32, 14, 14, + new ECBlocks(36, new ECB(1, 62))), + new Version(11, 36, 36, 16, 16, + new ECBlocks(42, new ECB(1, 86))), + new Version(12, 40, 40, 18, 18, + new ECBlocks(48, new ECB(1, 114))), + new Version(13, 44, 44, 20, 20, + new ECBlocks(56, new ECB(1, 144))), + new Version(14, 48, 48, 22, 22, + new ECBlocks(68, new ECB(1, 174))), + new Version(15, 52, 52, 24, 24, + new ECBlocks(42, new ECB(2, 102))), + new Version(16, 64, 64, 14, 14, + new ECBlocks(56, new ECB(2, 140))), + new Version(17, 72, 72, 16, 16, + new ECBlocks(36, new ECB(4, 92))), + new Version(18, 80, 80, 18, 18, + new ECBlocks(48, new ECB(4, 114))), + new Version(19, 88, 88, 20, 20, + new ECBlocks(56, new ECB(4, 144))), + new Version(20, 96, 96, 22, 22, + new ECBlocks(68, new ECB(4, 174))), + new Version(21, 104, 104, 24, 24, + new ECBlocks(56, new ECB(6, 136))), + new Version(22, 120, 120, 18, 18, + new ECBlocks(68, new ECB(6, 175))), + new Version(23, 132, 132, 20, 20, + new ECBlocks(62, new ECB(8, 163))), + new Version(24, 144, 144, 22, 22, + new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))), + new Version(25, 8, 18, 6, 16, + new ECBlocks(7, new ECB(1, 5))), + new Version(26, 8, 32, 6, 14, + new ECBlocks(11, new ECB(1, 10))), + new Version(27, 12, 26, 10, 24, + new ECBlocks(14, new ECB(1, 16))), + new Version(28, 12, 36, 10, 16, + new ECBlocks(18, new ECB(1, 22))), + new Version(29, 16, 36, 14, 16, + new ECBlocks(24, new ECB(1, 32))), + new Version(30, 16, 48, 14, 22, + new ECBlocks(28, new ECB(1, 49))) + ]; } } diff --git a/src/core/datamatrix/detector/Detector.ts b/src/core/datamatrix/detector/Detector.ts index ff6c133c..c668643c 100644 --- a/src/core/datamatrix/detector/Detector.ts +++ b/src/core/datamatrix/detector/Detector.ts @@ -44,7 +44,7 @@ export default class Detector { * * @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code * @throws NotFoundException if no Data Matrix Code can be found - */ + */ public detect(): DetectorResult { @@ -54,7 +54,7 @@ export default class Detector { points = this.detectSolid2(points); points[3] = this.correctTopRight(points); if (!points[3]) { - throw new NotFoundException(); + throw new NotFoundException(); } points = this.shiftToModuleCenter(points); @@ -78,12 +78,12 @@ export default class Detector { } let bits = Detector.sampleGrid(this.image, - topLeft, - bottomLeft, - bottomRight, - topRight, - dimensionTop, - dimensionRight); + topLeft, + bottomLeft, + bottomRight, + topRight, + dimensionTop, + dimensionRight); return new DetectorResult(bits, [topLeft, bottomLeft, bottomRight, topRight]); } @@ -115,7 +115,7 @@ export default class Detector { /** * Detect a solid side which has minimum transition. - */ + */ private detectSolid1(cornerPoints: ResultPoint[]): ResultPoint[] { // 0 2 // 1 3 @@ -160,7 +160,7 @@ export default class Detector { /** * Detect a second solid side next to first solid side. - */ + */ private detectSolid2(points: ResultPoint[]): ResultPoint[] { // A..D // : : @@ -200,7 +200,7 @@ export default class Detector { /** * Calculates the corner position of the white top right module. - */ + */ private correctTopRight(points: ResultPoint[]): ResultPoint { // A..D // | : @@ -222,7 +222,7 @@ export default class Detector { let candidate1 = new ResultPoint( pointD.getX() + (pointC.getX() - pointB.getX()) / (trTop + 1), pointD.getY() + (pointC.getY() - pointB.getY()) / (trTop + 1)); - let candidate2 = new ResultPoint( + let candidate2 = new ResultPoint( pointD.getX() + (pointA.getX() - pointB.getX()) / (trRight + 1), pointD.getY() + (pointA.getY() - pointB.getY()) / (trRight + 1)); @@ -248,7 +248,7 @@ export default class Detector { /** * Shift the edge points to the module center. - */ + */ private shiftToModuleCenter(points: ResultPoint[]): ResultPoint[] { // A..D // | : @@ -306,39 +306,39 @@ export default class Detector { } private static sampleGrid(image: BitMatrix, - topLeft: ResultPoint, - bottomLeft: ResultPoint, - bottomRight: ResultPoint, - topRight: ResultPoint, - dimensionX: int, - dimensionY: int): BitMatrix { + topLeft: ResultPoint, + bottomLeft: ResultPoint, + bottomRight: ResultPoint, + topRight: ResultPoint, + dimensionX: int, + dimensionY: int): BitMatrix { const sampler = GridSamplerInstance.getInstance(); return sampler.sampleGrid(image, - dimensionX, - dimensionY, - 0.5, - 0.5, - dimensionX - 0.5, - 0.5, - dimensionX - 0.5, - dimensionY - 0.5, - 0.5, - dimensionY - 0.5, - topLeft.getX(), - topLeft.getY(), - topRight.getX(), - topRight.getY(), - bottomRight.getX(), - bottomRight.getY(), - bottomLeft.getX(), - bottomLeft.getY()); + dimensionX, + dimensionY, + 0.5, + 0.5, + dimensionX - 0.5, + 0.5, + dimensionX - 0.5, + dimensionY - 0.5, + 0.5, + dimensionY - 0.5, + topLeft.getX(), + topLeft.getY(), + topRight.getX(), + topRight.getY(), + bottomRight.getX(), + bottomRight.getY(), + bottomLeft.getX(), + bottomLeft.getY()); } /** * Counts the number of black/white transitions between two points, using something like Bresenham's algorithm. - */ + */ private transitionsBetween(from: ResultPoint, to: ResultPoint): int { // See QR Code Detector, sizeOfBlackWhiteBlackRun() let fromX = Math.trunc(from.getX()); diff --git a/src/core/multi/MultipleBarcodeReader.ts b/src/core/multi/MultipleBarcodeReader.ts index b8d7c4e6..56184045 100644 --- a/src/core/multi/MultipleBarcodeReader.ts +++ b/src/core/multi/MultipleBarcodeReader.ts @@ -32,16 +32,16 @@ import Result from '../Result'; * @see com.google.zxing.Reader * @author Sean Owen */ -export default /*public*/ interface MultipleBarcodeReader { +export default /* public */ interface MultipleBarcodeReader { /** * @throws NotFoundException - */ + */ decodeMultiple(image: BinaryBitmap): Result[]; /** * @throws NotFoundException - */ + */ decodeMultiple(image: BinaryBitmap, hints: Map): Result[]; } diff --git a/src/core/multi/qrcode/QRCodeMultiReader.ts b/src/core/multi/qrcode/QRCodeMultiReader.ts new file mode 100644 index 00000000..71e3a227 --- /dev/null +++ b/src/core/multi/qrcode/QRCodeMultiReader.ts @@ -0,0 +1,193 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { int, List } from '../../../customTypings'; +import BarcodeFormat from '../../BarcodeFormat'; +import BinaryBitmap from '../../BinaryBitmap'; +import DecoderResult from '../../common/DecoderResult'; +import DetectorResult from '../../common/DetectorResult'; +import DecodeHintType from '../../DecodeHintType'; +import QRCodeDecoderMetaData from '../../qrcode/decoder/QRCodeDecoderMetaData'; +import QRCodeReader from '../../qrcode/QRCodeReader'; +import ReaderException from '../../ReaderException'; +import Result from '../../Result'; +import ResultMetadataType from '../../ResultMetadataType'; +import ResultPoint from '../../ResultPoint'; +import ByteArrayOutputStream from '../../util/ByteArrayOutputStream'; +import Collections from '../../util/Collections'; +import Comparator from '../../util/Comparator'; +import Integer from '../../util/Integer'; +import StringBuilder from '../../util/StringBuilder'; +import MultipleBarcodeReader from '../MultipleBarcodeReader'; +import MultiDetector from './detector/MultiDetector'; + +// package com.google.zxing.multi.qrcode; + +// import com.google.zxing.BarcodeFormat; +// import com.google.zxing.BinaryBitmap; +// import com.google.zxing.DecodeHintType; +// import com.google.zxing.NotFoundException; +// import com.google.zxing.ReaderException; +// import com.google.zxing.Result; +// import com.google.zxing.ResultMetadataType; +// import com.google.zxing.ResultPoint; +// import com.google.zxing.common.DecoderResult; +// import com.google.zxing.common.DetectorResult; +// import com.google.zxing.multi.MultipleBarcodeReader; +// import com.google.zxing.multi.qrcode.detector.MultiDetector; +// import com.google.zxing.qrcode.QRCodeReader; +// import com.google.zxing.qrcode.decoder.QRCodeDecoderMetaData; + +// import java.io.ByteArrayOutputStream; +// import java.io.Serializable; +// import java.util.ArrayList; +// import java.util.List; +// import java.util.Map; +// import java.util.Collections; +// import java.util.Comparator; + +/** + * This implementation can detect and decode multiple QR Codes in an image. + * + * @author Sean Owen + * @author Hannes Erven + */ +export default /*public final*/ class QRCodeMultiReader extends QRCodeReader implements MultipleBarcodeReader { + + private static /* final */ EMPTY_RESULT_ARRAY: Result[] = []; + protected static /* final */ NO_POINTS = new Array(); + + /** + * TYPESCRIPTPORT: this is an overloaded method so here it'll work only as a entrypoint for choosing which overload to call. + */ + public decodeMultiple(image: BinaryBitmap, hints: Map = null): Result[] { + + if (hints && hints instanceof Map) { + return this.decodeMultipleImpl(image, hints); + } + + return this.decodeMultipleOverload1(image); + } + + /** + * @throws NotFoundException + * @override decodeMultiple + */ + private decodeMultipleOverload1(image: BinaryBitmap): Result[] { + return this.decodeMultipleImpl(image, null); + } + + /** + * @override + * @throws NotFoundException + */ + private decodeMultipleImpl(image: BinaryBitmap, hints: Map): Result[] { + let results: List = []; + const detectorResults: DetectorResult[] = new MultiDetector(image.getBlackMatrix()).detectMulti(hints); + for (const detectorResult of detectorResults) { + try { + const decoderResult: DecoderResult = this.getDecoder().decodeBitMatrix(detectorResult.getBits(), hints); + const points: ResultPoint[] = detectorResult.getPoints(); + // If the code was mirrored: swap the bottom-left and the top-right points. + if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) { + ( decoderResult.getOther()).applyMirroredCorrection(points); + } + const result: Result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, + BarcodeFormat.QR_CODE); + const byteSegments: List = decoderResult.getByteSegments(); + if (byteSegments != null) { + result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); + } + const ecLevel: string = decoderResult.getECLevel(); + if (ecLevel != null) { + result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); + } + if (decoderResult.hasStructuredAppend()) { + result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, + decoderResult.getStructuredAppendSequenceNumber()); + result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, + decoderResult.getStructuredAppendParity()); + } + results.push(result); + } catch (re) { + if (re instanceof ReaderException) { + // ignore and continue + } else { + throw re; + } + } + } + if (results.length === 0) { + return QRCodeMultiReader.EMPTY_RESULT_ARRAY; + } else { + results = QRCodeMultiReader.processStructuredAppend(results); + return results/* .toArray(QRCodeMultiReader.EMPTY_RESULT_ARRAY) */; + } + } + + static processStructuredAppend( results: List): List { + const newResults: List = []; + const saResults: List = []; + for (const result of results) { + if (result.getResultMetadata().has(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) { + saResults.push(result); + } else { + newResults.push(result); + } + } + if (saResults.length === 0) { + return results; + } + + // sort and concatenate the SA list items + Collections.sort(saResults, new SAComparator()); + const newText: StringBuilder = new StringBuilder(); + const newRawBytes: ByteArrayOutputStream = new ByteArrayOutputStream(); + const newByteSegment: ByteArrayOutputStream = new ByteArrayOutputStream(); + for (const saResult of saResults) { + newText.append(saResult.getText()); + const saBytes: Uint8Array = saResult.getRawBytes(); + newRawBytes.writeBytesOffset(saBytes, 0, saBytes.length); + // @SuppressWarnings("unchecked") + const byteSegments: Iterable = + > saResult.getResultMetadata().get(ResultMetadataType.BYTE_SEGMENTS); + if (byteSegments != null) { + for (const segment of byteSegments) { + newByteSegment.writeBytesOffset(segment, 0, segment.length); + } + } + } + + const newResult: Result = new Result(newText.toString(), newRawBytes.toByteArray(), QRCodeMultiReader.NO_POINTS, BarcodeFormat.QR_CODE); + if (newByteSegment.size() > 0) { + newResult.putMetadata(ResultMetadataType.BYTE_SEGMENTS, Collections.singletonList(newByteSegment.toByteArray())); + } + newResults.push(newResult); // TYPESCRIPTPORT: inserted element at the start of the array because it seems the Java version does that as well. + return newResults; + } + +} + +/* private static final*/ class SAComparator implements Comparator/*, Serializable*/ { + /** + * @override + */ + public compare(a: Result, b: Result): int { + const aNumber: int = a.getResultMetadata().get(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE); + const bNumber: int = b.getResultMetadata().get(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE); + return Integer.compare(aNumber, bNumber); + } +} diff --git a/src/core/multi/qrcode/detector/MultiDetector.ts b/src/core/multi/qrcode/detector/MultiDetector.ts new file mode 100644 index 00000000..f669a4af --- /dev/null +++ b/src/core/multi/qrcode/detector/MultiDetector.ts @@ -0,0 +1,89 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import BitMatrix from '../../../common/BitMatrix'; +import DetectorResult from '../../../common/DetectorResult'; +import DecodeHintType from '../../../DecodeHintType'; +import NotFoundException from '../../../NotFoundException'; +import Detector from '../../../qrcode/detector/Detector'; +import FinderPatternInfo from '../../../qrcode/detector/FinderPatternInfo'; +import ReaderException from '../../../ReaderException'; +import ResultPointCallback from '../../../ResultPointCallback'; +import { List } from '../../../../customTypings'; +import MultiFinderPatternFinder from './MultiFinderPatternFinder'; + +// package com.google.zxing.multi.qrcode.detector; + +// import com.google.zxing.DecodeHintType; +// import com.google.zxing.NotFoundException; +// import com.google.zxing.ReaderException; +// import com.google.zxing.ResultPointCallback; +// import com.google.zxing.common.BitMatrix; +// import com.google.zxing.common.DetectorResult; +// import com.google.zxing.qrcode.detector.Detector; +// import com.google.zxing.qrcode.detector.FinderPatternInfo; + +// import java.util.ArrayList; +// import java.util.List; +// import java.util.Map; + +/** + *

Encapsulates logic that can detect one or more QR Codes in an image, even if the QR Code + * is rotated or skewed, or partially obscured.

+ * + * @author Sean Owen + * @author Hannes Erven + */ +export default /* public final */ class MultiDetector extends Detector { + + private static /* final */ EMPTY_DETECTOR_RESULTS: DetectorResult[] = []; + + public constructor( image: BitMatrix) { + super(image); + } + + /** @throws NotFoundException */ + public detectMulti(hints: Map): DetectorResult[] { + const image: BitMatrix = this.getImage(); + const resultPointCallback: ResultPointCallback = + hints == null ? null : hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); + const finder: MultiFinderPatternFinder = new MultiFinderPatternFinder(image, resultPointCallback); + const infos: FinderPatternInfo[] = finder.findMulti(hints); + + if (infos.length === 0) { + throw NotFoundException.getNotFoundInstance(); + } + + const result: List = []; + for (const info of infos) { + try { + result.push(this.processFinderPatternInfo(info)); + } catch (e) { + if (e instanceof ReaderException) { + // ignore + } else { + throw e; + } + } + } + if (result.length === 0) { + return MultiDetector.EMPTY_DETECTOR_RESULTS; + } else { + return result/* .toArray(EMPTY_DETECTOR_RESULTS) */; + } + } + +} diff --git a/src/core/multi/qrcode/detector/MultiFinderPatternFinder.ts b/src/core/multi/qrcode/detector/MultiFinderPatternFinder.ts new file mode 100644 index 00000000..6d6dbba9 --- /dev/null +++ b/src/core/multi/qrcode/detector/MultiFinderPatternFinder.ts @@ -0,0 +1,300 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import BitMatrix from '../../../common/BitMatrix'; +import DecodeHintType from '../../../DecodeHintType'; +import NotFoundException from '../../../NotFoundException'; +import FinderPattern from '../../../qrcode/detector/FinderPattern'; +import FinderPatternFinder from '../../../qrcode/detector/FinderPatternFinder'; +import FinderPatternInfo from '../../../qrcode/detector/FinderPatternInfo'; +import ResultPoint from '../../../ResultPoint'; +import ResultPointCallback from '../../../ResultPointCallback'; +import Collections from '../../../util/Collections'; +import Comparator from '../../../util/Comparator'; +import { double, float, int, List } from '../../../../customTypings'; + +// package com.google.zxing.multi.qrcode.detector; + +// import com.google.zxing.DecodeHintType; +// import com.google.zxing.NotFoundException; +// import com.google.zxing.ResultPoint; +// import com.google.zxing.ResultPointCallback; +// import com.google.zxing.common.BitMatrix; +// import com.google.zxing.qrcode.detector.FinderPattern; +// import com.google.zxing.qrcode.detector.FinderPatternFinder; +// import com.google.zxing.qrcode.detector.FinderPatternInfo; + +// import java.io.Serializable; +// import java.util.ArrayList; +// import java.util.Collections; +// import java.util.Comparator; +// import java.util.List; +// import java.util.Map; + +/** + *

This class attempts to find finder patterns in a QR Code. Finder patterns are the square + * markers at three corners of a QR Code.

+ * + *

This class is thread-safe but not reentrant. Each thread must allocate its own object. + * + *

In contrast to {@link FinderPatternFinder}, this class will return an array of all possible + * QR code locations in the image.

+ * + *

Use the TRY_HARDER hint to ask for a more thorough detection.

+ * + * @author Sean Owen + * @author Hannes Erven + */ +export default /* public final */ class MultiFinderPatternFinder extends FinderPatternFinder { + + private static /* final */ EMPTY_RESULT_ARRAY: FinderPatternInfo[] = []; + private static /* final */ EMPTY_FP_ARRAY: FinderPattern[] = []; + private static /* final */ EMPTY_FP_2D_ARRAY: FinderPattern[][] = [[]]; + + // TODO MIN_MODULE_COUNT and MAX_MODULE_COUNT would be great hints to ask the user for + // since it limits the number of regions to decode + + // max. legal count of modules per QR code edge (177) + private static /* final */ MAX_MODULE_COUNT_PER_EDGE: float = 180; + // min. legal count per modules per QR code edge (11) + private static /* final */ MIN_MODULE_COUNT_PER_EDGE: float = 9; + + /** + * More or less arbitrary cutoff point for determining if two finder patterns might belong + * to the same code if they differ less than DIFF_MODSIZE_CUTOFF_PERCENT percent in their + * estimated modules sizes. + */ + private static /* final */ DIFF_MODSIZE_CUTOFF_PERCENT: float = 0.05; + + /** + * More or less arbitrary cutoff point for determining if two finder patterns might belong + * to the same code if they differ less than DIFF_MODSIZE_CUTOFF pixels/module in their + * estimated modules sizes. + */ + private static /* final */ DIFF_MODSIZE_CUTOFF: float = 0.5; + + + public constructor(image: BitMatrix, resultPointCallback: ResultPointCallback) { + super(image, resultPointCallback); + } + + /** + * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are + * those that have been detected at least 2 times, and whose module + * size differs from the average among those patterns the least + * @throws NotFoundException if 3 such finder patterns do not exist + */ + private selectMultipleBestPatterns(): FinderPattern[][] { + const possibleCenters: List = this.getPossibleCenters(); + const size: int = possibleCenters.length; + + if (size < 3) { + // Couldn't find enough finder patterns + throw NotFoundException.getNotFoundInstance(); + } + + /* + * Begin HE modifications to safely detect multiple codes of equal size + */ + if (size === 3) { + return [ possibleCenters ]; + } + + // Sort by estimated module size to speed up the upcoming checks + Collections.sort(possibleCenters, new ModuleSizeComparator()); + + /* + * Now lets start: build a list of tuples of three finder locations that + * - feature similar module sizes + * - are placed in a distance so the estimated module count is within the QR specification + * - have similar distance between upper left/right and left top/bottom finder patterns + * - form a triangle with 90° angle (checked by comparing top right/bottom left distance + * with pythagoras) + * + * Note: we allow each point to be used for more than one code region: this might seem + * counterintuitive at first, but the performance penalty is not that big. At this point, + * we cannot make a good quality decision whether the three finders actually represent + * a QR code, or are just by chance laid out so it looks like there might be a QR code there. + * So, if the layout seems right, lets have the decoder try to decode. + */ + + const results: List = new Array(); // holder for the results + + for (let i1: int = 0; i1 < (size - 2); i1++) { + const p1: FinderPattern = possibleCenters[i1]; + if (p1 == null) { + continue; + } + + for (let i2: int = i1 + 1; i2 < (size - 1); i2++) { + const p2: FinderPattern = possibleCenters[i2]; + if (p2 == null) { + continue; + } + + // Compare the expected module sizes; if they are really off, skip + const vModSize12: float = (p1.getEstimatedModuleSize() - p2.getEstimatedModuleSize()) / + Math.min(p1.getEstimatedModuleSize(), p2.getEstimatedModuleSize()); + const vModSize12A: float = Math.abs(p1.getEstimatedModuleSize() - p2.getEstimatedModuleSize()); + if (vModSize12A > MultiFinderPatternFinder.DIFF_MODSIZE_CUTOFF && vModSize12 >= MultiFinderPatternFinder.DIFF_MODSIZE_CUTOFF_PERCENT) { + // break, since elements are ordered by the module size deviation there cannot be + // any more interesting elements for the given p1. + break; + } + + for (let i3: int = i2 + 1; i3 < size; i3++) { + const p3: FinderPattern = possibleCenters[i3]; + if (p3 == null) { + continue; + } + + // Compare the expected module sizes; if they are really off, skip + const vModSize23: float = (p2.getEstimatedModuleSize() - p3.getEstimatedModuleSize()) / + Math.min(p2.getEstimatedModuleSize(), p3.getEstimatedModuleSize()); + const vModSize23A: float = Math.abs(p2.getEstimatedModuleSize() - p3.getEstimatedModuleSize()); + if (vModSize23A > MultiFinderPatternFinder.DIFF_MODSIZE_CUTOFF && vModSize23 >= MultiFinderPatternFinder.DIFF_MODSIZE_CUTOFF_PERCENT) { + // break, since elements are ordered by the module size deviation there cannot be + // any more interesting elements for the given p1. + break; + } + + const test: FinderPattern[] = [p1, p2, p3]; + ResultPoint.orderBestPatterns(test); + + // Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal + const info: FinderPatternInfo = new FinderPatternInfo(test); + const dA: float = ResultPoint.distance(info.getTopLeft(), info.getBottomLeft()); + const dC: float = ResultPoint.distance(info.getTopRight(), info.getBottomLeft()); + const dB: float = ResultPoint.distance(info.getTopLeft(), info.getTopRight()); + + // Check the sizes + const estimatedModuleCount: float = (dA + dB) / (p1.getEstimatedModuleSize() * 2.0); + if (estimatedModuleCount > MultiFinderPatternFinder.MAX_MODULE_COUNT_PER_EDGE || + estimatedModuleCount < MultiFinderPatternFinder.MIN_MODULE_COUNT_PER_EDGE) { + continue; + } + + // Calculate the difference of the edge lengths in percent + const vABBC: float = Math.abs((dA - dB) / Math.min(dA, dB)); + if (vABBC >= 0.1) { + continue; + } + + // Calculate the diagonal length by assuming a 90° angle at topleft + const dCpy: float = Math.sqrt( dA * dA + dB * dB); + // Compare to the real distance in % + const vPyC: float = Math.abs((dC - dCpy) / Math.min(dC, dCpy)); + + if (vPyC >= 0.1) { + continue; + } + + // All tests passed! + results.push(test); + } + } + } + + if (results.length > 0) { + return results/* .toArray(MultiFinderPatternFinder.EMPTY_FP_2D_ARRAY) */; + } + + // Nothing found! + throw NotFoundException.getNotFoundInstance(); + } + + /** + * @throws NotFoundException + */ + public findMulti(hints: Map): FinderPatternInfo[] { + const tryHarder: boolean = hints != null && hints.has(DecodeHintType.TRY_HARDER); + const image: BitMatrix = this.getImage(); + const maxI: int = image.getHeight(); + const maxJ: int = image.getWidth(); + // We are looking for black/white/black/white/black modules in + // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far + + // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the + // image, and then account for the center being 3 modules in size. This gives the smallest + // number of pixels the center could be, so skip this often. When trying harder, look for all + // QR versions regardless of how dense they are. + let iSkip: int = Math.trunc((3 * maxI) / (4 * MultiFinderPatternFinder.MAX_MODULES)); // TYPESCRIPTPORT: Java integer divisions always discard decimal chars. + if (iSkip < MultiFinderPatternFinder.MIN_SKIP || tryHarder) { + iSkip = MultiFinderPatternFinder.MIN_SKIP; + } + + const stateCount: Int32Array = Int32Array.from({ length: 5 }); + for (let i: int = iSkip - 1; i < maxI; i += iSkip) { + // Get a row of black/white values + this.clearCounts(stateCount); + let currentState: int = 0; + for (let j: int = 0; j < maxJ; j++) { + if (image.get(j, i)) { + // Black pixel + if ((currentState & 1) === 1) { // Counting white pixels + currentState++; + } + stateCount[currentState]++; + } else { // White pixel + if ((currentState & 1) === 0) { // Counting black pixels + if (currentState === 4) { // A winner? + if (MultiFinderPatternFinder.foundPatternCross(stateCount) && this.handlePossibleCenter(stateCount, i, j)) { // Yes + // Clear state to start looking again + currentState = 0; + this.clearCounts(stateCount); + } else { // No, shift counts back by two + this.shiftCounts2(stateCount); + currentState = 3; + } + } else { + stateCount[++currentState]++; + } + } else { // Counting white pixels + stateCount[currentState]++; + } + } + } // for j=... + + if (MultiFinderPatternFinder.foundPatternCross(stateCount)) { + this.handlePossibleCenter(stateCount, i, maxJ); + } + } // for i=iSkip-1 ... + const patternInfo: FinderPattern[][] = this.selectMultipleBestPatterns(); + const result: List = new Array(); + for (const pattern of patternInfo) { + ResultPoint.orderBestPatterns(pattern); + result.push(new FinderPatternInfo(pattern)); + } + + if (result.length === 0) { + return MultiFinderPatternFinder.EMPTY_RESULT_ARRAY; + } else { + return result/* .toArray(MultiFinderPatternFinder.EMPTY_RESULT_ARRAY) */; + } + } + +} + + /** + * A comparator that orders FinderPatterns by their estimated module size. + */ + /* private static final */ class ModuleSizeComparator implements Comparator/* , Serializable */ { + /** @override */ + public compare(center1: FinderPattern, center2: FinderPattern): int { + const value: float = center2.getEstimatedModuleSize() - center1.getEstimatedModuleSize(); + return value < 0.0 ? -1 : value > 0.0 ? 1 : 0; + } + } diff --git a/src/core/oned/AbstractUPCEANReader.ts b/src/core/oned/AbstractUPCEANReader.ts index 5704dc0f..271c247d 100644 --- a/src/core/oned/AbstractUPCEANReader.ts +++ b/src/core/oned/AbstractUPCEANReader.ts @@ -16,6 +16,7 @@ import BitArray from '../common/BitArray'; import DecodeHintType from '../DecodeHintType'; +import StringBuilder from '../util/StringBuilder'; import Result from '../Result'; import OneDReader from './OneDReader'; @@ -32,210 +33,237 @@ import { int } from '../../customTypings'; * @author alasdair@google.com (Alasdair Mackintosh) */ export default abstract class AbstractUPCEANReader extends OneDReader { - // These two values are critical for determining how permissive the decoding will be. - // We've arrived at these values through a lot of trial and error. Setting them any higher - // lets false positives creep in quickly. - private static MAX_AVG_VARIANCE = 0.48; - private static MAX_INDIVIDUAL_VARIANCE = 0.7; - - /** - * Start/end guard pattern. - */ - public static START_END_PATTERN: Int32Array = Int32Array.from([1, 1, 1]); - - /** - * Pattern marking the middle of a UPC/EAN pattern, separating the two halves. - */ - public static MIDDLE_PATTERN: Int32Array = Int32Array.from([1, 1, 1, 1, 1]); - /** - * end guard pattern. - */ - public static END_PATTERN: Int32Array = Int32Array.from([1, 1, 1, 1, 1, 1]); - /** - * "Odd", or "L" patterns used to encode UPC/EAN digits. - */ - public static L_PATTERNS: Int32Array[] = [ - Int32Array.from([3, 2, 1, 1]), // 0 - Int32Array.from([2, 2, 2, 1]), // 1 - Int32Array.from([2, 1, 2, 2]), // 2 - Int32Array.from([1, 4, 1, 1]), // 3 - Int32Array.from([1, 1, 3, 2]), // 4 - Int32Array.from([1, 2, 3, 1]), // 5 - Int32Array.from([1, 1, 1, 4]), // 6 - Int32Array.from([1, 3, 1, 2]), // 7 - Int32Array.from([1, 2, 1, 3]), // 8 - Int32Array.from([3, 1, 1, 2]), // 9 - ]; - - /** - * As above but also including the "even", or "G" patterns used to encode UPC/EAN digits. - */ - public static L_AND_G_PATTERNS: Int32Array[]; - - protected decodeRowStringBuffer = ''; - // private final UPCEANExtensionSupport extensionReader; - // private final EANManufacturerOrgSupport eanManSupport; - - - /* - protected UPCEANReader() { - decodeRowStringBuffer = new StringBuilder(20); - extensionReader = new UPCEANExtensionSupport(); - eanManSupport = new EANManufacturerOrgSupport(); - } - */ - - static findStartGuardPattern(row: BitArray): Int32Array { - let foundStart = false; - let startRange: Int32Array; - let nextStart = 0; - let counters = Int32Array.from([0, 0, 0]); - while (!foundStart) { - counters = Int32Array.from([0, 0, 0]); - startRange = AbstractUPCEANReader.findGuardPattern(row, nextStart, false, this.START_END_PATTERN, counters); - let start = startRange[0]; - nextStart = startRange[1]; - let quietStart = start - (nextStart - start); - if (quietStart >= 0) { - foundStart = row.isRange(quietStart, start, false); - } - } - return startRange; - } + // These two values are critical for determining how permissive the decoding will be. + // We've arrived at these values through a lot of trial and error. Setting them any higher + // lets false positives creep in quickly. + private static MAX_AVG_VARIANCE = 0.48; + private static MAX_INDIVIDUAL_VARIANCE = 0.7; - public abstract decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result; + /** + * Start/end guard pattern. + */ + public static START_END_PATTERN: Int32Array = Int32Array.from([1, 1, 1]); - static checkChecksum(s: string): boolean { - return AbstractUPCEANReader.checkStandardUPCEANChecksum(s); - } + /** + * Pattern marking the middle of a UPC/EAN pattern, separating the two halves. + */ + public static MIDDLE_PATTERN: Int32Array = Int32Array.from([1, 1, 1, 1, 1]); + /** + * end guard pattern. + */ + public static END_PATTERN: Int32Array = Int32Array.from([1, 1, 1, 1, 1, 1]); + /** + * "Odd", or "L" patterns used to encode UPC/EAN digits. + */ + public static L_PATTERNS: Int32Array[] = [ + Int32Array.from([3, 2, 1, 1]), // 0 + Int32Array.from([2, 2, 2, 1]), // 1 + Int32Array.from([2, 1, 2, 2]), // 2 + Int32Array.from([1, 4, 1, 1]), // 3 + Int32Array.from([1, 1, 3, 2]), // 4 + Int32Array.from([1, 2, 3, 1]), // 5 + Int32Array.from([1, 1, 1, 4]), // 6 + Int32Array.from([1, 3, 1, 2]), // 7 + Int32Array.from([1, 2, 1, 3]), // 8 + Int32Array.from([3, 1, 1, 2]), // 9 + ]; - static checkStandardUPCEANChecksum(s: string): boolean { - let length = s.length; - if (length === 0) return false; + /** + * As above but also including the "even", or "G" patterns used to encode UPC/EAN digits. + */ + public static L_AND_G_PATTERNS: Int32Array[]; - let check = parseInt(s.charAt(length - 1), 10); - return AbstractUPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check; - } + protected decodeRowStringBuffer = new StringBuilder(); + // private final UPCEANExtensionSupport extensionReader; + // private final EANManufacturerOrgSupport eanManSupport; - static getStandardUPCEANChecksum(s: string): number { - let length = s.length; - let sum = 0; - for (let i = length - 1; i >= 0; i -= 2) { - let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); - if (digit < 0 || digit > 9) { - throw new FormatException(); - } - sum += digit; - } - sum *= 3; - for (let i = length - 2; i >= 0; i -= 2) { - let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); - if (digit < 0 || digit > 9) { - throw new FormatException(); - } - sum += digit; - } - return (1000 - sum) % 10; - } - static decodeEnd(row: BitArray, endStart: number): Int32Array { - return AbstractUPCEANReader.findGuardPattern(row, endStart, false, AbstractUPCEANReader.START_END_PATTERN, new Int32Array(AbstractUPCEANReader.START_END_PATTERN.length).fill(0)); - } + /* + protected UPCEANReader() { + decodeRowStringBuffer = new StringBuilder(20); + extensionReader = new UPCEANExtensionSupport(); + eanManSupport = new EANManufacturerOrgSupport(); + } + */ - /** - * @throws NotFoundException - */ - static findGuardPatternWithoutCounters( - row: BitArray, - rowOffset: int, - whiteFirst: boolean, - pattern: Int32Array, - ): Int32Array { - return this.findGuardPattern(row, rowOffset, whiteFirst, pattern, new Int32Array(pattern.length)); + static findStartGuardPattern(row: BitArray): Int32Array { + let foundStart = false; + let startRange: Int32Array; + let nextStart = 0; + let counters: Int32Array; + while (!foundStart) { + counters = new Int32Array(3); + startRange = AbstractUPCEANReader.findGuardPattern(row, nextStart, false, this.START_END_PATTERN, counters); + let start = startRange[0]; + nextStart = startRange[1]; + let quietStart = start - (nextStart - start); + if (quietStart >= 0) { + foundStart = row.isRange(quietStart, start, false); + } } + return startRange; + } - /** - * @param row row of black/white values to search - * @param rowOffset position to start search - * @param whiteFirst if true, indicates that the pattern specifies white/black/white/... - * pixel counts, otherwise, it is interpreted as black/white/black/... - * @param pattern pattern of counts of number of black and white pixels that are being - * searched for as a pattern - * @param counters array of counters, as long as pattern, to re-use - * @return start/end horizontal offset of guard pattern, as an array of two ints - * @throws NotFoundException if pattern is not found - */ - static findGuardPattern(row: BitArray, rowOffset: number, whiteFirst: boolean, pattern: Int32Array, counters: Int32Array): Int32Array { - let width = row.getSize(); - rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset); - let counterPosition = 0; - let patternStart = rowOffset; - let patternLength = pattern.length; - let isWhite = whiteFirst; - for (let x = rowOffset; x < width; x++) { - if (row.get(x) !== isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition === patternLength - 1) { - if (OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE) < AbstractUPCEANReader.MAX_AVG_VARIANCE) { - return Int32Array.from([patternStart, x]); - } - patternStart += counters[0] + counters[1]; - - let slice = counters.slice(2, counters.length - 1); - for (let i = 0; i < counterPosition - 1; i++) { - counters[i] = slice[i]; - } - - counters[counterPosition - 1] = 0; - counters[counterPosition] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw new NotFoundException(); + /** + * Attempts to decode a one-dimensional barcode format given a single row of + * an image. + * + * @param rowNumber row number from top of the row + * @param row the black/white pixel data of the row + * @param hints hints that influence decoding + * @return containing encoded string and start/end of barcode + * @throws {@link NotFoundException} if no potential barcode is found + * @throws {@link ChecksumException} if a potential barcode is found but does not pass its checksum + * @throws {@link FormatException} if a potential barcode is found but format is invalid + */ + public abstract decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result; + /** + * Attempts to decode a one-dimensional barcode format given a single row of + * an image, but allows caller to inform method about where the UPC/EAN start pattern is found. + * This allows this to be computed once and reused across many implementations. + * + * @param rowNumber row number from top of the row + * @param row the black/white pixel data of the row + * @param startGuardRange start/end column where the opening start pattern is found + * @param hints hints that influence decoding + * @return encapsulating the result of decoding a barcode in the row + * @throws {@link NotFoundException} if no potential barcode is found + * @throws {@link ChecksumException} if a potential barcode is found but does not pass its checksum + * @throws {@link FormatException} if a potential barcode is found but format is invalid + */ + public abstract decodeRow(rowNumber: number, row: BitArray, startGuardRange: Int32Array, hints?: Map): Result; + + static checkChecksum(s: string): boolean { + return AbstractUPCEANReader.checkStandardUPCEANChecksum(s); + } + + static checkStandardUPCEANChecksum(s: string): boolean { + let length = s.length; + if (length === 0) return false; + + let check = parseInt(s.charAt(length - 1), 10); + return AbstractUPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check; + } + + static getStandardUPCEANChecksum(s: string): number { + let length = s.length; + let sum = 0; + for (let i = length - 1; i >= 0; i -= 2) { + let digit = s.charCodeAt(i) - '0'.charCodeAt(0); + if (digit < 0 || digit > 9) { + throw new FormatException(); + } + sum += digit; + } + sum *= 3; + for (let i = length - 2; i >= 0; i -= 2) { + let digit = s.charCodeAt(i) - '0'.charCodeAt(0); + if (digit < 0 || digit > 9) { + throw new FormatException(); + } + sum += digit; } + return (1000 - sum) % 10; + } - static decodeDigit(row: BitArray, counters: Int32Array, rowOffset: int, patterns: Int32Array[]) { - this.recordPattern(row, rowOffset, counters); - let bestVariance = this.MAX_AVG_VARIANCE; - let bestMatch = -1; - let max = patterns.length; - for (let i = 0; i < max; i++) { - let pattern = patterns[i]; - let variance = OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) { - bestVariance = variance; - bestMatch = i; - } - } - if (bestMatch >= 0) { - return bestMatch; + protected decodeEnd(row: BitArray, endStart: number): Int32Array { + return AbstractUPCEANReader.findGuardPattern(row, endStart, false, AbstractUPCEANReader.START_END_PATTERN); + } + + /** + * @param row row of black/white values to search + * @param rowOffset position to start search + * @param whiteFirst if true, indicates that the pattern specifies white/black/white/... + * pixel counts, otherwise, it is interpreted as black/white/black/... + * @param pattern pattern of counts of number of black and white pixels that are being + * searched for as a pattern + * @return start/end horizontal offset of guard pattern, as an array of two ints + * @throws {@link NotFoundException} if pattern is not found + */ + static findGuardPattern(row: BitArray, rowOffset: int, whiteFirst: boolean, pattern: Int32Array): Int32Array; + /** + * @param row row of black/white values to search + * @param rowOffset position to start search + * @param whiteFirst if true, indicates that the pattern specifies white/black/white/... + * pixel counts, otherwise, it is interpreted as black/white/black/... + * @param pattern pattern of counts of number of black and white pixels that are being + * searched for as a pattern + * @param counters array of counters, as long as pattern, to re-use + * @return start/end horizontal offset of guard pattern, as an array of two ints + * @throws {@link NotFoundException} if pattern is not found + */ + static findGuardPattern(row: BitArray, rowOffset: number, whiteFirst: boolean, pattern: Int32Array, counters: Int32Array): Int32Array; + static findGuardPattern(row: BitArray, rowOffset: number, whiteFirst: boolean, pattern: Int32Array, counters?: Int32Array): Int32Array { + if (typeof counters === 'undefined') counters = new Int32Array(pattern.length); + return this.findGuardPatternImpl(row, rowOffset, whiteFirst, pattern, counters); + } + + static findGuardPatternImpl(row: BitArray, rowOffset: number, whiteFirst: boolean, pattern: Int32Array, counters: Int32Array): Int32Array { + let width = row.getSize(); + rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset); + let counterPosition = 0; + let patternStart = rowOffset; + let patternLength = pattern.length; + let isWhite = whiteFirst; + for (let x = rowOffset; x < width; x++) { + if (row.get(x) !== isWhite) { + counters[counterPosition]++; + } else { + if (counterPosition === patternLength - 1) { + if (OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE) < AbstractUPCEANReader.MAX_AVG_VARIANCE) { + return new Int32Array([patternStart, x]); + } + patternStart += counters[0] + counters[1]; + counters.copyWithin(0, 2, 2 + counterPosition - 1); + counters[counterPosition - 1] = 0; + counters[counterPosition] = 0; + counterPosition--; } else { - throw new NotFoundException(); + counterPosition++; } + counters[counterPosition] = 1; + isWhite = !isWhite; + } + } + throw new NotFoundException(); + } + + static decodeDigit(row: BitArray, counters: Int32Array, rowOffset: int, patterns: Int32Array[]) { + this.recordPattern(row, rowOffset, counters); + let bestVariance = this.MAX_AVG_VARIANCE; + let bestMatch = -1; + let max = patterns.length; + for (let i = 0; i < max; i++) { + let pattern = patterns[i]; + let variance = OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE); + if (variance < bestVariance) { + bestVariance = variance; + bestMatch = i; + } + } + if (bestMatch >= 0) { + return bestMatch; + } else { + throw new NotFoundException(); } + } - /** - * Get the format of this decoder. - * - * @return The 1D format. - */ - public abstract getBarcodeFormat(); - - /** - * Subclasses override this to decode the portion of a barcode between the start - * and end guard patterns. - * - * @param row row of black/white values to search - * @param startRange start/end offset of start guard pattern - * @param resultString {@link StringBuilder} to append decoded chars to - * @return horizontal offset of first pixel after the "middle" that was decoded - * @throws NotFoundException if decoding could not complete successfully - */ - public abstract decodeMiddle(row: BitArray, startRange: Int32Array, resultString: /*StringBuilder*/string); + /** + * Get the format of this decoder. + * + * @return The 1D format. + */ + public abstract getBarcodeFormat(); + + /** + * Subclasses override this to decode the portion of a barcode between the start + * and end guard patterns. + * + * @param row row of black/white values to search + * @param startRange start/end offset of start guard pattern + * @param resultString to append decoded chars to + * @return horizontal offset of first pixel after the "middle" that was decoded + * @throws NotFoundException if decoding could not complete successfully + */ + public abstract decodeMiddle(row: BitArray, startRange: Int32Array, resultString: StringBuilder); } diff --git a/src/core/oned/Code128Reader.ts b/src/core/oned/Code128Reader.ts index 72c5bb68..9e483329 100644 --- a/src/core/oned/Code128Reader.ts +++ b/src/core/oned/Code128Reader.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.oned {*/ +/* namespace com.google.zxing.oned { */ import BarcodeFormat from '../BarcodeFormat'; import ChecksumException from '../ChecksumException'; @@ -37,115 +37,115 @@ import OneDReader from './OneDReader'; */ export default class Code128Reader extends OneDReader { - private static CODE_PATTERNS: Int32Array[] = [ - Int32Array.from([2, 1, 2, 2, 2, 2]), - Int32Array.from([2, 2, 2, 1, 2, 2]), - Int32Array.from([2, 2, 2, 2, 2, 1]), - Int32Array.from([1, 2, 1, 2, 2, 3]), - Int32Array.from([1, 2, 1, 3, 2, 2]), - Int32Array.from([1, 3, 1, 2, 2, 2]), - Int32Array.from([1, 2, 2, 2, 1, 3]), - Int32Array.from([1, 2, 2, 3, 1, 2]), - Int32Array.from([1, 3, 2, 2, 1, 2]), - Int32Array.from([2, 2, 1, 2, 1, 3]), - Int32Array.from([2, 2, 1, 3, 1, 2]), - Int32Array.from([2, 3, 1, 2, 1, 2]), - Int32Array.from([1, 1, 2, 2, 3, 2]), - Int32Array.from([1, 2, 2, 1, 3, 2]), - Int32Array.from([1, 2, 2, 2, 3, 1]), - Int32Array.from([1, 1, 3, 2, 2, 2]), - Int32Array.from([1, 2, 3, 1, 2, 2]), - Int32Array.from([1, 2, 3, 2, 2, 1]), - Int32Array.from([2, 2, 3, 2, 1, 1]), - Int32Array.from([2, 2, 1, 1, 3, 2]), - Int32Array.from([2, 2, 1, 2, 3, 1]), - Int32Array.from([2, 1, 3, 2, 1, 2]), - Int32Array.from([2, 2, 3, 1, 1, 2]), - Int32Array.from([3, 1, 2, 1, 3, 1]), - Int32Array.from([3, 1, 1, 2, 2, 2]), - Int32Array.from([3, 2, 1, 1, 2, 2]), - Int32Array.from([3, 2, 1, 2, 2, 1]), - Int32Array.from([3, 1, 2, 2, 1, 2]), - Int32Array.from([3, 2, 2, 1, 1, 2]), - Int32Array.from([3, 2, 2, 2, 1, 1]), - Int32Array.from([2, 1, 2, 1, 2, 3]), - Int32Array.from([2, 1, 2, 3, 2, 1]), - Int32Array.from([2, 3, 2, 1, 2, 1]), - Int32Array.from([1, 1, 1, 3, 2, 3]), - Int32Array.from([1, 3, 1, 1, 2, 3]), - Int32Array.from([1, 3, 1, 3, 2, 1]), - Int32Array.from([1, 1, 2, 3, 1, 3]), - Int32Array.from([1, 3, 2, 1, 1, 3]), - Int32Array.from([1, 3, 2, 3, 1, 1]), - Int32Array.from([2, 1, 1, 3, 1, 3]), - Int32Array.from([2, 3, 1, 1, 1, 3]), - Int32Array.from([2, 3, 1, 3, 1, 1]), - Int32Array.from([1, 1, 2, 1, 3, 3]), - Int32Array.from([1, 1, 2, 3, 3, 1]), - Int32Array.from([1, 3, 2, 1, 3, 1]), - Int32Array.from([1, 1, 3, 1, 2, 3]), - Int32Array.from([1, 1, 3, 3, 2, 1]), - Int32Array.from([1, 3, 3, 1, 2, 1]), - Int32Array.from([3, 1, 3, 1, 2, 1]), - Int32Array.from([2, 1, 1, 3, 3, 1]), - Int32Array.from([2, 3, 1, 1, 3, 1]), - Int32Array.from([2, 1, 3, 1, 1, 3]), - Int32Array.from([2, 1, 3, 3, 1, 1]), - Int32Array.from([2, 1, 3, 1, 3, 1]), - Int32Array.from([3, 1, 1, 1, 2, 3]), - Int32Array.from([3, 1, 1, 3, 2, 1]), - Int32Array.from([3, 3, 1, 1, 2, 1]), - Int32Array.from([3, 1, 2, 1, 1, 3]), - Int32Array.from([3, 1, 2, 3, 1, 1]), - Int32Array.from([3, 3, 2, 1, 1, 1]), - Int32Array.from([3, 1, 4, 1, 1, 1]), - Int32Array.from([2, 2, 1, 4, 1, 1]), - Int32Array.from([4, 3, 1, 1, 1, 1]), - Int32Array.from([1, 1, 1, 2, 2, 4]), - Int32Array.from([1, 1, 1, 4, 2, 2]), - Int32Array.from([1, 2, 1, 1, 2, 4]), - Int32Array.from([1, 2, 1, 4, 2, 1]), - Int32Array.from([1, 4, 1, 1, 2, 2]), - Int32Array.from([1, 4, 1, 2, 2, 1]), - Int32Array.from([1, 1, 2, 2, 1, 4]), - Int32Array.from([1, 1, 2, 4, 1, 2]), - Int32Array.from([1, 2, 2, 1, 1, 4]), - Int32Array.from([1, 2, 2, 4, 1, 1]), - Int32Array.from([1, 4, 2, 1, 1, 2]), - Int32Array.from([1, 4, 2, 2, 1, 1]), - Int32Array.from([2, 4, 1, 2, 1, 1]), - Int32Array.from([2, 2, 1, 1, 1, 4]), - Int32Array.from([4, 1, 3, 1, 1, 1]), - Int32Array.from([2, 4, 1, 1, 1, 2]), - Int32Array.from([1, 3, 4, 1, 1, 1]), - Int32Array.from([1, 1, 1, 2, 4, 2]), - Int32Array.from([1, 2, 1, 1, 4, 2]), - Int32Array.from([1, 2, 1, 2, 4, 1]), - Int32Array.from([1, 1, 4, 2, 1, 2]), - Int32Array.from([1, 2, 4, 1, 1, 2]), - Int32Array.from([1, 2, 4, 2, 1, 1]), - Int32Array.from([4, 1, 1, 2, 1, 2]), - Int32Array.from([4, 2, 1, 1, 1, 2]), - Int32Array.from([4, 2, 1, 2, 1, 1]), - Int32Array.from([2, 1, 2, 1, 4, 1]), - Int32Array.from([2, 1, 4, 1, 2, 1]), - Int32Array.from([4, 1, 2, 1, 2, 1]), - Int32Array.from([1, 1, 1, 1, 4, 3]), - Int32Array.from([1, 1, 1, 3, 4, 1]), - Int32Array.from([1, 3, 1, 1, 4, 1]), - Int32Array.from([1, 1, 4, 1, 1, 3]), - Int32Array.from([1, 1, 4, 3, 1, 1]), - Int32Array.from([4, 1, 1, 1, 1, 3]), - Int32Array.from([4, 1, 1, 3, 1, 1]), - Int32Array.from([1, 1, 3, 1, 4, 1]), - Int32Array.from([1, 1, 4, 1, 3, 1]), - Int32Array.from([3, 1, 1, 1, 4, 1]), - Int32Array.from([4, 1, 1, 1, 3, 1]), - Int32Array.from([2, 1, 1, 4, 1, 2]), - Int32Array.from([2, 1, 1, 2, 1, 4]), - Int32Array.from([2, 1, 1, 2, 3, 2]), - Int32Array.from([2, 3, 3, 1, 1, 1, 2]), - ]; + private static CODE_PATTERNS: Int32Array[] = [ + Int32Array.from([2, 1, 2, 2, 2, 2]), + Int32Array.from([2, 2, 2, 1, 2, 2]), + Int32Array.from([2, 2, 2, 2, 2, 1]), + Int32Array.from([1, 2, 1, 2, 2, 3]), + Int32Array.from([1, 2, 1, 3, 2, 2]), + Int32Array.from([1, 3, 1, 2, 2, 2]), + Int32Array.from([1, 2, 2, 2, 1, 3]), + Int32Array.from([1, 2, 2, 3, 1, 2]), + Int32Array.from([1, 3, 2, 2, 1, 2]), + Int32Array.from([2, 2, 1, 2, 1, 3]), + Int32Array.from([2, 2, 1, 3, 1, 2]), + Int32Array.from([2, 3, 1, 2, 1, 2]), + Int32Array.from([1, 1, 2, 2, 3, 2]), + Int32Array.from([1, 2, 2, 1, 3, 2]), + Int32Array.from([1, 2, 2, 2, 3, 1]), + Int32Array.from([1, 1, 3, 2, 2, 2]), + Int32Array.from([1, 2, 3, 1, 2, 2]), + Int32Array.from([1, 2, 3, 2, 2, 1]), + Int32Array.from([2, 2, 3, 2, 1, 1]), + Int32Array.from([2, 2, 1, 1, 3, 2]), + Int32Array.from([2, 2, 1, 2, 3, 1]), + Int32Array.from([2, 1, 3, 2, 1, 2]), + Int32Array.from([2, 2, 3, 1, 1, 2]), + Int32Array.from([3, 1, 2, 1, 3, 1]), + Int32Array.from([3, 1, 1, 2, 2, 2]), + Int32Array.from([3, 2, 1, 1, 2, 2]), + Int32Array.from([3, 2, 1, 2, 2, 1]), + Int32Array.from([3, 1, 2, 2, 1, 2]), + Int32Array.from([3, 2, 2, 1, 1, 2]), + Int32Array.from([3, 2, 2, 2, 1, 1]), + Int32Array.from([2, 1, 2, 1, 2, 3]), + Int32Array.from([2, 1, 2, 3, 2, 1]), + Int32Array.from([2, 3, 2, 1, 2, 1]), + Int32Array.from([1, 1, 1, 3, 2, 3]), + Int32Array.from([1, 3, 1, 1, 2, 3]), + Int32Array.from([1, 3, 1, 3, 2, 1]), + Int32Array.from([1, 1, 2, 3, 1, 3]), + Int32Array.from([1, 3, 2, 1, 1, 3]), + Int32Array.from([1, 3, 2, 3, 1, 1]), + Int32Array.from([2, 1, 1, 3, 1, 3]), + Int32Array.from([2, 3, 1, 1, 1, 3]), + Int32Array.from([2, 3, 1, 3, 1, 1]), + Int32Array.from([1, 1, 2, 1, 3, 3]), + Int32Array.from([1, 1, 2, 3, 3, 1]), + Int32Array.from([1, 3, 2, 1, 3, 1]), + Int32Array.from([1, 1, 3, 1, 2, 3]), + Int32Array.from([1, 1, 3, 3, 2, 1]), + Int32Array.from([1, 3, 3, 1, 2, 1]), + Int32Array.from([3, 1, 3, 1, 2, 1]), + Int32Array.from([2, 1, 1, 3, 3, 1]), + Int32Array.from([2, 3, 1, 1, 3, 1]), + Int32Array.from([2, 1, 3, 1, 1, 3]), + Int32Array.from([2, 1, 3, 3, 1, 1]), + Int32Array.from([2, 1, 3, 1, 3, 1]), + Int32Array.from([3, 1, 1, 1, 2, 3]), + Int32Array.from([3, 1, 1, 3, 2, 1]), + Int32Array.from([3, 3, 1, 1, 2, 1]), + Int32Array.from([3, 1, 2, 1, 1, 3]), + Int32Array.from([3, 1, 2, 3, 1, 1]), + Int32Array.from([3, 3, 2, 1, 1, 1]), + Int32Array.from([3, 1, 4, 1, 1, 1]), + Int32Array.from([2, 2, 1, 4, 1, 1]), + Int32Array.from([4, 3, 1, 1, 1, 1]), + Int32Array.from([1, 1, 1, 2, 2, 4]), + Int32Array.from([1, 1, 1, 4, 2, 2]), + Int32Array.from([1, 2, 1, 1, 2, 4]), + Int32Array.from([1, 2, 1, 4, 2, 1]), + Int32Array.from([1, 4, 1, 1, 2, 2]), + Int32Array.from([1, 4, 1, 2, 2, 1]), + Int32Array.from([1, 1, 2, 2, 1, 4]), + Int32Array.from([1, 1, 2, 4, 1, 2]), + Int32Array.from([1, 2, 2, 1, 1, 4]), + Int32Array.from([1, 2, 2, 4, 1, 1]), + Int32Array.from([1, 4, 2, 1, 1, 2]), + Int32Array.from([1, 4, 2, 2, 1, 1]), + Int32Array.from([2, 4, 1, 2, 1, 1]), + Int32Array.from([2, 2, 1, 1, 1, 4]), + Int32Array.from([4, 1, 3, 1, 1, 1]), + Int32Array.from([2, 4, 1, 1, 1, 2]), + Int32Array.from([1, 3, 4, 1, 1, 1]), + Int32Array.from([1, 1, 1, 2, 4, 2]), + Int32Array.from([1, 2, 1, 1, 4, 2]), + Int32Array.from([1, 2, 1, 2, 4, 1]), + Int32Array.from([1, 1, 4, 2, 1, 2]), + Int32Array.from([1, 2, 4, 1, 1, 2]), + Int32Array.from([1, 2, 4, 2, 1, 1]), + Int32Array.from([4, 1, 1, 2, 1, 2]), + Int32Array.from([4, 2, 1, 1, 1, 2]), + Int32Array.from([4, 2, 1, 2, 1, 1]), + Int32Array.from([2, 1, 2, 1, 4, 1]), + Int32Array.from([2, 1, 4, 1, 2, 1]), + Int32Array.from([4, 1, 2, 1, 2, 1]), + Int32Array.from([1, 1, 1, 1, 4, 3]), + Int32Array.from([1, 1, 1, 3, 4, 1]), + Int32Array.from([1, 3, 1, 1, 4, 1]), + Int32Array.from([1, 1, 4, 1, 1, 3]), + Int32Array.from([1, 1, 4, 3, 1, 1]), + Int32Array.from([4, 1, 1, 1, 1, 3]), + Int32Array.from([4, 1, 1, 3, 1, 1]), + Int32Array.from([1, 1, 3, 1, 4, 1]), + Int32Array.from([1, 1, 4, 1, 3, 1]), + Int32Array.from([3, 1, 1, 1, 4, 1]), + Int32Array.from([4, 1, 1, 1, 3, 1]), + Int32Array.from([2, 1, 1, 4, 1, 2]), + Int32Array.from([2, 1, 1, 2, 1, 4]), + Int32Array.from([2, 1, 1, 2, 3, 2]), + Int32Array.from([2, 3, 3, 1, 1, 1, 2]), + ]; private static MAX_AVG_VARIANCE = 0.25; private static MAX_INDIVIDUAL_VARIANCE = 0.7; @@ -171,11 +171,11 @@ export default class Code128Reader extends OneDReader { const width = row.getSize(); const rowOffset = row.getNextSet(0); - let counterPosition = 0; - let counters = Int32Array.from([0, 0, 0, 0, 0, 0]); - let patternStart = rowOffset; - let isWhite = false; - const patternLength = 6; + let counterPosition = 0; + let counters = Int32Array.from([0, 0, 0, 0, 0, 0]); + let patternStart = rowOffset; + let isWhite = false; + const patternLength = 6; for (let i = rowOffset; i < width; i++) { if (row.get(i) !== isWhite) { diff --git a/src/core/oned/Code39Reader.ts b/src/core/oned/Code39Reader.ts index 4a2c91af..d57aff13 100644 --- a/src/core/oned/Code39Reader.ts +++ b/src/core/oned/Code39Reader.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.oned {*/ +/* namespace com.google.zxing.oned { */ import BarcodeFormat from '../BarcodeFormat'; import BitArray from '../common/BitArray'; @@ -40,13 +40,13 @@ export default class Code39Reader extends OneDReader { * These represent the encodings of characters, as patterns of wide and narrow bars. * The 9 least-significant bits of each int correspond to the pattern of wide and narrow, * with 1s representing "wide" and 0s representing narrow. - */ + */ private static readonly CHARACTER_ENCODINGS: number[] = [ - 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9 - 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J - 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T - 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x0A8, // U-$ - 0x0A2, 0x08A, 0x02A // /-% + 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9 + 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J + 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T + 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x0A8, // U-$ + 0x0A2, 0x08A, 0x02A // /-% ]; private static readonly ASTERISK_ENCODING = 0x094; @@ -59,7 +59,7 @@ export default class Code39Reader extends OneDReader { /** * Creates a reader that assumes all encoded data is data, and does not treat the final * character as a check digit. It will not decoded "extended Code 39" sequences. - */ + */ // public Code39Reader() { // this(false); // } @@ -70,7 +70,7 @@ export default class Code39Reader extends OneDReader { * * @param usingCheckDigit if true, treat the last data character as a check digit, not * data, and verify that the checksum passes. - */ + */ // public Code39Reader(boolean usingCheckDigit) { // this(usingCheckDigit, false); // } @@ -84,7 +84,7 @@ export default class Code39Reader extends OneDReader { * data, and verify that the checksum passes. * @param extendedMode if true, will attempt to decode extended Code 39 sequences in the * text. - */ + */ public constructor(usingCheckDigit: boolean = false, extendedMode: boolean = false) { super(); this.usingCheckDigit = usingCheckDigit; @@ -186,7 +186,7 @@ export default class Code39Reader extends OneDReader { if (counterPosition === patternLength - 1) { // Look for whitespace before start pattern, >= 50% of width of start pattern if (this.toNarrowWidePattern(counters) === Code39Reader.ASTERISK_ENCODING && - row.isRange(Math.max(0, patternStart - Math.floor((i - patternStart) / 2)), patternStart, false)) { + row.isRange(Math.max(0, patternStart - Math.floor((i - patternStart) / 2)), patternStart, false)) { return [patternStart, i]; } patternStart += counters[0] + counters[1]; diff --git a/src/core/oned/EAN13Reader.ts b/src/core/oned/EAN13Reader.ts index 6412285e..dbb748eb 100644 --- a/src/core/oned/EAN13Reader.ts +++ b/src/core/oned/EAN13Reader.ts @@ -16,6 +16,7 @@ import BarcodeFormat from '../BarcodeFormat'; import BitArray from '../common/BitArray'; +import StringBuilder from '../util/StringBuilder'; import UPCEANReader from './UPCEANReader'; import NotFoundException from '../NotFoundException'; @@ -28,64 +29,64 @@ import NotFoundException from '../NotFoundException'; * @author alasdair@google.com (Alasdair Mackintosh) */ export default class EAN13Reader extends UPCEANReader { - private static FIRST_DIGIT_ENCODINGS: number[] = [0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A]; + private static FIRST_DIGIT_ENCODINGS: number[] = [0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A]; private decodeMiddleCounters: Int32Array; - public constructor() { - super(); - this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]); - } - - public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: string) { - let counters = this.decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - let end = row.getSize(); - let rowOffset = startRange[1]; + public constructor() { + super(); + this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]); + } - let lgPatternFound = 0; + public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: StringBuilder) { + let counters = this.decodeMiddleCounters; + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + let end = row.getSize(); + let rowOffset = startRange[1]; - for (let x = 0; x < 6 && rowOffset < end; x++) { - let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS); - resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10)); - for (let counter of counters) { - rowOffset += counter; - } - if (bestMatch >= 10) { - lgPatternFound |= 1 << (5 - x); - } - } + let lgPatternFound = 0; - resultString = EAN13Reader.determineFirstDigit(resultString, lgPatternFound); + for (let x = 0; x < 6 && rowOffset < end; x++) { + let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS); + resultString.append('0'.charCodeAt(0) + bestMatch % 10); + for (let counter of counters) { + rowOffset += counter; + } + if (bestMatch >= 10) { + lgPatternFound |= 1 << (5 - x); + } + } - let middleRange = UPCEANReader.findGuardPattern(row, rowOffset, true, UPCEANReader.MIDDLE_PATTERN, new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0)); - rowOffset = middleRange[1]; + EAN13Reader.determineFirstDigit(resultString, lgPatternFound); - for (let x = 0; x < 6 && rowOffset < end; x++) { - let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS); - resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch)); - for (let counter of counters) { - rowOffset += counter; - } - } + let middleRange = UPCEANReader.findGuardPattern(row, rowOffset, true, UPCEANReader.MIDDLE_PATTERN, new Int32Array(UPCEANReader.MIDDLE_PATTERN.length)); + rowOffset = middleRange[1]; - return {rowOffset, resultString}; + for (let x = 0; x < 6 && rowOffset < end; x++) { + let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS); + resultString.append('0'.charCodeAt(0) + bestMatch); + for (let counter of counters) { + rowOffset += counter; + } } - public getBarcodeFormat(): BarcodeFormat { - return BarcodeFormat.EAN_13; - } + return rowOffset; + } + + public getBarcodeFormat(): BarcodeFormat { + return BarcodeFormat.EAN_13; + } - static determineFirstDigit(resultString: string, lgPatternFound: number) { - for (let d = 0; d < 10; d++) { - if (lgPatternFound === this.FIRST_DIGIT_ENCODINGS[d]) { - resultString = String.fromCharCode(('0'.charCodeAt(0) + d)) + resultString; - return resultString; - } - } - throw new NotFoundException(); + static determineFirstDigit(resultString: StringBuilder, lgPatternFound: number) { + for (let d = 0; d < 10; d++) { + if (lgPatternFound === this.FIRST_DIGIT_ENCODINGS[d]) { + resultString.insert(0, '0'.charCodeAt(0) + d); + return; + } } + throw new NotFoundException(); + } } diff --git a/src/core/oned/EAN8Reader.ts b/src/core/oned/EAN8Reader.ts index c49e55d5..71065c61 100644 --- a/src/core/oned/EAN8Reader.ts +++ b/src/core/oned/EAN8Reader.ts @@ -16,6 +16,7 @@ import BarcodeFormat from '../BarcodeFormat'; import BitArray from '../common/BitArray'; +import StringBuilder from '../util/StringBuilder'; import UPCEANReader from './UPCEANReader'; @@ -25,47 +26,46 @@ import UPCEANReader from './UPCEANReader'; * @author Sean Owen */ export default class EAN8Reader extends UPCEANReader { - private decodeMiddleCounters: Int32Array; + private decodeMiddleCounters: Int32Array; - public constructor() { - super(); - this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]); - } - - public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: string) { - const counters = this.decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - let end = row.getSize(); - let rowOffset = startRange[1]; - - for (let x = 0; x < 4 && rowOffset < end; x++) { - let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS); - resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch)); + public constructor() { + super(); + this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]); + } - for (let counter of counters) { - rowOffset += counter; - } - } + public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: StringBuilder) { + const counters = this.decodeMiddleCounters; + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + let end = row.getSize(); + let rowOffset = startRange[1]; + for (let x = 0; x < 4 && rowOffset < end; x++) { + let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS); + resultString.append('0'.charCodeAt(0) + bestMatch); - let middleRange = UPCEANReader.findGuardPattern(row, rowOffset, true, UPCEANReader.MIDDLE_PATTERN, new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0)); - rowOffset = middleRange[1]; + for (let counter of counters) { + rowOffset += counter; + } + } - for (let x = 0; x < 4 && rowOffset < end; x++) { - let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS); - resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch)); + let middleRange = UPCEANReader.findGuardPattern(row, rowOffset, true, UPCEANReader.MIDDLE_PATTERN, new Int32Array(UPCEANReader.MIDDLE_PATTERN.length)); + rowOffset = middleRange[1]; - for (let counter of counters) { - rowOffset += counter; - } - } + for (let x = 0; x < 4 && rowOffset < end; x++) { + let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS); + resultString.append('0'.charCodeAt(0) + bestMatch); - return {rowOffset, resultString}; + for (let counter of counters) { + rowOffset += counter; + } } - public getBarcodeFormat(): BarcodeFormat { - return BarcodeFormat.EAN_8; - } + return rowOffset; + } + + public getBarcodeFormat(): BarcodeFormat { + return BarcodeFormat.EAN_8; + } } diff --git a/src/core/oned/ITFReader.ts b/src/core/oned/ITFReader.ts index e52e2535..9fb0e40d 100644 --- a/src/core/oned/ITFReader.ts +++ b/src/core/oned/ITFReader.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.oned {*/ +/* namespace com.google.zxing.oned { */ import BarcodeFormat from '../BarcodeFormat'; import BitArray from '../common/BitArray'; @@ -39,60 +39,59 @@ export default class ITFReader extends OneDReader { // private static w = 2; // Pixel width of a 2x wide line // private static N = 1; // Pixed width of a narrow line - private static PATTERNS: Int32Array[] = [ - Int32Array.from([1, 1, 2, 2, 1]), // 0 - Int32Array.from([2, 1, 1, 1, 2]), // 1 - Int32Array.from([1, 2, 1, 1, 2]), // 2 - Int32Array.from([2, 2, 1, 1, 1]), // 3 - Int32Array.from([1, 1, 2, 1, 2]), // 4 - Int32Array.from([2, 1, 2, 1, 1]), // 5 - Int32Array.from([1, 2, 2, 1, 1]), // 6 - Int32Array.from([1, 1, 1, 2, 2]), // 7 - Int32Array.from([2, 1, 1, 2, 1]), // 8 - Int32Array.from([1, 2, 1, 2, 1]), // 9 - Int32Array.from([1, 1, 3, 3, 1]), // 0 - Int32Array.from([3, 1, 1, 1, 3]), // 1 - Int32Array.from([1, 3, 1, 1, 3]), // 2 - Int32Array.from([3, 3, 1, 1, 1]), // 3 - Int32Array.from([1, 1, 3, 1, 3]), // 4 - Int32Array.from([3, 1, 3, 1, 1]), // 5 - Int32Array.from([1, 3, 3, 1, 1]), // 6 - Int32Array.from([1, 1, 1, 3, 3]), // 7 - Int32Array.from([3, 1, 1, 3, 1]), // 8 - Int32Array.from([1, 3, 1, 3, 1]) // 9 - ]; + private static PATTERNS: Int32Array[] = [ + Int32Array.from([1, 1, 2, 2, 1]), // 0 + Int32Array.from([2, 1, 1, 1, 2]), // 1 + Int32Array.from([1, 2, 1, 1, 2]), // 2 + Int32Array.from([2, 2, 1, 1, 1]), // 3 + Int32Array.from([1, 1, 2, 1, 2]), // 4 + Int32Array.from([2, 1, 2, 1, 1]), // 5 + Int32Array.from([1, 2, 2, 1, 1]), // 6 + Int32Array.from([1, 1, 1, 2, 2]), // 7 + Int32Array.from([2, 1, 1, 2, 1]), // 8 + Int32Array.from([1, 2, 1, 2, 1]), // 9 + Int32Array.from([1, 1, 3, 3, 1]), // 0 + Int32Array.from([3, 1, 1, 1, 3]), // 1 + Int32Array.from([1, 3, 1, 1, 3]), // 2 + Int32Array.from([3, 3, 1, 1, 1]), // 3 + Int32Array.from([1, 1, 3, 1, 3]), // 4 + Int32Array.from([3, 1, 3, 1, 1]), // 5 + Int32Array.from([1, 3, 3, 1, 1]), // 6 + Int32Array.from([1, 1, 1, 3, 3]), // 7 + Int32Array.from([3, 1, 1, 3, 1]), // 8 + Int32Array.from([1, 3, 1, 3, 1]) // 9 + ]; private static MAX_AVG_VARIANCE = 0.38; private static MAX_INDIVIDUAL_VARIANCE = 0.5; - /* /!** Valid ITF lengths. Anything longer than the largest value is also allowed. *!/*/ + /* /!** Valid ITF lengths. Anything longer than the largest value is also allowed. *!/ */ private static DEFAULT_ALLOWED_LENGTHS: number[] = [6, 8, 10, 12, 14]; // Stores the actual narrow line width of the image being decoded. private narrowLineWidth = -1; - /*/!** - * Start/end guard pattern. - * - * Note: The end pattern is reversed because the row is reversed before - * searching for the END_PATTERN - *!/*/ - private static START_PATTERN = Int32Array.from([1, 1, 1, 1]); - private static END_PATTERN_REVERSED: Int32Array[] = [ - Int32Array.from([1, 1, 2]), // 2x - Int32Array.from([1, 1, 3]) // 3x - ]; + /** + * Start/end guard pattern. + * + * Note: The end pattern is reversed because the row is reversed before + * searching for the END_PATTERN + */ + private static START_PATTERN = Int32Array.from([1, 1, 1, 1]); + private static END_PATTERN_REVERSED: Int32Array[] = [ + Int32Array.from([1, 1, 2]), // 2x + Int32Array.from([1, 1, 3]) // 3x + ]; // See ITFWriter.PATTERNS /* - /!** + /** * Patterns of Wide / Narrow lines to indicate each digit - *!/ - */ - + * + */ public decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result { // Find out where the Middle section (payload) starts & ends @@ -149,13 +148,13 @@ export default class ITFReader extends OneDReader { return resultReturn; } - /* - /!** + + /** * @param row row of black/white values to search * @param payloadStart offset of start pattern * @param resultString {@link StringBuilder} to append decoded chars to * @throws NotFoundException if decoding could not complete successfully - *!/*/ + */ private static decodeMiddle( row: BitArray, payloadStart: number, @@ -169,9 +168,9 @@ export default class ITFReader extends OneDReader { // Therefore, need to scan 10 lines and then // split these into two arrays - let counterDigitPair: Int32Array = new Int32Array(10); // 10 - let counterBlack: Int32Array = new Int32Array(5); // 5 - let counterWhite: Int32Array = new Int32Array(5); // 5 + let counterDigitPair: Int32Array = new Int32Array(10); // 10 + let counterBlack: Int32Array = new Int32Array(5); // 5 + let counterWhite: Int32Array = new Int32Array(5); // 5 counterDigitPair.fill(0); counterBlack.fill(0); @@ -199,13 +198,13 @@ export default class ITFReader extends OneDReader { } } - /*/!** + /** * Identify where the start of the middle / payload section starts. * * @param row row of black/white values to search * @return Array, containing index of start of 'start block' and end of * 'start block' - *!/*/ + */ private decodeStart(row: BitArray): number[] { let endStart = ITFReader.skipWhiteSpace(row); @@ -221,7 +220,7 @@ export default class ITFReader extends OneDReader { return startPattern; } - /*/!** + /** * The start & end patterns must be pre/post fixed by a quiet zone. This * zone must be at least 10 times the width of a narrow line. Scan back until * we either get to the start of the barcode or match the necessary number of @@ -235,7 +234,7 @@ export default class ITFReader extends OneDReader { * @param row bit array representing the scanned barcode. * @param startPattern index into row of the start or end pattern. * @throws NotFoundException if the quiet zone cannot be found - *!/*/ + */ private validateQuietZone(row: BitArray, startPattern: number): void { let quietCount: number = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone @@ -254,14 +253,14 @@ export default class ITFReader extends OneDReader { throw new NotFoundException(); } } - /* - /!** + + /** * Skip all whitespace until we get to the first black line. * * @param row row of black/white values to search * @return index of the first black line. * @throws NotFoundException Throws exception if no black lines are found in the row - *!/*/ + */ private static skipWhiteSpace(row: BitArray): number { const width = row.getSize(); @@ -274,13 +273,13 @@ export default class ITFReader extends OneDReader { return endStart; } - /*/!** + /** * Identify where the end of the middle / payload section ends. * * @param row row of black/white values to search * @return Array, containing index of start of 'end block' and end of 'end * block' - *!/*/ + */ private decodeEnd(row: BitArray): number[] { // For convenience, reverse the row and then @@ -319,26 +318,25 @@ export default class ITFReader extends OneDReader { } } - /* - /!** - * @param row row of black/white values to search - * @param rowOffset position to start search - * @param pattern pattern of counts of number of black and white pixels that are - * being searched for as a pattern - * @return start/end horizontal offset of guard pattern, as an array of two - * ints - * @throws NotFoundException if pattern is not found - *!/*/ - private static findGuardPattern( - row: BitArray, - rowOffset: number, - pattern: Int32Array - ): number[] { - - let patternLength: number = pattern.length; - let counters: Int32Array = new Int32Array(patternLength); - let width: number = row.getSize(); - let isWhite: boolean = false; + /** + * @param row row of black/white values to search + * @param rowOffset position to start search + * @param pattern pattern of counts of number of black and white pixels that are + * being searched for as a pattern + * @return start/end horizontal offset of guard pattern, as an array of two + * ints + * @throws NotFoundException if pattern is not found + */ + private static findGuardPattern( + row: BitArray, + rowOffset: number, + pattern: Int32Array + ): number[] { + + let patternLength: number = pattern.length; + let counters: Int32Array = new Int32Array(patternLength); + let width: number = row.getSize(); + let isWhite: boolean = false; let counterPosition: number = 0; let patternStart: number = rowOffset; @@ -368,15 +366,15 @@ export default class ITFReader extends OneDReader { throw new NotFoundException(); } - /*/!** - * Attempts to decode a sequence of ITF black/white lines into single - * digit. - * - * @param counters the counts of runs of observed black/white/black/... values - * @return The decoded digit - * @throws NotFoundException if digit cannot be decoded - *!/*/ - private static decodeDigit(counters: Int32Array): number { + /** + * Attempts to decode a sequence of ITF black/white lines into single + * digit. + * + * @param counters the counts of runs of observed black/white/black/... values + * @return The decoded digit + * @throws NotFoundException if digit cannot be decoded + */ + private static decodeDigit(counters: Int32Array): number { let bestVariance: number = ITFReader.MAX_AVG_VARIANCE; // worst variance we'll accept let bestMatch: number = -1; @@ -402,5 +400,4 @@ export default class ITFReader extends OneDReader { throw new NotFoundException(); } } - } diff --git a/src/core/oned/MultiFormatOneDReader.ts b/src/core/oned/MultiFormatOneDReader.ts index d75118a7..bf113b40 100644 --- a/src/core/oned/MultiFormatOneDReader.ts +++ b/src/core/oned/MultiFormatOneDReader.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.oned {*/ +/* namespace com.google.zxing.oned { */ import BarcodeFormat from '../BarcodeFormat'; import BitArray from '../common/BitArray'; @@ -53,7 +53,7 @@ export default class MultiFormatOneDReader extends OneDReader { this.readers.push(new Code39Reader(useCode39CheckDigit)); } // if (possibleFormats.includes(BarcodeFormat.CODE_93)) { - // this.readers.push(new Code93Reader()); + // this.readers.push(new Code93Reader()); // } if (possibleFormats.includes(BarcodeFormat.CODE_128)) { this.readers.push(new Code128Reader()); @@ -62,7 +62,7 @@ export default class MultiFormatOneDReader extends OneDReader { this.readers.push(new ITFReader()); } // if (possibleFormats.includes(BarcodeFormat.CODABAR)) { - // this.readers.push(new CodaBarReader()); + // this.readers.push(new CodaBarReader()); // } if (possibleFormats.includes(BarcodeFormat.RSS_14)) { this.readers.push(new RSS14Reader()); @@ -77,7 +77,6 @@ export default class MultiFormatOneDReader extends OneDReader { this.readers.push(new Code39Reader()); // this.readers.push(new CodaBarReader()); // this.readers.push(new Code93Reader()); - this.readers.push(new MultiFormatUPCEANReader(hints)); this.readers.push(new Code128Reader()); this.readers.push(new ITFReader()); this.readers.push(new RSS14Reader()); diff --git a/src/core/oned/MultiFormatUPCEANReader.ts b/src/core/oned/MultiFormatUPCEANReader.ts index 94455f5d..bf686ad8 100644 --- a/src/core/oned/MultiFormatUPCEANReader.ts +++ b/src/core/oned/MultiFormatUPCEANReader.ts @@ -26,7 +26,7 @@ import EAN8Reader from './EAN8Reader'; import UPCAReader from './UPCAReader'; import NotFoundException from '../NotFoundException'; import UPCEReader from './UPCEReader'; -import { Collection } from 'src/customTypings'; +import { Collection } from 'customTypings'; /** *

A reader that can read all available UPC/EAN formats. If a caller wants to try to @@ -69,11 +69,13 @@ export default class MultiFormatUPCEANReader extends OneDReader { this.readers = readers; } + // @Override public decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result { + const startGuardPattern = UPCEANReader.findStartGuardPattern(row); for (let reader of this.readers) { try { // const result: Result = reader.decodeRow(rowNumber, row, startGuardPattern, hints); - const result = reader.decodeRow(rowNumber, row, hints); + const result = reader.decodeRow(rowNumber, row, startGuardPattern, hints); // Special case: a 12-digit code encoded in UPC-A is identical to a "0" // followed by those 12 digits encoded as EAN-13. Each will recognize such a code, // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0". @@ -100,7 +102,6 @@ export default class MultiFormatUPCEANReader extends OneDReader { const resultUPCA: Result = new Result( result.getText().substring(1), rawBytes, - rawBytes.length, result.getResultPoints(), BarcodeFormat.UPC_A ); diff --git a/src/core/oned/OneDReader.ts b/src/core/oned/OneDReader.ts index 2969ff7d..87345fba 100644 --- a/src/core/oned/OneDReader.ts +++ b/src/core/oned/OneDReader.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.oned {*/ +/* namespace com.google.zxing.oned { */ import BinaryBitmap from '../BinaryBitmap'; import BitArray from '../common/BitArray'; @@ -35,253 +35,255 @@ import NotFoundException from '../NotFoundException'; */ export default abstract class OneDReader implements Reader { - /* - @Override - public Result decode(BinaryBitmap image) throws NotFoundException, FormatException { - return decode(image, null); - } - */ + /* + @Override + public Result decode(BinaryBitmap image) throws NotFoundException, FormatException { + return decode(image, null); + } + */ - // Note that we don't try rotation without the try harder flag, even if rotation was supported. - // @Override - public decode(image: BinaryBitmap, hints?: Map): Result { - try { - return this.doDecode(image, hints); - } catch (nfe) { - const tryHarder = hints && (hints.get(DecodeHintType.TRY_HARDER) === true); + // Note that we don't try rotation without the try harder flag, even if rotation was supported. + // @Override + public decode(image: BinaryBitmap, hints?: Map): Result { + try { + return this.doDecode(image, hints); + } catch (nfe) { + const tryHarder = hints && (hints.get(DecodeHintType.TRY_HARDER) === true); - if (tryHarder && image.isRotateSupported()) { - const rotatedImage = image.rotateCounterClockwise(); - const result = this.doDecode(rotatedImage, hints); - // Record that we found it rotated 90 degrees CCW / 270 degrees CW - const metadata = result.getResultMetadata(); - let orientation = 270; - if (metadata !== null && (metadata.get(ResultMetadataType.ORIENTATION) === true)) { - // But if we found it reversed in doDecode(), add in that result here: - orientation = (orientation + (metadata.get(ResultMetadataType.ORIENTATION) as number) % 360); - } - result.putMetadata(ResultMetadataType.ORIENTATION, orientation); - // Update result points - const points = result.getResultPoints(); - if (points !== null) { - const height = rotatedImage.getHeight(); - for (let i = 0; i < points.length; i++) { - points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX()); - } - } - return result; - } else { - throw new NotFoundException(); - } + if (tryHarder && image.isRotateSupported()) { + const rotatedImage = image.rotateCounterClockwise(); + const result = this.doDecode(rotatedImage, hints); + // Record that we found it rotated 90 degrees CCW / 270 degrees CW + const metadata = result.getResultMetadata(); + let orientation = 270; + if (metadata !== null && (metadata.get(ResultMetadataType.ORIENTATION) === true)) { + // But if we found it reversed in doDecode(), add in that result here: + orientation = (orientation + (metadata.get(ResultMetadataType.ORIENTATION) as number) % 360); + } + result.putMetadata(ResultMetadataType.ORIENTATION, orientation); + // Update result points + const points = result.getResultPoints(); + if (points !== null) { + const height = rotatedImage.getHeight(); + for (let i = 0; i < points.length; i++) { + points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX()); + } } + return result; + } else { + throw new NotFoundException(); + } } + } - // @Override - public reset(): void { - // do nothing - } + // @Override + public reset(): void { + // do nothing + } - /** - * We're going to examine rows from the middle outward, searching alternately above and below the - * middle, and farther out each time. rowStep is the number of rows between each successive - * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then - * middle + rowStep, then middle - (2 * rowStep), etc. - * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily - * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the - * image if "trying harder". - * - * @param image The image to decode - * @param hints Any hints that were requested - * @return The contents of the decoded barcode - * @throws NotFoundException Any spontaneous errors which occur - */ - private doDecode(image: BinaryBitmap, hints?: Map): Result { - const width = image.getWidth(); - const height = image.getHeight(); - let row = new BitArray(width); + /** + * We're going to examine rows from the middle outward, searching alternately above and below the + * middle, and farther out each time. rowStep is the number of rows between each successive + * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then + * middle + rowStep, then middle - (2 * rowStep), etc. + * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily + * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the + * image if "trying harder". + * + * @param image The image to decode + * @param hints Any hints that were requested + * @return The contents of the decoded barcode + * @throws NotFoundException Any spontaneous errors which occur + */ + private doDecode(image: BinaryBitmap, hints?: Map): Result { + const width = image.getWidth(); + const height = image.getHeight(); + let row = new BitArray(width); - const tryHarder = hints && (hints.get(DecodeHintType.TRY_HARDER) === true); - const rowStep = Math.max(1, height >> (tryHarder ? 8 : 5)); - let maxLines; - if (tryHarder) { - maxLines = height; // Look at the whole image, not just the center - } else { - maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image - } + const tryHarder = hints && (hints.get(DecodeHintType.TRY_HARDER) === true); + const rowStep = Math.max(1, height >> (tryHarder ? 8 : 5)); + let maxLines; + if (tryHarder) { + maxLines = height; // Look at the whole image, not just the center + } else { + maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image + } - const middle = Math.trunc(height / 2); - for (let x = 0; x < maxLines; x++) { - // Scanning from the middle out. Determine which row we're looking at next: - const rowStepsAboveOrBelow = Math.trunc((x + 1) / 2); - const isAbove = (x & 0x01) === 0; // i.e. is x even? - const rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow); - if (rowNumber < 0 || rowNumber >= height) { - // Oops, if we run off the top or bottom, stop - break; - } + const middle = Math.trunc(height / 2); + for (let x = 0; x < maxLines; x++) { + // Scanning from the middle out. Determine which row we're looking at next: + const rowStepsAboveOrBelow = Math.trunc((x + 1) / 2); + const isAbove = (x & 0x01) === 0; // i.e. is x even? + const rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow); + if (rowNumber < 0 || rowNumber >= height) { + // Oops, if we run off the top or bottom, stop + break; + } - // Estimate black point for this row and load it: - try { - row = image.getBlackRow(rowNumber, row); - } catch (ignored) { continue; } + // Estimate black point for this row and load it: + try { + row = image.getBlackRow(rowNumber, row); + } catch (ignored) { + continue; + } - // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to - // handle decoding upside down barcodes. - for (let attempt = 0; attempt < 2; attempt++) { - if (attempt === 1) { // trying again? - row.reverse(); // reverse the row and continue + // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to + // handle decoding upside down barcodes. + for (let attempt = 0; attempt < 2; attempt++) { + if (attempt === 1) { // trying again? + row.reverse(); // reverse the row and continue - // This means we will only ever draw result points *once* in the life of this method - // since we want to avoid drawing the wrong points after flipping the row, and, - // don't want to clutter with noise from every single row scan -- just the scans - // that start on the center line. - if (hints && (hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK) === true)) { - const newHints = new Map(); - hints.forEach((hint, key) => newHints.set(key, hint)); - newHints.delete(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - hints = newHints; - } - } + // This means we will only ever draw result points *once* in the life of this method + // since we want to avoid drawing the wrong points after flipping the row, and, + // don't want to clutter with noise from every single row scan -- just the scans + // that start on the center line. + if (hints && (hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK) === true)) { + const newHints = new Map(); + hints.forEach((hint, key) => newHints.set(key, hint)); + newHints.delete(DecodeHintType.NEED_RESULT_POINT_CALLBACK); + hints = newHints; + } + } - try { - // Look for a barcode - const result = this.decodeRow(rowNumber, row, hints); - // We found our barcode - if (attempt === 1) { - // But it was upside down, so note that - result.putMetadata(ResultMetadataType.ORIENTATION, 180); - // And remember to flip the result points horizontally. - const points = result.getResultPoints(); - if (points !== null) { - points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY()); - points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY()); - } - } - return result; - } catch (re) { - // continue -- just couldn't decode this row - } + try { + // Look for a barcode + const result = this.decodeRow(rowNumber, row, hints); + // We found our barcode + if (attempt === 1) { + // But it was upside down, so note that + result.putMetadata(ResultMetadataType.ORIENTATION, 180); + // And remember to flip the result points horizontally. + const points = result.getResultPoints(); + if (points !== null) { + points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY()); + points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY()); } + } + return result; + } catch (re) { + // continue -- just couldn't decode this row } - - throw new NotFoundException(); + } } - /** - * Records the size of successive runs of white and black pixels in a row, starting at a given point. - * The values are recorded in the given array, and the number of runs recorded is equal to the size - * of the array. If the row starts on a white pixel at the given start point, then the first count - * recorded is the run of white pixels starting from that point; likewise it is the count of a run - * of black pixels if the row begin on a black pixels at that point. - * - * @param row row to count from - * @param start offset into row to start at - * @param counters array into which to record counts - * @throws NotFoundException if counters cannot be filled entirely from row before running out - * of pixels - */ - protected static recordPattern(row: BitArray, start: number, counters: Int32Array): void { - const numCounters = counters.length; - for (let index = 0; index < numCounters; index++) - counters[index] = 0; + throw new NotFoundException(); + } - const end = row.getSize(); - if (start >= end) { - throw new NotFoundException(); - } + /** + * Records the size of successive runs of white and black pixels in a row, starting at a given point. + * The values are recorded in the given array, and the number of runs recorded is equal to the size + * of the array. If the row starts on a white pixel at the given start point, then the first count + * recorded is the run of white pixels starting from that point; likewise it is the count of a run + * of black pixels if the row begin on a black pixels at that point. + * + * @param row row to count from + * @param start offset into row to start at + * @param counters array into which to record counts + * @throws NotFoundException if counters cannot be filled entirely from row before running out + * of pixels + */ + protected static recordPattern(row: BitArray, start: number, counters: Int32Array): void { + const numCounters = counters.length; + for (let index = 0; index < numCounters; index++) + counters[index] = 0; - let isWhite = !row.get(start); - let counterPosition = 0; - let i = start; - while (i < end) { - if (row.get(i) !== isWhite) { - counters[counterPosition]++; - } else { - if (++counterPosition === numCounters) { - break; - } else { - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - i++; - } + const end = row.getSize(); + if (start >= end) { + throw new NotFoundException(); + } - // If we read fully the last section of pixels and filled up our counters -- or filled - // the last counter but ran off the side of the image, OK. Otherwise, a problem. - if (!(counterPosition === numCounters || (counterPosition === numCounters - 1 && i === end))) { - throw new NotFoundException(); + let isWhite = !row.get(start); + let counterPosition = 0; + let i = start; + while (i < end) { + if (row.get(i) !== isWhite) { + counters[counterPosition]++; + } else { + if (++counterPosition === numCounters) { + break; + } else { + counters[counterPosition] = 1; + isWhite = !isWhite; } + } + i++; } - protected static recordPatternInReverse(row: BitArray, start: number, counters: Int32Array): void { - // This could be more efficient I guess - let numTransitionsLeft = counters.length; - let last = row.get(start); - while (start > 0 && numTransitionsLeft >= 0) { - if (row.get(--start) !== last) { - numTransitionsLeft--; - last = !last; - } - } - if (numTransitionsLeft >= 0) { - throw new NotFoundException(); - } + // If we read fully the last section of pixels and filled up our counters -- or filled + // the last counter but ran off the side of the image, OK. Otherwise, a problem. + if (!(counterPosition === numCounters || (counterPosition === numCounters - 1 && i === end))) { + throw new NotFoundException(); + } + } - OneDReader.recordPattern(row, start + 1, counters); + protected static recordPatternInReverse(row: BitArray, start: number, counters: Int32Array): void { + // This could be more efficient I guess + let numTransitionsLeft = counters.length; + let last = row.get(start); + while (start > 0 && numTransitionsLeft >= 0) { + if (row.get(--start) !== last) { + numTransitionsLeft--; + last = !last; + } + } + if (numTransitionsLeft >= 0) { + throw new NotFoundException(); } - /** - * Determines how closely a set of observed counts of runs of black/white values matches a given - * target pattern. This is reported as the ratio of the total variance from the expected pattern - * proportions across all pattern elements, to the length of the pattern. - * - * @param counters observed counters - * @param pattern expected pattern - * @param maxIndividualVariance The most any counter can differ before we give up - * @return ratio of total variance between counters and pattern compared to total pattern size - */ - protected static patternMatchVariance(counters: Int32Array, pattern: Int32Array, maxIndividualVariance: number): number { - const numCounters = counters.length; - let total = 0; - let patternLength = 0; - for (let i = 0; i < numCounters; i++) { - total += counters[i]; - patternLength += pattern[i]; - } - if (total < patternLength) { - // If we don't even have one pixel per unit of bar width, assume this is too small - // to reliably match, so fail: - return Number.POSITIVE_INFINITY; - } + OneDReader.recordPattern(row, start + 1, counters); + } + + /** + * Determines how closely a set of observed counts of runs of black/white values matches a given + * target pattern. This is reported as the ratio of the total variance from the expected pattern + * proportions across all pattern elements, to the length of the pattern. + * + * @param counters observed counters + * @param pattern expected pattern + * @param maxIndividualVariance The most any counter can differ before we give up + * @return ratio of total variance between counters and pattern compared to total pattern size + */ + protected static patternMatchVariance(counters: Int32Array, pattern: Int32Array, maxIndividualVariance: number): number { + const numCounters = counters.length; + let total = 0; + let patternLength = 0; + for (let i = 0; i < numCounters; i++) { + total += counters[i]; + patternLength += pattern[i]; + } + if (total < patternLength) { + // If we don't even have one pixel per unit of bar width, assume this is too small + // to reliably match, so fail: + return Number.POSITIVE_INFINITY; + } - const unitBarWidth = total / patternLength; - maxIndividualVariance *= unitBarWidth; + const unitBarWidth = total / patternLength; + maxIndividualVariance *= unitBarWidth; - let totalVariance = 0.0; - for (let x = 0; x < numCounters; x++) { - const counter = counters[x]; - const scaledPattern = pattern[x] * unitBarWidth; - const variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter; - if (variance > maxIndividualVariance) { - return Number.POSITIVE_INFINITY; - } - totalVariance += variance; - } - return totalVariance / total; + let totalVariance = 0.0; + for (let x = 0; x < numCounters; x++) { + const counter = counters[x]; + const scaledPattern = pattern[x] * unitBarWidth; + const variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter; + if (variance > maxIndividualVariance) { + return Number.POSITIVE_INFINITY; + } + totalVariance += variance; } + return totalVariance / total; + } - /** - *

Attempts to decode a one-dimensional barcode format given a single row of - * an image.

- * - * @param rowNumber row number from top of the row - * @param row the black/white pixel data of the row - * @param hints decode hints - * @return {@link Result} containing encoded string and start/end of barcode - * @throws NotFoundException if no potential barcode is found - * @throws ChecksumException if a potential barcode is found but does not pass its checksum - * @throws FormatException if a potential barcode is found but format is invalid - */ - public abstract decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result; + /** + * Attempts to decode a one-dimensional barcode format given a single row of + * an image. + * + * @param rowNumber row number from top of the row + * @param row the black/white pixel data of the row + * @param hints hints that influence decoding + * @return containing encoded string and start/end of barcode + * @throws {@link NotFoundException} if no potential barcode is found + * @throws {@link ChecksumException} if a potential barcode is found but does not pass its checksum + * @throws {@link FormatException} if a potential barcode is found but format is invalid + */ + public abstract decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result; } diff --git a/src/core/oned/UPCAReader.ts b/src/core/oned/UPCAReader.ts index 49ea740d..e31d8e19 100644 --- a/src/core/oned/UPCAReader.ts +++ b/src/core/oned/UPCAReader.ts @@ -14,22 +14,19 @@ * limitations under the License. */ -/*namespace com.google.zxing.oned {*/ +/* namespace com.google.zxing.oned { */ import BarcodeFormat from '../BarcodeFormat'; import BinaryBitmap from '../BinaryBitmap'; import BitArray from '../common/BitArray'; import DecodeHintType from '../DecodeHintType'; +import StringBuilder from '../util/StringBuilder'; -import Reader from '../Reader'; import Result from '../Result'; -import ResultMetadataType from '../ResultMetadataType'; -import ResultPoint from '../ResultPoint'; import NotFoundException from '../NotFoundException'; import EAN13Reader from './EAN13Reader'; import UPCEANReader from './UPCEANReader'; -import { int } from 'src/customTypings'; /** * Encapsulates functionality and implementation that is common to all families @@ -58,20 +55,27 @@ export default class UPCAReader extends UPCEANReader { return this.maybeReturnResult(this.ean13Reader.decode(image)); } - // @Override - public decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result { - return this.maybeReturnResult(this.ean13Reader.decodeRow(rowNumber, row, hints)); + public decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result; + public decodeRow(rowNumber: number, row: BitArray, startGuardRange: Int32Array, hints?: Map): Result; + public decodeRow(rowNumber: number, row: BitArray, arg3: Int32Array | Map, arg4?: Map): Result { + const startGuardRange = arg3 instanceof Int32Array ? arg3 : UPCEANReader.findStartGuardPattern(row); + const hints = arg3 instanceof Map ? arg3 : arg4; + return this.decodeRowImpl(rowNumber, row, startGuardRange, hints); + } + + protected decodeRowImpl(rowNumber: number, row: BitArray, startGuardRange: Int32Array, hints?: Map): Result { + return this.maybeReturnResult(this.ean13Reader.decodeRow(rowNumber, row, startGuardRange, hints)); } // @Override - public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: string) { + public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: StringBuilder) { return this.ean13Reader.decodeMiddle(row, startRange, resultString); } public maybeReturnResult(result: Result) { let text = result.getText(); if (text.charAt(0) === '0') { - let upcaResult = new Result(text.substring(1), null, null, result.getResultPoints(), BarcodeFormat.UPC_A); + let upcaResult = new Result(text.substring(1), null, null, BarcodeFormat.UPC_A); if (result.getResultMetadata() != null) { upcaResult.putAllMetadata(result.getResultMetadata()); } diff --git a/src/core/oned/UPCEANExtension2Support.ts b/src/core/oned/UPCEANExtension2Support.ts index 8008a12c..f4ce2d1d 100644 --- a/src/core/oned/UPCEANExtension2Support.ts +++ b/src/core/oned/UPCEANExtension2Support.ts @@ -16,6 +16,7 @@ import BarcodeFormat from '../BarcodeFormat'; import BitArray from '../common/BitArray'; +import StringBuilder from '../util/StringBuilder'; import AbstractUPCEANReader from './AbstractUPCEANReader'; import Result from '../Result'; @@ -27,74 +28,74 @@ import NotFoundException from '../NotFoundException'; * @see UPCEANExtension5Support */ export default class UPCEANExtension2Support { - private decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]); - private decodeRowStringBuffer = ''; + private decodeMiddleCounters = new Int32Array(4); + private decodeRowStringBuffer = new StringBuilder(); - public decodeRow(rowNumber: number, row: BitArray, extensionStartRange: Int32Array) { - let result = this.decodeRowStringBuffer; - let end = this.decodeMiddle(row, extensionStartRange, result); + public decodeRow(rowNumber: number, row: BitArray, extensionStartRange: Int32Array) { + let result = this.decodeRowStringBuffer; + let end = this.decodeMiddle(row, extensionStartRange, result); - let resultString = result.toString(); - let extensionData = UPCEANExtension2Support.parseExtensionString(resultString); + let resultString = result.toString(); + let extensionData = UPCEANExtension2Support.parseExtensionString(resultString); - let resultPoints = [ - new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber), - new ResultPoint(end, rowNumber) - ]; + let resultPoints = [ + new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber), + new ResultPoint(end, rowNumber) + ]; - let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat.UPC_EAN_EXTENSION, new Date().getTime()); + let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat.UPC_EAN_EXTENSION, new Date().getTime()); - if (extensionData != null) { - extensionResult.putAllMetadata(extensionData); - } + if (extensionData != null) { + extensionResult.putAllMetadata(extensionData); + } + + return extensionResult; + } + + public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: StringBuilder) { + let counters = this.decodeMiddleCounters; + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + let end = row.getSize(); + let rowOffset = startRange[1]; + + let checkParity = 0; + + for (let x = 0; x < 2 && rowOffset < end; x++) { + let bestMatch = AbstractUPCEANReader.decodeDigit(row, counters, rowOffset, AbstractUPCEANReader.L_AND_G_PATTERNS); + resultString.append('0'.charCodeAt(0) + bestMatch % 10); + for (let counter of counters) { + rowOffset += counter; + } + if (bestMatch >= 10) { + checkParity |= 1 << (1 - x); + } + if (x !== 1) { + // Read off separator if not last + rowOffset = row.getNextSet(rowOffset); + rowOffset = row.getNextUnset(rowOffset); + } + } - return extensionResult; + if (resultString.length() !== 2) { + throw new NotFoundException(); } - public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: string) { - let counters = this.decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - let end = row.getSize(); - let rowOffset = startRange[1]; - - let checkParity = 0; - - for (let x = 0; x < 2 && rowOffset < end; x++) { - let bestMatch = AbstractUPCEANReader.decodeDigit(row, counters, rowOffset, AbstractUPCEANReader.L_AND_G_PATTERNS); - resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10)); - for (let counter of counters) { - rowOffset += counter; - } - if (bestMatch >= 10) { - checkParity |= 1 << (1 - x); - } - if (x !== 1) { - // Read off separator if not last - rowOffset = row.getNextSet(rowOffset); - rowOffset = row.getNextUnset(rowOffset); - } - } - - if (resultString.length !== 2) { - throw new NotFoundException(); - } - - if (parseInt(resultString.toString()) % 4 !== checkParity) { - throw new NotFoundException(); - } - - return rowOffset; + if (parseInt(resultString.toString()) % 4 !== checkParity) { + throw new NotFoundException(); } - static parseExtensionString(raw: string) { - if (raw.length !== 2) { - return null; - } + return rowOffset; + } - return new Map([[ResultMetadataType.ISSUE_NUMBER, parseInt(raw)]]); + static parseExtensionString(raw: string) { + if (raw.length !== 2) { + return null; } + + return new Map([[ResultMetadataType.ISSUE_NUMBER, parseInt(raw)]]); + } } diff --git a/src/core/oned/UPCEANExtension5Support.ts b/src/core/oned/UPCEANExtension5Support.ts index 8765b513..574fbff5 100644 --- a/src/core/oned/UPCEANExtension5Support.ts +++ b/src/core/oned/UPCEANExtension5Support.ts @@ -16,6 +16,7 @@ import BarcodeFormat from '../BarcodeFormat'; import BitArray from '../common/BitArray'; +import StringBuilder from '../util/StringBuilder'; // import UPCEANReader from './UPCEANReader'; import AbstractUPCEANReader from './AbstractUPCEANReader'; @@ -28,138 +29,138 @@ import NotFoundException from '../NotFoundException'; * @see UPCEANExtension2Support */ export default class UPCEANExtension5Support { - private CHECK_DIGIT_ENCODINGS = [0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05]; - private decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]); - private decodeRowStringBuffer = ''; + private CHECK_DIGIT_ENCODINGS = [0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05]; + private decodeMiddleCounters = new Int32Array(4); + private decodeRowStringBuffer = new StringBuilder(); - public decodeRow(rowNumber: number, row: BitArray, extensionStartRange: Int32Array): Result { - let result = this.decodeRowStringBuffer; - let end = this.decodeMiddle(row, extensionStartRange, result); + public decodeRow(rowNumber: number, row: BitArray, extensionStartRange: Int32Array): Result { + let result = this.decodeRowStringBuffer; + let end = this.decodeMiddle(row, extensionStartRange, result); - let resultString = result.toString(); - let extensionData = UPCEANExtension5Support.parseExtensionString(resultString); + let resultString = result.toString(); + let extensionData = UPCEANExtension5Support.parseExtensionString(resultString); - let resultPoints = [ - new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber), - new ResultPoint(end, rowNumber) - ]; + let resultPoints = [ + new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber), + new ResultPoint(end, rowNumber) + ]; - let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat.UPC_EAN_EXTENSION, new Date().getTime()); + let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat.UPC_EAN_EXTENSION, new Date().getTime()); - if (extensionData != null) { - extensionResult.putAllMetadata(extensionData); - } + if (extensionData != null) { + extensionResult.putAllMetadata(extensionData); + } - return extensionResult; + return extensionResult; + } + + public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: StringBuilder) { + let counters = this.decodeMiddleCounters; + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + let end = row.getSize(); + let rowOffset = startRange[1]; + + let lgPatternFound = 0; + + for (let x = 0; x < 5 && rowOffset < end; x++) { + let bestMatch = AbstractUPCEANReader.decodeDigit(row, counters, rowOffset, AbstractUPCEANReader.L_AND_G_PATTERNS); + resultString.append('0'.charCodeAt(0) + bestMatch % 10); + for (let counter of counters) { + rowOffset += counter; + } + if (bestMatch >= 10) { + lgPatternFound |= 1 << (4 - x); + } + if (x !== 4) { + // Read off separator if not last + rowOffset = row.getNextSet(rowOffset); + rowOffset = row.getNextUnset(rowOffset); + } } - public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: string) { - let counters = this.decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - let end = row.getSize(); - let rowOffset = startRange[1]; - - let lgPatternFound = 0; - - for (let x = 0; x < 5 && rowOffset < end; x++) { - let bestMatch = AbstractUPCEANReader.decodeDigit(row, counters, rowOffset, AbstractUPCEANReader.L_AND_G_PATTERNS); - resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10)); - for (let counter of counters) { - rowOffset += counter; - } - if (bestMatch >= 10) { - lgPatternFound |= 1 << (4 - x); - } - if (x !== 4) { - // Read off separator if not last - rowOffset = row.getNextSet(rowOffset); - rowOffset = row.getNextUnset(rowOffset); - } - } + if (resultString.length() !== 5) { + throw new NotFoundException(); + } - if (resultString.length !== 5) { - throw new NotFoundException(); - } + let checkDigit = this.determineCheckDigit(lgPatternFound); + if (UPCEANExtension5Support.extensionChecksum(resultString.toString()) !== checkDigit) { + throw new NotFoundException(); + } - let checkDigit = this.determineCheckDigit(lgPatternFound); - if (UPCEANExtension5Support.extensionChecksum(resultString.toString()) !== checkDigit) { - throw new NotFoundException(); - } + return rowOffset; + } - return rowOffset; + static extensionChecksum(s: string) { + let length = s.length; + let sum = 0; + for (let i = length - 2; i >= 0; i -= 2) { + sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); } - - static extensionChecksum(s: string) { - let length = s.length; - let sum = 0; - for (let i = length - 2; i >= 0; i -= 2) { - sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); - } - sum *= 3; - for (let i = length - 1; i >= 0; i -= 2) { - sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); - } - sum *= 3; - return sum % 10; + sum *= 3; + for (let i = length - 1; i >= 0; i -= 2) { + sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); } - - public determineCheckDigit(lgPatternFound: number) { - for (let d = 0; d < 10; d++) { - if (lgPatternFound === this.CHECK_DIGIT_ENCODINGS[d]) { - return d; - } - } - throw new NotFoundException(); + sum *= 3; + return sum % 10; + } + + public determineCheckDigit(lgPatternFound: number) { + for (let d = 0; d < 10; d++) { + if (lgPatternFound === this.CHECK_DIGIT_ENCODINGS[d]) { + return d; + } } + throw new NotFoundException(); + } - static parseExtensionString(raw: string) { - if (raw.length !== 5) { - return null; - } - let value = UPCEANExtension5Support.parseExtension5String(raw); - if (value == null) { - return null; - } - - return new Map([[ResultMetadataType.SUGGESTED_PRICE, value]]); + static parseExtensionString(raw: string) { + if (raw.length !== 5) { + return null; + } + let value = UPCEANExtension5Support.parseExtension5String(raw); + if (value == null) { + return null; } - static parseExtension5String(raw: string) { - let currency; - switch (raw.charAt(0)) { - case '0': - currency = '£'; - break; - case '5': - currency = '$'; - break; - case '9': - // Reference: http://www.jollytech.com - switch (raw) { - case '90000': - // No suggested retail price - return null; - case '99991': - // Complementary - return '0.00'; - case '99990': - return 'Used'; - } - // Otherwise... unknown currency? - currency = ''; - break; - default: - currency = ''; - break; + return new Map([[ResultMetadataType.SUGGESTED_PRICE, value]]); + } + + static parseExtension5String(raw: string) { + let currency; + switch (raw.charAt(0)) { + case '0': + currency = '£'; + break; + case '5': + currency = '$'; + break; + case '9': + // Reference: http://www.jollytech.com + switch (raw) { + case '90000': + // No suggested retail price + return null; + case '99991': + // Complementary + return '0.00'; + case '99990': + return 'Used'; } - let rawAmount = parseInt(raw.substring(1)); - let unitsString = (rawAmount / 100).toString(); - let hundredths = rawAmount % 100; - let hundredthsString = hundredths < 10 ? '0' + hundredths : hundredths.toString(); // fixme - return currency + unitsString + '.' + hundredthsString; + // Otherwise... unknown currency? + currency = ''; + break; + default: + currency = ''; + break; } + let rawAmount = parseInt(raw.substring(1)); + let unitsString = (rawAmount / 100).toString(); + let hundredths = rawAmount % 100; + let hundredthsString = hundredths < 10 ? '0' + hundredths : hundredths.toString(); // fixme + return currency + unitsString + '.' + hundredthsString; + } } diff --git a/src/core/oned/UPCEANExtensionSupport.ts b/src/core/oned/UPCEANExtensionSupport.ts index 21e19089..4359c071 100644 --- a/src/core/oned/UPCEANExtensionSupport.ts +++ b/src/core/oned/UPCEANExtensionSupport.ts @@ -21,18 +21,18 @@ import UPCEANExtension2Support from './UPCEANExtension2Support'; import Result from '../Result'; export default class UPCEANExtensionSupport { - private static EXTENSION_START_PATTERN = Int32Array.from([1, 1, 2]); + private static EXTENSION_START_PATTERN = Int32Array.from([1, 1, 2]); - static decodeRow(rowNumber: number, row: BitArray, rowOffset: number): Result { - let extensionStartRange = AbstractUPCEANReader.findGuardPattern(row, rowOffset, false, this.EXTENSION_START_PATTERN, new Int32Array(this.EXTENSION_START_PATTERN.length).fill(0)); - try { - // return null; - let fiveSupport = new UPCEANExtension5Support(); - return fiveSupport.decodeRow(rowNumber, row, extensionStartRange); - } catch (err) { - // return null; - let twoSupport = new UPCEANExtension2Support(); - return twoSupport.decodeRow(rowNumber, row, extensionStartRange); - } + static decodeRow(rowNumber: number, row: BitArray, rowOffset: number): Result { + let extensionStartRange = AbstractUPCEANReader.findGuardPattern(row, rowOffset, false, this.EXTENSION_START_PATTERN, new Int32Array(this.EXTENSION_START_PATTERN.length)); + try { + // return null; + let fiveSupport = new UPCEANExtension5Support(); + return fiveSupport.decodeRow(rowNumber, row, extensionStartRange); + } catch (err) { + // return null; + let twoSupport = new UPCEANExtension2Support(); + return twoSupport.decodeRow(rowNumber, row, extensionStartRange); } + } } diff --git a/src/core/oned/UPCEANReader.ts b/src/core/oned/UPCEANReader.ts index cc70395e..3d7089a6 100644 --- a/src/core/oned/UPCEANReader.ts +++ b/src/core/oned/UPCEANReader.ts @@ -28,8 +28,8 @@ import FormatException from '../FormatException'; import ChecksumException from '../ChecksumException'; /** - *

Encapsulates functionality and implementation that is common to UPC and EAN families - * of one-dimensional barcodes.

+ * Encapsulates functionality and implementation that is common to UPC and EAN families + * of one-dimensional barcodes. * * @author dswitkin@google.com (Daniel Switkin) * @author Sean Owen @@ -37,140 +37,110 @@ import ChecksumException from '../ChecksumException'; */ export default abstract class UPCEANReader extends AbstractUPCEANReader { - public constructor() { - super(); - this.decodeRowStringBuffer = ''; + public constructor() { + super(); - UPCEANReader.L_AND_G_PATTERNS = UPCEANReader.L_PATTERNS.map(arr => Int32Array.from(arr)); + UPCEANReader.L_AND_G_PATTERNS = UPCEANReader.L_PATTERNS.map(arr => Int32Array.from(arr)); - for (let i = 10; i < 20; i++) { - let widths = UPCEANReader.L_PATTERNS[i - 10]; - let reversedWidths = new Int32Array(widths.length); - for (let j = 0; j < widths.length; j++) { - reversedWidths[j] = widths[widths.length - j - 1]; - } - UPCEANReader.L_AND_G_PATTERNS[i] = reversedWidths; - } + for (let i = 10; i < 20; i++) { + let widths = UPCEANReader.L_PATTERNS[i - 10]; + let reversedWidths = new Int32Array(widths.length); + for (let j = 0; j < widths.length; j++) { + reversedWidths[j] = widths[widths.length - j - 1]; + } + UPCEANReader.L_AND_G_PATTERNS[i] = reversedWidths; + } + } + + public decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result; + public decodeRow(rowNumber: number, row: BitArray, startGuardRange: Int32Array, hints?: Map): Result; + public decodeRow(rowNumber: number, row: BitArray, arg3: Int32Array | Map, arg4?: Map): Result { + const startGuardRange = arg3 instanceof Int32Array ? arg3 : UPCEANReader.findStartGuardPattern(row); + const hints = arg3 instanceof Map ? arg3 : arg4; + return this.decodeRowImpl(rowNumber, row, startGuardRange, hints); + } + + protected decodeRowImpl(rowNumber: number, row: BitArray, startGuardRange: Int32Array, hints?: Map): Result { + let resultPointCallback = hints == null ? null : hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); + + if (resultPointCallback != null) { + const resultPoint = new ResultPoint((startGuardRange[0] + startGuardRange[1]) / 2.0, rowNumber); + resultPointCallback.foundPossibleResultPoint(resultPoint); } - public decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result { - let startGuardRange = UPCEANReader.findStartGuardPattern(row); - let resultPointCallback = hints == null ? null : hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - - if (resultPointCallback != null) { - const resultPoint = new ResultPoint((startGuardRange[0] + startGuardRange[1]) / 2.0, rowNumber); - resultPointCallback.foundPossibleResultPoint(resultPoint); - } - - let budello = this.decodeMiddle(row, startGuardRange, this.decodeRowStringBuffer); - let endStart = budello.rowOffset; - let result = budello.resultString; - - if (resultPointCallback != null) { - const resultPoint = new ResultPoint(endStart, rowNumber); - resultPointCallback.foundPossibleResultPoint(resultPoint); - } - - let endRange = UPCEANReader.decodeEnd(row, endStart); - - if (resultPointCallback != null) { - const resultPoint = new ResultPoint((endRange[0] + endRange[1]) / 2.0, rowNumber); - resultPointCallback.foundPossibleResultPoint(resultPoint); - } - - // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The - // spec might want more whitespace, but in practice this is the maximum we can count on. - let end = endRange[1]; - let quietEnd = end + (end - endRange[0]); - - if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) { - throw new NotFoundException(); - } + let result = this.decodeRowStringBuffer; + result.setLengthToZero(); + let endStart = this.decodeMiddle(row, startGuardRange, result); - let resultString = result.toString(); - // UPC/EAN should never be less than 8 chars anyway - if (resultString.length < 8) { - throw new FormatException(); - } - if (!UPCEANReader.checkChecksum(resultString)) { - throw new ChecksumException(); - } + if (resultPointCallback != null) { + const resultPoint = new ResultPoint(endStart, rowNumber); + resultPointCallback.foundPossibleResultPoint(resultPoint); + } - let left = (startGuardRange[1] + startGuardRange[0]) / 2.0; - let right = (endRange[1] + endRange[0]) / 2.0; - let format = this.getBarcodeFormat(); - let resultPoint = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)]; - let decodeResult = new Result(resultString, null, 0, resultPoint, format, new Date().getTime()); - - let extensionLength = 0; - - try { - let extensionResult = UPCEANExtensionSupport.decodeRow(rowNumber, row, endRange[1]); - decodeResult.putMetadata(ResultMetadataType.UPC_EAN_EXTENSION, extensionResult.getText()); - decodeResult.putAllMetadata(extensionResult.getResultMetadata()); - decodeResult.addResultPoints(extensionResult.getResultPoints()); - extensionLength = extensionResult.getText().length; - } catch (err) { - } + let endRange = this.decodeEnd(row, endStart); - let allowedExtensions = hints == null ? null : hints.get(DecodeHintType.ALLOWED_EAN_EXTENSIONS); - if (allowedExtensions != null) { - let valid = false; - for (let length in allowedExtensions) { - if (extensionLength.toString() === length) { // check me - valid = true; - break; - } - } - if (!valid) { - throw new NotFoundException(); - } - } + if (resultPointCallback != null) { + const resultPoint = new ResultPoint((endRange[0] + endRange[1]) / 2.0, rowNumber); + resultPointCallback.foundPossibleResultPoint(resultPoint); + } - if (format === BarcodeFormat.EAN_13 || format === BarcodeFormat.UPC_A) { - // let countryID = eanManSupport.lookupContryIdentifier(resultString); todo - // if (countryID != null) { - // decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID); - // } - } + // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The + // spec might want more whitespace, but in practice this is the maximum we can count on. + let end = endRange[1]; + let quietEnd = end + (end - endRange[0]); - return decodeResult; + if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) { + throw new NotFoundException(); } - static checkChecksum(s: string): boolean { - return UPCEANReader.checkStandardUPCEANChecksum(s); + let resultString = result.toString(); + // UPC/EAN should never be less than 8 chars anyway + if (resultString.length < 8) { + throw new FormatException(); + } + if (!UPCEANReader.checkChecksum(resultString)) { + throw new ChecksumException(); } - static checkStandardUPCEANChecksum(s: string): boolean { - let length = s.length; - if (length === 0) return false; - - let check = parseInt(s.charAt(length - 1), 10); - return UPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check; + let left = (startGuardRange[1] + startGuardRange[0]) / 2.0; + let right = (endRange[1] + endRange[0]) / 2.0; + let format = this.getBarcodeFormat(); + let resultPoint = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)]; + let decodeResult = new Result(resultString, null, 0, resultPoint, format, new Date().getTime()); + + let extensionLength = 0; + + try { + let extensionResult = UPCEANExtensionSupport.decodeRow(rowNumber, row, endRange[1]); + decodeResult.putMetadata(ResultMetadataType.UPC_EAN_EXTENSION, extensionResult.getText()); + decodeResult.putAllMetadata(extensionResult.getResultMetadata()); + decodeResult.addResultPoints(extensionResult.getResultPoints()); + extensionLength = extensionResult.getText().length; + } catch (err) { } - static getStandardUPCEANChecksum(s: string): number { - let length = s.length; - let sum = 0; - for (let i = length - 1; i >= 0; i -= 2) { - let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); - if (digit < 0 || digit > 9) { - throw new FormatException(); - } - sum += digit; - } - sum *= 3; - for (let i = length - 2; i >= 0; i -= 2) { - let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); - if (digit < 0 || digit > 9) { - throw new FormatException(); - } - sum += digit; + let allowedExtensions = hints == null ? null : hints.get(DecodeHintType.ALLOWED_EAN_EXTENSIONS); + if (allowedExtensions != null) { + let valid = false; + for (let length in allowedExtensions) { + // Todo: investigate + if (extensionLength.toString() === length) { // check me + valid = true; + break; } - return (1000 - sum) % 10; + } + if (!valid) { + throw new NotFoundException(); + } } - static decodeEnd(row: BitArray, endStart: number): Int32Array { - return UPCEANReader.findGuardPattern(row, endStart, false, UPCEANReader.START_END_PATTERN, new Int32Array(UPCEANReader.START_END_PATTERN.length).fill(0)); + if (format === BarcodeFormat.EAN_13 || format === BarcodeFormat.UPC_A) { + // let countryID = eanManSupport.lookupContryIdentifier(resultString); todo + // if (countryID != null) { + // decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID); + // } } + + return decodeResult; + } } diff --git a/src/core/oned/UPCEReader.ts b/src/core/oned/UPCEReader.ts index 8381b11e..3890fe7c 100644 --- a/src/core/oned/UPCEReader.ts +++ b/src/core/oned/UPCEReader.ts @@ -19,7 +19,7 @@ import BitArray from '../common/BitArray'; import StringBuilder from '../util/StringBuilder'; import NotFoundException from '../NotFoundException'; import BarcodeFormat from '../BarcodeFormat'; -import { int, char } from 'src/customTypings'; +import { int, char } from 'customTypings'; // package com.google.zxing.oned; @@ -44,8 +44,8 @@ export default /* final */ class UPCEReader extends UPCEANReader { /** * The pattern that marks the middle, and end, of a UPC-E pattern. * There is no "second half" to a UPC-E barcode. - */ - private static /*final*/ MIDDLE_END_PATTERN: Int32Array = Int32Array.from([1, 1, 1, 1, 1, 1]); + */ + private static /* final */ MIDDLE_END_PATTERN: Int32Array = Int32Array.from([1, 1, 1, 1, 1, 1]); // For an UPC-E barcode, the final digit is represented by the parities used // to encode the middle six digits, according to the table below. @@ -75,13 +75,13 @@ export default /* final */ class UPCEReader extends UPCEANReader { * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of * even-odd parity encodings of digits that imply both the number system (0 or 1) * used, and the check digit. - */ - static /*final*/ NUMSYS_AND_CHECK_DIGIT_PATTERNS: Int32Array[] = [ + */ + static /* final */ NUMSYS_AND_CHECK_DIGIT_PATTERNS: Int32Array[] = [ Int32Array.from([0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25]), Int32Array.from([0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1]), ]; - private /*final*/ decodeMiddleCounters: Int32Array; + private /* final */ decodeMiddleCounters: Int32Array; public constructor() { super(); @@ -90,10 +90,10 @@ export default /* final */ class UPCEReader extends UPCEANReader { /** * @throws NotFoundException - */ + */ // @Override - public decodeMiddle(row: BitArray, startRange: Int32Array, result: string) { - const counters: Int32Array = this.decodeMiddleCounters.map(x => x); + public decodeMiddle(row: BitArray, startRange: Int32Array, resultString: StringBuilder) { + const counters: Int32Array = new Int32Array(this.decodeMiddleCounters); counters[0] = 0; counters[1] = 0; counters[2] = 0; @@ -105,7 +105,7 @@ export default /* final */ class UPCEReader extends UPCEANReader { for (let x: int = 0; x < 6 && rowOffset < end; x++) { const bestMatch: int = UPCEReader.decodeDigit(row, counters, rowOffset, UPCEReader.L_AND_G_PATTERNS); - result += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10)); + resultString.append('0'.charCodeAt(0) + bestMatch % 10); for (let counter of counters) { rowOffset += counter; } @@ -114,22 +114,22 @@ export default /* final */ class UPCEReader extends UPCEANReader { } } - UPCEReader.determineNumSysAndCheckDigit(new StringBuilder(result), lgPatternFound); + UPCEReader.determineNumSysAndCheckDigit(resultString, lgPatternFound); return rowOffset; } /** * @throws NotFoundException - */ + */ // @Override protected decodeEnd(row: BitArray, endStart: int): Int32Array { - return UPCEReader.findGuardPatternWithoutCounters(row, endStart, true, UPCEReader.MIDDLE_END_PATTERN); + return UPCEReader.findGuardPattern(row, endStart, true, UPCEReader.MIDDLE_END_PATTERN); } /** * @throws FormatException - */ + */ // @Override protected checkChecksum(s: string): boolean { return UPCEANReader.checkChecksum(UPCEReader.convertUPCEtoUPCA(s)); @@ -137,14 +137,13 @@ export default /* final */ class UPCEReader extends UPCEANReader { /** * @throws NotFoundException - */ - private static determineNumSysAndCheckDigit(resultString: StringBuilder, lgPatternFound: int): void { - + */ + private static determineNumSysAndCheckDigit(resultString: StringBuilder, lgPatternFound: int) { for (let numSys: int = 0; numSys <= 1; numSys++) { for (let d: int = 0; d < 10; d++) { if (lgPatternFound === this.NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) { - resultString.insert(0, /*(char)*/('0' + numSys)); - resultString.append(/*(char)*/('0' + d)); + resultString.insert(0, '0'.charCodeAt(0) + numSys); + resultString.append('0'.charCodeAt(0) + d); return; } } @@ -162,11 +161,11 @@ export default /* final */ class UPCEReader extends UPCEANReader { * * @param upce UPC-E code as string of digits * @return equivalent UPC-A code as string of digits - */ + */ public static convertUPCEtoUPCA(upce: string): string { // the following line is equivalent to upce.getChars(1, 7, upceChars, 0); const upceChars = upce.slice(1, 7).split('').map(x => x.charCodeAt(0)); - const result: StringBuilder = new StringBuilder(/*12*/); + const result: StringBuilder = new StringBuilder(/* 12 */); result.append(upce.charAt(0)); let lastChar: char = upceChars[5]; switch (lastChar) { diff --git a/src/core/oned/rss/AbstractRSSReader.ts b/src/core/oned/rss/AbstractRSSReader.ts index 7da91451..bdb745fb 100644 --- a/src/core/oned/rss/AbstractRSSReader.ts +++ b/src/core/oned/rss/AbstractRSSReader.ts @@ -12,30 +12,30 @@ export default abstract class AbstractRSSReader extends OneDReader { private static readonly MIN_FINDER_PATTERN_RATIO: number = 9.5 / 12.0; private static readonly MAX_FINDER_PATTERN_RATIO: number = 12.5 / 14.0; - private readonly decodeFinderCounters: Int32Array; - private readonly dataCharacterCounters: Int32Array; - private readonly oddRoundingErrors: number[]; - private readonly evenRoundingErrors: number[]; - private readonly oddCounts: number[]; - private readonly evenCounts: number[]; - - public constructor() { - super(); - this.decodeFinderCounters = new Int32Array(4); - this.dataCharacterCounters = new Int32Array(8); - this.oddRoundingErrors = new Array(4); - this.evenRoundingErrors = new Array(4); - this.oddCounts = new Array(this.dataCharacterCounters.length / 2); - this.evenCounts = new Array(this.dataCharacterCounters.length / 2); - } + private readonly decodeFinderCounters: Int32Array; + private readonly dataCharacterCounters: Int32Array; + private readonly oddRoundingErrors: number[]; + private readonly evenRoundingErrors: number[]; + private readonly oddCounts: number[]; + private readonly evenCounts: number[]; + + public constructor() { + super(); + this.decodeFinderCounters = new Int32Array(4); + this.dataCharacterCounters = new Int32Array(8); + this.oddRoundingErrors = new Array(4); + this.evenRoundingErrors = new Array(4); + this.oddCounts = new Array(this.dataCharacterCounters.length / 2); + this.evenCounts = new Array(this.dataCharacterCounters.length / 2); + } - protected getDecodeFinderCounters(): Int32Array { - return this.decodeFinderCounters; - } + protected getDecodeFinderCounters(): Int32Array { + return this.decodeFinderCounters; + } - protected getDataCharacterCounters(): Int32Array { - return this.dataCharacterCounters; - } + protected getDataCharacterCounters(): Int32Array { + return this.dataCharacterCounters; + } protected getOddRoundingErrors(): number[] { return this.oddRoundingErrors; @@ -66,7 +66,7 @@ export default abstract class AbstractRSSReader extends OneDReader { * @param array values to sum * @return sum of values * @deprecated call {@link MathUtils#sum(int[])} - */ + */ protected static count(array: number[]) { return MathUtils.sum(new Int32Array(array)); } diff --git a/src/core/oned/rss/DataCharacter.ts b/src/core/oned/rss/DataCharacter.ts index 49026803..75e0b784 100644 --- a/src/core/oned/rss/DataCharacter.ts +++ b/src/core/oned/rss/DataCharacter.ts @@ -1,34 +1,34 @@ export default class DataCharacter { - private value: number; - private checksumPortion: number; + private value: number; + private checksumPortion: number; - public constructor(value: number, checksumPortion: number) { - this.value = value; - this.checksumPortion = checksumPortion; - } + public constructor(value: number, checksumPortion: number) { + this.value = value; + this.checksumPortion = checksumPortion; + } - public getValue(): number { - return this.value; - } + public getValue(): number { + return this.value; + } - public getChecksumPortion(): number { - return this.checksumPortion; - } + public getChecksumPortion(): number { + return this.checksumPortion; + } - public toString(): string { - return this.value + '(' + this.checksumPortion + ')'; - } + public toString(): string { + return this.value + '(' + this.checksumPortion + ')'; + } - public equals(o: object): boolean { - if (!(o instanceof DataCharacter)) { - return false; - } - const that = o; - return this.value === that.value && this.checksumPortion === that.checksumPortion; + public equals(o: object): boolean { + if (!(o instanceof DataCharacter)) { + return false; } + const that = o; + return this.value === that.value && this.checksumPortion === that.checksumPortion; + } - public hashCode(): number { - return this.value ^ this.checksumPortion; - } + public hashCode(): number { + return this.value ^ this.checksumPortion; + } } diff --git a/src/core/oned/rss/FinderPattern.ts b/src/core/oned/rss/FinderPattern.ts index d78b4e7a..e5f2dbda 100644 --- a/src/core/oned/rss/FinderPattern.ts +++ b/src/core/oned/rss/FinderPattern.ts @@ -3,37 +3,37 @@ import ResultPoint from '../../ResultPoint'; export default class FinderPattern { - private resultPoints: Array; - - public constructor(private value: number, private startEnd: number[], start: number, end: number, rowNumber: number) { - this.value = value; - this.startEnd = startEnd; - this.resultPoints = new Array(); - this.resultPoints.push(new ResultPoint(start, rowNumber)); - this.resultPoints.push(new ResultPoint(end, rowNumber)); + private resultPoints: Array; + + public constructor(private value: number, private startEnd: number[], start: number, end: number, rowNumber: number) { + this.value = value; + this.startEnd = startEnd; + this.resultPoints = new Array(); + this.resultPoints.push(new ResultPoint(start, rowNumber)); + this.resultPoints.push(new ResultPoint(end, rowNumber)); + } + + public getValue(): number { + return this.value; + } + + public getStartEnd(): number[] { + return this.startEnd; + } + + public getResultPoints(): Array { + return this.resultPoints; + } + + public equals(o: object): boolean { + if (!(o instanceof FinderPattern)) { + return false; } + const that = o; + return this.value === that.value; + } - public getValue(): number { - return this.value; - } - - public getStartEnd(): number[] { - return this.startEnd; - } - - public getResultPoints(): Array { - return this.resultPoints; - } - - public equals(o: object): boolean { - if (!(o instanceof FinderPattern)) { - return false; - } - const that = o; - return this.value === that.value; - } - - public hashCode(): number { - return this.value; - } + public hashCode(): number { + return this.value; + } } diff --git a/src/core/oned/rss/Pair.ts b/src/core/oned/rss/Pair.ts index 2aca169c..6ff97a50 100644 --- a/src/core/oned/rss/Pair.ts +++ b/src/core/oned/rss/Pair.ts @@ -3,24 +3,24 @@ import FinderPattern from './FinderPattern'; export default class Pair extends DataCharacter { - private finderPattern: FinderPattern; - private count: number = 0; + private finderPattern: FinderPattern; + private count: number = 0; - public constructor(value: number, checksumPortion: number, finderPattern: FinderPattern) { - super(value, checksumPortion); - this.finderPattern = finderPattern; - } + public constructor(value: number, checksumPortion: number, finderPattern: FinderPattern) { + super(value, checksumPortion); + this.finderPattern = finderPattern; + } - getFinderPattern(): FinderPattern { - return this.finderPattern; - } + getFinderPattern(): FinderPattern { + return this.finderPattern; + } - getCount(): number { - return this.count; - } + getCount(): number { + return this.count; + } - incrementCount() { - this.count++; - } + incrementCount() { + this.count++; + } } diff --git a/src/core/oned/rss/RSS14Reader.ts b/src/core/oned/rss/RSS14Reader.ts index 30bd17ab..6d3bb4c1 100644 --- a/src/core/oned/rss/RSS14Reader.ts +++ b/src/core/oned/rss/RSS14Reader.ts @@ -17,407 +17,398 @@ import OneDReader from '../OneDReader'; export default class RSS14Reader extends AbstractRSSReader { - private static readonly OUTSIDE_EVEN_TOTAL_SUBSET: number[] = [1, 10, 34, 70, 126]; - private static readonly INSIDE_ODD_TOTAL_SUBSET: number[] = [4, 20, 48, 81]; - private static readonly OUTSIDE_GSUM: number[] = [0, 161, 961, 2015, 2715]; - private static readonly INSIDE_GSUM: number[] = [0, 336, 1036, 1516]; - private static readonly OUTSIDE_ODD_WIDEST: number[] = [8, 6, 4, 3, 1]; - private static readonly INSIDE_ODD_WIDEST: number[] = [2, 4, 6, 8]; - - private static readonly FINDER_PATTERNS: Int32Array[] = [ - Int32Array.from([ 3, 8, 2, 1 ]), - Int32Array.from([ 3, 5, 5, 1 ]), - Int32Array.from([ 3, 3, 7, 1 ]), - Int32Array.from([ 3, 1, 9, 1 ]), - Int32Array.from([ 2, 7, 4, 1 ]), - Int32Array.from([ 2, 5, 6, 1 ]), - Int32Array.from([ 2, 3, 8, 1 ]), - Int32Array.from([ 1, 5, 7, 1 ]), - Int32Array.from([ 1, 3, 9, 1 ]), - ]; - - private readonly possibleLeftPairs: Pair[] = []; - private readonly possibleRightPairs: Pair[] = []; - - public decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result { - const leftPair = this.decodePair(row, false, rowNumber, hints); - RSS14Reader.addOrTally(this.possibleLeftPairs, leftPair); - row.reverse(); - let rightPair = this.decodePair(row, true, rowNumber, hints); - RSS14Reader.addOrTally(this.possibleRightPairs, rightPair); - row.reverse(); - for (let left of this.possibleLeftPairs) { - if (left.getCount() > 1) { - for (let right of this.possibleRightPairs) { - if (right.getCount() > 1 && RSS14Reader.checkChecksum(left, right)) { - return RSS14Reader.constructResult(left, right); - } - } - } + private static readonly OUTSIDE_EVEN_TOTAL_SUBSET: number[] = [1, 10, 34, 70, 126]; + private static readonly INSIDE_ODD_TOTAL_SUBSET: number[] = [4, 20, 48, 81]; + private static readonly OUTSIDE_GSUM: number[] = [0, 161, 961, 2015, 2715]; + private static readonly INSIDE_GSUM: number[] = [0, 336, 1036, 1516]; + private static readonly OUTSIDE_ODD_WIDEST: number[] = [8, 6, 4, 3, 1]; + private static readonly INSIDE_ODD_WIDEST: number[] = [2, 4, 6, 8]; + + private static readonly FINDER_PATTERNS: Int32Array[] = [ + Int32Array.from([3, 8, 2, 1]), + Int32Array.from([3, 5, 5, 1]), + Int32Array.from([3, 3, 7, 1]), + Int32Array.from([3, 1, 9, 1]), + Int32Array.from([2, 7, 4, 1]), + Int32Array.from([2, 5, 6, 1]), + Int32Array.from([2, 3, 8, 1]), + Int32Array.from([1, 5, 7, 1]), + Int32Array.from([1, 3, 9, 1]), + ]; + + private readonly possibleLeftPairs: Pair[] = []; + private readonly possibleRightPairs: Pair[] = []; + + public decodeRow(rowNumber: number, row: BitArray, hints?: Map): Result { + const leftPair = this.decodePair(row, false, rowNumber, hints); + RSS14Reader.addOrTally(this.possibleLeftPairs, leftPair); + row.reverse(); + let rightPair = this.decodePair(row, true, rowNumber, hints); + RSS14Reader.addOrTally(this.possibleRightPairs, rightPair); + row.reverse(); + for (let left of this.possibleLeftPairs) { + if (left.getCount() > 1) { + for (let right of this.possibleRightPairs) { + if (right.getCount() > 1 && RSS14Reader.checkChecksum(left, right)) { + return RSS14Reader.constructResult(left, right); + } } - throw new NotFoundException(); + } } + throw new NotFoundException(); + } - private static addOrTally(possiblePairs: Pair[], pair: Pair) { - if (pair == null) { - return; - } - let found = false; - for (let other of possiblePairs) { - if (other.getValue() === pair.getValue()) { - other.incrementCount(); - found = true; - break; - } - } - if (!found) { - possiblePairs.push(pair); - } + private static addOrTally(possiblePairs: Pair[], pair: Pair) { + if (pair == null) { + return; } - - public reset() { - this.possibleLeftPairs.length = 0; - this.possibleRightPairs.length = 0; + let found = false; + for (let other of possiblePairs) { + if (other.getValue() === pair.getValue()) { + other.incrementCount(); + found = true; + break; + } } + if (!found) { + possiblePairs.push(pair); + } + } - private static constructResult(leftPair: Pair, rightPair: Pair): Result { - let symbolValue = 4537077 * leftPair.getValue() + rightPair.getValue(); - let text = new String(symbolValue).toString(); - - let buffer = new StringBuilder(); - for (let i = 13 - text.length; i > 0; i--) { - buffer.append('0'); - } - buffer.append(text); + public reset() { + this.possibleLeftPairs.length = 0; + this.possibleRightPairs.length = 0; + } - let checkDigit = 0; - for (let i = 0; i < 13; i++) { - let digit = buffer.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); - checkDigit += ((i & 0x01) === 0) ? 3 * digit : digit; - } - checkDigit = 10 - (checkDigit % 10); - if (checkDigit === 10) { - checkDigit = 0; - } - buffer.append(checkDigit.toString()); + private static constructResult(leftPair: Pair, rightPair: Pair): Result { + let symbolValue = 4537077 * leftPair.getValue() + rightPair.getValue(); + let text = new String(symbolValue).toString(); - let leftPoints = leftPair.getFinderPattern().getResultPoints(); - let rightPoints = rightPair.getFinderPattern().getResultPoints(); - return new Result(buffer.toString(), null, 0, [leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1]], BarcodeFormat.RSS_14, new Date().getTime()); + let buffer = new StringBuilder(); + for (let i = 13 - text.length; i > 0; i--) { + buffer.append('0'); } + buffer.append(text); - private static checkChecksum(leftPair: Pair, rightPair: Pair): boolean { - let checkValue = (leftPair.getChecksumPortion() + 16 * rightPair.getChecksumPortion()) % 79; - let targetCheckValue = - 9 * leftPair.getFinderPattern().getValue() + rightPair.getFinderPattern().getValue(); - if (targetCheckValue > 72) { - targetCheckValue--; - } - if (targetCheckValue > 8) { - targetCheckValue--; - } - return checkValue === targetCheckValue; + let checkDigit = 0; + for (let i = 0; i < 13; i++) { + let digit = buffer.charAt(i).charCodeAt(0) - '0'.charCodeAt(0); + checkDigit += ((i & 0x01) === 0) ? 3 * digit : digit; } - - private decodePair(row: BitArray, right: boolean, rowNumber: number, hints: Map): Pair { - try { - let startEnd = this.findFinderPattern(row, right); - let pattern = this.parseFoundFinderPattern(row, rowNumber, right, startEnd); - - let resultPointCallback = hints == null ? null : hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - - if (resultPointCallback != null) { - let center = (startEnd[0] + startEnd[1]) / 2.0; - if (right) { - // row is actually reversed - center = row.getSize() - 1 - center; - } - resultPointCallback.foundPossibleResultPoint(new ResultPoint(center, rowNumber)); - } - - let outside = this.decodeDataCharacter(row, pattern, true); - let inside = this.decodeDataCharacter(row, pattern, false); - return new Pair(1597 * outside.getValue() + inside.getValue(), - outside.getChecksumPortion() + 4 * inside.getChecksumPortion(), - pattern); - } - catch (err) { - return null; - } + checkDigit = 10 - (checkDigit % 10); + if (checkDigit === 10) { + checkDigit = 0; + } + buffer.append(checkDigit.toString()); + + let leftPoints = leftPair.getFinderPattern().getResultPoints(); + let rightPoints = rightPair.getFinderPattern().getResultPoints(); + return new Result(buffer.toString(), null, 0, [leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1]], BarcodeFormat.RSS_14, new Date().getTime()); + } + + private static checkChecksum(leftPair: Pair, rightPair: Pair): boolean { + let checkValue = (leftPair.getChecksumPortion() + 16 * rightPair.getChecksumPortion()) % 79; + let targetCheckValue = + 9 * leftPair.getFinderPattern().getValue() + rightPair.getFinderPattern().getValue(); + if (targetCheckValue > 72) { + targetCheckValue--; } + if (targetCheckValue > 8) { + targetCheckValue--; + } + return checkValue === targetCheckValue; + } - private decodeDataCharacter(row: BitArray, pattern: FinderPattern, outsideChar: boolean): DataCharacter { + private decodePair(row: BitArray, right: boolean, rowNumber: number, hints: Map): Pair { + try { + let startEnd = this.findFinderPattern(row, right); + let pattern = this.parseFoundFinderPattern(row, rowNumber, right, startEnd); - let counters = this.getDataCharacterCounters(); - for (let x = 0; x < counters.length; x++) { - counters[x] = 0; - } + let resultPointCallback = hints == null ? null : hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - if (outsideChar) { - OneDReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters); - } else { - OneDReader.recordPattern(row, pattern.getStartEnd()[1] + 1, counters); - // reverse it - for (let i = 0, j = counters.length - 1; i < j; i++ , j--) { - let temp = counters[i]; - counters[i] = counters[j]; - counters[j] = temp; - } + if (resultPointCallback != null) { + let center = (startEnd[0] + startEnd[1]) / 2.0; + if (right) { + // row is actually reversed + center = row.getSize() - 1 - center; } + resultPointCallback.foundPossibleResultPoint(new ResultPoint(center, rowNumber)); + } + + let outside = this.decodeDataCharacter(row, pattern, true); + let inside = this.decodeDataCharacter(row, pattern, false); + return new Pair(1597 * outside.getValue() + inside.getValue(), + outside.getChecksumPortion() + 4 * inside.getChecksumPortion(), + pattern); + } catch (err) { + return null; + } + } - let numModules = outsideChar ? 16 : 15; - let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules; - - let oddCounts = this.getOddCounts(); - let evenCounts = this.getEvenCounts(); - let oddRoundingErrors = this.getOddRoundingErrors(); - let evenRoundingErrors = this.getEvenRoundingErrors(); - - for (let i = 0; i < counters.length; i++) { - let value = counters[i] / elementWidth; - let count = Math.floor(value + 0.5); - if (count < 1) { - count = 1; - } else if (count > 8) { - count = 8; - } - let offset = Math.floor(i / 2); - if ((i & 0x01) === 0) { - oddCounts[offset] = count; - oddRoundingErrors[offset] = value - count; - } else { - evenCounts[offset] = count; - evenRoundingErrors[offset] = value - count; - } - } + private decodeDataCharacter(row: BitArray, pattern: FinderPattern, outsideChar: boolean): DataCharacter { - this.adjustOddEvenCounts(outsideChar, numModules); + let counters = this.getDataCharacterCounters(); + for (let x = 0; x < counters.length; x++) { + counters[x] = 0; + } - let oddSum = 0; - let oddChecksumPortion = 0; - for (let i = oddCounts.length - 1; i >= 0; i--) { - oddChecksumPortion *= 9; - oddChecksumPortion += oddCounts[i]; - oddSum += oddCounts[i]; - } - let evenChecksumPortion = 0; - let evenSum = 0; - for (let i = evenCounts.length - 1; i >= 0; i--) { - evenChecksumPortion *= 9; - evenChecksumPortion += evenCounts[i]; - evenSum += evenCounts[i]; - } - let checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion; - - if (outsideChar) { - if ((oddSum & 0x01) !== 0 || oddSum > 12 || oddSum < 4) { - throw new NotFoundException(); - } - let group = (12 - oddSum) / 2; - let oddWidest = RSS14Reader.OUTSIDE_ODD_WIDEST[group]; - let evenWidest = 9 - oddWidest; - let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false); - let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true); - let tEven = RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET[group]; - let gSum = RSS14Reader.OUTSIDE_GSUM[group]; - return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion); - } else { - if ((evenSum & 0x01) !== 0 || evenSum > 10 || evenSum < 4) { - throw new NotFoundException(); - } - let group = (10 - evenSum) / 2; - let oddWidest = RSS14Reader.INSIDE_ODD_WIDEST[group]; - let evenWidest = 9 - oddWidest; - let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true); - let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false); - let tOdd = RSS14Reader.INSIDE_ODD_TOTAL_SUBSET[group]; - let gSum = RSS14Reader.INSIDE_GSUM[group]; - return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion); - } + if (outsideChar) { + OneDReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters); + } else { + OneDReader.recordPattern(row, pattern.getStartEnd()[1] + 1, counters); + // reverse it + for (let i = 0, j = counters.length - 1; i < j; i++, j--) { + let temp = counters[i]; + counters[i] = counters[j]; + counters[j] = temp; + } + } + let numModules = outsideChar ? 16 : 15; + let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules; + + let oddCounts = this.getOddCounts(); + let evenCounts = this.getEvenCounts(); + let oddRoundingErrors = this.getOddRoundingErrors(); + let evenRoundingErrors = this.getEvenRoundingErrors(); + + for (let i = 0; i < counters.length; i++) { + let value = counters[i] / elementWidth; + let count = Math.floor(value + 0.5); + if (count < 1) { + count = 1; + } else if (count > 8) { + count = 8; + } + let offset = Math.floor(i / 2); + if ((i & 0x01) === 0) { + oddCounts[offset] = count; + oddRoundingErrors[offset] = value - count; + } else { + evenCounts[offset] = count; + evenRoundingErrors[offset] = value - count; + } } - private findFinderPattern(row: BitArray, rightFinderPattern: boolean): number[] { - - let counters = this.getDecodeFinderCounters(); - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - - let width = row.getSize(); - let isWhite = false; - let rowOffset = 0; - while (rowOffset < width) { - isWhite = !row.get(rowOffset); - if (rightFinderPattern === isWhite) { - // Will encounter white first when searching for right finder pattern - break; - } - rowOffset++; - } + this.adjustOddEvenCounts(outsideChar, numModules); - let counterPosition = 0; - let patternStart = rowOffset; - for (let x = rowOffset; x < width; x++) { - if (row.get(x) !== isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition === 3) { - if (AbstractRSSReader.isFinderPattern(counters)) { - return [patternStart, x ]; - } - patternStart += counters[0] + counters[1]; - counters[0] = counters[2]; - counters[1] = counters[3]; - counters[2] = 0; - counters[3] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw new NotFoundException(); + let oddSum = 0; + let oddChecksumPortion = 0; + for (let i = oddCounts.length - 1; i >= 0; i--) { + oddChecksumPortion *= 9; + oddChecksumPortion += oddCounts[i]; + oddSum += oddCounts[i]; } + let evenChecksumPortion = 0; + let evenSum = 0; + for (let i = evenCounts.length - 1; i >= 0; i--) { + evenChecksumPortion *= 9; + evenChecksumPortion += evenCounts[i]; + evenSum += evenCounts[i]; + } + let checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion; - private parseFoundFinderPattern(row: BitArray, rowNumber: number, right: boolean, startEnd: number[]): FinderPattern { - // Actually we found elements 2-5 - let firstIsBlack = row.get(startEnd[0]); - let firstElementStart = startEnd[0] - 1; - // Locate element 1 - while (firstElementStart >= 0 && firstIsBlack !== row.get(firstElementStart)) { - firstElementStart--; - } - firstElementStart++; - const firstCounter = startEnd[0] - firstElementStart; - // Make 'counters' hold 1-4 - const counters = this.getDecodeFinderCounters(); - const copy = new Int32Array(counters.length); - System.arraycopy(counters, 0, copy, 1, counters.length - 1); - copy[0] = firstCounter; - const value = this.parseFinderValue(copy, RSS14Reader.FINDER_PATTERNS); - let start = firstElementStart; - let end = startEnd[1]; - if (right) { - // row is actually reversed - start = row.getSize() - 1 - start; - end = row.getSize() - 1 - end; - } - return new FinderPattern(value, [ firstElementStart, startEnd[1] ], start, end, rowNumber); + if (outsideChar) { + if ((oddSum & 0x01) !== 0 || oddSum > 12 || oddSum < 4) { + throw new NotFoundException(); + } + let group = (12 - oddSum) / 2; + let oddWidest = RSS14Reader.OUTSIDE_ODD_WIDEST[group]; + let evenWidest = 9 - oddWidest; + let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false); + let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true); + let tEven = RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET[group]; + let gSum = RSS14Reader.OUTSIDE_GSUM[group]; + return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion); + } else { + if ((evenSum & 0x01) !== 0 || evenSum > 10 || evenSum < 4) { + throw new NotFoundException(); + } + let group = (10 - evenSum) / 2; + let oddWidest = RSS14Reader.INSIDE_ODD_WIDEST[group]; + let evenWidest = 9 - oddWidest; + let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true); + let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false); + let tOdd = RSS14Reader.INSIDE_ODD_TOTAL_SUBSET[group]; + let gSum = RSS14Reader.INSIDE_GSUM[group]; + return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion); } - private adjustOddEvenCounts(outsideChar: boolean, numModules: number) { - - let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts())); - let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts())); - - let incrementOdd = false; - let decrementOdd = false; - let incrementEven = false; - let decrementEven = false; - - if (outsideChar) { - if (oddSum > 12) { - decrementOdd = true; - } - else if (oddSum < 4) { - incrementOdd = true; - } - if (evenSum > 12) { - decrementEven = true; - } - else if (evenSum < 4) { - incrementEven = true; - } - } - else { - if (oddSum > 11) { - decrementOdd = true; - } - else if (oddSum < 5) { - incrementOdd = true; - } - if (evenSum > 10) { - decrementEven = true; - } - else if (evenSum < 4) { - incrementEven = true; - } - } + } + + private findFinderPattern(row: BitArray, rightFinderPattern: boolean): number[] { + + let counters = this.getDecodeFinderCounters(); + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + + let width = row.getSize(); + let isWhite = false; + let rowOffset = 0; + while (rowOffset < width) { + isWhite = !row.get(rowOffset); + if (rightFinderPattern === isWhite) { + // Will encounter white first when searching for right finder pattern + break; + } + rowOffset++; + } - let mismatch = oddSum + evenSum - numModules; - let oddParityBad = (oddSum & 0x01) === (outsideChar ? 1 : 0); - let evenParityBad = (evenSum & 0x01) === 1; - if (mismatch === 1) { - if (oddParityBad) { - if (evenParityBad) { - throw new NotFoundException(); - } - decrementOdd = true; + let counterPosition = 0; + let patternStart = rowOffset; + for (let x = rowOffset; x < width; x++) { + if (row.get(x) !== isWhite) { + counters[counterPosition]++; + } else { + if (counterPosition === 3) { + if (AbstractRSSReader.isFinderPattern(counters)) { + return [patternStart, x]; + } + patternStart += counters[0] + counters[1]; + counters[0] = counters[2]; + counters[1] = counters[3]; + counters[2] = 0; + counters[3] = 0; + counterPosition--; } else { - if (!evenParityBad) { - throw new NotFoundException(); - } - decrementEven = true; + counterPosition++; } - } else if (mismatch === -1) { - if (oddParityBad) { - if (evenParityBad) { - throw new NotFoundException(); - } - incrementOdd = true; - } else { - if (!evenParityBad) { - throw new NotFoundException(); - } - incrementEven = true; - } + counters[counterPosition] = 1; + isWhite = !isWhite; + } + } + throw new NotFoundException(); + } + + private parseFoundFinderPattern(row: BitArray, rowNumber: number, right: boolean, startEnd: number[]): FinderPattern { + // Actually we found elements 2-5 + let firstIsBlack = row.get(startEnd[0]); + let firstElementStart = startEnd[0] - 1; + // Locate element 1 + while (firstElementStart >= 0 && firstIsBlack !== row.get(firstElementStart)) { + firstElementStart--; + } + firstElementStart++; + const firstCounter = startEnd[0] - firstElementStart; + // Make 'counters' hold 1-4 + const counters = this.getDecodeFinderCounters(); + const copy = new Int32Array(counters.length); + System.arraycopy(counters, 0, copy, 1, counters.length - 1); + copy[0] = firstCounter; + const value = this.parseFinderValue(copy, RSS14Reader.FINDER_PATTERNS); + let start = firstElementStart; + let end = startEnd[1]; + if (right) { + // row is actually reversed + start = row.getSize() - 1 - start; + end = row.getSize() - 1 - end; + } + return new FinderPattern(value, [firstElementStart, startEnd[1]], start, end, rowNumber); + } + + private adjustOddEvenCounts(outsideChar: boolean, numModules: number) { + + let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts())); + let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts())); + + let incrementOdd = false; + let decrementOdd = false; + let incrementEven = false; + let decrementEven = false; + + if (outsideChar) { + if (oddSum > 12) { + decrementOdd = true; + } else if (oddSum < 4) { + incrementOdd = true; + } + if (evenSum > 12) { + decrementEven = true; + } else if (evenSum < 4) { + incrementEven = true; + } + } else { + if (oddSum > 11) { + decrementOdd = true; + } else if (oddSum < 5) { + incrementOdd = true; + } + if (evenSum > 10) { + decrementEven = true; + } else if (evenSum < 4) { + incrementEven = true; + } + } + + let mismatch = oddSum + evenSum - numModules; + let oddParityBad = (oddSum & 0x01) === (outsideChar ? 1 : 0); + let evenParityBad = (evenSum & 0x01) === 1; + if (mismatch === 1) { + if (oddParityBad) { + if (evenParityBad) { + throw new NotFoundException(); } - else if (mismatch === 0) { - if (oddParityBad) { - if (!evenParityBad) { - throw new NotFoundException(); - } - // Both bad - if (oddSum < evenSum) { - incrementOdd = true; - decrementEven = true; - } else { - decrementOdd = true; - incrementEven = true; - } - } - else { - if (evenParityBad) { - throw new NotFoundException(); - } - // Nothing to do! - } + decrementOdd = true; + } else { + if (!evenParityBad) { + throw new NotFoundException(); } - else { - throw new NotFoundException(); + decrementEven = true; + } + } else if (mismatch === -1) { + if (oddParityBad) { + if (evenParityBad) { + throw new NotFoundException(); } - - if (incrementOdd) { - if (decrementOdd) { - throw new NotFoundException(); - } - AbstractRSSReader.increment(this.getOddCounts(), this.getOddRoundingErrors()); + incrementOdd = true; + } else { + if (!evenParityBad) { + throw new NotFoundException(); } - if (decrementOdd) { - AbstractRSSReader.decrement(this.getOddCounts(), this.getOddRoundingErrors()); + incrementEven = true; + } + } else if (mismatch === 0) { + if (oddParityBad) { + if (!evenParityBad) { + throw new NotFoundException(); } - if (incrementEven) { - if (decrementEven) { - throw new NotFoundException(); - } - AbstractRSSReader.increment(this.getEvenCounts(), this.getOddRoundingErrors()); + // Both bad + if (oddSum < evenSum) { + incrementOdd = true; + decrementEven = true; + } else { + decrementOdd = true; + incrementEven = true; } - if (decrementEven) { - AbstractRSSReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors()); + } else { + if (evenParityBad) { + throw new NotFoundException(); } + // Nothing to do! + } + } else { + throw new NotFoundException(); + } + + if (incrementOdd) { + if (decrementOdd) { + throw new NotFoundException(); + } + AbstractRSSReader.increment(this.getOddCounts(), this.getOddRoundingErrors()); + } + if (decrementOdd) { + AbstractRSSReader.decrement(this.getOddCounts(), this.getOddRoundingErrors()); + } + if (incrementEven) { + if (decrementEven) { + throw new NotFoundException(); + } + AbstractRSSReader.increment(this.getEvenCounts(), this.getOddRoundingErrors()); + } + if (decrementEven) { + AbstractRSSReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors()); } + } } diff --git a/src/core/oned/rss/RSSUtils.ts b/src/core/oned/rss/RSSUtils.ts index 78d3d3ea..cec43b7f 100644 --- a/src/core/oned/rss/RSSUtils.ts +++ b/src/core/oned/rss/RSSUtils.ts @@ -15,7 +15,7 @@ export default class RSSUtils { let elements = widths.length; for (let bar = 0; bar < elements - 1; bar++) { let elmWidth; - for (elmWidth = 1, narrowMask |= 1 << bar; elmWidth < widths[bar]; elmWidth++ , narrowMask &= ~(1 << bar)) { + for (elmWidth = 1, narrowMask |= 1 << bar; elmWidth < widths[bar]; elmWidth++, narrowMask &= ~(1 << bar)) { let subVal = RSSUtils.combins(n - elmWidth - 1, elements - bar - 2); if (noNarrow && (narrowMask === 0) && (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) { subVal -= RSSUtils.combins(n - elmWidth - (elements - bar), elements - bar - 2); diff --git a/src/core/oned/rss/expanded/BitArrayBuilder.ts b/src/core/oned/rss/expanded/BitArrayBuilder.ts index d3dac0c2..545e654f 100644 --- a/src/core/oned/rss/expanded/BitArrayBuilder.ts +++ b/src/core/oned/rss/expanded/BitArrayBuilder.ts @@ -17,7 +17,7 @@ export default class BitArrayBuilder { let firstPair: ExpandedPair = pairs[0]; let firstValue = firstPair.getRightChar().getValue(); for (let i = 11; i >= 0; --i) { - if ((firstValue & (1 << i)) != 0) { + if ((firstValue & (1 << i)) !== 0) { binary.set(accPos); } accPos++; @@ -28,7 +28,7 @@ export default class BitArrayBuilder { let leftValue = currentPair.getLeftChar().getValue(); for (let j = 11; j >= 0; --j) { - if ((leftValue & (1 << j)) != 0) { + if ((leftValue & (1 << j)) !== 0) { binary.set(accPos); } accPos++; @@ -37,7 +37,7 @@ export default class BitArrayBuilder { if (currentPair.getRightChar() != null) { let rightValue = currentPair.getRightChar().getValue(); for (let j = 11; j >= 0; --j) { - if ((rightValue & (1 << j)) != 0) { + if ((rightValue & (1 << j)) !== 0) { binary.set(accPos); } accPos++; diff --git a/src/core/oned/rss/expanded/ExpandedRow.ts b/src/core/oned/rss/expanded/ExpandedRow.ts index d1c7d7ee..89f2f54a 100644 --- a/src/core/oned/rss/expanded/ExpandedRow.ts +++ b/src/core/oned/rss/expanded/ExpandedRow.ts @@ -36,7 +36,7 @@ export default class ExpandedRow { /** * Two rows are equal if they contain the same pairs in the same order. - */ + */ // @Override // check implementation public equals(o1: ExpandedRow, o2: ExpandedRow): boolean { diff --git a/src/core/oned/rss/expanded/RSSExpandedReader.ts b/src/core/oned/rss/expanded/RSSExpandedReader.ts index 1ccc4cd6..368c77e2 100644 --- a/src/core/oned/rss/expanded/RSSExpandedReader.ts +++ b/src/core/oned/rss/expanded/RSSExpandedReader.ts @@ -32,7 +32,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { private static readonly EVEN_TOTAL_SUBSET = [4, 20, 52, 104, 204]; private static readonly GSUM = [0, 348, 1388, 2948, 3988]; - private static readonly FINDER_PATTERNS = [ + private static readonly FINDER_PATTERNS = [ Int32Array.from([1, 8, 4, 1]), // A Int32Array.from([3, 6, 4, 1]), // B Int32Array.from([3, 4, 6, 1]), // C @@ -237,7 +237,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { let stop = true; for (let j = 0; j < pairs.length; j++) { - if (pairs[j].getFinderPattern().getValue() != sequence[j]) { + if (pairs[j].getFinderPattern().getValue() !== sequence[j]) { stop = false; break; } @@ -407,7 +407,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { let checkCharacterValue = 211 * (s - 4) + checksum; - return checkCharacterValue == checkCharacter.getValue(); + return checkCharacterValue === checkCharacter.getValue(); } private static getNextSecondBar(row: BitArray, initialPos: number): number { @@ -424,7 +424,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { // not private for testing retrieveNextPair(row: BitArray, previousPairs: Array, rowNumber: number): ExpandedPair { - let isOddPattern = previousPairs.length % 2 == 0; + let isOddPattern = previousPairs.length % 2 === 0; if (this.startFromEven) { isOddPattern = !isOddPattern; } @@ -485,7 +485,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { let lastPair = previousPairs[previousPairs.length - 1]; rowOffset = lastPair.getFinderPattern().getStartEnd()[1]; } - let searchingEvenPair = previousPairs.length % 2 != 0; + let searchingEvenPair = previousPairs.length % 2 !== 0; if (this.startFromEven) { searchingEvenPair = !searchingEvenPair; } @@ -502,10 +502,10 @@ export default class RSSExpandedReader extends AbstractRSSReader { let counterPosition = 0; let patternStart = rowOffset; for (let x = rowOffset; x < width; x++) { - if (row.get(x) != isWhite) { + if (row.get(x) !== isWhite) { counters[counterPosition]++; } else { - if (counterPosition == 3) { + if (counterPosition === 3) { if (searchingEvenPair) { RSSExpandedReader.reverseCounters(counters); } @@ -601,7 +601,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { } else { RSSExpandedReader.recordPattern(row, pattern.getStartEnd()[1], counters); // reverse it - for (let i = 0, j = counters.length - 1; i < j; i++ , j--) { + for (let i = 0, j = counters.length - 1; i < j; i++, j--) { let temp = counters[i]; counters[i] = counters[j]; counters[j] = temp; @@ -637,7 +637,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { count = 8; } let offset = i / 2; - if ((i & 0x01) == 0) { + if ((i & 0x01) === 0) { oddCounts[offset] = count; oddRoundingErrors[offset] = value - count; } else { @@ -670,7 +670,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { } let checksumPortion = oddChecksumPortion + evenChecksumPortion; - if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4) { + if ((oddSum & 0x01) !== 0 || oddSum > 13 || oddSum < 4) { throw new NotFoundException(); } @@ -688,7 +688,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { private static isNotA1left(pattern: FinderPattern, isOddPattern: boolean, leftChar: boolean): boolean { // A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char - return !(pattern.getValue() == 0 && isOddPattern && leftChar); + return !(pattern.getValue() === 0 && isOddPattern && leftChar); } private adjustOddEvenCounts(numModules) { @@ -713,9 +713,9 @@ export default class RSSExpandedReader extends AbstractRSSReader { } let mismatch = oddSum + evenSum - numModules; - let oddParityBad = (oddSum & 0x01) == 1; - let evenParityBad = (evenSum & 0x01) == 0; - if (mismatch == 1) { + let oddParityBad = (oddSum & 0x01) === 1; + let evenParityBad = (evenSum & 0x01) === 0; + if (mismatch === 1) { if (oddParityBad) { if (evenParityBad) { throw new NotFoundException(); @@ -727,7 +727,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { } decrementEven = true; } - } else if (mismatch == -1) { + } else if (mismatch === -1) { if (oddParityBad) { if (evenParityBad) { throw new NotFoundException(); @@ -739,7 +739,7 @@ export default class RSSExpandedReader extends AbstractRSSReader { } incrementEven = true; } - } else if (mismatch == 0) { + } else if (mismatch === 0) { if (oddParityBad) { if (!evenParityBad) { throw new NotFoundException(); diff --git a/src/core/oned/rss/expanded/decoders/AI01393xDecoder.ts b/src/core/oned/rss/expanded/decoders/AI01393xDecoder.ts index 0120e23f..b2ef01e6 100644 --- a/src/core/oned/rss/expanded/decoders/AI01393xDecoder.ts +++ b/src/core/oned/rss/expanded/decoders/AI01393xDecoder.ts @@ -28,10 +28,10 @@ export default class AI01393xDecoder extends AI01decoder { buf.append(')'); let firstThreeDigits = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE, AI01393xDecoder.FIRST_THREE_DIGITS_SIZE); - if (firstThreeDigits / 100 == 0) { + if (firstThreeDigits / 100 === 0) { buf.append('0'); } - if (firstThreeDigits / 10 == 0) { + if (firstThreeDigits / 10 === 0) { buf.append('0'); } buf.append(firstThreeDigits); diff --git a/src/core/oned/rss/expanded/decoders/AI013x0x1xDecoder.ts b/src/core/oned/rss/expanded/decoders/AI013x0x1xDecoder.ts index 581d9056..056fd405 100644 --- a/src/core/oned/rss/expanded/decoders/AI013x0x1xDecoder.ts +++ b/src/core/oned/rss/expanded/decoders/AI013x0x1xDecoder.ts @@ -18,7 +18,7 @@ export default class AI013x0x1xDecoder extends AI01weightDecoder { } public parseInformation(): string { - if (this.getInformation().getSize() != AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE + AI013x0x1xDecoder.DATE_SIZE) { + if (this.getInformation().getSize() !== AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE + AI013x0x1xDecoder.DATE_SIZE) { throw new NotFoundException(); } @@ -33,7 +33,7 @@ export default class AI013x0x1xDecoder extends AI01weightDecoder { private encodeCompressedDate(buf: StringBuilder, currentPos: number): void { let numericDate = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, AI013x0x1xDecoder.DATE_SIZE); - if (numericDate == 38400) { + if (numericDate === 38400) { return; } @@ -47,15 +47,15 @@ export default class AI013x0x1xDecoder extends AI01weightDecoder { numericDate /= 12; let year = numericDate; - if (year / 10 == 0) { + if (year / 10 === 0) { buf.append('0'); } buf.append(year); - if (month / 10 == 0) { + if (month / 10 === 0) { buf.append('0'); } buf.append(month); - if (day / 10 == 0) { + if (day / 10 === 0) { buf.append('0'); } buf.append(day); diff --git a/src/core/oned/rss/expanded/decoders/AI013x0xDecoder.ts b/src/core/oned/rss/expanded/decoders/AI013x0xDecoder.ts index 631a6d72..10df69e8 100644 --- a/src/core/oned/rss/expanded/decoders/AI013x0xDecoder.ts +++ b/src/core/oned/rss/expanded/decoders/AI013x0xDecoder.ts @@ -12,7 +12,7 @@ export default abstract class AI013x0xDecoder extends AI01weightDecoder { } public parseInformation() { - if (this.getInformation().getSize() != AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE + AI013x0xDecoder.WEIGHT_SIZE) { + if (this.getInformation().getSize() !== AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE + AI013x0xDecoder.WEIGHT_SIZE) { throw new NotFoundException(); } diff --git a/src/core/oned/rss/expanded/decoders/BlockParsedResult.ts b/src/core/oned/rss/expanded/decoders/BlockParsedResult.ts index 669cbb77..a6ade430 100644 --- a/src/core/oned/rss/expanded/decoders/BlockParsedResult.ts +++ b/src/core/oned/rss/expanded/decoders/BlockParsedResult.ts @@ -22,4 +22,4 @@ export default class BlockParsedResult { return this.finished; } -} \ No newline at end of file +} diff --git a/src/core/oned/rss/expanded/decoders/createDecoder.ts b/src/core/oned/rss/expanded/decoders/createDecoder.ts index 2c0efc4c..27965777 100644 --- a/src/core/oned/rss/expanded/decoders/createDecoder.ts +++ b/src/core/oned/rss/expanded/decoders/createDecoder.ts @@ -1,4 +1,5 @@ -import { BitArray, IllegalStateException } from '../../../../..'; +import BitArray from '../../../../common/BitArray'; +import IllegalStateException from '../../../../IllegalStateException'; import AbstractExpandedDecoder from './AbstractExpandedDecoder'; import AI013103decoder from './AI013103decoder'; import AI01320xDecoder from './AI01320xDecoder'; diff --git a/src/core/pdf417/PDF417Common.ts b/src/core/pdf417/PDF417Common.ts index a083b4c0..48294b36 100644 --- a/src/core/pdf417/PDF417Common.ts +++ b/src/core/pdf417/PDF417Common.ts @@ -28,440 +28,440 @@ import { int } from '../../customTypings'; * @author SITA Lab (kevin.osullivan@sita.aero) * @author Guenther Grau */ -export default /*public final*/ class PDF417Common { +export default /* public final */ class PDF417Common { - public static /*final int*/ NUMBER_OF_CODEWORDS = 929; - // Maximum Codewords (Data + Error). - public static /*final int*/ MAX_CODEWORDS_IN_BARCODE = PDF417Common.NUMBER_OF_CODEWORDS - 1; - public static /*final int*/ MIN_ROWS_IN_BARCODE = 3; - public static /*final int*/ MAX_ROWS_IN_BARCODE = 90; - // One left row indication column + max 30 data columns + one right row indicator column - // public static /*final*/ MAX_CODEWORDS_IN_ROW: /*int*/ number = 32; - public static /*final int*/ MODULES_IN_CODEWORD = 17; - public static /*final int*/ MODULES_IN_STOP_PATTERN = 18; - public static /*final int*/ BARS_IN_MODULE = 8; + public static /* final int */ NUMBER_OF_CODEWORDS = 929; + // Maximum Codewords (Data + Error). + public static /* final int */ MAX_CODEWORDS_IN_BARCODE = PDF417Common.NUMBER_OF_CODEWORDS - 1; + public static /* final int */ MIN_ROWS_IN_BARCODE = 3; + public static /* final int */ MAX_ROWS_IN_BARCODE = 90; + // One left row indication column + max 30 data columns + one right row indicator column + // public static /*final */ MAX_CODEWORDS_IN_ROW: /*int */ number = 32; + public static /* final int */ MODULES_IN_CODEWORD = 17; + public static /* final int */ MODULES_IN_STOP_PATTERN = 18; + public static /* final int */ BARS_IN_MODULE = 8; - private static /*final int[]*/ EMPTY_INT_ARRAY: Int32Array = new Int32Array([]); + private static /* final int[] */ EMPTY_INT_ARRAY: Int32Array = new Int32Array([]); - private PDF417Common() { - } + private PDF417Common() { + } - /** - * @param moduleBitCount values to sum - * @return sum of values - * @deprecated call {@link MathUtils#sum(int[])} - */ - // @Deprecated - public static getBitCountSum(moduleBitCount: Int32Array): int { - return MathUtils.sum(moduleBitCount); - } + /** + * @param moduleBitCount values to sum + * @return sum of values + * @deprecated call {@link MathUtils#sum(int[])} + */ + // @Deprecated + public static getBitCountSum(moduleBitCount: Int32Array): int { + return MathUtils.sum(moduleBitCount); + } - public static toIntArray(list: /*Collection*/ int[]): Int32Array { - if (list == null || !list.length) { - return PDF417Common.EMPTY_INT_ARRAY; - } - const result = new Int32Array(list.length); - let i: int = 0; - for (const integer of list) { - result[i++] = integer; - } - return result; + public static toIntArray(list: /* Collection */ int[]): Int32Array { + if (list == null || !list.length) { + return PDF417Common.EMPTY_INT_ARRAY; + } + const result = new Int32Array(list.length); + let i: int = 0; + for (const integer of list) { + result[i++] = integer; } + return result; + } - /** - * @param symbol encoded symbol to translate to a codeword - * @return the codeword corresponding to the symbol. - */ - public static getCodeword(symbol: number/*int*/): number/*int*/ { - const i = Arrays.binarySearch(PDF417Common.SYMBOL_TABLE, symbol & 0x3FFFF); - if (i < 0) { - return -1; - } - return (PDF417Common.CODEWORD_TABLE[i] - 1) % PDF417Common.NUMBER_OF_CODEWORDS; + /** + * @param symbol encoded symbol to translate to a codeword + * @return the codeword corresponding to the symbol. + */ + public static getCodeword(symbol: number/* int */): number/* int */ { + const i = Arrays.binarySearch(PDF417Common.SYMBOL_TABLE, symbol & 0x3FFFF); + if (i < 0) { + return -1; } + return (PDF417Common.CODEWORD_TABLE[i] - 1) % PDF417Common.NUMBER_OF_CODEWORDS; + } - /** - * The sorted table of all possible symbols. Extracted from the PDF417 - * specification. The index of a symbol in this table corresponds to the - * index into the codeword table. - */ - public static /*final int[]*/ SYMBOL_TABLE = Int32Array.from([ - 0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac, - 0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482, - 0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e, - 0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2, - 0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716, - 0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6, - 0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890, - 0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e, - 0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4, - 0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c, - 0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0, - 0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c, - 0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38, - 0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8, - 0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98, - 0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44, - 0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050, - 0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee, - 0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be, - 0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c, - 0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6, - 0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618, - 0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784, - 0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e, - 0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de, - 0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e, - 0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70, - 0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98, - 0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46, - 0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8, - 0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4, - 0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28, - 0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e, - 0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c, - 0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc, - 0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0, - 0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306, - 0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6, - 0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8, - 0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8, - 0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60, - 0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08, - 0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc, - 0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de, - 0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc, - 0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308, - 0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2, - 0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8, - 0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e, - 0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816, - 0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce, - 0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c, - 0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e, - 0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e, - 0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28, - 0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0, - 0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c, - 0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6, - 0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c, - 0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46, - 0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110, - 0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8, - 0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330, - 0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410, - 0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660, - 0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0, - 0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0, - 0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0, - 0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98, - 0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0, - 0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20, - 0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e, - 0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170, - 0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4, - 0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320, - 0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4, - 0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610, - 0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e, - 0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870, - 0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0, - 0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e, - 0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046, - 0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106, - 0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8, - 0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c, - 0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc, - 0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0, - 0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e, - 0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822, - 0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884, - 0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902, - 0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0, - 0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20, - 0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e, - 0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e, - 0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0, - 0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e, - 0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58, - 0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8, - 0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274, - 0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426, - 0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc, - 0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e, - 0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614, - 0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e, - 0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796, - 0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872, - 0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c, - 0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec, - 0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e, - 0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2, - 0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82, - 0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e, - 0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32, - 0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8, - 0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94, - 0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086, - 0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e, - 0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa, - 0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390, - 0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460, - 0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708, - 0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc, - 0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882, - 0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920, - 0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e, - 0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8, - 0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8, - 0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84, - 0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58, - 0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12, - 0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae, - 0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2, - 0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c, - 0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260, - 0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e, - 0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460, - 0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704, - 0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be, - 0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0, - 0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40, - 0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8, - 0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e, - 0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c, - 0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e, - 0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8, - 0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660, - 0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e, - 0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c, - 0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4, - 0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40, - 0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72, - 0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c, - 0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa, - 0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82, - 0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34, - 0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162, - 0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268, - 0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326, - 0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462, - 0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec, - 0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc, - 0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c, - 0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2, - 0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e, - 0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c, - 0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6, - 0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc, - 0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02, - 0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe, - 0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58, - 0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18, - 0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa, - 0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e, - 0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64, - 0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c, - 0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de, - 0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e, - 0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e, - 0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386, - 0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e, - 0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706, - 0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8, - 0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874, - 0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918, - 0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c, - 0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90, - 0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66, - 0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04, - 0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4, - 0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8, - 0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58, - 0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2, - 0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142, - 0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214, - 0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282, - 0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a, - 0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428, - 0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e, - 0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510, - 0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc, - 0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668, - 0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c, - 0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6, - 0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866, - 0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8, - 0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986, - 0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08, - 0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c, - 0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e, - 0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4, - 0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88, - 0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c, - 0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2, - 0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e, - 0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca, - 0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174, - 0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246, - 0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2, - 0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350, - 0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446, - 0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc, - 0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e, - 0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612, - 0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a, - 0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e, - 0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba, - 0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934, - 0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2, - 0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e, - 0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c, - 0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4, - 0x1fba8, 0x1fbb6, 0x1fbda]); + /** + * The sorted table of all possible symbols. Extracted from the PDF417 + * specification. The index of a symbol in this table corresponds to the + * index into the codeword table. + */ + public static /* final int[] */ SYMBOL_TABLE = Int32Array.from([ + 0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac, + 0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482, + 0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e, + 0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2, + 0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716, + 0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6, + 0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890, + 0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e, + 0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4, + 0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c, + 0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0, + 0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c, + 0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38, + 0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8, + 0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98, + 0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44, + 0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050, + 0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee, + 0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be, + 0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c, + 0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6, + 0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618, + 0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784, + 0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e, + 0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de, + 0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e, + 0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70, + 0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98, + 0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46, + 0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8, + 0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4, + 0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28, + 0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e, + 0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c, + 0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc, + 0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0, + 0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306, + 0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6, + 0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8, + 0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8, + 0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60, + 0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08, + 0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc, + 0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de, + 0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc, + 0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308, + 0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2, + 0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8, + 0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e, + 0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816, + 0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce, + 0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c, + 0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e, + 0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e, + 0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28, + 0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0, + 0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c, + 0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6, + 0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c, + 0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46, + 0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110, + 0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8, + 0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330, + 0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410, + 0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660, + 0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0, + 0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0, + 0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0, + 0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98, + 0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0, + 0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20, + 0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e, + 0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170, + 0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4, + 0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320, + 0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4, + 0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610, + 0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e, + 0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870, + 0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0, + 0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e, + 0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046, + 0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106, + 0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8, + 0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c, + 0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc, + 0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0, + 0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e, + 0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822, + 0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884, + 0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902, + 0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0, + 0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20, + 0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e, + 0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e, + 0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0, + 0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e, + 0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58, + 0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8, + 0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274, + 0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426, + 0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc, + 0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e, + 0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614, + 0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e, + 0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796, + 0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872, + 0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c, + 0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec, + 0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e, + 0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2, + 0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82, + 0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e, + 0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32, + 0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8, + 0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94, + 0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086, + 0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e, + 0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa, + 0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390, + 0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460, + 0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708, + 0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc, + 0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882, + 0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920, + 0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e, + 0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8, + 0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8, + 0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84, + 0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58, + 0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12, + 0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae, + 0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2, + 0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c, + 0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260, + 0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e, + 0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460, + 0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704, + 0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be, + 0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0, + 0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40, + 0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8, + 0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e, + 0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c, + 0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e, + 0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8, + 0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660, + 0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e, + 0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c, + 0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4, + 0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40, + 0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72, + 0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c, + 0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa, + 0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82, + 0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34, + 0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162, + 0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268, + 0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326, + 0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462, + 0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec, + 0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc, + 0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c, + 0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2, + 0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e, + 0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c, + 0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6, + 0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc, + 0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02, + 0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe, + 0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58, + 0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18, + 0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa, + 0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e, + 0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64, + 0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c, + 0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de, + 0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e, + 0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e, + 0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386, + 0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e, + 0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706, + 0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8, + 0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874, + 0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918, + 0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c, + 0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90, + 0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66, + 0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04, + 0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4, + 0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8, + 0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58, + 0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2, + 0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142, + 0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214, + 0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282, + 0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a, + 0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428, + 0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e, + 0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510, + 0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc, + 0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668, + 0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c, + 0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6, + 0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866, + 0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8, + 0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986, + 0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08, + 0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c, + 0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e, + 0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4, + 0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88, + 0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c, + 0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2, + 0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e, + 0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca, + 0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174, + 0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246, + 0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2, + 0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350, + 0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446, + 0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc, + 0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e, + 0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612, + 0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a, + 0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e, + 0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba, + 0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934, + 0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2, + 0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e, + 0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c, + 0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4, + 0x1fba8, 0x1fbb6, 0x1fbda]); - /** - * This table contains to codewords for all symbols. - */ - private static /*final int[]*/ CODEWORD_TABLE = Int32Array.from([ - 2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511, - 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815, - 814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752, - 2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752, - 1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651, - 646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606, - 2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909, - 2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830, - 2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629, - 1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591, - 588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466, - 2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419, - 2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155, - 2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384, - 1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756, - 753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337, - 2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653, - 1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900, - 910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713, - 2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654, - 2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142, - 332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262, - 257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052, - 202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266, - 1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171, - 169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313, - 2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529, - 2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241, - 493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414, - 412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434, - 1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785, - 2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353, - 1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689, - 2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573, - 2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539, - 906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669, - 2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133, - 131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971, - 1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78, - 1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100, - 1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64, - 1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867, - 1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989, - 987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359, - 343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308, - 305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089, - 2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279, - 277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205, - 2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232, - 1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590, - 2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262, - 2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549, - 1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480, - 477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466, - 2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427, - 2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388, - 2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751, - 748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592, - 2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569, - 2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695, - 2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818, - 2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648, - 602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892, - 886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632, - 2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486, - 483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366, - 363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412, - 1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684, - 1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527, - 894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759, - 2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342, - 1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195, - 2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997, - 150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183, - 1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268, - 508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395, - 2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779, - 776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688, - 1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718, - 2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138, - 134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108, - 1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98, - 1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920, - 1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9, - 1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975, - 33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339, - 1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090, - 239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033, - 2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284, - 2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569, - 1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467, - 2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379, - 1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579, - 1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688, - 2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636, - 1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524, - 1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361, - 358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672, - 669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849, - 848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343, - 255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210, - 1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157, - 1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458, - 447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460, - 2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919, - 2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127, - 109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060, - 87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008, - 51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952, - 949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350, - 349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086, - 233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231, - 1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499, - 2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798, - 797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546, - 2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670, - 1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504, - 1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394, - 1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281, - 1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150, - 1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582, - 510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709, - 662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094, - 1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007, - 1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940, - 938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897, - 1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185, - 181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513, - 1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706, - 2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204, - 1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207, - 1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487, - 1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062, - 1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951, - 948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275, - 1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548, - 440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208, - 2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954, - 1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270, - 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700]); + /** + * This table contains to codewords for all symbols. + */ + private static /* final int[] */ CODEWORD_TABLE = Int32Array.from([ + 2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511, + 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815, + 814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752, + 2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752, + 1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651, + 646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606, + 2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909, + 2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830, + 2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629, + 1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591, + 588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466, + 2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419, + 2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155, + 2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384, + 1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756, + 753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337, + 2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653, + 1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900, + 910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713, + 2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654, + 2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142, + 332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262, + 257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052, + 202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266, + 1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171, + 169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313, + 2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529, + 2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241, + 493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414, + 412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434, + 1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785, + 2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353, + 1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689, + 2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573, + 2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539, + 906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669, + 2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133, + 131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971, + 1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78, + 1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100, + 1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64, + 1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867, + 1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989, + 987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359, + 343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308, + 305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089, + 2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279, + 277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205, + 2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232, + 1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590, + 2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262, + 2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549, + 1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480, + 477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466, + 2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427, + 2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388, + 2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751, + 748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592, + 2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569, + 2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695, + 2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818, + 2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648, + 602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892, + 886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632, + 2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486, + 483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366, + 363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412, + 1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684, + 1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527, + 894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759, + 2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342, + 1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195, + 2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997, + 150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183, + 1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268, + 508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395, + 2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779, + 776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688, + 1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718, + 2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138, + 134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108, + 1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98, + 1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920, + 1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9, + 1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975, + 33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339, + 1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090, + 239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033, + 2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284, + 2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569, + 1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467, + 2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379, + 1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579, + 1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688, + 2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636, + 1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524, + 1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361, + 358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672, + 669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849, + 848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343, + 255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210, + 1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157, + 1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458, + 447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460, + 2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919, + 2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127, + 109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060, + 87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008, + 51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952, + 949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350, + 349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086, + 233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231, + 1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499, + 2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798, + 797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546, + 2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670, + 1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504, + 1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394, + 1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281, + 1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150, + 1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582, + 510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709, + 662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094, + 1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007, + 1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940, + 938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897, + 1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185, + 181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513, + 1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706, + 2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204, + 1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207, + 1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487, + 1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062, + 1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951, + 948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275, + 1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548, + 440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208, + 2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954, + 1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270, + 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700]); } diff --git a/src/core/pdf417/PDF417Reader.ts b/src/core/pdf417/PDF417Reader.ts index 55c78450..7f2d9548 100644 --- a/src/core/pdf417/PDF417Reader.ts +++ b/src/core/pdf417/PDF417Reader.ts @@ -61,9 +61,9 @@ import { int } from '../../customTypings'; * * @author Guenther Grau */ -export default /*public final*/ class PDF417Reader implements Reader, MultipleBarcodeReader { +export default /* public final */ class PDF417Reader implements Reader, MultipleBarcodeReader { - // private static /*final Result[]*/ EMPTY_RESULT_ARRAY: Result[] = new Result([0]); + // private static /*final Result[] */ EMPTY_RESULT_ARRAY: Result[] = new Result([0]); /** * Locates and decodes a PDF417 code in an image. @@ -72,8 +72,8 @@ export default /*public final*/ class PDF417Reader implements Reader, MultipleBa * @throws NotFoundException if a PDF417 code cannot be found, * @throws FormatException if a PDF417 cannot be decoded * @throws ChecksumException + * @override decode */ - // @Override public decode(image: BinaryBitmap, hints: Map = null): Result { let result = PDF417Reader.decode(image, hints, false); if (result == null || result.length === 0 || result[0] == null) { @@ -82,14 +82,43 @@ export default /*public final*/ class PDF417Reader implements Reader, MultipleBa return result[0]; } + /** + * + * @override decodeMultiple + */ + public decodeMultiple(image: BinaryBitmap): Result[]; /** * * @param BinaryBitmap * @param image * @throws NotFoundException + * @override */ - // @Override public decodeMultiple(image: BinaryBitmap, hints: Map = null): Result[] { + + if (!hints) { + return this.decodeMultipleOverload1(image); + } + + return this.decodeMultipleImpl(image, hints); + } + + /** + * + * @override decodeMultiple + */ + private decodeMultipleOverload1(image: BinaryBitmap): Result[] { + return this.decodeMultipleImpl(image, null); + } + + /** + * + * @param BinaryBitmap + * @param image + * @throws NotFoundException + * @override + */ + private decodeMultipleImpl(image: BinaryBitmap, hints: Map = null): Result[] { try { return PDF417Reader.decode(image, hints, true); } catch (ignored) { @@ -110,14 +139,14 @@ export default /*public final*/ class PDF417Reader implements Reader, MultipleBa * @throws NotFoundException * @throws FormatExceptionß * @throws ChecksumException - */ + */ private static decode(image: BinaryBitmap, hints: Map, multiple: boolean) { const results = new Array(); const detectorResult = Detector.detectMultiple(image, hints, multiple); for (const points of detectorResult.getPoints()) { const decoderResult = PDF417ScanningDecoder.decode(detectorResult.getBits(), points[4], points[5], points[6], points[7], PDF417Reader.getMinCodewordWidth(points), PDF417Reader.getMaxCodewordWidth(points)); - const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat.PDF_417); + const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.PDF_417); result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.getECLevel()); const pdf417ResultMetadata: PDF417ResultMetadata = decoderResult.getOther(); if (pdf417ResultMetadata != null) { @@ -128,21 +157,21 @@ export default /*public final*/ class PDF417Reader implements Reader, MultipleBa return results.map(x => x); } - private static getMaxWidth(p1: ResultPoint, p2: ResultPoint): number /*int*/ { + private static getMaxWidth(p1: ResultPoint, p2: ResultPoint): number /* int */ { if (p1 == null || p2 == null) { return 0; } - return Math.trunc(Math.abs(p1.getX() - p2.getX())); + return Math.trunc(Math.abs(p1.getX() - p2.getX())); } - private static getMinWidth(p1: ResultPoint, p2: ResultPoint): number /*int*/ { + private static getMinWidth(p1: ResultPoint, p2: ResultPoint): number /* int */ { if (p1 == null || p2 == null) { return Integer.MAX_VALUE; } - return Math.trunc(Math.abs(p1.getX() - p2.getX())); + return Math.trunc(Math.abs(p1.getX() - p2.getX())); } - private static getMaxCodewordWidth(p: ResultPoint[]): number /*int*/ { + private static getMaxCodewordWidth(p: ResultPoint[]): number /* int */ { return Math.floor(Math.max( Math.max(PDF417Reader.getMaxWidth(p[0], p[4]), PDF417Reader.getMaxWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN), @@ -150,7 +179,7 @@ export default /*public final*/ class PDF417Reader implements Reader, MultipleBa PDF417Common.MODULES_IN_STOP_PATTERN))); } - private static getMinCodewordWidth(p: ResultPoint[]): number /*int*/ { + private static getMinCodewordWidth(p: ResultPoint[]): number /* int */ { return Math.floor(Math.min( Math.min(PDF417Reader.getMinWidth(p[0], p[4]), PDF417Reader.getMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN), diff --git a/src/core/pdf417/PDF417ResultMetadata.ts b/src/core/pdf417/PDF417ResultMetadata.ts index f6d9744e..e4aa5e94 100644 --- a/src/core/pdf417/PDF417ResultMetadata.ts +++ b/src/core/pdf417/PDF417ResultMetadata.ts @@ -19,153 +19,153 @@ /** * @author Guenther Grau */ -export default /*public final*/ class PDF417ResultMetadata { - - private segmentIndex: /*int*/ number; - private fileId: string; - private lastSegment: boolean; - private segmentCount: /*int*/ number = -1; - private sender: string; - private addressee: string; - private fileName: string; - private fileSize: /*long*/ number = -1; - private timestamp: /*long*/ number = -1; - private checksum: /*int*/ number = -1; - private optionalData: Int32Array; - - /** - * The Segment ID represents the segment of the whole file distributed over different symbols. - * - * @return File segment index - */ - public getSegmentIndex(): /*int*/ number { - return this.segmentIndex; - } - - public setSegmentIndex(segmentIndex: /*int*/ number): void { - this.segmentIndex = segmentIndex; - } - - /** - * Is the same for each related PDF417 symbol - * - * @return File ID - */ - public getFileId(): string { - return this.fileId; - } - - public setFileId(fileId: string): void { - this.fileId = fileId; - } - - /** - * @return always null - * @deprecated use dedicated already parsed fields - */ - // @Deprecated - public getOptionalData(): Int32Array { - return this.optionalData; - } - - /** - * @param optionalData old optional data format as int array - * @deprecated parse and use new fields - */ - // @Deprecated - public setOptionalData(optionalData: Int32Array): void { - this.optionalData = optionalData; - } - - - /** - * @return true if it is the last segment - */ - public isLastSegment(): boolean { - return this.lastSegment; - } - - public setLastSegment(lastSegment: boolean): void { - this.lastSegment = lastSegment; - } - - /** - * @return count of segments, -1 if not set - */ - public getSegmentCount(): /*int*/ number { - return this.segmentCount; - } - - public setSegmentCount(segmentCount: number /*int*/): void { - this.segmentCount = segmentCount; - } - - public getSender(): string { - return this.sender || null; - } - - public setSender(sender: string): void { - this.sender = sender; - } - - public getAddressee(): string { - return this.addressee || null; - } - - public setAddressee(addressee: string): void { - this.addressee = addressee; - } - - /** - * Filename of the encoded file - * - * @return filename - */ - public getFileName(): string { - return this.fileName; - } - - public setFileName(fileName: string): void { - this.fileName = fileName; - } - - /** - * filesize in bytes of the encoded file - * - * @return filesize in bytes, -1 if not set - */ - public getFileSize(): /*long*/ number { - return this.fileSize; - } - - public setFileSize(fileSize: number /*long*/): void { - this.fileSize = fileSize; - } - - /** - * 16-bit CRC checksum using CCITT-16 - * - * @return crc checksum, -1 if not set - */ - public getChecksum(): /*int*/ number { - return this.checksum; - } - - public setChecksum(checksum: number/*int*/): void { - this.checksum = checksum; - } - - /** - * unix epock timestamp, elapsed seconds since 1970-01-01 - * - * @return elapsed seconds, -1 if not set - */ - public getTimestamp(): /*long*/ number { - return this.timestamp; - } - - public setTimestamp(timestamp: number /*long*/): void { - this.timestamp = timestamp; - } +export default /* public final */ class PDF417ResultMetadata { + + private segmentIndex: /* int */ number; + private fileId: string; + private lastSegment: boolean; + private segmentCount: /* int */ number = -1; + private sender: string; + private addressee: string; + private fileName: string; + private fileSize: /* long */ number = -1; + private timestamp: /* long */ number = -1; + private checksum: /* int */ number = -1; + private optionalData: Int32Array; + + /** + * The Segment ID represents the segment of the whole file distributed over different symbols. + * + * @return File segment index + */ + public getSegmentIndex(): /* int */ number { + return this.segmentIndex; + } + + public setSegmentIndex(segmentIndex: /* int */ number): void { + this.segmentIndex = segmentIndex; + } + + /** + * Is the same for each related PDF417 symbol + * + * @return File ID + */ + public getFileId(): string { + return this.fileId; + } + + public setFileId(fileId: string): void { + this.fileId = fileId; + } + + /** + * @return always null + * @deprecated use dedicated already parsed fields + */ + // @Deprecated + public getOptionalData(): Int32Array { + return this.optionalData; + } + + /** + * @param optionalData old optional data format as int array + * @deprecated parse and use new fields + */ + // @Deprecated + public setOptionalData(optionalData: Int32Array): void { + this.optionalData = optionalData; + } + + + /** + * @return true if it is the last segment + */ + public isLastSegment(): boolean { + return this.lastSegment; + } + + public setLastSegment(lastSegment: boolean): void { + this.lastSegment = lastSegment; + } + + /** + * @return count of segments, -1 if not set + */ + public getSegmentCount(): /* int */ number { + return this.segmentCount; + } + + public setSegmentCount(segmentCount: number /* int */): void { + this.segmentCount = segmentCount; + } + + public getSender(): string { + return this.sender || null; + } + + public setSender(sender: string): void { + this.sender = sender; + } + + public getAddressee(): string { + return this.addressee || null; + } + + public setAddressee(addressee: string): void { + this.addressee = addressee; + } + + /** + * Filename of the encoded file + * + * @return filename + */ + public getFileName(): string { + return this.fileName; + } + + public setFileName(fileName: string): void { + this.fileName = fileName; + } + + /** + * filesize in bytes of the encoded file + * + * @return filesize in bytes, -1 if not set + */ + public getFileSize(): /* long */ number { + return this.fileSize; + } + + public setFileSize(fileSize: number /* long */): void { + this.fileSize = fileSize; + } + + /** + * 16-bit CRC checksum using CCITT-16 + * + * @return crc checksum, -1 if not set + */ + public getChecksum(): /* int */ number { + return this.checksum; + } + + public setChecksum(checksum: number/* int */): void { + this.checksum = checksum; + } + + /** + * unix epock timestamp, elapsed seconds since 1970-01-01 + * + * @return elapsed seconds, -1 if not set + */ + public getTimestamp(): /* long */ number { + return this.timestamp; + } + + public setTimestamp(timestamp: number /* long */): void { + this.timestamp = timestamp; + } } diff --git a/src/core/pdf417/decoder/BarcodeMetadata.ts b/src/core/pdf417/decoder/BarcodeMetadata.ts index a348b160..d4eb6e0d 100644 --- a/src/core/pdf417/decoder/BarcodeMetadata.ts +++ b/src/core/pdf417/decoder/BarcodeMetadata.ts @@ -21,13 +21,13 @@ import { int } from '../../../customTypings'; /** * @author Guenther Grau */ -export default /*final*/ class BarcodeMetadata { +export default /* final */ class BarcodeMetadata { - private /*final*/ columnCount: int; - private /*final*/ errorCorrectionLevel: int; - private /*final*/ rowCountUpperPart: int; - private /*final*/ rowCountLowerPart: int; - private /*final*/ rowCount: int; + private /* final */ columnCount: int; + private /* final */ errorCorrectionLevel: int; + private /* final */ rowCountUpperPart: int; + private /* final */ rowCountLowerPart: int; + private /* final */ rowCount: int; constructor(columnCount: int, rowCountUpperPart: int, rowCountLowerPart: int, errorCorrectionLevel: int) { this.columnCount = columnCount; diff --git a/src/core/pdf417/decoder/BarcodeValue.ts b/src/core/pdf417/decoder/BarcodeValue.ts index 8eec779d..f02530a9 100644 --- a/src/core/pdf417/decoder/BarcodeValue.ts +++ b/src/core/pdf417/decoder/BarcodeValue.ts @@ -30,13 +30,13 @@ import { int, Collection } from '../../../customTypings'; /** * @author Guenther Grau */ -export default /*final*/ class BarcodeValue { - private /*final*/ values = new Map(); +export default /* final */ class BarcodeValue { + private /* final */ values = new Map(); /** * Add an occurrence of a value - */ - setValue(value: int): void { + */ + setValue(value: int): void { value = Math.trunc(value); let confidence: int = this.values.get(value); if (confidence == null) { @@ -49,8 +49,8 @@ export default /*final*/ class BarcodeValue { /** * Determines the maximum occurrence of a set value and returns all values which were set with this occurrence. * @return an array of int, containing the values with the highest occurrence, or null, if no value was set - */ - getValue(): Int32Array { + */ + getValue(): Int32Array { let maxConfidence: int = -1; let result: Collection = new Array(); for (const [key, value] of this.values.entries()) { @@ -71,7 +71,7 @@ export default /*final*/ class BarcodeValue { return PDF417Common.toIntArray(result); } - getConfidence(value: int): int { + getConfidence(value: int): int { return this.values.get(value); } diff --git a/src/core/pdf417/decoder/BoundingBox.ts b/src/core/pdf417/decoder/BoundingBox.ts index cd5014f6..5dca3442 100644 --- a/src/core/pdf417/decoder/BoundingBox.ts +++ b/src/core/pdf417/decoder/BoundingBox.ts @@ -27,23 +27,23 @@ import { int } from '../../../customTypings'; /** * @author Guenther Grau */ -export default /*final*/ class BoundingBox { - - private /*final*/ image: BitMatrix; - private /*final*/ topLeft: ResultPoint; - private /*final*/ bottomLeft: ResultPoint; - private /*final*/ topRight: ResultPoint; - private /*final*/ bottomRight: ResultPoint; - private /*final*/ minX: int; - private /*final*/ maxX: int; - private /*final*/ minY: int; - private /*final*/ maxY: int; - - constructor( image: BitMatrix|BoundingBox, - topLeft?: ResultPoint, - bottomLeft?: ResultPoint, - topRight?: ResultPoint, - bottomRight?: ResultPoint) { +export default /* final */ class BoundingBox { + + private /* final */ image: BitMatrix; + private /* final */ topLeft: ResultPoint; + private /* final */ bottomLeft: ResultPoint; + private /* final */ topRight: ResultPoint; + private /* final */ bottomRight: ResultPoint; + private /* final */ minX: int; + private /* final */ maxX: int; + private /* final */ minY: int; + private /* final */ maxY: int; + + constructor(image: BitMatrix | BoundingBox, + topLeft?: ResultPoint, + bottomLeft?: ResultPoint, + topRight?: ResultPoint, + bottomRight?: ResultPoint) { if (image instanceof BoundingBox) { this.constructor_2(image); } else { @@ -60,12 +60,12 @@ export default /*final*/ class BoundingBox { * @param bottomRight * * @throws NotFoundException - */ - private constructor_1( image: BitMatrix, - topLeft: ResultPoint, - bottomLeft: ResultPoint, - topRight: ResultPoint, - bottomRight: ResultPoint) { + */ + private constructor_1(image: BitMatrix, + topLeft: ResultPoint, + bottomLeft: ResultPoint, + topRight: ResultPoint, + bottomRight: ResultPoint) { const leftUnspecified = topLeft == null || bottomLeft == null; const rightUnspecified = topRight == null || bottomRight == null; if (leftUnspecified && rightUnspecified) { @@ -83,10 +83,10 @@ export default /*final*/ class BoundingBox { this.bottomLeft = bottomLeft; this.topRight = topRight; this.bottomRight = bottomRight; - this.minX = Math.trunc(Math.min(topLeft.getX(), bottomLeft.getX())); - this.maxX = Math.trunc(Math.max(topRight.getX(), bottomRight.getX())); - this.minY = Math.trunc(Math.min(topLeft.getY(), topRight.getY())); - this.maxY = Math.trunc(Math.max(bottomLeft.getY(), bottomRight.getY())); + this.minX = Math.trunc(Math.min(topLeft.getX(), bottomLeft.getX())); + this.maxX = Math.trunc(Math.max(topRight.getX(), bottomRight.getX())); + this.minY = Math.trunc(Math.min(topLeft.getY(), topRight.getY())); + this.maxY = Math.trunc(Math.max(bottomLeft.getY(), bottomRight.getY())); } private constructor_2(boundingBox: BoundingBox) { @@ -103,8 +103,8 @@ export default /*final*/ class BoundingBox { /** * @throws NotFoundException - */ - static merge( leftBox: BoundingBox, rightBox: BoundingBox): BoundingBox { + */ + static merge(leftBox: BoundingBox, rightBox: BoundingBox): BoundingBox { if (leftBox == null) { return rightBox; } @@ -116,7 +116,7 @@ export default /*final*/ class BoundingBox { /** * @throws NotFoundException - */ + */ addMissingRows(missingStartRows: int, missingEndRows: int, isLeft: boolean): BoundingBox { let newTopLeft: ResultPoint = this.topLeft; let newBottomLeft: ResultPoint = this.bottomLeft; @@ -125,7 +125,7 @@ export default /*final*/ class BoundingBox { if (missingStartRows > 0) { let top: ResultPoint = isLeft ? this.topLeft : this.topRight; - let newMinY: int = Math.trunc(top.getY() - missingStartRows); + let newMinY: int = Math.trunc(top.getY() - missingStartRows); if (newMinY < 0) { newMinY = 0; } @@ -139,7 +139,7 @@ export default /*final*/ class BoundingBox { if (missingEndRows > 0) { let bottom: ResultPoint = isLeft ? this.bottomLeft : this.bottomRight; - let newMaxY: int = Math.trunc(bottom.getY() + missingEndRows); + let newMaxY: int = Math.trunc(bottom.getY() + missingEndRows); if (newMaxY >= this.image.getHeight()) { newMaxY = this.image.getHeight() - 1; } @@ -170,19 +170,19 @@ export default /*final*/ class BoundingBox { return this.maxY; } - getTopLeft(): ResultPoint { + getTopLeft(): ResultPoint { return this.topLeft; } - getTopRight(): ResultPoint { + getTopRight(): ResultPoint { return this.topRight; } - getBottomLeft(): ResultPoint { + getBottomLeft(): ResultPoint { return this.bottomLeft; } - getBottomRight(): ResultPoint { + getBottomRight(): ResultPoint { return this.bottomRight; } diff --git a/src/core/pdf417/decoder/Codeword.ts b/src/core/pdf417/decoder/Codeword.ts index 6b2118fa..549df5e1 100644 --- a/src/core/pdf417/decoder/Codeword.ts +++ b/src/core/pdf417/decoder/Codeword.ts @@ -21,14 +21,14 @@ import { int } from '../../../customTypings'; /** * @author Guenther Grau */ -export default /*final*/ class Codeword { +export default /* final */ class Codeword { - private static /*final*/ BARCODE_ROW_UNKNOWN: int = -1; + private static /* final */ BARCODE_ROW_UNKNOWN: int = -1; - private /*final*/ startX: int; - private /*final*/ endX: int; - private /*final*/ bucket: int; - private /*final*/ value: int; + private /* final */ startX: int; + private /* final */ endX: int; + private /* final */ bucket: int; + private /* final */ value: int; private rowNumber: int = Codeword.BARCODE_ROW_UNKNOWN; constructor(startX: int, endX: int, bucket: int, value: int) { @@ -74,12 +74,12 @@ export default /*final*/ class Codeword { return this.rowNumber; } - setRowNumber(rowNumber: int ): void { + setRowNumber(rowNumber: int): void { this.rowNumber = rowNumber; } -// @Override - public toString(): string { + // @Override + public toString(): string { return this.rowNumber + '|' + this.value; } diff --git a/src/core/pdf417/decoder/DecodedBitStreamParser.ts b/src/core/pdf417/decoder/DecodedBitStreamParser.ts index 9ab6c519..3dbf552f 100644 --- a/src/core/pdf417/decoder/DecodedBitStreamParser.ts +++ b/src/core/pdf417/decoder/DecodedBitStreamParser.ts @@ -41,7 +41,7 @@ import StringEncoding from '../../util/StringEncoding'; import { int } from '../../../customTypings'; -/*private*/ enum Mode { +/* private */ enum Mode { ALPHA, LOWER, MIXED, @@ -107,7 +107,7 @@ function getEXP900(): bigint[] { EXP900[1] = nineHundred; // in Java - array with length = 16 - for (let i /*int*/ = 2; i < 16; i++) { + for (let i /* int */ = 2; i < 16; i++) { EXP900[i] = EXP900[i - 1] * nineHundred; } @@ -120,50 +120,50 @@ function getEXP900(): bigint[] { * @author SITA Lab (kevin.osullivan@sita.aero) * @author Guenther Grau */ -export default /*final*/ class DecodedBitStreamParser { - - private static /*final*/ TEXT_COMPACTION_MODE_LATCH: int = 900; - private static /*final*/ BYTE_COMPACTION_MODE_LATCH: int = 901; - private static /*final*/ NUMERIC_COMPACTION_MODE_LATCH: int = 902; - private static /*final*/ BYTE_COMPACTION_MODE_LATCH_6: int = 924; - private static /*final*/ ECI_USER_DEFINED: int = 925; - private static /*final*/ ECI_GENERAL_PURPOSE: int = 926; - private static /*final*/ ECI_CHARSET: int = 927; - private static /*final*/ BEGIN_MACRO_PDF417_CONTROL_BLOCK: int = 928; - private static /*final*/ BEGIN_MACRO_PDF417_OPTIONAL_FIELD: int = 923; - private static /*final*/ MACRO_PDF417_TERMINATOR: int = 922; - private static /*final*/ MODE_SHIFT_TO_BYTE_COMPACTION_MODE: int = 913; - private static /*final*/ MAX_NUMERIC_CODEWORDS: int = 15; - - private static /*final*/ MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME: int = 0; - private static /*final*/ MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT: int = 1; - private static /*final*/ MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP: int = 2; - private static /*final*/ MACRO_PDF417_OPTIONAL_FIELD_SENDER: int = 3; - private static /*final*/ MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE: int = 4; - private static /*final*/ MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE: int = 5; - private static /*final*/ MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM: int = 6; - - private static /*final*/ PL: int = 25; - private static /*final*/ LL: int = 27; - private static /*final*/ AS: int = 27; - private static /*final*/ ML: int = 28; - private static /*final*/ AL: int = 28; - private static /*final*/ PS: int = 29; - private static /*final*/ PAL: int = 29; - - private static /*final*/ PUNCT_CHARS: string = - ';<>@[\\]_`~!\r\t,:\n-.$/"|*()?{}\''; - - private static /*final*/ MIXED_CHARS: string = - '0123456789&\r\t,:#-.$/+%*=^'; +export default /* final */ class DecodedBitStreamParser { + + private static /* final */ TEXT_COMPACTION_MODE_LATCH: int = 900; + private static /* final */ BYTE_COMPACTION_MODE_LATCH: int = 901; + private static /* final */ NUMERIC_COMPACTION_MODE_LATCH: int = 902; + private static /* final */ BYTE_COMPACTION_MODE_LATCH_6: int = 924; + private static /* final */ ECI_USER_DEFINED: int = 925; + private static /* final */ ECI_GENERAL_PURPOSE: int = 926; + private static /* final */ ECI_CHARSET: int = 927; + private static /* final */ BEGIN_MACRO_PDF417_CONTROL_BLOCK: int = 928; + private static /* final */ BEGIN_MACRO_PDF417_OPTIONAL_FIELD: int = 923; + private static /* final */ MACRO_PDF417_TERMINATOR: int = 922; + private static /* final */ MODE_SHIFT_TO_BYTE_COMPACTION_MODE: int = 913; + private static /* final */ MAX_NUMERIC_CODEWORDS: int = 15; + + private static /* final */ MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME: int = 0; + private static /* final */ MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT: int = 1; + private static /* final */ MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP: int = 2; + private static /* final */ MACRO_PDF417_OPTIONAL_FIELD_SENDER: int = 3; + private static /* final */ MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE: int = 4; + private static /* final */ MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE: int = 5; + private static /* final */ MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM: int = 6; + + private static /* final */ PL: int = 25; + private static /* final */ LL: int = 27; + private static /* final */ AS: int = 27; + private static /* final */ ML: int = 28; + private static /* final */ AL: int = 28; + private static /* final */ PS: int = 29; + private static /* final */ PAL: int = 29; + + private static /* final */ PUNCT_CHARS: string = + ';<>@[\\]_`~!\r\t,:\n-.$/"|*()?{}\''; + + private static /* final */ MIXED_CHARS: string = + '0123456789&\r\t,:#-.$/+%*=^'; /** * Table containing values for the exponent of 900. * This is used in the numeric compaction decode algorithm. - */ - private static /*final*/ EXP900: bigint[] = getBigIntConstructor() ? getEXP900() : []; + */ + private static /* final */ EXP900: bigint[] = getBigIntConstructor() ? getEXP900() : []; - private static /*final*/ NUMBER_OF_SEQUENCE_CODEWORDS: int = 2; + private static /* final */ NUMBER_OF_SEQUENCE_CODEWORDS: int = 2; // private DecodedBitStreamParser() { // } @@ -174,7 +174,7 @@ export default /*final*/ class DecodedBitStreamParser { * @param ecLevel * * @throws FormatException - */ + */ static decode(codewords: Int32Array, ecLevel: string): DecoderResult { // pass encoding to result (will be used for decode symbols in byte mode) let result: StringBuilder = new StringBuilder(''); @@ -186,7 +186,7 @@ export default /*final*/ class DecodedBitStreamParser { * convert it to string later correctly due to encoding * differences from Java version. As reported here: * https://github.com/zxing-js/library/pull/264/files#r382831593 - */ + */ result.enableDecoding(encoding); // Get compaction mode let codeIndex: int = 1; @@ -202,7 +202,7 @@ export default /*final*/ class DecodedBitStreamParser { codeIndex = DecodedBitStreamParser.byteCompaction(code, codewords, encoding, codeIndex, result); break; case DecodedBitStreamParser.MODE_SHIFT_TO_BYTE_COMPACTION_MODE: - result.append(/*(char)*/ codewords[codeIndex++]); + result.append(/* (char) */ codewords[codeIndex++]); break; case DecodedBitStreamParser.NUMERIC_COMPACTION_MODE_LATCH: codeIndex = DecodedBitStreamParser.numericCompaction(codewords, codeIndex, result); @@ -260,7 +260,7 @@ export default /*final*/ class DecodedBitStreamParser { * @param resultMetadata * * @throws FormatException - */ + */ // @SuppressWarnings("deprecation") static decodeMacroBlock(codewords: Int32Array, codeIndex: int, resultMetadata: PDF417ResultMetadata): int { if (codeIndex + DecodedBitStreamParser.NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) { @@ -268,7 +268,7 @@ export default /*final*/ class DecodedBitStreamParser { throw FormatException.getFormatInstance(); } let segmentIndexArray: Int32Array = new Int32Array(DecodedBitStreamParser.NUMBER_OF_SEQUENCE_CODEWORDS); - for (let i /*int*/ = 0; i < DecodedBitStreamParser.NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) { + for (let i /* int */ = 0; i < DecodedBitStreamParser.NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) { segmentIndexArray[i] = codewords[codeIndex]; } resultMetadata.setSegmentIndex(Integer.parseInt(DecodedBitStreamParser.decodeBase900toBase10(segmentIndexArray, @@ -358,7 +358,7 @@ export default /*final*/ class DecodedBitStreamParser { * @param codeIndex The current index into the codeword array. * @param result The decoded data is appended to the result. * @return The next index into the codeword array. - */ + */ private static textCompaction(codewords: Int32Array, codeIndex: int, result: StringBuilder): int { // 2 character per codeword let textCompactionData: Int32Array = new Int32Array((codewords[0] - codeIndex) * 2); @@ -422,7 +422,7 @@ export default /*final*/ class DecodedBitStreamParser { * was a mode shift. * @param length The size of the text compaction and byte compaction data. * @param result The decoded data is appended to the result. - */ + */ private static decodeTextCompaction(textCompactionData: Int32Array, byteCompactionData: Int32Array, length: int, @@ -436,14 +436,14 @@ export default /*final*/ class DecodedBitStreamParser { let i: int = 0; while (i < length) { let subModeCh: int = textCompactionData[i]; - let ch: /*char*/ string = ''; + let ch: /* char */ string = ''; switch (subMode) { case Mode.ALPHA: // Alpha (alphabetic: uppercase) if (subModeCh < 26) { // Upper case Alpha Character // Note: 65 = 'A' ASCII -> there is byte code of symbol - ch = /*(char)('A' + subModeCh) */ String.fromCharCode(65 + subModeCh); + ch = /* (char)('A' + subModeCh) */ String.fromCharCode(65 + subModeCh); } else { switch (subModeCh) { case 26: @@ -461,7 +461,7 @@ export default /*final*/ class DecodedBitStreamParser { subMode = Mode.PUNCT_SHIFT; break; case DecodedBitStreamParser.MODE_SHIFT_TO_BYTE_COMPACTION_MODE: - result.append(/*(char)*/ byteCompactionData[i]); + result.append(/* (char) */ byteCompactionData[i]); break; case DecodedBitStreamParser.TEXT_COMPACTION_MODE_LATCH: subMode = Mode.ALPHA; @@ -473,7 +473,7 @@ export default /*final*/ class DecodedBitStreamParser { case Mode.LOWER: // Lower (alphabetic: lowercase) if (subModeCh < 26) { - ch = /*(char)('a' + subModeCh)*/String.fromCharCode(97 + subModeCh); + ch = /* (char)('a' + subModeCh) */String.fromCharCode(97 + subModeCh); } else { switch (subModeCh) { case 26: @@ -494,7 +494,7 @@ export default /*final*/ class DecodedBitStreamParser { break; case DecodedBitStreamParser.MODE_SHIFT_TO_BYTE_COMPACTION_MODE: // TODO Does this need to use the current character encoding? See other occurrences below - result.append(/*(char)*/ byteCompactionData[i]); + result.append(/* (char) */ byteCompactionData[i]); break; case DecodedBitStreamParser.TEXT_COMPACTION_MODE_LATCH: subMode = Mode.ALPHA; @@ -527,7 +527,7 @@ export default /*final*/ class DecodedBitStreamParser { subMode = Mode.PUNCT_SHIFT; break; case DecodedBitStreamParser.MODE_SHIFT_TO_BYTE_COMPACTION_MODE: - result.append(/*(char)*/ byteCompactionData[i]); + result.append(/* (char) */ byteCompactionData[i]); break; case DecodedBitStreamParser.TEXT_COMPACTION_MODE_LATCH: subMode = Mode.ALPHA; @@ -546,7 +546,7 @@ export default /*final*/ class DecodedBitStreamParser { subMode = Mode.ALPHA; break; case DecodedBitStreamParser.MODE_SHIFT_TO_BYTE_COMPACTION_MODE: - result.append(/*(char)*/ byteCompactionData[i]); + result.append(/* (char) */ byteCompactionData[i]); break; case DecodedBitStreamParser.TEXT_COMPACTION_MODE_LATCH: subMode = Mode.ALPHA; @@ -559,7 +559,7 @@ export default /*final*/ class DecodedBitStreamParser { // Restore sub-mode subMode = priorToShiftMode; if (subModeCh < 26) { - ch = /*(char)('A' + subModeCh)*/ String.fromCharCode(65 + subModeCh); + ch = /* (char)('A' + subModeCh) */ String.fromCharCode(65 + subModeCh); } else { switch (subModeCh) { case 26: @@ -585,7 +585,7 @@ export default /*final*/ class DecodedBitStreamParser { case DecodedBitStreamParser.MODE_SHIFT_TO_BYTE_COMPACTION_MODE: // PS before Shift-to-Byte is used as a padding character, // see 5.4.2.4 of the specification - result.append(/*(char)*/ byteCompactionData[i]); + result.append(/* (char) */ byteCompactionData[i]); break; case DecodedBitStreamParser.TEXT_COMPACTION_MODE_LATCH: subMode = Mode.ALPHA; @@ -614,15 +614,15 @@ export default /*final*/ class DecodedBitStreamParser { * @param codeIndex The current index into the codeword array. * @param result The decoded data is appended to the result. * @return The next index into the codeword array. - */ - private static /*int*/ byteCompaction(mode: int, + */ + private static /* int */ byteCompaction(mode: int, codewords: Int32Array, - encoding: /*Charset*/ CharacterSetECI, + encoding: /* Charset */ CharacterSetECI, codeIndex: int, result: StringBuilder) { let decodedBytes: ByteArrayOutputStream = new ByteArrayOutputStream(); let count: int = 0; - let value: /*long*/ number = 0; + let value: /* long */ number = 0; let end: boolean = false; switch (mode) { @@ -653,12 +653,12 @@ export default /*final*/ class DecodedBitStreamParser { if ((count % 5 === 0) && (count > 0)) { // Decode every 5 codewords // Convert to Base 256 - for (let j /*int*/ = 0; j < 6; ++j) { + for (let j /* int */ = 0; j < 6; ++j) { /* @note * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers. * So the next bitwise operation could not be done with simple numbers - */ - decodedBytes.write(/*(byte)*/Number(createBigInt(value) >> createBigInt(8 * (5 - j)))); + */ + decodedBytes.write(/* (byte) */Number(createBigInt(value) >> createBigInt(8 * (5 - j)))); } value = 0; count = 0; @@ -675,8 +675,8 @@ export default /*final*/ class DecodedBitStreamParser { // If Byte Compaction mode is invoked with codeword 901, // the last group of codewords is interpreted directly // as one byte per codeword, without compaction. - for (let i /*int*/ = 0; i < count; i++) { - decodedBytes.write(/*(byte)*/ byteCompactedCodewords[i]); + for (let i /* int */ = 0; i < count; i++) { + decodedBytes.write(/* (byte) */ byteCompactedCodewords[i]); } break; @@ -710,9 +710,9 @@ export default /*final*/ class DecodedBitStreamParser { /* @note * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers. * So the next bitwise operation could not be done with simple numbers - */ - for (let j /*int*/ = 0; j < 6; ++j) { - decodedBytes.write(/*(byte)*/Number(createBigInt(value) >> createBigInt(8 * (5 - j)))); + */ + for (let j /* int */ = 0; j < 6; ++j) { + decodedBytes.write(/* (byte) */Number(createBigInt(value) >> createBigInt(8 * (5 - j)))); } value = 0; count = 0; @@ -733,8 +733,8 @@ export default /*final*/ class DecodedBitStreamParser { * @return The next index into the codeword array. * * @throws FormatException - */ - private static numericCompaction(codewords: Int32Array, codeIndex: number /*int*/, result: StringBuilder): int { + */ + private static numericCompaction(codewords: Int32Array, codeIndex: number /* int */, result: StringBuilder): int { let count: int = 0; let end: boolean = false; @@ -816,10 +816,10 @@ export default /*final*/ class DecodedBitStreamParser { * Remove leading 1 => Result is 000213298174000 * * @throws FormatException - */ + */ private static decodeBase900toBase10(codewords: Int32Array, count: int): string { let result = createBigInt(0); - for (let i /*int*/ = 0; i < count; i++) { + for (let i /* int */ = 0; i < count; i++) { result += DecodedBitStreamParser.EXP900[count - i - 1] * createBigInt(codewords[i]); } let resultString: String = result.toString(); diff --git a/src/core/pdf417/decoder/DetectionResult.ts b/src/core/pdf417/decoder/DetectionResult.ts index 3426d049..a5f54238 100644 --- a/src/core/pdf417/decoder/DetectionResult.ts +++ b/src/core/pdf417/decoder/DetectionResult.ts @@ -33,14 +33,14 @@ import { int } from '../../../customTypings'; /** * @author Guenther Grau */ -export default /*final*/ class DetectionResult { +export default /* final */ class DetectionResult { - /*final*/ ADJUST_ROW_NUMBER_SKIP: int = 2; + /* final */ ADJUST_ROW_NUMBER_SKIP: int = 2; - private /*final*/ barcodeMetadata: BarcodeMetadata; - private /*final*/ detectionResultColumns: DetectionResultColumn[]; + private /* final */ barcodeMetadata: BarcodeMetadata; + private /* final */ detectionResultColumns: DetectionResultColumn[]; private boundingBox: BoundingBox; - private /*final*/ barcodeColumnCount: int; + private /* final */ barcodeColumnCount: int; constructor(barcodeMetadata: BarcodeMetadata, boundingBox: BoundingBox) { this.barcodeMetadata = barcodeMetadata; @@ -75,15 +75,15 @@ export default /*final*/ class DetectionResult { /** * @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords * will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers - */ + */ private adjustRowNumbersAndGetCount(): int { let unadjustedCount: int = this.adjustRowNumbersByRow(); if (unadjustedCount === 0) { return 0; } - for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1; barcodeColumn++) { + for (let barcodeColumn /* int */ = 1; barcodeColumn < this.barcodeColumnCount + 1; barcodeColumn++) { let codewords: Codeword[] = this.detectionResultColumns[barcodeColumn].getCodewords(); - for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) { + for (let codewordsRow /* int */ = 0; codewordsRow < codewords.length; codewordsRow++) { if (codewords[codewordsRow] == null) { continue; } @@ -111,11 +111,11 @@ export default /*final*/ class DetectionResult { } let LRIcodewords: Codeword[] = this.detectionResultColumns[0].getCodewords(); let RRIcodewords: Codeword[] = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords(); - for (let codewordsRow /*int*/ = 0; codewordsRow < LRIcodewords.length; codewordsRow++) { + for (let codewordsRow /* int */ = 0; codewordsRow < LRIcodewords.length; codewordsRow++) { if (LRIcodewords[codewordsRow] != null && RRIcodewords[codewordsRow] != null && LRIcodewords[codewordsRow].getRowNumber() === RRIcodewords[codewordsRow].getRowNumber()) { - for (let barcodeColumn /*int*/ = 1; barcodeColumn <= this.barcodeColumnCount; barcodeColumn++) { + for (let barcodeColumn /* int */ = 1; barcodeColumn <= this.barcodeColumnCount; barcodeColumn++) { let codeword: Codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow]; if (codeword == null) { continue; @@ -135,13 +135,13 @@ export default /*final*/ class DetectionResult { } let unadjustedCount: int = 0; let codewords: Codeword[] = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords(); - for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) { + for (let codewordsRow /* int */ = 0; codewordsRow < codewords.length; codewordsRow++) { if (codewords[codewordsRow] == null) { continue; } let rowIndicatorRowNumber: int = codewords[codewordsRow].getRowNumber(); let invalidRowCounts: int = 0; - for (let barcodeColumn /*int*/ = this.barcodeColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) { + for (let barcodeColumn /* int */ = this.barcodeColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) { let codeword: Codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow]; if (codeword != null) { invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword); @@ -160,13 +160,13 @@ export default /*final*/ class DetectionResult { } let unadjustedCount: int = 0; let codewords: Codeword[] = this.detectionResultColumns[0].getCodewords(); - for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) { + for (let codewordsRow /* int */ = 0; codewordsRow < codewords.length; codewordsRow++) { if (codewords[codewordsRow] == null) { continue; } let rowIndicatorRowNumber: int = codewords[codewordsRow].getRowNumber(); let invalidRowCounts: int = 0; - for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) { + for (let barcodeColumn /* int */ = 1; barcodeColumn < this.barcodeColumnCount + 1 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) { let codeword: Codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow]; if (codeword != null) { invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword); @@ -237,7 +237,7 @@ export default /*final*/ class DetectionResult { /** * @return true, if row number was adjusted, false otherwise - */ + */ private static adjustRowNumber(codeword: Codeword, otherCodeword: Codeword): boolean { if (otherCodeword == null) { return false; @@ -286,9 +286,9 @@ export default /*final*/ class DetectionResult { // try ( let formatter: Formatter = new Formatter(); // ) { - for (let codewordsRow /*int*/ = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) { + for (let codewordsRow /* int */ = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) { formatter.format('CW %3d:', codewordsRow); - for (let barcodeColumn /*int*/ = 0; barcodeColumn < this.barcodeColumnCount + 2; barcodeColumn++) { + for (let barcodeColumn /* int */ = 0; barcodeColumn < this.barcodeColumnCount + 2; barcodeColumn++) { if (this.detectionResultColumns[barcodeColumn] == null) { formatter.format(' | '); continue; diff --git a/src/core/pdf417/decoder/DetectionResultColumn.ts b/src/core/pdf417/decoder/DetectionResultColumn.ts index 17b5f8b4..5ba63080 100644 --- a/src/core/pdf417/decoder/DetectionResultColumn.ts +++ b/src/core/pdf417/decoder/DetectionResultColumn.ts @@ -29,74 +29,74 @@ import { int } from '../../../customTypings'; */ export default class DetectionResultColumn { - private static /*final*/ MAX_NEARBY_DISTANCE: int = 5; + private static /* final */ MAX_NEARBY_DISTANCE: int = 5; - private /*final*/ boundingBox: BoundingBox; - private /*final*/ codewords: Codeword[]; + private /* final */ boundingBox: BoundingBox; + private /* final */ codewords: Codeword[]; - constructor(boundingBox: BoundingBox) { - this.boundingBox = new BoundingBox(boundingBox); - // this.codewords = new Codeword[boundingBox.getMaxY() - boundingBox.getMinY() + 1]; - this.codewords = new Array(boundingBox.getMaxY() - boundingBox.getMinY() + 1); - } + constructor(boundingBox: BoundingBox) { + this.boundingBox = new BoundingBox(boundingBox); + // this.codewords = new Codeword[boundingBox.getMaxY() - boundingBox.getMinY() + 1]; + this.codewords = new Array(boundingBox.getMaxY() - boundingBox.getMinY() + 1); + } - /*final*/ getCodewordNearby(imageRow: int): Codeword { - let codeword = this.getCodeword(imageRow); + /* final */ getCodewordNearby(imageRow: int): Codeword { + let codeword = this.getCodeword(imageRow); + if (codeword != null) { + return codeword; + } + for (let i = 1; i < DetectionResultColumn.MAX_NEARBY_DISTANCE; i++) { + let nearImageRow = this.imageRowToCodewordIndex(imageRow) - i; + if (nearImageRow >= 0) { + codeword = this.codewords[nearImageRow]; if (codeword != null) { - return codeword; + return codeword; } - for (let i = 1; i < DetectionResultColumn.MAX_NEARBY_DISTANCE; i++) { - let nearImageRow = this.imageRowToCodewordIndex(imageRow) - i; - if (nearImageRow >= 0) { - codeword = this.codewords[nearImageRow]; - if (codeword != null) { - return codeword; - } - } - nearImageRow = this.imageRowToCodewordIndex(imageRow) + i; - if (nearImageRow < this.codewords.length) { - codeword = this.codewords[nearImageRow]; - if (codeword != null) { - return codeword; - } - } + } + nearImageRow = this.imageRowToCodewordIndex(imageRow) + i; + if (nearImageRow < this.codewords.length) { + codeword = this.codewords[nearImageRow]; + if (codeword != null) { + return codeword; } - return null; - } - - /*final int*/ imageRowToCodewordIndex(imageRow: int): int { - return imageRow - this.boundingBox.getMinY(); - } - - /*final void*/ setCodeword(imageRow: int, codeword: Codeword): void { - this.codewords[this.imageRowToCodewordIndex(imageRow)] = codeword; + } } - -/*final*/ getCodeword(imageRow: int): Codeword { - return this.codewords[this.imageRowToCodewordIndex(imageRow)]; + return null; + } + + /* final int */ imageRowToCodewordIndex(imageRow: int): int { + return imageRow - this.boundingBox.getMinY(); + } + + /* final void */ setCodeword(imageRow: int, codeword: Codeword): void { + this.codewords[this.imageRowToCodewordIndex(imageRow)] = codeword; + } + + /* final */ getCodeword(imageRow: int): Codeword { + return this.codewords[this.imageRowToCodewordIndex(imageRow)]; + } + + /* final */ getBoundingBox(): BoundingBox { + return this.boundingBox; + } + + /* final */ getCodewords(): Codeword[] { + return this.codewords; + } + + // @Override + public toString(): string { + const formatter = new Formatter(); + let row = 0; + for (const codeword of this.codewords) { + if (codeword == null) { + formatter.format('%3d: | %n', row++); + continue; + } + formatter.format('%3d: %3d|%3d%n', row++, codeword.getRowNumber(), codeword.getValue()); } + return formatter.toString(); -/*final*/ getBoundingBox(): BoundingBox { - return this.boundingBox; - } - -/*final*/ getCodewords(): Codeword[] { - return this.codewords; - } - - // @Override - public toString(): string { - const formatter = new Formatter(); - let row = 0; - for (const codeword of this.codewords) { - if (codeword == null) { - formatter.format('%3d: | %n', row++); - continue; - } - formatter.format('%3d: %3d|%3d%n', row++, codeword.getRowNumber(), codeword.getValue()); - } - return formatter.toString(); - - } + } } diff --git a/src/core/pdf417/decoder/DetectionResultRowIndicatorColumn.ts b/src/core/pdf417/decoder/DetectionResultRowIndicatorColumn.ts index e7202bd8..cbd39dbd 100644 --- a/src/core/pdf417/decoder/DetectionResultRowIndicatorColumn.ts +++ b/src/core/pdf417/decoder/DetectionResultRowIndicatorColumn.ts @@ -32,17 +32,17 @@ import { int } from '../../../customTypings'; /** * @author Guenther Grau */ -export default /*final*/ class DetectionResultRowIndicatorColumn extends DetectionResultColumn { +export default /* final */ class DetectionResultRowIndicatorColumn extends DetectionResultColumn { - private /*final*/ _isLeft: boolean; + public readonly isLeft: boolean; constructor(boundingBox: BoundingBox, isLeft: boolean) { super(boundingBox); - this._isLeft = isLeft; + this.isLeft = isLeft; } private setRowNumbers(): void { - for (let codeword /*Codeword*/ of this.getCodewords()) { + for (let codeword /* Codeword */ of this.getCodewords()) { if (codeword != null) { codeword.setRowNumberAsRowIndicatorColumn(); } @@ -58,17 +58,17 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti this.setRowNumbers(); this.removeIncorrectCodewords(codewords, barcodeMetadata); let boundingBox: BoundingBox = this.getBoundingBox(); - let top: ResultPoint = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight(); - let bottom: ResultPoint = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight(); - let firstRow: int = this.imageRowToCodewordIndex( Math.trunc(top.getY())); - let lastRow: int = this.imageRowToCodewordIndex( Math.trunc(bottom.getY())); + let top: ResultPoint = this.isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight(); + let bottom: ResultPoint = this.isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight(); + let firstRow: int = this.imageRowToCodewordIndex(Math.trunc(top.getY())); + let lastRow: int = this.imageRowToCodewordIndex(Math.trunc(bottom.getY())); // We need to be careful using the average row height. Barcode could be skewed so that we have smaller and // taller rows - // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount(); + // float averageRowHeight = (lastRow - firstRow) / /*(float) */ barcodeMetadata.getRowCount(); let barcodeRow: int = -1; let maxRowHeight: int = 1; let currentRowHeight: int = 0; - for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) { + for (let codewordsRow /* int */ = firstRow; codewordsRow < lastRow; codewordsRow++) { if (codewords[codewordsRow] == null) { continue; } @@ -93,8 +93,8 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti currentRowHeight = 1; barcodeRow = codeword.getRowNumber(); } else if (rowDifference < 0 || - codeword.getRowNumber() >= barcodeMetadata.getRowCount() || - rowDifference > codewordsRow) { + codeword.getRowNumber() >= barcodeMetadata.getRowCount() || + rowDifference > codewordsRow) { codewords[codewordsRow] = null; } else { let checkedRows: int; @@ -104,7 +104,7 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti checkedRows = rowDifference; } let closePreviousCodewordFound: boolean = checkedRows >= codewordsRow; - for (let i /*int*/ = 1; i <= checkedRows && !closePreviousCodewordFound; i++) { + for (let i /* int */ = 1; i <= checkedRows && !closePreviousCodewordFound; i++) { // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1. // This should hopefully get rid of most problems already. closePreviousCodewordFound = codewords[codewordsRow - i] != null; @@ -127,7 +127,7 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti } this.adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata); let result: Int32Array = new Int32Array(barcodeMetadata.getRowCount()); - for (let codeword /*Codeword*/ of this.getCodewords()) { + for (let codeword /* Codeword */ of this.getCodewords()) { if (codeword != null) { let rowNumber: int = codeword.getRowNumber(); if (rowNumber >= result.length) { @@ -145,16 +145,16 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti // use row height count to make detection of invalid row numbers more reliable private adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata: BarcodeMetadata): void { let boundingBox: BoundingBox = this.getBoundingBox(); - let top: ResultPoint = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight(); - let bottom: ResultPoint = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight(); - let firstRow: int = this.imageRowToCodewordIndex( Math.trunc(top.getY())); - let lastRow: int = this.imageRowToCodewordIndex( Math.trunc(bottom.getY())); - // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount(); + let top: ResultPoint = this.isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight(); + let bottom: ResultPoint = this.isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight(); + let firstRow: int = this.imageRowToCodewordIndex(Math.trunc(top.getY())); + let lastRow: int = this.imageRowToCodewordIndex(Math.trunc(bottom.getY())); + // float averageRowHeight = (lastRow - firstRow) / /*(float) */ barcodeMetadata.getRowCount(); let codewords: Codeword[] = this.getCodewords(); let barcodeRow: int = -1; let maxRowHeight: int = 1; let currentRowHeight: int = 0; - for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) { + for (let codewordsRow /* int */ = firstRow; codewordsRow < lastRow; codewordsRow++) { if (codewords[codewordsRow] == null) { continue; } @@ -188,14 +188,14 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti let barcodeRowCountUpperPart: BarcodeValue = new BarcodeValue(); let barcodeRowCountLowerPart: BarcodeValue = new BarcodeValue(); let barcodeECLevel: BarcodeValue = new BarcodeValue(); - for (let codeword /*Codeword*/ of codewords) { + for (let codeword /* Codeword */ of codewords) { if (codeword == null) { continue; } codeword.setRowNumberAsRowIndicatorColumn(); let rowIndicatorValue: int = codeword.getValue() % 30; let codewordRowNumber: int = codeword.getRowNumber(); - if (!this._isLeft) { + if (!this.isLeft) { codewordRowNumber += 2; } switch (codewordRowNumber % 3) { @@ -213,16 +213,16 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti } // Maybe we should check if we have ambiguous values? if ((barcodeColumnCount.getValue().length === 0) || - (barcodeRowCountUpperPart.getValue().length === 0) || - (barcodeRowCountLowerPart.getValue().length === 0) || - (barcodeECLevel.getValue().length === 0) || - barcodeColumnCount.getValue()[0] < 1 || - barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] < PDF417Common.MIN_ROWS_IN_BARCODE || - barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] > PDF417Common.MAX_ROWS_IN_BARCODE) { + (barcodeRowCountUpperPart.getValue().length === 0) || + (barcodeRowCountLowerPart.getValue().length === 0) || + (barcodeECLevel.getValue().length === 0) || + barcodeColumnCount.getValue()[0] < 1 || + barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] < PDF417Common.MIN_ROWS_IN_BARCODE || + barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] > PDF417Common.MAX_ROWS_IN_BARCODE) { return null; } let barcodeMetadata: BarcodeMetadata = new BarcodeMetadata(barcodeColumnCount.getValue()[0], - barcodeRowCountUpperPart.getValue()[0], barcodeRowCountLowerPart.getValue()[0], barcodeECLevel.getValue()[0]); + barcodeRowCountUpperPart.getValue()[0], barcodeRowCountLowerPart.getValue()[0], barcodeECLevel.getValue()[0]); this.removeIncorrectCodewords(codewords, barcodeMetadata); return barcodeMetadata; } @@ -230,7 +230,7 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti private removeIncorrectCodewords(codewords: Codeword[], barcodeMetadata: BarcodeMetadata): void { // Remove codewords which do not match the metadata // TODO Maybe we should keep the incorrect codewords for the start and end positions? - for (let codewordRow /*int*/ = 0; codewordRow < codewords.length; codewordRow++) { + for (let codewordRow /* int */ = 0; codewordRow < codewords.length; codewordRow++) { let codeword: Codeword = codewords[codewordRow]; if (codewords[codewordRow] == null) { continue; @@ -241,7 +241,7 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti codewords[codewordRow] = null; continue; } - if (!this._isLeft) { + if (!this.isLeft) { codewordRowNumber += 2; } switch (codewordRowNumber % 3) { @@ -252,7 +252,7 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti break; case 1: if (Math.trunc(rowIndicatorValue / 3) !== barcodeMetadata.getErrorCorrectionLevel() || - rowIndicatorValue % 3 !== barcodeMetadata.getRowCountLowerPart()) { + rowIndicatorValue % 3 !== barcodeMetadata.getRowCountLowerPart()) { codewords[codewordRow] = null; } break; @@ -265,13 +265,9 @@ export default /*final*/ class DetectionResultRowIndicatorColumn extends Detecti } } - isLeft(): boolean { - return this._isLeft; - } - // @Override public toString(): string { - return 'IsLeft: ' + this._isLeft + '\n' + super.toString(); + return 'IsLeft: ' + this.isLeft + '\n' + super.toString(); } } diff --git a/src/core/pdf417/decoder/PDF417CodewordDecoder.ts b/src/core/pdf417/decoder/PDF417CodewordDecoder.ts index 4710a1d6..215ac8af 100644 --- a/src/core/pdf417/decoder/PDF417CodewordDecoder.ts +++ b/src/core/pdf417/decoder/PDF417CodewordDecoder.ts @@ -28,25 +28,25 @@ import { int, float } from '../../../customTypings'; * @author Guenther Grau * @author creatale GmbH (christoph.schulz@creatale.de) */ -export default /*final*/ class PDF417CodewordDecoder { +export default /* final */ class PDF417CodewordDecoder { // flag that the table is ready for use private static bSymbolTableReady: boolean = false; - private static /*final float[][]*/ RATIOS_TABLE: number[][] = - new Array(PDF417Common.SYMBOL_TABLE.length).map(x => x = new Array(PDF417Common.BARS_IN_MODULE)); + private static /* final float[][] */ RATIOS_TABLE: number[][] = + new Array(PDF417Common.SYMBOL_TABLE.length).map(x => x = new Array(PDF417Common.BARS_IN_MODULE)); /* @note * this action have to be performed before first use of class * - static constructor * working with 32bit float (based from Java logic) - */ + */ static initialize() { - // Pre-computes the symbol ratio table. - for (/*int*/let i = 0; i < PDF417Common.SYMBOL_TABLE.length; i++) { + // Pre-computes the symbol ratio table. + for (/* int */let i = 0; i < PDF417Common.SYMBOL_TABLE.length; i++) { let currentSymbol: int = PDF417Common.SYMBOL_TABLE[i]; let currentBit: int = currentSymbol & 0x1; - for (/*int*/ let j = 0; j < PDF417Common.BARS_IN_MODULE; j++) { + for (/* int */ let j = 0; j < PDF417Common.BARS_IN_MODULE; j++) { let size: float = 0.0; while ((currentSymbol & 0x1) === currentBit) { size += 1.0; @@ -63,10 +63,10 @@ export default /*final*/ class PDF417CodewordDecoder { } static getDecodedValue(moduleBitCount: Int32Array): int { - let decodedValue: int = PDF417CodewordDecoder.getDecodedCodewordValue(PDF417CodewordDecoder.sampleBitCounts(moduleBitCount)); - if (decodedValue !== -1) { + let decodedValue: int = PDF417CodewordDecoder.getDecodedCodewordValue(PDF417CodewordDecoder.sampleBitCounts(moduleBitCount)); + if (decodedValue !== -1) { return decodedValue; - } + } return PDF417CodewordDecoder.getClosestDecodedValue(moduleBitCount); } @@ -75,10 +75,10 @@ export default /*final*/ class PDF417CodewordDecoder { let result: Int32Array = new Int32Array(PDF417Common.BARS_IN_MODULE); let bitCountIndex: int = 0; let sumPreviousBits: int = 0; - for (/*int*/ let i = 0; i < PDF417Common.MODULES_IN_CODEWORD; i++) { + for (/* int */ let i = 0; i < PDF417Common.MODULES_IN_CODEWORD; i++) { let sampleIndex: float = - bitCountSum / (2 * PDF417Common.MODULES_IN_CODEWORD) + - (i * bitCountSum) / PDF417Common.MODULES_IN_CODEWORD; + bitCountSum / (2 * PDF417Common.MODULES_IN_CODEWORD) + + (i * bitCountSum) / PDF417Common.MODULES_IN_CODEWORD; if (sumPreviousBits + moduleBitCount[bitCountIndex] <= sampleIndex) { sumPreviousBits += moduleBitCount[bitCountIndex]; bitCountIndex++; @@ -94,13 +94,13 @@ export default /*final*/ class PDF417CodewordDecoder { } private static getBitValue(moduleBitCount: Int32Array): int { - let result: /*long*/ number = 0; - for (let /*int*/ i = 0; i < moduleBitCount.length; i++) { - for (/*int*/ let bit = 0; bit < moduleBitCount[i]; bit++) { + let result: /* long */ number = 0; + for (let /* int */ i = 0; i < moduleBitCount.length; i++) { + for (/* int */ let bit = 0; bit < moduleBitCount[i]; bit++) { result = (result << 1) | (i % 2 === 0 ? 1 : 0); } } - return Math.trunc(result); + return Math.trunc(result); } // working with 32bit float (as in Java) @@ -108,7 +108,7 @@ export default /*final*/ class PDF417CodewordDecoder { let bitCountSum: int = MathUtils.sum(moduleBitCount); let bitCountRatios: float[] = new Array(PDF417Common.BARS_IN_MODULE); if (bitCountSum > 1) { - for (let /*int*/ i = 0; i < bitCountRatios.length; i++) { + for (let /* int */ i = 0; i < bitCountRatios.length; i++) { bitCountRatios[i] = Math.fround(moduleBitCount[i] / bitCountSum); } } @@ -117,10 +117,10 @@ export default /*final*/ class PDF417CodewordDecoder { if (!this.bSymbolTableReady) { PDF417CodewordDecoder.initialize(); } - for (/*int*/ let j = 0; j < PDF417CodewordDecoder.RATIOS_TABLE.length; j++) { + for (/* int */ let j = 0; j < PDF417CodewordDecoder.RATIOS_TABLE.length; j++) { let error: float = 0.0; let ratioTableRow: float[] = PDF417CodewordDecoder.RATIOS_TABLE[j]; - for (/*int*/ let k = 0; k < PDF417Common.BARS_IN_MODULE; k++) { + for (/* int */ let k = 0; k < PDF417Common.BARS_IN_MODULE; k++) { let diff: float = Math.fround(ratioTableRow[k] - bitCountRatios[k]); error += Math.fround(diff * diff); if (error >= bestMatchError) { diff --git a/src/core/pdf417/decoder/PDF417ScanningDecoder.ts b/src/core/pdf417/decoder/PDF417ScanningDecoder.ts index e9062e5d..096e65b3 100644 --- a/src/core/pdf417/decoder/PDF417ScanningDecoder.ts +++ b/src/core/pdf417/decoder/PDF417ScanningDecoder.ts @@ -58,15 +58,15 @@ import { int, List, Collection } from '../../../customTypings'; /** * @author Guenther Grau */ -export default /*public final*/ class PDF417ScanningDecoder { +export default /* public final */ class PDF417ScanningDecoder { - /*final*/ static CODEWORD_SKEW_SIZE: int = 2; + /* final */ static CODEWORD_SKEW_SIZE: int = 2; - /*final*/ static MAX_ERRORS: int = 3; - /*final*/ static MAX_EC_CODEWORDS: int = 512; - /*final*/ static errorCorrection: ErrorCorrection = new ErrorCorrection(); + /* final */ static MAX_ERRORS: int = 3; + /* final */ static MAX_EC_CODEWORDS: int = 512; + /* final */ static errorCorrection: ErrorCorrection = new ErrorCorrection(); - private constructor() {} + private constructor() { } /** * @TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern @@ -93,7 +93,7 @@ export default /*public final*/ class PDF417ScanningDecoder { * @throws NotFoundException * @throws FormatException * @throws ChecksumException - */ + */ public static decode(image: BitMatrix, imageTopLeft: ResultPoint, imageBottomLeft: ResultPoint, @@ -105,7 +105,7 @@ export default /*public final*/ class PDF417ScanningDecoder { let leftRowIndicatorColumn: DetectionResultRowIndicatorColumn = null; let rightRowIndicatorColumn: DetectionResultRowIndicatorColumn = null; let detectionResult: DetectionResult; - for (let firstPass /*boolean*/ = true; ; firstPass = false) { + for (let firstPass /* boolean */ = true; ; firstPass = false) { if (imageTopLeft != null) { leftRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth); @@ -132,7 +132,7 @@ export default /*public final*/ class PDF417ScanningDecoder { detectionResult.setDetectionResultColumn(maxBarcodeColumn, rightRowIndicatorColumn); let leftToRight: boolean = leftRowIndicatorColumn != null; - for (let barcodeColumnCount /*int*/ = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++) { + for (let barcodeColumnCount /* int */ = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++) { let barcodeColumn: int = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount; if (detectionResult.getDetectionResultColumn(barcodeColumn) !== /* null */ undefined) { // This will be the case for the opposite row indicator column, which doesn't need to be decoded again. @@ -148,7 +148,7 @@ export default /*public final*/ class PDF417ScanningDecoder { let startColumn: int = -1; let previousStartColumn: int = startColumn; // TODO start at a row for which we know the start position, then detect upwards and downwards from there. - for (let imageRow /*int*/ = boundingBox.getMinY(); imageRow <= boundingBox.getMaxY(); imageRow++) { + for (let imageRow /* int */ = boundingBox.getMinY(); imageRow <= boundingBox.getMaxY(); imageRow++) { startColumn = PDF417ScanningDecoder.getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight); if (startColumn < 0 || startColumn > boundingBox.getMaxX()) { if (previousStartColumn === -1) { @@ -175,7 +175,7 @@ export default /*public final*/ class PDF417ScanningDecoder { * @param rightRowIndicatorColumn * * @throws NotFoundException - */ + */ private static merge(leftRowIndicatorColumn: DetectionResultRowIndicatorColumn, rightRowIndicatorColumn: DetectionResultRowIndicatorColumn): DetectionResult { if (leftRowIndicatorColumn == null && rightRowIndicatorColumn == null) { @@ -195,7 +195,7 @@ export default /*public final*/ class PDF417ScanningDecoder { * @param rowIndicatorColumn * * @throws NotFoundException - */ + */ private static adjustBoundingBox(rowIndicatorColumn: DetectionResultRowIndicatorColumn): BoundingBox { if (rowIndicatorColumn == null) { return null; @@ -206,33 +206,33 @@ export default /*public final*/ class PDF417ScanningDecoder { } let maxRowHeight: int = PDF417ScanningDecoder.getMax(rowHeights); let missingStartRows: int = 0; - for (let rowHeight /*int*/ of rowHeights) { + for (let rowHeight /* int */ of rowHeights) { missingStartRows += maxRowHeight - rowHeight; if (rowHeight > 0) { break; } } let codewords: Codeword[] = rowIndicatorColumn.getCodewords(); - for (let row /*int*/ = 0; missingStartRows > 0 && codewords[row] == null; row++) { + for (let row /* int */ = 0; missingStartRows > 0 && codewords[row] == null; row++) { missingStartRows--; } let missingEndRows: int = 0; - for (let row /*int*/ = rowHeights.length - 1; row >= 0; row--) { + for (let row /* int */ = rowHeights.length - 1; row >= 0; row--) { missingEndRows += maxRowHeight - rowHeights[row]; if (rowHeights[row] > 0) { break; } } - for (let row /*int*/ = codewords.length - 1; missingEndRows > 0 && codewords[row] == null; row--) { + for (let row /* int */ = codewords.length - 1; missingEndRows > 0 && codewords[row] == null; row--) { missingEndRows--; } return rowIndicatorColumn.getBoundingBox().addMissingRows(missingStartRows, missingEndRows, - rowIndicatorColumn.isLeft()); + rowIndicatorColumn.isLeft); } private static getMax(values: Int32Array): int { let maxValue: int = -1; - for (let value /*int*/ of values) { + for (let value /* int */ of values) { maxValue = Math.max(maxValue, value); } return maxValue; @@ -267,10 +267,10 @@ export default /*public final*/ class PDF417ScanningDecoder { maxCodewordWidth: int): DetectionResultRowIndicatorColumn { let rowIndicatorColumn: DetectionResultRowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight); - for (let i /*int*/ = 0; i < 2; i++) { + for (let i /* int */ = 0; i < 2; i++) { let increment: int = i === 0 ? 1 : -1; let startColumn: int = Math.trunc(Math.trunc(startPoint.getX())); - for (let imageRow /*int*/ = Math.trunc(Math.trunc(startPoint.getY())); imageRow <= boundingBox.getMaxY() && + for (let imageRow /* int */ = Math.trunc(Math.trunc(startPoint.getY())); imageRow <= boundingBox.getMaxY() && imageRow >= boundingBox.getMinY(); imageRow += increment) { let codeword: Codeword = PDF417ScanningDecoder.detectCodeword(image, 0, image.getWidth(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth); @@ -296,7 +296,7 @@ export default /*public final*/ class PDF417ScanningDecoder { * @param barcodeMatrix * * @throws NotFoundException - */ + */ private static adjustCodewordCount(detectionResult: DetectionResult, barcodeMatrix: BarcodeValue[][]): void { let barcodeMatrix01: BarcodeValue = barcodeMatrix[0][1]; let numberOfCodewords: Int32Array = barcodeMatrix01.getValue(); @@ -321,16 +321,16 @@ export default /*public final*/ class PDF417ScanningDecoder { * @throws FormatException * @throws ChecksumException * @throws NotFoundException - */ + */ private static createDecoderResult(detectionResult: DetectionResult): DecoderResult { let barcodeMatrix: BarcodeValue[][] = PDF417ScanningDecoder.createBarcodeMatrix(detectionResult); PDF417ScanningDecoder.adjustCodewordCount(detectionResult, barcodeMatrix); - let erasures /*Collection*/ = new Array(); + let erasures /* Collection */ = new Array(); let codewords: Int32Array = new Int32Array(detectionResult.getBarcodeRowCount() * detectionResult.getBarcodeColumnCount()); - let ambiguousIndexValuesList: /*List*/ List = []; - let ambiguousIndexesList: /*Collection*/ Collection = new Array(); - for (let row /*int*/ = 0; row < detectionResult.getBarcodeRowCount(); row++) { - for (let column /*int*/ = 0; column < detectionResult.getBarcodeColumnCount(); column++) { + let ambiguousIndexValuesList: /* List */ List = []; + let ambiguousIndexesList: /* Collection */ Collection = new Array(); + for (let row /* int */ = 0; row < detectionResult.getBarcodeRowCount(); row++) { + for (let column /* int */ = 0; column < detectionResult.getBarcodeColumnCount(); column++) { let values: Int32Array = barcodeMatrix[row][column + 1].getValue(); let codewordIndex: int = row * detectionResult.getBarcodeColumnCount() + column; if (values.length === 0) { @@ -344,7 +344,7 @@ export default /*public final*/ class PDF417ScanningDecoder { } } let ambiguousIndexValues: Int32Array[] = new Array(ambiguousIndexValuesList.length); - for (let i /*int*/ = 0; i < ambiguousIndexValues.length; i++) { + for (let i /* int */ = 0; i < ambiguousIndexValues.length; i++) { ambiguousIndexValues[i] = ambiguousIndexValuesList[i]; } return PDF417ScanningDecoder.createDecoderResultFromAmbiguousValues(detectionResult.getBarcodeECLevel(), codewords, @@ -366,7 +366,7 @@ export default /*public final*/ class PDF417ScanningDecoder { * * @throws FormatException * @throws ChecksumException - */ + */ private static createDecoderResultFromAmbiguousValues(ecLevel: int, codewords: Int32Array, erasureArray: Int32Array, @@ -376,7 +376,7 @@ export default /*public final*/ class PDF417ScanningDecoder { let tries: int = 100; while (tries-- > 0) { - for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) { + for (let i /* int */ = 0; i < ambiguousIndexCount.length; i++) { codewords[ambiguousIndexes[i]] = ambiguousIndexValues[i][ambiguousIndexCount[i]]; } try { @@ -390,7 +390,7 @@ export default /*public final*/ class PDF417ScanningDecoder { if (ambiguousIndexCount.length === 0) { throw ChecksumException.getChecksumInstance(); } - for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) { + for (let i /* int */ = 0; i < ambiguousIndexCount.length; i++) { if (ambiguousIndexCount[i] < ambiguousIndexValues[i].length - 1) { ambiguousIndexCount[i]++; break; @@ -407,19 +407,19 @@ export default /*public final*/ class PDF417ScanningDecoder { private static createBarcodeMatrix(detectionResult: DetectionResult): BarcodeValue[][] { // let barcodeMatrix: BarcodeValue[][] = - // new BarcodeValue[detectionResult.getBarcodeRowCount()][detectionResult.getBarcodeColumnCount() + 2]; + // new BarcodeValue[detectionResult.getBarcodeRowCount()][detectionResult.getBarcodeColumnCount() + 2]; let barcodeMatrix: BarcodeValue[][] = Array.from({ length: detectionResult.getBarcodeRowCount() }, () => new Array(detectionResult.getBarcodeColumnCount() + 2)); - for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) { - for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) { + for (let row /* int */ = 0; row < barcodeMatrix.length; row++) { + for (let column /* int */ = 0; column < barcodeMatrix[row].length; column++) { barcodeMatrix[row][column] = new BarcodeValue(); } } let column: int = 0; - for (let detectionResultColumn /*DetectionResultColumn*/ of detectionResult.getDetectionResultColumns()) { + for (let detectionResultColumn /* DetectionResultColumn */ of detectionResult.getDetectionResultColumns()) { if (detectionResultColumn != null) { - for (let codeword /*Codeword*/ of detectionResultColumn.getCodewords()) { + for (let codeword /* Codeword */ of detectionResultColumn.getCodewords()) { if (codeword != null) { let rowNumber: int = codeword.getRowNumber(); if (rowNumber >= 0) { @@ -467,7 +467,7 @@ export default /*public final*/ class PDF417ScanningDecoder { while (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { barcodeColumn -= offset; - for (let previousRowCodeword /*Codeword*/ of detectionResult.getDetectionResultColumn(barcodeColumn).getCodewords()) { + for (let previousRowCodeword /* Codeword */ of detectionResult.getDetectionResultColumn(barcodeColumn).getCodewords()) { if (previousRowCodeword != null) { return (leftToRight ? previousRowCodeword.getEndX() : previousRowCodeword.getStartX()) + offset * @@ -502,7 +502,7 @@ export default /*public final*/ class PDF417ScanningDecoder { if (leftToRight) { endColumn = startColumn + codewordBitCount; } else { - for (let i /*int*/ = 0; i < moduleBitCount.length / 2; i++) { + for (let i /* int */ = 0; i < moduleBitCount.length / 2; i++) { let tmpCount: int = moduleBitCount[i]; moduleBitCount[i] = moduleBitCount[moduleBitCount.length - 1 - i]; moduleBitCount[moduleBitCount.length - 1 - i] = tmpCount; @@ -514,7 +514,7 @@ export default /*public final*/ class PDF417ScanningDecoder { // use start (and maybe stop pattern) to determine if black bars are wider than white bars. If so, adjust. // should probably done only for codewords with a lot more than 17 bits. // The following fixes 10-1.png, which has wide black bars and small white bars - // for (let i /*int*/ = 0; i < moduleBitCount.length; i++) { + // for (let i /*int */ = 0; i < moduleBitCount.length; i++) { // if (i % 2 === 0) { // moduleBitCount[i]--; // } else { @@ -580,7 +580,7 @@ export default /*public final*/ class PDF417ScanningDecoder { let correctedStartColumn: int = codewordStartColumn; let increment: int = leftToRight ? -1 : 1; // there should be no black pixels before the start column. If there are, then we need to start earlier. - for (let i /*int*/ = 0; i < 2; i++) { + for (let i /* int */ = 0; i < 2; i++) { while ((leftToRight ? correctedStartColumn >= minColumn : correctedStartColumn < maxColumn) && leftToRight === image.get(correctedStartColumn, imageRow)) { if (Math.abs(codewordStartColumn - correctedStartColumn) > PDF417ScanningDecoder.CODEWORD_SKEW_SIZE) { @@ -602,7 +602,7 @@ export default /*public final*/ class PDF417ScanningDecoder { /** * @throws FormatException, * @throws ChecksumException - */ + */ private static decodeCodewords(codewords: Int32Array, ecLevel: int, erasures: Int32Array): DecoderResult { if (codewords.length === 0) { throw FormatException.getFormatInstance(); @@ -627,7 +627,7 @@ export default /*public final*/ class PDF417ScanningDecoder { * @param erasures positions of any known erasures * @param numECCodewords number of error correction codewords that are available in codewords * @throws ChecksumException if error correction fails - */ + */ private static correctErrors(codewords: Int32Array, erasures: Int32Array, numECCodewords: int): int { if (erasures != null && erasures.length > numECCodewords / 2 + PDF417ScanningDecoder.MAX_ERRORS || @@ -642,7 +642,7 @@ export default /*public final*/ class PDF417ScanningDecoder { /** * Verify that all is OK with the codeword array. * @throws FormatException - */ + */ private static verifyCodewordCount(codewords: Int32Array, numECCodewords: int): void { if (codewords.length < 4) { // Codeword array size should be at least 4 allowing for @@ -702,9 +702,9 @@ export default /*public final*/ class PDF417ScanningDecoder { public static toString(barcodeMatrix: BarcodeValue[][]): String { let formatter = new Formatter(); // try (let formatter = new Formatter()) { - for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) { + for (let row /* int */ = 0; row < barcodeMatrix.length; row++) { formatter.format('Row %2d: ', row); - for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) { + for (let column /* int */ = 0; column < barcodeMatrix[row].length; column++) { let barcodeValue: BarcodeValue = barcodeMatrix[row][column]; if (barcodeValue.getValue().length === 0) { formatter.format(' ', null); diff --git a/src/core/pdf417/decoder/ec/ErrorCorrection.ts b/src/core/pdf417/decoder/ec/ErrorCorrection.ts index 989c52cb..39ff699d 100644 --- a/src/core/pdf417/decoder/ec/ErrorCorrection.ts +++ b/src/core/pdf417/decoder/ec/ErrorCorrection.ts @@ -33,9 +33,9 @@ import { int } from '../../../../customTypings'; * @author Sean Owen * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder */ -export default /*public final*/ class ErrorCorrection { +export default /* public final */ class ErrorCorrection { - private /*final*/ field: ModulusGF; + private /* final */ field: ModulusGF; public constructor() { this.field = ModulusGF.PDF417_GF; @@ -47,7 +47,7 @@ export default /*public final*/ class ErrorCorrection { * @param erasures location of erasures * @return number of errors * @throws ChecksumException if errors cannot be corrected, maybe because of too many errors - */ + */ public decode(received: Int32Array, numECCodewords: int, erasures: Int32Array): int { @@ -55,7 +55,7 @@ export default /*public final*/ class ErrorCorrection { let poly: ModulusPoly = new ModulusPoly(this.field, received); let S: Int32Array = new Int32Array(numECCodewords); let error: boolean = false; - for (let i /*int*/ = numECCodewords; i > 0; i--) { + for (let i /* int */ = numECCodewords; i > 0; i--) { let evaluation: int = poly.evaluateAt(this.field.exp(i)); S[numECCodewords - i] = evaluation; if (evaluation !== 0) { @@ -90,7 +90,7 @@ export default /*public final*/ class ErrorCorrection { let errorLocations: Int32Array = this.findErrorLocations(sigma); let errorMagnitudes: Int32Array = this.findErrorMagnitudes(omega, sigma, errorLocations); - for (let i /*int*/ = 0; i < errorLocations.length; i++) { + for (let i /* int */ = 0; i < errorLocations.length; i++) { let position: int = received.length - 1 - this.field.log(errorLocations[i]); if (position < 0) { throw ChecksumException.getChecksumInstance(); @@ -109,7 +109,7 @@ export default /*public final*/ class ErrorCorrection { * @param int * @param R * @throws ChecksumException - */ + */ private runEuclideanAlgorithm(a: ModulusPoly, b: ModulusPoly, R: int): ModulusPoly[] { // Assume a's degree is >= b's if (a.getDegree() < b.getDegree()) { @@ -164,13 +164,13 @@ export default /*public final*/ class ErrorCorrection { * * @param errorLocator * @throws ChecksumException - */ + */ private findErrorLocations(errorLocator: ModulusPoly): Int32Array { // This is a direct application of Chien's search let numErrors: int = errorLocator.getDegree(); let result: Int32Array = new Int32Array(numErrors); let e: int = 0; - for (let i /*int*/ = 1; i < this.field.getSize() && e < numErrors; i++) { + for (let i /* int */ = 1; i < this.field.getSize() && e < numErrors; i++) { if (errorLocator.evaluateAt(i) === 0) { result[e] = this.field.inverse(i); e++; @@ -187,7 +187,7 @@ export default /*public final*/ class ErrorCorrection { errorLocations: Int32Array): Int32Array { let errorLocatorDegree: int = errorLocator.getDegree(); let formalDerivativeCoefficients: Int32Array = new Int32Array(errorLocatorDegree); - for (let i /*int*/ = 1; i <= errorLocatorDegree; i++) { + for (let i /* int */ = 1; i <= errorLocatorDegree; i++) { formalDerivativeCoefficients[errorLocatorDegree - i] = this.field.multiply(i, errorLocator.getCoefficient(i)); } @@ -196,7 +196,7 @@ export default /*public final*/ class ErrorCorrection { // This is directly applying Forney's Formula let s: int = errorLocations.length; let result: Int32Array = new Int32Array(s); - for (let i /*int*/ = 0; i < s; i++) { + for (let i /* int */ = 0; i < s; i++) { let xiInverse: int = this.field.inverse(errorLocations[i]); let numerator: int = this.field.subtract(0, errorEvaluator.evaluateAt(xiInverse)); let denominator: int = this.field.inverse(formalDerivative.evaluateAt(xiInverse)); diff --git a/src/core/pdf417/decoder/ec/ModulusBase.ts b/src/core/pdf417/decoder/ec/ModulusBase.ts index 927ffd65..ef2f77cc 100644 --- a/src/core/pdf417/decoder/ec/ModulusBase.ts +++ b/src/core/pdf417/decoder/ec/ModulusBase.ts @@ -3,9 +3,9 @@ import ArithmeticException from '../../../ArithmeticException'; export default class ModulusBase { - protected /*final*/ logTable: Int32Array; - protected /*final*/ expTable: Int32Array; - protected /*final*/ modulus: number; + protected /* final */ logTable: Int32Array; + protected /* final */ expTable: Int32Array; + protected /* final */ modulus: number; add(a: number, b: number): number { return (a + b) % this.modulus; diff --git a/src/core/pdf417/decoder/ec/ModulusGF.ts b/src/core/pdf417/decoder/ec/ModulusGF.ts index 31b73d83..22a8a9a4 100644 --- a/src/core/pdf417/decoder/ec/ModulusGF.ts +++ b/src/core/pdf417/decoder/ec/ModulusGF.ts @@ -33,27 +33,27 @@ import ModulusBase from './ModulusBase'; * @author Sean Owen * @see com.google.zxing.common.reedsolomon.GenericGF */ -export default /*public final*/ class ModulusGF extends ModulusBase { +export default /* public final */ class ModulusGF extends ModulusBase { - public static /*final*/ PDF417_GF: ModulusGF = new ModulusGF(PDF417Common.NUMBER_OF_CODEWORDS, 3); + public static /* final */ PDF417_GF: ModulusGF = new ModulusGF(PDF417Common.NUMBER_OF_CODEWORDS, 3); - // private /*final*/ expTable: Int32Array; - // private /*final*/ logTable: Int32Array; - private /*final*/ zero: ModulusPoly; - private /*final*/ one: ModulusPoly; - // private /*final*/ modulus: /*int*/ number; + // private /*final */ expTable: Int32Array; + // private /*final */ logTable: Int32Array; + private /* final */ zero: ModulusPoly; + private /* final */ one: ModulusPoly; + // private /*final */ modulus: /*int */ number; - private constructor(modulus: /*int*/ number, generator: /*int*/ number) { + private constructor(modulus: /* int */ number, generator: /* int */ number) { super(); this.modulus = modulus; this.expTable = new Int32Array(modulus); this.logTable = new Int32Array(modulus); - let x: /*int*/ number = 1; - for (let i /*int*/ = 0; i < modulus; i++) { + let x: /* int */ number = 1; + for (let i /* int */ = 0; i < modulus; i++) { this.expTable[i] = x; x = (x * generator) % modulus; } - for (let i /*int*/ = 0; i < modulus - 1; i++) { + for (let i /* int */ = 0; i < modulus - 1; i++) { this.logTable[this.expTable[i]] = i; } // logTable[0] == 0 but this should never be used @@ -70,7 +70,7 @@ export default /*public final*/ class ModulusGF extends ModulusBase { return this.one; } - buildMonomial(degree: /*int*/ number, coefficient: /*int*/ number): ModulusPoly { + buildMonomial(degree: /* int */ number, coefficient: /* int */ number): ModulusPoly { if (degree < 0) { throw new IllegalArgumentException(); } diff --git a/src/core/pdf417/decoder/ec/ModulusPoly.ts b/src/core/pdf417/decoder/ec/ModulusPoly.ts index c1875f5b..7bbe8385 100644 --- a/src/core/pdf417/decoder/ec/ModulusPoly.ts +++ b/src/core/pdf417/decoder/ec/ModulusPoly.ts @@ -25,20 +25,20 @@ import ModulusBase from './ModulusBase'; * @author Sean Owen * @see com.google.zxing.common.reedsolomon.GenericGFPoly */ -export default /*final*/ class ModulusPoly { +export default /* final */ class ModulusPoly { - private /*final*/ field: ModulusBase; - private /*final*/ coefficients: Int32Array; + private /* final */ field: ModulusBase; + private /* final */ coefficients: Int32Array; constructor(field: ModulusBase, coefficients: Int32Array) { if (coefficients.length === 0) { throw new IllegalArgumentException(); } this.field = field; - let coefficientsLength: /*int*/ number = coefficients.length; + let coefficientsLength: /* int */ number = coefficients.length; if (coefficientsLength > 1 && coefficients[0] === 0) { // Leading term must be non-zero for anything except the constant polynomial "0" - let firstNonZero: /*int*/ number = 1; + let firstNonZero: /* int */ number = 1; while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) { firstNonZero++; } @@ -63,44 +63,44 @@ export default /*final*/ class ModulusPoly { /** * @return degree of this polynomial - */ - getDegree(): /*int*/ number { + */ + getDegree(): /* int */ number { return this.coefficients.length - 1; } /** * @return true iff this polynomial is the monomial "0" - */ + */ isZero(): boolean { return this.coefficients[0] === 0; } /** * @return coefficient of x^degree term in this polynomial - */ - getCoefficient(degree: /*int*/ number): /*int*/ number { + */ + getCoefficient(degree: /* int */ number): /* int */ number { return this.coefficients[this.coefficients.length - 1 - degree]; } /** * @return evaluation of this polynomial at a given point - */ - evaluateAt(a: /*int*/ number): /*int*/ number { + */ + evaluateAt(a: /* int */ number): /* int */ number { if (a === 0) { // Just return the x^0 coefficient return this.getCoefficient(0); } if (a === 1) { // Just the sum of the coefficients - let sum: /*int*/ number = 0; - for (let coefficient /*int*/ of this.coefficients) { + let sum: /* int */ number = 0; + for (let coefficient /* int */ of this.coefficients) { sum = this.field.add(sum, coefficient); } return sum; } - let result: /*int*/ number = this.coefficients[0]; - let size: /*int*/ number = this.coefficients.length; - for (let i /*int*/ = 1; i < size; i++) { + let result: /* int */ number = this.coefficients[0]; + let size: /* int */ number = this.coefficients.length; + for (let i /* int */ = 1; i < size; i++) { result = this.field.add(this.field.multiply(a, result), this.coefficients[i]); } return result; @@ -125,11 +125,11 @@ export default /*final*/ class ModulusPoly { largerCoefficients = temp; } let sumDiff: Int32Array = new Int32Array(largerCoefficients.length); - let lengthDiff: /*int*/ number = largerCoefficients.length - smallerCoefficients.length; + let lengthDiff: /* int */ number = largerCoefficients.length - smallerCoefficients.length; // Copy high-order terms only found in higher-degree polynomial's coefficients System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff); - for (let i /*int*/ = lengthDiff; i < largerCoefficients.length; i++) { + for (let i /* int */ = lengthDiff; i < largerCoefficients.length; i++) { sumDiff[i] = this.field.add(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); } @@ -162,13 +162,13 @@ export default /*final*/ class ModulusPoly { return new ModulusPoly(this.field, new Int32Array([0])); } let aCoefficients: Int32Array = this.coefficients; - let aLength: /*int*/ number = aCoefficients.length; + let aLength: /* int */ number = aCoefficients.length; let bCoefficients: Int32Array = other.coefficients; - let bLength: /*int*/ number = bCoefficients.length; + let bLength: /* int */ number = bCoefficients.length; let product: Int32Array = new Int32Array(aLength + bLength - 1); - for (let i /*int*/ = 0; i < aLength; i++) { - let aCoeff: /*int*/ number = aCoefficients[i]; - for (let j /*int*/ = 0; j < bLength; j++) { + for (let i /* int */ = 0; i < aLength; i++) { + let aCoeff: /* int */ number = aCoefficients[i]; + for (let j /* int */ = 0; j < bLength; j++) { product[i + j] = this.field.add(product[i + j], this.field.multiply(aCoeff, bCoefficients[j])); } } @@ -176,39 +176,39 @@ export default /*final*/ class ModulusPoly { } negative(): ModulusPoly { - let size: /*int*/ number = this.coefficients.length; + let size: /* int */ number = this.coefficients.length; let negativeCoefficients: Int32Array = new Int32Array(size); - for (let i /*int*/ = 0; i < size; i++) { + for (let i /* int */ = 0; i < size; i++) { negativeCoefficients[i] = this.field.subtract(0, this.coefficients[i]); } return new ModulusPoly(this.field, negativeCoefficients); } - multiplyScalar(scalar: /*int*/ number): ModulusPoly { + multiplyScalar(scalar: /* int */ number): ModulusPoly { if (scalar === 0) { return new ModulusPoly(this.field, new Int32Array([0])); } if (scalar === 1) { return this; } - let size: /*int*/ number = this.coefficients.length; + let size: /* int */ number = this.coefficients.length; let product: Int32Array = new Int32Array(size); - for (let i /*int*/ = 0; i < size; i++) { + for (let i /* int */ = 0; i < size; i++) { product[i] = this.field.multiply(this.coefficients[i], scalar); } return new ModulusPoly(this.field, product); } - multiplyByMonomial(degree: /*int*/ number, coefficient: /*int*/ number): ModulusPoly { + multiplyByMonomial(degree: /* int */ number, coefficient: /* int */ number): ModulusPoly { if (degree < 0) { throw new IllegalArgumentException(); } if (coefficient === 0) { return new ModulusPoly(this.field, new Int32Array([0])); } - let size: /*int*/ number = this.coefficients.length; + let size: /* int */ number = this.coefficients.length; let product: Int32Array = new Int32Array(size + degree); - for (let i /*int*/ = 0; i < size; i++) { + for (let i /* int */ = 0; i < size; i++) { product[i] = this.field.multiply(this.coefficients[i], coefficient); } return new ModulusPoly(this.field, product); @@ -240,13 +240,13 @@ export default /*final*/ class ModulusPoly { return new ModulusPoly[] { quotient, remainder }; } - */ + */ // @Override public toString(): String { - let result: StringBuilder = new StringBuilder(/*8 * this.getDegree()*/); // dynamic string size in JS - for (let degree /*int*/ = this.getDegree(); degree >= 0; degree--) { - let coefficient: /*int*/ number = this.getCoefficient(degree); + let result: StringBuilder = new StringBuilder(/* 8 * this.getDegree() */); // dynamic string size in JS + for (let degree /* int */ = this.getDegree(); degree >= 0; degree--) { + let coefficient: /* int */ number = this.getCoefficient(degree); if (coefficient !== 0) { if (coefficient < 0) { result.append(' - '); diff --git a/src/core/pdf417/detector/Detector.ts b/src/core/pdf417/detector/Detector.ts index 610ac4df..3783a3ab 100644 --- a/src/core/pdf417/detector/Detector.ts +++ b/src/core/pdf417/detector/Detector.ts @@ -44,27 +44,27 @@ import { float, int } from '../../../customTypings'; * @author dswitkin@google.com (Daniel Switkin) * @author Guenther Grau */ -export default /*public*/ /*final*/ class Detector { +export default /* public */ /* final */ class Detector { - private static /*final*/ INDEXES_START_PATTERN = Int32Array.from([0, 4, 1, 5]); - private static /*final*/ INDEXES_STOP_PATTERN = Int32Array.from([6, 2, 7, 3]); - private static /*final*/ MAX_AVG_VARIANCE: float = /*0.42f*/ 0.42; - private static /*final*/ MAX_INDIVIDUAL_VARIANCE: float = /*0.8f*/ 0.8; + private static /* final */ INDEXES_START_PATTERN = Int32Array.from([0, 4, 1, 5]); + private static /* final */ INDEXES_STOP_PATTERN = Int32Array.from([6, 2, 7, 3]); + private static /* final */ MAX_AVG_VARIANCE: float = /* 0.42f */ 0.42; + private static /* final */ MAX_INDIVIDUAL_VARIANCE: float = /* 0.8f */ 0.8; // B S B S B S B S Bar/Space pattern // 11111111 0 1 0 1 0 1 000 - private static /*final*/ START_PATTERN = Int32Array.from([8, 1, 1, 1, 1, 1, 1, 3]); + private static /* final */ START_PATTERN = Int32Array.from([8, 1, 1, 1, 1, 1, 1, 3]); // 1111111 0 1 000 1 0 1 00 1 - private static /*final*/ STOP_PATTERN = Int32Array.from([7, 1, 1, 3, 1, 1, 1, 2, 1]); - private static /*final*/ MAX_PIXEL_DRIFT: /*int*/ number = 3; - private static /*final*/ MAX_PATTERN_DRIFT: /*int*/ number = 5; + private static /* final */ STOP_PATTERN = Int32Array.from([7, 1, 1, 3, 1, 1, 1, 2, 1]); + private static /* final */ MAX_PIXEL_DRIFT: /* int */ number = 3; + private static /* final */ MAX_PATTERN_DRIFT: /* int */ number = 5; // if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged. // if we set the value too high, then we might detect the start pattern from a neighbor barcode. - private static /*final*/ SKIPPED_ROW_COUNT_MAX: /*int*/ number = 25; + private static /* final */ SKIPPED_ROW_COUNT_MAX: /* int */ number = 25; // A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. Therefore it should be at least // 9 pixels tall. To be conservative, we use about half the size to ensure we don't miss it. - private static /*final*/ ROW_STEP: /*int*/ number = 5; - private static /*final*/ BARCODE_MIN_HEIGHT: /*int*/ number = 10; + private static /* final */ ROW_STEP: /* int */ number = 5; + private static /* final */ BARCODE_MIN_HEIGHT: /* int */ number = 10; /** *

Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.

@@ -75,8 +75,8 @@ export default /*public*/ /*final*/ class Detector { * be found and returned * @return {@link PDF417DetectorResult} encapsulating results of detecting a PDF417 code * @throws NotFoundException if no PDF417 Code can be found - */ - public static detectMultiple( image: BinaryBitmap, hints: Map, multiple: boolean): PDF417DetectorResult { + */ + public static detectMultiple(image: BinaryBitmap, hints: Map, multiple: boolean): PDF417DetectorResult { // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even // different binarizers // boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); @@ -98,8 +98,8 @@ export default /*public*/ /*final*/ class Detector { * be found and returned * @param bitMatrix bit matrix to detect barcodes in * @return List of ResultPoint arrays containing the coordinates of found barcodes - */ - private static detect( multiple: boolean, bitMatrix: BitMatrix): Array { + */ + private static detect(multiple: boolean, bitMatrix: BitMatrix): Array { const barcodeCoordinates = new Array(); let row = 0; let column = 0; @@ -118,10 +118,10 @@ export default /*public*/ /*final*/ class Detector { column = 0; for (const barcodeCoordinate of barcodeCoordinates) { if (barcodeCoordinate[1] != null) { - row = Math.trunc(Math.max(row, barcodeCoordinate[1].getY())); + row = Math.trunc(Math.max(row, barcodeCoordinate[1].getY())); } if (barcodeCoordinate[3] != null) { - row = Math.max(row, Math.trunc(barcodeCoordinate[3].getY())); + row = Math.max(row, Math.trunc(barcodeCoordinate[3].getY())); } } row += Detector.ROW_STEP; @@ -135,11 +135,11 @@ export default /*public*/ /*final*/ class Detector { // if we didn't find a right row indicator column, then continue the search for the next barcode after the // start pattern of the barcode just found. if (vertices[2] != null) { - column = Math.trunc(vertices[2].getX()); - row = Math.trunc(vertices[2].getY()); + column = Math.trunc(vertices[2].getX()); + row = Math.trunc(vertices[2].getY()); } else { - column = Math.trunc(vertices[4].getX()); - row = Math.trunc(vertices[4].getY()); + column = Math.trunc(vertices[4].getX()); + row = Math.trunc(vertices[4].getY()); } } return barcodeCoordinates; @@ -159,22 +159,22 @@ export default /*public*/ /*final*/ class Detector { * vertices[5] x, y bottom left codeword area * vertices[6] x, y top right codeword area * vertices[7] x, y bottom right codeword area - */ - private static findVertices( matrix: BitMatrix, startRow: /*int*/ number, startColumn: /*int*/ number): ResultPoint[] { + */ + private static findVertices(matrix: BitMatrix, startRow: /* int */ number, startColumn: /* int */ number): ResultPoint[] { const height = matrix.getHeight(); const width = matrix.getWidth(); // const result = new ResultPoint[8]; const result = new Array(8); Detector.copyToResult(result, Detector.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector.START_PATTERN), - Detector.INDEXES_START_PATTERN); + Detector.INDEXES_START_PATTERN); if (result[4] != null) { - startColumn = Math.trunc(result[4].getX()); - startRow = Math.trunc(result[4].getY()); + startColumn = Math.trunc(result[4].getX()); + startRow = Math.trunc(result[4].getY()); } Detector.copyToResult(result, Detector.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector.STOP_PATTERN), - Detector.INDEXES_STOP_PATTERN); + Detector.INDEXES_STOP_PATTERN); return result; } @@ -184,12 +184,12 @@ export default /*public*/ /*final*/ class Detector { } } - private static findRowsWithPattern( matrix: BitMatrix, - height: /*int*/ number, - width: /*int*/ number, - startRow: /*int*/ number, - startColumn: /*int*/ number, - pattern: Int32Array): ResultPoint[] { + private static findRowsWithPattern(matrix: BitMatrix, + height: /* int */ number, + width: /* int */ number, + startRow: /* int */ number, + startColumn: /* int */ number, + pattern: Int32Array): ResultPoint[] { // const result = new ResultPoint[4]; const result = new Array(4); let found = false; @@ -216,7 +216,7 @@ export default /*public*/ /*final*/ class Detector { // Last row of the current symbol that contains pattern if (found) { let skippedRowCount = 0; - let previousRowLoc = Int32Array.from([ Math.trunc(result[0].getX()), Math.trunc(result[1].getX())]); + let previousRowLoc = Int32Array.from([Math.trunc(result[0].getX()), Math.trunc(result[1].getX())]); for (; stopRow < height; stopRow++) { const loc = Detector.findGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters); // a found pattern is only considered to belong to the same barcode if the start and end positions @@ -224,8 +224,8 @@ export default /*public*/ /*final*/ class Detector { // a higher number of skipped rows drift could be larger. To keep it simple for now, we allow a slightly // larger drift and don't check for skipped rows. if (loc != null && - Math.abs(previousRowLoc[0] - loc[0]) < Detector.MAX_PATTERN_DRIFT && - Math.abs(previousRowLoc[1] - loc[1]) < Detector.MAX_PATTERN_DRIFT) { + Math.abs(previousRowLoc[0] - loc[0]) < Detector.MAX_PATTERN_DRIFT && + Math.abs(previousRowLoc[1] - loc[1]) < Detector.MAX_PATTERN_DRIFT) { previousRowLoc = loc; skippedRowCount = 0; } else { @@ -255,14 +255,14 @@ export default /*public*/ /*final*/ class Detector { * being searched for as a pattern * @param counters array of counters, as long as pattern, to re-use * @return start/end horizontal offset of guard pattern, as an array of two ints. - */ - private static findGuardPattern( matrix: BitMatrix, - column: /*int*/ number, - row: /*int*/ number, - width: /*int*/ number, - whiteFirst: boolean, - pattern: Int32Array, - counters: Int32Array): Int32Array { + */ + private static findGuardPattern(matrix: BitMatrix, + column: /* int */ number, + row: /* int */ number, + width: /* int */ number, + whiteFirst: boolean, + pattern: Int32Array, + counters: Int32Array): Int32Array { Arrays.fillWithin(counters, 0, counters.length, 0); let patternStart = column; let pixelDrift = 0; @@ -296,7 +296,7 @@ export default /*public*/ /*final*/ class Detector { } } if (counterPosition === patternLength - 1 && - Detector.patternMatchVariance(counters, pattern, Detector.MAX_INDIVIDUAL_VARIANCE) < Detector.MAX_AVG_VARIANCE) { + Detector.patternMatchVariance(counters, pattern, Detector.MAX_INDIVIDUAL_VARIANCE) < Detector.MAX_AVG_VARIANCE) { return new Int32Array([patternStart, x - 1]); } return null; @@ -312,8 +312,8 @@ export default /*public*/ /*final*/ class Detector { * @param pattern expected pattern * @param maxIndividualVariance The most any counter can differ before we give up * @return ratio of total variance between counters and pattern compared to total pattern size - */ - private static patternMatchVariance( counters: Int32Array, pattern: Int32Array, maxIndividualVariance: float): float { + */ + private static patternMatchVariance(counters: Int32Array, pattern: Int32Array, maxIndividualVariance: float): float { let numCounters = counters.length; let total = 0; let patternLength = 0; @@ -324,12 +324,12 @@ export default /*public*/ /*final*/ class Detector { if (total < patternLength) { // If we don't even have one pixel per unit of bar width, assume this // is too small to reliably match, so fail: - return /*Float.POSITIVE_INFINITY*/ Infinity; + return /* Float.POSITIVE_INFINITY */ Infinity; } // We're going to fake floating-point math in integers. We just need to use more bits. // Scale up patternLength so that intermediate values below like scaledCounter will have // more "significant digits". - let unitBarWidth = total / patternLength; + let unitBarWidth = total / patternLength; maxIndividualVariance *= unitBarWidth; let totalVariance = 0.0; @@ -338,7 +338,7 @@ export default /*public*/ /*final*/ class Detector { let scaledPattern = pattern[x] * unitBarWidth; let variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter; if (variance > maxIndividualVariance) { - return /*Float.POSITIVE_INFINITY*/ Infinity; + return /* Float.POSITIVE_INFINITY */ Infinity; } totalVariance += variance; } diff --git a/src/core/pdf417/detector/PDF417DetectorResult.ts b/src/core/pdf417/detector/PDF417DetectorResult.ts index eb5c2c42..ccc6db61 100644 --- a/src/core/pdf417/detector/PDF417DetectorResult.ts +++ b/src/core/pdf417/detector/PDF417DetectorResult.ts @@ -26,22 +26,22 @@ import BitMatrix from '../../common/BitMatrix'; /** * @author Guenther Grau */ -export default /*public final*/ class PDF417DetectorResult { +export default /* public final */ class PDF417DetectorResult { - private /*final*/ bits: BitMatrix; - private /*final*/ points: ResultPoint[][]; + private /* final */ bits: BitMatrix; + private /* final */ points: ResultPoint[][]; - constructor(bits: BitMatrix, points: ResultPoint[][]) { - this.bits = bits; - this.points = points; - } + constructor(bits: BitMatrix, points: ResultPoint[][]) { + this.bits = bits; + this.points = points; + } - public getBits(): BitMatrix { - return this.bits; - } + public getBits(): BitMatrix { + return this.bits; + } - public getPoints(): ResultPoint[][] { - return this.points; - } + public getPoints(): ResultPoint[][] { + return this.points; + } } diff --git a/src/core/qrcode/QRCodeReader.ts b/src/core/qrcode/QRCodeReader.ts index 6380bcea..b800c871 100644 --- a/src/core/qrcode/QRCodeReader.ts +++ b/src/core/qrcode/QRCodeReader.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode {*/ +/* namespace com.google.zxing.qrcode { */ import BarcodeFormat from '../BarcodeFormat'; import BinaryBitmap from '../BinaryBitmap'; @@ -32,8 +32,8 @@ import QRCodeDecoderMetaData from './decoder/QRCodeDecoderMetaData'; import Detector from './detector/Detector'; -/*import java.util.List;*/ -/*import java.util.Map;*/ +/* import java.util.List; */ +/* import java.util.Map; */ /** * This implementation can detect and decode QR Codes in an image. @@ -42,7 +42,7 @@ import Detector from './detector/Detector'; */ export default class QRCodeReader implements Reader { - private static NO_POINTS = new Array(); + protected static NO_POINTS = new Array(); private decoder = new Decoder(); @@ -58,13 +58,35 @@ export default class QRCodeReader implements Reader { * @throws FormatException if a QR code cannot be decoded * @throws ChecksumException if error correction fails */ - /*@Override*/ - // public decode(image: BinaryBitmap): Result /*throws NotFoundException, ChecksumException, FormatException */ { - // return this.decode(image, null) - // } - - /*@Override*/ + public decode(image: BinaryBitmap): Result /*throws NotFoundException, ChecksumException, FormatException */; + /** + * @override + */ public decode(image: BinaryBitmap, hints?: Map): Result { + + if (!hints) { + this.decodeOverload1(image); + } + + return this.decodeImpl(image, hints); + } + + /** + * Locates and decodes a QR code in an image. + * + * @return a representing: string the content encoded by the QR code + * @throws NotFoundException if a QR code cannot be found + * @throws FormatException if a QR code cannot be decoded + * @throws ChecksumException if error correction fails + */ + public decodeOverload1(image: BinaryBitmap): Result /*throws NotFoundException, ChecksumException, FormatException */ { + return this.decodeImpl(image, null); + } + + /** + * @override + */ + public decodeImpl(image: BinaryBitmap, hints?: Map): Result { let decoderResult: DecoderResult; let points: Array; if (hints !== undefined && hints !== null && undefined !== hints.get(DecodeHintType.PURE_BARCODE)) { @@ -100,7 +122,7 @@ export default class QRCodeReader implements Reader { return result; } - /*@Override*/ + /* @Override */ public reset(): void { // do nothing } @@ -112,8 +134,8 @@ export default class QRCodeReader implements Reader { * case. * * @see com.google.zxing.datamatrix.DataMatrixReader#extractPureBits(BitMatrix) - */ - private static extractPureBits(image: BitMatrix): BitMatrix /*throws NotFoundException */ { + */ + private static extractPureBits(image: BitMatrix): BitMatrix /* throws NotFoundException */ { const leftTopBlack: Int32Array = image.getTopLeftOnBit(); const rightBottomBlack: Int32Array = image.getBottomRightOnBit(); @@ -121,7 +143,7 @@ export default class QRCodeReader implements Reader { throw new NotFoundException(); } - const moduleSize: number /*float*/ = this.moduleSize(leftTopBlack, image); + const moduleSize: number /* float */ = this.moduleSize(leftTopBlack, image); let top = leftTopBlack[1]; let bottom = rightBottomBlack[1]; @@ -156,14 +178,14 @@ export default class QRCodeReader implements Reader { // Push in the "border" by half the module width so that we start // sampling in the middle of the module. Just in case the image is a // little off, this will help recover. - const nudge = /*(int) */Math.floor(moduleSize / 2.0); + const nudge = /* (int) */Math.floor(moduleSize / 2.0); top += nudge; left += nudge; // But careful that this does not sample off the edge // "right" is the farthest-right valid pixel location -- right+1 is not necessarily // This is positive by how much the inner x loop below would be too large - const nudgedTooFarRight = left + /*(int) */Math.floor((matrixWidth - 1) * moduleSize) - right; + const nudgedTooFarRight = left + /* (int) */Math.floor((matrixWidth - 1) * moduleSize) - right; if (nudgedTooFarRight > 0) { if (nudgedTooFarRight > nudge) { // Neither way fits; abort @@ -172,7 +194,7 @@ export default class QRCodeReader implements Reader { left -= nudgedTooFarRight; } // See logic above - const nudgedTooFarDown = top + /*(int) */Math.floor((matrixHeight - 1) * moduleSize) - bottom; + const nudgedTooFarDown = top + /* (int) */Math.floor((matrixHeight - 1) * moduleSize) - bottom; if (nudgedTooFarDown > 0) { if (nudgedTooFarDown > nudge) { // Neither way fits; abort @@ -184,9 +206,9 @@ export default class QRCodeReader implements Reader { // Now just read off the bits const bits = new BitMatrix(matrixWidth, matrixHeight); for (let y = 0; y < matrixHeight; y++) { - const iOffset = top + /*(int) */Math.floor(y * moduleSize); + const iOffset = top + /* (int) */Math.floor(y * moduleSize); for (let x = 0; x < matrixWidth; x++) { - if (image.get(left + /*(int) */Math.floor(x * moduleSize), iOffset)) { + if (image.get(left + /* (int) */Math.floor(x * moduleSize), iOffset)) { bits.set(x, y); } } @@ -194,9 +216,9 @@ export default class QRCodeReader implements Reader { return bits; } - private static moduleSize(leftTopBlack: Int32Array, image: BitMatrix): number/*float*/ /*throws NotFoundException */ { - const height: number /*int*/ = image.getHeight(); - const width: number /*int*/ = image.getWidth(); + private static moduleSize(leftTopBlack: Int32Array, image: BitMatrix): number/* float */ /* throws NotFoundException */ { + const height: number /* int */ = image.getHeight(); + const width: number /* int */ = image.getWidth(); let x = leftTopBlack[0]; let y = leftTopBlack[1]; let inBlack: boolean = true; diff --git a/src/core/qrcode/QRCodeWriter.ts b/src/core/qrcode/QRCodeWriter.ts index f3787c3d..29c10f66 100644 --- a/src/core/qrcode/QRCodeWriter.ts +++ b/src/core/qrcode/QRCodeWriter.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode {*/ +/* namespace com.google.zxing.qrcode { */ import BarcodeFormat from '../BarcodeFormat'; import EncodeHintType from '../EncodeHintType'; @@ -27,7 +27,7 @@ import QRCode from './encoder/QRCode'; import IllegalArgumentException from '../IllegalArgumentException'; import IllegalStateException from '../IllegalStateException'; -/*import java.util.Map;*/ +/* import java.util.Map; */ /** * This object renders a QR Code as a BitMatrix 2D array of greyscale values. @@ -36,83 +36,83 @@ import IllegalStateException from '../IllegalStateException'; */ export default class QRCodeWriter implements Writer { - private static QUIET_ZONE_SIZE = 4; + private static QUIET_ZONE_SIZE = 4; - /*@Override*/ - // public encode(contents: string, format: BarcodeFormat, width: number /*int*/, height: number /*int*/): BitMatrix - // /*throws WriterException */ { + /* @Override */ + // public encode(contents: string, format: BarcodeFormat, width: number /*int */, height: number /*int */): BitMatrix + // /*throws WriterException */ { - // return encode(contents, format, width, height, null) - // } + // return encode(contents, format, width, height, null) + // } - /*@Override*/ - public encode(contents: string, - format: BarcodeFormat, - width: number /*int*/, - height: number /*int*/, - hints: Map): BitMatrix /*throws WriterException */ { + /* @Override */ + public encode(contents: string, + format: BarcodeFormat, + width: number /* int */, + height: number /* int */, + hints: Map): BitMatrix /* throws WriterException */ { - if (contents.length === 0) { - throw new IllegalArgumentException('Found empty contents'); - } - - if (format !== BarcodeFormat.QR_CODE) { - throw new IllegalArgumentException('Can only encode QR_CODE, but got ' + format); - } + if (contents.length === 0) { + throw new IllegalArgumentException('Found empty contents'); + } - if (width < 0 || height < 0) { - throw new IllegalArgumentException(`Requested dimensions are too small: ${width}x${height}`); - } + if (format !== BarcodeFormat.QR_CODE) { + throw new IllegalArgumentException('Can only encode QR_CODE, but got ' + format); + } - let errorCorrectionLevel = ErrorCorrectionLevel.L; - let quietZone = QRCodeWriter.QUIET_ZONE_SIZE; - if (hints !== null) { - if (undefined !== hints.get(EncodeHintType.ERROR_CORRECTION)) { - errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType.ERROR_CORRECTION).toString()); - } - if (undefined !== hints.get(EncodeHintType.MARGIN)) { - quietZone = Number.parseInt(hints.get(EncodeHintType.MARGIN).toString(), 10); - } - } + if (width < 0 || height < 0) { + throw new IllegalArgumentException(`Requested dimensions are too small: ${width}x${height}`); + } - const code: QRCode = Encoder.encode(contents, errorCorrectionLevel, hints); - return QRCodeWriter.renderResult(code, width, height, quietZone); + let errorCorrectionLevel = ErrorCorrectionLevel.L; + let quietZone = QRCodeWriter.QUIET_ZONE_SIZE; + if (hints !== null) { + if (undefined !== hints.get(EncodeHintType.ERROR_CORRECTION)) { + errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType.ERROR_CORRECTION).toString()); + } + if (undefined !== hints.get(EncodeHintType.MARGIN)) { + quietZone = Number.parseInt(hints.get(EncodeHintType.MARGIN).toString(), 10); + } } - // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses - // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap). - private static renderResult(code: QRCode, width: number /*int*/, height: number /*int*/, quietZone: number /*int*/): BitMatrix { - const input = code.getMatrix(); - if (input === null) { - throw new IllegalStateException(); - } - const inputWidth = input.getWidth(); - const inputHeight = input.getHeight(); - const qrWidth = inputWidth + (quietZone * 2); - const qrHeight = inputHeight + (quietZone * 2); - const outputWidth = Math.max(width, qrWidth); - const outputHeight = Math.max(height, qrHeight); - - const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight)); - // Padding includes both the quiet zone and the extra white pixels to accommodate the requested - // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone. - // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will - // handle all the padding from 100x100 (the actual QR) up to 200x160. - const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2); - const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2); - - const output = new BitMatrix(outputWidth, outputHeight); - - for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++ , outputY += multiple) { - // Write the contents of this row of the barcode - for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++ , outputX += multiple) { - if (input.get(inputX, inputY) === 1) { - output.setRegion(outputX, outputY, multiple, multiple); - } - } - } + const code: QRCode = Encoder.encode(contents, errorCorrectionLevel, hints); + return QRCodeWriter.renderResult(code, width, height, quietZone); + } - return output; + // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses + // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap). + private static renderResult(code: QRCode, width: number /* int */, height: number /* int */, quietZone: number /* int */): BitMatrix { + const input = code.getMatrix(); + if (input === null) { + throw new IllegalStateException(); } + const inputWidth = input.getWidth(); + const inputHeight = input.getHeight(); + const qrWidth = inputWidth + (quietZone * 2); + const qrHeight = inputHeight + (quietZone * 2); + const outputWidth = Math.max(width, qrWidth); + const outputHeight = Math.max(height, qrHeight); + + const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight)); + // Padding includes both the quiet zone and the extra white pixels to accommodate the requested + // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone. + // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will + // handle all the padding from 100x100 (the actual QR) up to 200x160. + const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2); + const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2); + + const output = new BitMatrix(outputWidth, outputHeight); + + for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) { + // Write the contents of this row of the barcode + for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) { + if (input.get(inputX, inputY) === 1) { + output.setRegion(outputX, outputY, multiple, multiple); + } + } + } + + return output; + } } diff --git a/src/core/qrcode/decoder/BitMatrixParser.ts b/src/core/qrcode/decoder/BitMatrixParser.ts index 28dd828f..d94a50bb 100644 --- a/src/core/qrcode/decoder/BitMatrixParser.ts +++ b/src/core/qrcode/decoder/BitMatrixParser.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import BitMatrix from '../../common/BitMatrix'; import Version from './Version'; @@ -27,223 +27,223 @@ import FormatException from '../../FormatException'; */ export default class BitMatrixParser { - private bitMatrix: BitMatrix; - private parsedVersion: Version; - private parsedFormatInfo: FormatInformation; - private isMirror: boolean; - - /** - * @param bitMatrix {@link BitMatrix} to parse - * @throws FormatException if dimension is not >= 21 and 1 mod 4 - */ - public constructor(bitMatrix: BitMatrix) /*throws FormatException*/ { - const dimension = bitMatrix.getHeight(); - if (dimension < 21 || (dimension & 0x03) !== 1) { - throw new FormatException(); - } - this.bitMatrix = bitMatrix; - } - - /** - *

Reads format information from one of its two locations within the QR Code.

- * - * @return {@link FormatInformation} encapsulating the QR Code's format info - * @throws FormatException if both format information locations cannot be parsed as - * the valid encoding of format information - */ - public readFormatInformation(): FormatInformation /*throws FormatException*/ { + private bitMatrix: BitMatrix; + private parsedVersion: Version; + private parsedFormatInfo: FormatInformation; + private isMirror: boolean; - if (this.parsedFormatInfo !== null && this.parsedFormatInfo !== undefined) { - return this.parsedFormatInfo; - } + /** + * @param bitMatrix {@link BitMatrix} to parse + * @throws FormatException if dimension is not >= 21 and 1 mod 4 + */ + public constructor(bitMatrix: BitMatrix) /* throws FormatException */ { + const dimension = bitMatrix.getHeight(); + if (dimension < 21 || (dimension & 0x03) !== 1) { + throw new FormatException(); + } + this.bitMatrix = bitMatrix; + } + + /** + *

Reads format information from one of its two locations within the QR Code.

+ * + * @return {@link FormatInformation} encapsulating the QR Code's format info + * @throws FormatException if both format information locations cannot be parsed as + * the valid encoding of format information + */ + public readFormatInformation(): FormatInformation /* throws FormatException */ { - // Read top-left format info bits - let formatInfoBits1 = 0; - for (let i = 0; i < 6; i++) { - formatInfoBits1 = this.copyBit(i, 8, formatInfoBits1); - } - // .. and skip a bit in the timing pattern ... - formatInfoBits1 = this.copyBit(7, 8, formatInfoBits1); - formatInfoBits1 = this.copyBit(8, 8, formatInfoBits1); - formatInfoBits1 = this.copyBit(8, 7, formatInfoBits1); - // .. and skip a bit in the timing pattern ... - for (let j = 5; j >= 0; j--) { - formatInfoBits1 = this.copyBit(8, j, formatInfoBits1); - } + if (this.parsedFormatInfo !== null && this.parsedFormatInfo !== undefined) { + return this.parsedFormatInfo; + } - // Read the top-right/bottom-left pattern too - const dimension = this.bitMatrix.getHeight(); - let formatInfoBits2 = 0; - const jMin = dimension - 7; - for (let j = dimension - 1; j >= jMin; j--) { - formatInfoBits2 = this.copyBit(8, j, formatInfoBits2); - } - for (let i = dimension - 8; i < dimension; i++) { - formatInfoBits2 = this.copyBit(i, 8, formatInfoBits2); - } + // Read top-left format info bits + let formatInfoBits1 = 0; + for (let i = 0; i < 6; i++) { + formatInfoBits1 = this.copyBit(i, 8, formatInfoBits1); + } + // .. and skip a bit in the timing pattern ... + formatInfoBits1 = this.copyBit(7, 8, formatInfoBits1); + formatInfoBits1 = this.copyBit(8, 8, formatInfoBits1); + formatInfoBits1 = this.copyBit(8, 7, formatInfoBits1); + // .. and skip a bit in the timing pattern ... + for (let j = 5; j >= 0; j--) { + formatInfoBits1 = this.copyBit(8, j, formatInfoBits1); + } - this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2); - if (this.parsedFormatInfo !== null) { - return this.parsedFormatInfo; - } - throw new FormatException(); + // Read the top-right/bottom-left pattern too + const dimension = this.bitMatrix.getHeight(); + let formatInfoBits2 = 0; + const jMin = dimension - 7; + for (let j = dimension - 1; j >= jMin; j--) { + formatInfoBits2 = this.copyBit(8, j, formatInfoBits2); + } + for (let i = dimension - 8; i < dimension; i++) { + formatInfoBits2 = this.copyBit(i, 8, formatInfoBits2); } - /** - *

Reads version information from one of its two locations within the QR Code.

- * - * @return {@link Version} encapsulating the QR Code's version - * @throws FormatException if both version information locations cannot be parsed as - * the valid encoding of version information - */ - public readVersion(): Version /*throws FormatException*/ { + this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2); + if (this.parsedFormatInfo !== null) { + return this.parsedFormatInfo; + } + throw new FormatException(); + } + + /** + *

Reads version information from one of its two locations within the QR Code.

+ * + * @return {@link Version} encapsulating the QR Code's version + * @throws FormatException if both version information locations cannot be parsed as + * the valid encoding of version information + */ + public readVersion(): Version /* throws FormatException */ { - if (this.parsedVersion !== null && this.parsedVersion !== undefined) { - return this.parsedVersion; - } + if (this.parsedVersion !== null && this.parsedVersion !== undefined) { + return this.parsedVersion; + } - const dimension = this.bitMatrix.getHeight(); + const dimension = this.bitMatrix.getHeight(); - const provisionalVersion = Math.floor((dimension - 17) / 4); - if (provisionalVersion <= 6) { - return Version.getVersionForNumber(provisionalVersion); - } + const provisionalVersion = Math.floor((dimension - 17) / 4); + if (provisionalVersion <= 6) { + return Version.getVersionForNumber(provisionalVersion); + } - // Read top-right version info: 3 wide by 6 tall - let versionBits = 0; - const ijMin = dimension - 11; - for (let j = 5; j >= 0; j--) { - for (let i = dimension - 9; i >= ijMin; i--) { - versionBits = this.copyBit(i, j, versionBits); - } - } + // Read top-right version info: 3 wide by 6 tall + let versionBits = 0; + const ijMin = dimension - 11; + for (let j = 5; j >= 0; j--) { + for (let i = dimension - 9; i >= ijMin; i--) { + versionBits = this.copyBit(i, j, versionBits); + } + } - let theParsedVersion = Version.decodeVersionInformation(versionBits); - if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) { - this.parsedVersion = theParsedVersion; - return theParsedVersion; - } + let theParsedVersion = Version.decodeVersionInformation(versionBits); + if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) { + this.parsedVersion = theParsedVersion; + return theParsedVersion; + } - // Hmm, failed. Try bottom left: 6 wide by 3 tall - versionBits = 0; - for (let i = 5; i >= 0; i--) { - for (let j = dimension - 9; j >= ijMin; j--) { - versionBits = this.copyBit(i, j, versionBits); - } - } + // Hmm, failed. Try bottom left: 6 wide by 3 tall + versionBits = 0; + for (let i = 5; i >= 0; i--) { + for (let j = dimension - 9; j >= ijMin; j--) { + versionBits = this.copyBit(i, j, versionBits); + } + } - theParsedVersion = Version.decodeVersionInformation(versionBits); - if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) { - this.parsedVersion = theParsedVersion; - return theParsedVersion; - } - throw new FormatException(); - } - - private copyBit(i: number /*int*/, j: number /*int*/, versionBits: number /*int*/): number /*int*/ { - const bit: boolean = this.isMirror ? this.bitMatrix.get(j, i) : this.bitMatrix.get(i, j); - return bit ? (versionBits << 1) | 0x1 : versionBits << 1; - } - - /** - *

Reads the bits in the {@link BitMatrix} representing the finder pattern in the - * correct order in order to reconstruct the codewords bytes contained within the - * QR Code.

- * - * @return bytes encoded within the QR Code - * @throws FormatException if the exact number of bytes expected is not read - */ - public readCodewords(): Uint8Array /*throws FormatException*/ { - - const formatInfo = this.readFormatInformation(); - const version = this.readVersion(); - - // Get the data mask for the format used in this QR Code. This will exclude - // some bits from reading as we wind through the bit matrix. - const dataMask = DataMask.values.get(formatInfo.getDataMask()); - const dimension = this.bitMatrix.getHeight(); - dataMask.unmaskBitMatrix(this.bitMatrix, dimension); - - const functionPattern = version.buildFunctionPattern(); - - let readingUp: boolean = true; - const result = new Uint8Array(version.getTotalCodewords()); - let resultOffset = 0; - let currentByte = 0; - let bitsRead = 0; - // Read columns in pairs, from right to left - for (let j = dimension - 1; j > 0; j -= 2) { - if (j === 6) { - // Skip whole column with vertical alignment pattern - // saves time and makes the other code proceed more cleanly - j--; + theParsedVersion = Version.decodeVersionInformation(versionBits); + if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) { + this.parsedVersion = theParsedVersion; + return theParsedVersion; + } + throw new FormatException(); + } + + private copyBit(i: number /* int */, j: number /* int */, versionBits: number /* int */): number /* int */ { + const bit: boolean = this.isMirror ? this.bitMatrix.get(j, i) : this.bitMatrix.get(i, j); + return bit ? (versionBits << 1) | 0x1 : versionBits << 1; + } + + /** + *

Reads the bits in the {@link BitMatrix} representing the finder pattern in the + * correct order in order to reconstruct the codewords bytes contained within the + * QR Code.

+ * + * @return bytes encoded within the QR Code + * @throws FormatException if the exact number of bytes expected is not read + */ + public readCodewords(): Uint8Array /* throws FormatException */ { + + const formatInfo = this.readFormatInformation(); + const version = this.readVersion(); + + // Get the data mask for the format used in this QR Code. This will exclude + // some bits from reading as we wind through the bit matrix. + const dataMask = DataMask.values.get(formatInfo.getDataMask()); + const dimension = this.bitMatrix.getHeight(); + dataMask.unmaskBitMatrix(this.bitMatrix, dimension); + + const functionPattern = version.buildFunctionPattern(); + + let readingUp: boolean = true; + const result = new Uint8Array(version.getTotalCodewords()); + let resultOffset = 0; + let currentByte = 0; + let bitsRead = 0; + // Read columns in pairs, from right to left + for (let j = dimension - 1; j > 0; j -= 2) { + if (j === 6) { + // Skip whole column with vertical alignment pattern + // saves time and makes the other code proceed more cleanly + j--; + } + // Read alternatingly from bottom to top then top to bottom + for (let count = 0; count < dimension; count++) { + const i = readingUp ? dimension - 1 - count : count; + for (let col = 0; col < 2; col++) { + // Ignore bits covered by the function pattern + if (!functionPattern.get(j - col, i)) { + // Read a bit + bitsRead++; + currentByte <<= 1; + if (this.bitMatrix.get(j - col, i)) { + currentByte |= 1; } - // Read alternatingly from bottom to top then top to bottom - for (let count = 0; count < dimension; count++) { - const i = readingUp ? dimension - 1 - count : count; - for (let col = 0; col < 2; col++) { - // Ignore bits covered by the function pattern - if (!functionPattern.get(j - col, i)) { - // Read a bit - bitsRead++; - currentByte <<= 1; - if (this.bitMatrix.get(j - col, i)) { - currentByte |= 1; - } - // If we've made a whole byte, save it off - if (bitsRead === 8) { - result[resultOffset++] = /*(byte) */currentByte; - bitsRead = 0; - currentByte = 0; - } - } - } + // If we've made a whole byte, save it off + if (bitsRead === 8) { + result[resultOffset++] = /* (byte) */currentByte; + bitsRead = 0; + currentByte = 0; } - readingUp = !readingUp; // readingUp ^= true; // readingUp = !readingUp; // switch directions - } - if (resultOffset !== version.getTotalCodewords()) { - throw new FormatException(); + } } - return result; + } + readingUp = !readingUp; // readingUp ^= true; // readingUp = !readingUp; // switch directions + } + if (resultOffset !== version.getTotalCodewords()) { + throw new FormatException(); } + return result; + } - /** - * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state. - */ - public remask(): void { - if (this.parsedFormatInfo === null) { - return; // We have no format information, and have no data mask - } - const dataMask = DataMask.values[this.parsedFormatInfo.getDataMask()]; - const dimension = this.bitMatrix.getHeight(); - dataMask.unmaskBitMatrix(this.bitMatrix, dimension); - } - - /** - * Prepare the parser for a mirrored operation. - * This flag has effect only on the {@link #readFormatInformation()} and the - * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the - * {@link #mirror()} method should be called. - * - * @param mirror Whether to read version and format information mirrored. - */ - public setMirror(isMirror: boolean): void { - this.parsedVersion = null; - this.parsedFormatInfo = null; - this.isMirror = isMirror; - } - - /** Mirror the bit matrix in order to attempt a second reading. */ - public mirror(): void { - const bitMatrix = this.bitMatrix; - for (let x = 0, width = bitMatrix.getWidth(); x < width; x++) { - for (let y = x + 1, height = bitMatrix.getHeight(); y < height; y++) { - if (bitMatrix.get(x, y) !== bitMatrix.get(y, x)) { - bitMatrix.flip(y, x); - bitMatrix.flip(x, y); - } - } - } +/** + * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state. + */ + public remask(): void { + if (this.parsedFormatInfo === null) { + return; // We have no format information, and have no data mask + } + const dataMask = DataMask.values.get(this.parsedFormatInfo.getDataMask()); + const dimension = this.bitMatrix.getHeight(); + dataMask.unmaskBitMatrix(this.bitMatrix, dimension); + } + + /** + * Prepare the parser for a mirrored operation. + * This flag has effect only on the {@link #readFormatInformation()} and the + * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the + * {@link #mirror()} method should be called. + * + * @param mirror Whether to read version and format information mirrored. + */ + public setMirror(isMirror: boolean): void { + this.parsedVersion = null; + this.parsedFormatInfo = null; + this.isMirror = isMirror; + } + + /** Mirror the bit matrix in order to attempt a second reading. */ + public mirror(): void { + const bitMatrix = this.bitMatrix; + for (let x = 0, width = bitMatrix.getWidth(); x < width; x++) { + for (let y = x + 1, height = bitMatrix.getHeight(); y < height; y++) { + if (bitMatrix.get(x, y) !== bitMatrix.get(y, x)) { + bitMatrix.flip(y, x); + bitMatrix.flip(x, y); + } + } } + } } diff --git a/src/core/qrcode/decoder/DataBlock.ts b/src/core/qrcode/decoder/DataBlock.ts index beb0b6e5..8e43a457 100644 --- a/src/core/qrcode/decoder/DataBlock.ts +++ b/src/core/qrcode/decoder/DataBlock.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import Version from './Version'; import ECBlocks from './ECBlocks'; @@ -32,93 +32,93 @@ import IllegalArgumentException from '../../IllegalArgumentException'; */ export default class DataBlock { - private constructor(private numDataCodewords: number /*int*/, private codewords: Uint8Array) { } + private constructor(private numDataCodewords: number /* int */, private codewords: Uint8Array) { } - /** - *

When QR Codes use multiple data blocks, they are actually interleaved. - * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This - * method will separate the data into original blocks.

- * - * @param rawCodewords bytes as read directly from the QR Code - * @param version version of the QR Code - * @param ecLevel error-correction level of the QR Code - * @return DataBlocks containing original bytes, "de-interleaved" from representation in the - * QR Code - */ - public static getDataBlocks(rawCodewords: Uint8Array, - version: Version, - ecLevel: ErrorCorrectionLevel): DataBlock[] { - - if (rawCodewords.length !== version.getTotalCodewords()) { - throw new IllegalArgumentException(); - } - - // Figure out the number and size of data blocks used by this version and - // error correction level - const ecBlocks: ECBlocks = version.getECBlocksForLevel(ecLevel); + /** + *

When QR Codes use multiple data blocks, they are actually interleaved. + * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This + * method will separate the data into original blocks.

+ * + * @param rawCodewords bytes as read directly from the QR Code + * @param version version of the QR Code + * @param ecLevel error-correction level of the QR Code + * @return DataBlocks containing original bytes, "de-interleaved" from representation in the + * QR Code + */ + public static getDataBlocks(rawCodewords: Uint8Array, + version: Version, + ecLevel: ErrorCorrectionLevel): DataBlock[] { - // First count the total number of data blocks - let totalBlocks = 0; - const ecBlockArray: ECB[] = ecBlocks.getECBlocks(); - for (const ecBlock of ecBlockArray) { - totalBlocks += ecBlock.getCount(); - } + if (rawCodewords.length !== version.getTotalCodewords()) { + throw new IllegalArgumentException(); + } - // Now establish DataBlocks of the appropriate size and number of data codewords - const result = new Array(totalBlocks); - let numResultBlocks = 0; - for (const ecBlock of ecBlockArray) { - for (let i = 0; i < ecBlock.getCount(); i++) { - const numDataCodewords = ecBlock.getDataCodewords(); - const numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords; - result[numResultBlocks++] = new DataBlock(numDataCodewords, new Uint8Array(numBlockCodewords)); - } - } + // Figure out the number and size of data blocks used by this version and + // error correction level + const ecBlocks: ECBlocks = version.getECBlocksForLevel(ecLevel); - // All blocks have the same amount of data, except that the last n - // (where n may be 0) have 1 more byte. Figure out where these start. - const shorterBlocksTotalCodewords = result[0].codewords.length; - let longerBlocksStartAt = result.length - 1; - // TYPESCRIPTPORT: check length is correct here - while (longerBlocksStartAt >= 0) { - const numCodewords = result[longerBlocksStartAt].codewords.length; - if (numCodewords === shorterBlocksTotalCodewords) { - break; - } - longerBlocksStartAt--; - } - longerBlocksStartAt++; + // First count the total number of data blocks + let totalBlocks = 0; + const ecBlockArray: ECB[] = ecBlocks.getECBlocks(); + for (const ecBlock of ecBlockArray) { + totalBlocks += ecBlock.getCount(); + } - const shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock(); - // The last elements of result may be 1 element longer - // first fill out as many elements as all of them have - let rawCodewordsOffset = 0; - for (let i = 0; i < shorterBlocksNumDataCodewords; i++) { - for (let j = 0; j < numResultBlocks; j++) { - result[j].codewords[i] = rawCodewords[rawCodewordsOffset++]; - } - } - // Fill out the last data block in the longer ones - for (let j = longerBlocksStartAt; j < numResultBlocks; j++) { - result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++]; - } - // Now add in error correction blocks - const max = result[0].codewords.length; - for (let i = shorterBlocksNumDataCodewords; i < max; i++) { - for (let j = 0; j < numResultBlocks; j++) { - const iOffset = j < longerBlocksStartAt ? i : i + 1; - result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++]; - } - } - return result; + // Now establish DataBlocks of the appropriate size and number of data codewords + const result = new Array(totalBlocks); + let numResultBlocks = 0; + for (const ecBlock of ecBlockArray) { + for (let i = 0; i < ecBlock.getCount(); i++) { + const numDataCodewords = ecBlock.getDataCodewords(); + const numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords; + result[numResultBlocks++] = new DataBlock(numDataCodewords, new Uint8Array(numBlockCodewords)); + } } - public getNumDataCodewords(): number /*int*/ { - return this.numDataCodewords; + // All blocks have the same amount of data, except that the last n + // (where n may be 0) have 1 more byte. Figure out where these start. + const shorterBlocksTotalCodewords = result[0].codewords.length; + let longerBlocksStartAt = result.length - 1; + // TYPESCRIPTPORT: check length is correct here + while (longerBlocksStartAt >= 0) { + const numCodewords = result[longerBlocksStartAt].codewords.length; + if (numCodewords === shorterBlocksTotalCodewords) { + break; + } + longerBlocksStartAt--; } + longerBlocksStartAt++; - public getCodewords(): Uint8Array { - return this.codewords; + const shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock(); + // The last elements of result may be 1 element longer + // first fill out as many elements as all of them have + let rawCodewordsOffset = 0; + for (let i = 0; i < shorterBlocksNumDataCodewords; i++) { + for (let j = 0; j < numResultBlocks; j++) { + result[j].codewords[i] = rawCodewords[rawCodewordsOffset++]; + } } + // Fill out the last data block in the longer ones + for (let j = longerBlocksStartAt; j < numResultBlocks; j++) { + result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++]; + } + // Now add in error correction blocks + const max = result[0].codewords.length; + for (let i = shorterBlocksNumDataCodewords; i < max; i++) { + for (let j = 0; j < numResultBlocks; j++) { + const iOffset = j < longerBlocksStartAt ? i : i + 1; + result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++]; + } + } + return result; + } + + public getNumDataCodewords(): number /* int */ { + return this.numDataCodewords; + } + + public getCodewords(): Uint8Array { + return this.codewords; + } } diff --git a/src/core/qrcode/decoder/DataMask.ts b/src/core/qrcode/decoder/DataMask.ts index c70792f0..a6373531 100644 --- a/src/core/qrcode/decoder/DataMask.ts +++ b/src/core/qrcode/decoder/DataMask.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import BitMatrix from '../../common/BitMatrix'; @@ -50,46 +50,62 @@ export default class DataMask { public static values = new Map([ /** * 000: mask bits for which (x + y) mod 2 == 0 - */ - [DataMaskValues.DATA_MASK_000, new DataMask(DataMaskValues.DATA_MASK_000, (i: number /*int*/, j: number /*int*/) => { return ((i + j) & 0x01) === 0; })], + */ + [DataMaskValues.DATA_MASK_000, new DataMask(DataMaskValues.DATA_MASK_000, (i: number /* int */, j: number /* int */) => { + return ((i + j) & 0x01) === 0; + })], /** * 001: mask bits for which x mod 2 == 0 - */ - [DataMaskValues.DATA_MASK_001, new DataMask(DataMaskValues.DATA_MASK_001, (i: number /*int*/, j: number /*int*/) => { return (i & 0x01) === 0; })], + */ + [DataMaskValues.DATA_MASK_001, new DataMask(DataMaskValues.DATA_MASK_001, (i: number /* int */, j: number /* int */) => { + return (i & 0x01) === 0; + })], /** * 010: mask bits for which y mod 3 == 0 - */ - [DataMaskValues.DATA_MASK_010, new DataMask(DataMaskValues.DATA_MASK_010, (i: number /*int*/, j: number /*int*/) => { return j % 3 === 0; })], + */ + [DataMaskValues.DATA_MASK_010, new DataMask(DataMaskValues.DATA_MASK_010, (i: number /* int */, j: number /* int */) => { + return j % 3 === 0; + })], /** * 011: mask bits for which (x + y) mod 3 == 0 - */ - [DataMaskValues.DATA_MASK_011, new DataMask(DataMaskValues.DATA_MASK_011, (i: number /*int*/, j: number /*int*/) => { return (i + j) % 3 === 0; })], + */ + [DataMaskValues.DATA_MASK_011, new DataMask(DataMaskValues.DATA_MASK_011, (i: number /* int */, j: number /* int */) => { + return (i + j) % 3 === 0; + })], /** * 100: mask bits for which (x/2 + y/3) mod 2 == 0 - */ - [DataMaskValues.DATA_MASK_100, new DataMask(DataMaskValues.DATA_MASK_100, (i: number /*int*/, j: number /*int*/) => { return ((Math.floor(i / 2) + Math.floor(j / 3)) & 0x01) === 0; })], + */ + [DataMaskValues.DATA_MASK_100, new DataMask(DataMaskValues.DATA_MASK_100, (i: number /* int */, j: number /* int */) => { + return ((Math.floor(i / 2) + Math.floor(j / 3)) & 0x01) === 0; + })], /** * 101: mask bits for which xy mod 2 + xy mod 3 == 0 * equivalently, such that xy mod 6 == 0 - */ - [DataMaskValues.DATA_MASK_101, new DataMask(DataMaskValues.DATA_MASK_101, (i: number /*int*/, j: number /*int*/) => { return (i * j) % 6 === 0; })], + */ + [DataMaskValues.DATA_MASK_101, new DataMask(DataMaskValues.DATA_MASK_101, (i: number /* int */, j: number /* int */) => { + return (i * j) % 6 === 0; + })], /** * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0 * equivalently, such that xy mod 6 < 3 - */ - [DataMaskValues.DATA_MASK_110, new DataMask(DataMaskValues.DATA_MASK_110, (i: number /*int*/, j: number /*int*/) => { return ((i * j) % 6) < 3; })], + */ + [DataMaskValues.DATA_MASK_110, new DataMask(DataMaskValues.DATA_MASK_110, (i: number /* int */, j: number /* int */) => { + return ((i * j) % 6) < 3; + })], /** * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0 * equivalently, such that (x + y + xy mod 3) mod 2 == 0 - */ - [DataMaskValues.DATA_MASK_111, new DataMask(DataMaskValues.DATA_MASK_111, (i: number /*int*/, j: number /*int*/) => { return ((i + j + ((i * j) % 3)) & 0x01) === 0; })], + */ + [DataMaskValues.DATA_MASK_111, new DataMask(DataMaskValues.DATA_MASK_111, (i: number /* int */, j: number /* int */) => { + return ((i + j + ((i * j) % 3)) & 0x01) === 0; + })], ]); // End of enum constants. @@ -101,8 +117,8 @@ export default class DataMask { * * @param bits representation of QR Code bits * @param dimension dimension of QR Code, represented by bits, being unmasked - */ - public unmaskBitMatrix(bits: BitMatrix, dimension: number /*int*/): void { + */ + public unmaskBitMatrix(bits: BitMatrix, dimension: number /* int */): void { for (let i = 0; i < dimension; i++) { for (let j = 0; j < dimension; j++) { if (this.isMasked(i, j)) { @@ -112,6 +128,6 @@ export default class DataMask { } } - // abstract boolean isMasked(i: number /*int*/, j: number /*int*/); + // abstract boolean isMasked(i: number /*int */, j: number /*int */); } diff --git a/src/core/qrcode/decoder/DecodedBitStreamParser.ts b/src/core/qrcode/decoder/DecodedBitStreamParser.ts index b0a6e56f..05190e07 100644 --- a/src/core/qrcode/decoder/DecodedBitStreamParser.ts +++ b/src/core/qrcode/decoder/DecodedBitStreamParser.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import BitSource from '../../common/BitSource'; import CharacterSetECI from '../../common/CharacterSetECI'; @@ -29,11 +29,11 @@ import Mode from './Mode'; import Version from './Version'; -/*import java.io.UnsupportedEncodingException;*/ -/*import java.util.ArrayList;*/ -/*import java.util.Collection;*/ -/*import java.util.List;*/ -/*import java.util.Map;*/ +/* import java.io.UnsupportedEncodingException; */ +/* import java.util.ArrayList; */ +/* import java.util.Collection; */ +/* import java.util.List; */ +/* import java.util.Map; */ /** *

QR Codes can encode text as bits in one of several modes, and can use multiple modes @@ -47,15 +47,15 @@ export default class DecodedBitStreamParser { /** * See ISO 18004:2006, 6.4.4 Table 5 - */ + */ private static ALPHANUMERIC_CHARS = - '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'; + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'; private static GB2312_SUBSET = 1; public static decode(bytes: Uint8Array, version: Version, ecLevel: ErrorCorrectionLevel, - hints: Map): DecoderResult /*throws FormatException*/ { + hints: Map): DecoderResult /* throws FormatException */ { const bits = new BitSource(bytes); let result = new StringBuilder(); const byteSegments = new Array(); // 1 @@ -133,7 +133,7 @@ export default class DecodedBitStreamParser { break; } } while (mode !== Mode.TERMINATOR); - } catch (iae/*: IllegalArgumentException*/) { + } catch (iae/* : IllegalArgumentException */) { // from readBits() calls throw new FormatException(); } @@ -148,10 +148,10 @@ export default class DecodedBitStreamParser { /** * See specification GBT 18284-2000 - */ + */ private static decodeHanziSegment(bits: BitSource, result: StringBuilder, - count: number /*int*/): void /*throws FormatException*/ { + count: number /* int */): void /* throws FormatException */ { // Don't crash trying to read more bits than we have available. if (count * 13 > bits.available()) { throw new FormatException(); @@ -172,8 +172,8 @@ export default class DecodedBitStreamParser { // In the 0xB0A1 to 0xFAFE range assembledTwoBytes += 0x0A6A1; } - buffer[offset] = /*(byte) */((assembledTwoBytes >> 8) & 0xFF); - buffer[offset + 1] = /*(byte) */(assembledTwoBytes & 0xFF); + buffer[offset] = /* (byte) */((assembledTwoBytes >> 8) & 0xFF); + buffer[offset + 1] = /* (byte) */(assembledTwoBytes & 0xFF); offset += 2; count--; } @@ -181,14 +181,14 @@ export default class DecodedBitStreamParser { try { result.append(StringEncoding.decode(buffer, StringUtils.GB2312)); // TYPESCRIPTPORT: TODO: implement GB2312 decode. StringView from MDN could be a starting point - } catch (ignored/*: UnsupportedEncodingException*/) { + } catch (ignored/* : UnsupportedEncodingException */) { throw new FormatException(ignored); } } private static decodeKanjiSegment(bits: BitSource, result: StringBuilder, - count: number /*int*/): void /*throws FormatException*/ { + count: number /* int */): void /* throws FormatException */ { // Don't crash trying to read more bits than we have available. if (count * 13 > bits.available()) { throw new FormatException(); @@ -209,8 +209,8 @@ export default class DecodedBitStreamParser { // In the 0xE040 to 0xEBBF range assembledTwoBytes += 0x0C140; } - buffer[offset] = /*(byte) */(assembledTwoBytes >> 8); - buffer[offset + 1] = /*(byte) */assembledTwoBytes; + buffer[offset] = /* (byte) */(assembledTwoBytes >> 8); + buffer[offset + 1] = /* (byte) */assembledTwoBytes; offset += 2; count--; } @@ -218,17 +218,17 @@ export default class DecodedBitStreamParser { try { result.append(StringEncoding.decode(buffer, StringUtils.SHIFT_JIS)); // TYPESCRIPTPORT: TODO: implement SHIFT_JIS decode. StringView from MDN could be a starting point - } catch (ignored/*: UnsupportedEncodingException*/) { + } catch (ignored/* : UnsupportedEncodingException */) { throw new FormatException(ignored); } } private static decodeByteSegment(bits: BitSource, result: StringBuilder, - count: number /*int*/, + count: number /* int */, currentCharacterSetECI: CharacterSetECI, byteSegments: Uint8Array[], - hints: Map): void /*throws FormatException*/ { + hints: Map): void /* throws FormatException */ { // Don't crash trying to read more bits than we have available. if (8 * count > bits.available()) { throw new FormatException(); @@ -236,7 +236,7 @@ export default class DecodedBitStreamParser { const readBytes = new Uint8Array(count); for (let i = 0; i < count; i++) { - readBytes[i] = /*(byte) */bits.readBits(8); + readBytes[i] = /* (byte) */bits.readBits(8); } let encoding: string; if (currentCharacterSetECI === null) { @@ -251,13 +251,13 @@ export default class DecodedBitStreamParser { } try { result.append(StringEncoding.decode(readBytes, encoding)); - } catch (ignored/*: UnsupportedEncodingException*/) { + } catch (ignored/* : UnsupportedEncodingException */) { throw new FormatException(ignored); } byteSegments.push(readBytes); } - private static toAlphaNumericChar(value: number /*int*/): string /*throws FormatException*/ { + private static toAlphaNumericChar(value: number /* int */): string /* throws FormatException */ { if (value >= DecodedBitStreamParser.ALPHANUMERIC_CHARS.length) { throw new FormatException(); } @@ -266,8 +266,8 @@ export default class DecodedBitStreamParser { private static decodeAlphanumericSegment(bits: BitSource, result: StringBuilder, - count: number /*int*/, - fc1InEffect: boolean): void /*throws FormatException*/ { + count: number /* int */, + fc1InEffect: boolean): void /* throws FormatException */ { // Read two characters at a time const start = result.length(); while (count > 1) { @@ -305,7 +305,7 @@ export default class DecodedBitStreamParser { private static decodeNumericSegment(bits: BitSource, result: StringBuilder, - count: number /*int*/): void /*throws FormatException*/ { + count: number /* int */): void /* throws FormatException */ { // Read three digits at a time while (count >= 3) { // Each 10 bits encodes three digits @@ -345,7 +345,7 @@ export default class DecodedBitStreamParser { } } - private static parseECIValue(bits: BitSource): number /*int*/ /*throws FormatException*/ { + private static parseECIValue(bits: BitSource): number /* int */ /* throws FormatException */ { const firstByte = bits.readBits(8); if ((firstByte & 0x80) === 0) { // just one byte diff --git a/src/core/qrcode/decoder/Decoder.ts b/src/core/qrcode/decoder/Decoder.ts index 7a5a9264..c172699d 100644 --- a/src/core/qrcode/decoder/Decoder.ts +++ b/src/core/qrcode/decoder/Decoder.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import ChecksumException from '../../ChecksumException'; import BitMatrix from '../../common/BitMatrix'; @@ -28,7 +28,7 @@ import DecodedBitStreamParser from './DecodedBitStreamParser'; import QRCodeDecoderMetaData from './QRCodeDecoderMetaData'; -/*import java.util.Map;*/ +/* import java.util.Map; */ /** *

The main class which implements QR Code decoding -- as opposed to locating and extracting @@ -44,7 +44,7 @@ export default class Decoder { this.rsDecoder = new ReedSolomonDecoder(GenericGF.QR_CODE_FIELD_256); } - // public decode(image: boolean[][]): DecoderResult /*throws ChecksumException, FormatException*/ { + // public decode(image: boolean[][]): DecoderResult /*throws ChecksumException, FormatException */ { // return decode(image, null) // } @@ -57,12 +57,12 @@ export default class Decoder { * @return text and bytes encoded within the QR Code * @throws FormatException if the QR Code cannot be decoded * @throws ChecksumException if error correction fails - */ + */ public decodeBooleanArray(image: boolean[][], hints?: Map): DecoderResult { return this.decodeBitMatrix(BitMatrix.parseFromBooleanArray(image), hints); } - // public decodeBitMatrix(bits: BitMatrix): DecoderResult /*throws ChecksumException, FormatException*/ { + // public decodeBitMatrix(bits: BitMatrix): DecoderResult /*throws ChecksumException, FormatException */ { // return decode(bits, null) // } @@ -74,6 +74,7 @@ export default class Decoder { * @return text and bytes encoded within the QR Code * @throws FormatException if the QR Code cannot be decoded * @throws ChecksumException if error correction fails + * @override decode */ public decodeBitMatrix(bits: BitMatrix, hints?: Map): DecoderResult { @@ -82,7 +83,7 @@ export default class Decoder { let ex = null; try { return this.decodeBitMatrixParser(parser, hints); - } catch (e/*: FormatException, ChecksumException*/) { + } catch (e/* : FormatException, ChecksumException */) { ex = e; } @@ -105,7 +106,7 @@ export default class Decoder { * of version and format information when mirrored. This is a good sign, * that the QR code may be mirrored, and we should try once more with a * mirrored content. - */ + */ // Prepare for a mirrored reading. parser.mirror(); @@ -116,7 +117,7 @@ export default class Decoder { return result; - } catch (e/*FormatException | ChecksumException*/) { + } catch (e/* FormatException | ChecksumException */) { // Throw the exception from the original reading if (ex !== null) { throw ex; @@ -164,8 +165,8 @@ export default class Decoder { * @param codewordBytes data and error correction codewords * @param numDataCodewords number of codewords that are data bytes * @throws ChecksumException if error correction fails - */ - private correctErrors(codewordBytes: Uint8Array, numDataCodewords: number /*int*/): void /*throws ChecksumException*/ { + */ + private correctErrors(codewordBytes: Uint8Array, numDataCodewords: number /* int */): void /* throws ChecksumException */ { // const numCodewords = codewordBytes.length; // First read into an array of ints const codewordsInts = new Int32Array(codewordBytes); @@ -176,13 +177,13 @@ export default class Decoder { // } try { this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords); - } catch (ignored/*: ReedSolomonException*/) { + } catch (ignored/* : ReedSolomonException */) { throw new ChecksumException(); } // Copy back into array of bytes -- only need to worry about the bytes that were data // We don't care about errors in the error-correction codewords for (let i = 0; i < numDataCodewords; i++) { - codewordBytes[i] = /*(byte) */codewordsInts[i]; + codewordBytes[i] = /* (byte) */codewordsInts[i]; } } diff --git a/src/core/qrcode/decoder/ECB.ts b/src/core/qrcode/decoder/ECB.ts index f7e7e2bb..0710b2ed 100644 --- a/src/core/qrcode/decoder/ECB.ts +++ b/src/core/qrcode/decoder/ECB.ts @@ -4,19 +4,19 @@ * parameters is used consecutively in the QR code version's format.

*/ export default class ECB { - private count: number; /*int*/ - private dataCodewords: number; /*int*/ + private count: number; /* int */ + private dataCodewords: number; /* int */ - public constructor(count: number /*int*/, dataCodewords: number /*int*/) { - this.count = count; - this.dataCodewords = dataCodewords; - } + public constructor(count: number /* int */, dataCodewords: number /* int */) { + this.count = count; + this.dataCodewords = dataCodewords; + } - public getCount(): number /*int*/ { - return this.count; - } + public getCount(): number /* int */ { + return this.count; + } - public getDataCodewords(): number /*int*/ { - return this.dataCodewords; - } + public getDataCodewords(): number /* int */ { + return this.dataCodewords; + } } diff --git a/src/core/qrcode/decoder/ECBlocks.ts b/src/core/qrcode/decoder/ECBlocks.ts index fc7ffe2f..3f84cc7e 100644 --- a/src/core/qrcode/decoder/ECBlocks.ts +++ b/src/core/qrcode/decoder/ECBlocks.ts @@ -7,30 +7,30 @@ import ECB from './ECB'; * will be the same across all blocks within one version.

*/ export default class ECBlocks { - private ecBlocks: ECB[]; + private ecBlocks: ECB[]; - public constructor(private ecCodewordsPerBlock: number /*int*/, ...ecBlocks: ECB[]) { - this.ecBlocks = ecBlocks; - } + public constructor(private ecCodewordsPerBlock: number /* int */, ...ecBlocks: ECB[]) { + this.ecBlocks = ecBlocks; + } - public getECCodewordsPerBlock(): number /*int*/ { - return this.ecCodewordsPerBlock; - } + public getECCodewordsPerBlock(): number /* int */ { + return this.ecCodewordsPerBlock; + } - public getNumBlocks(): number /*int*/ { - let total = 0; - const ecBlocks = this.ecBlocks; - for (const ecBlock of ecBlocks) { - total += ecBlock.getCount(); - } - return total; + public getNumBlocks(): number /* int */ { + let total = 0; + const ecBlocks = this.ecBlocks; + for (const ecBlock of ecBlocks) { + total += ecBlock.getCount(); } + return total; + } - public getTotalECCodewords(): number /*int*/ { - return this.ecCodewordsPerBlock * this.getNumBlocks(); - } + public getTotalECCodewords(): number /* int */ { + return this.ecCodewordsPerBlock * this.getNumBlocks(); + } - public getECBlocks(): ECB[] { - return this.ecBlocks; - } + public getECBlocks(): ECB[] { + return this.ecBlocks; + } } diff --git a/src/core/qrcode/decoder/ErrorCorrectionLevel.ts b/src/core/qrcode/decoder/ErrorCorrectionLevel.ts index b63a1f02..695b402a 100644 --- a/src/core/qrcode/decoder/ErrorCorrectionLevel.ts +++ b/src/core/qrcode/decoder/ErrorCorrectionLevel.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import ArgumentException from '../../ArgumentException'; import IllegalArgumentException from '../../IllegalArgumentException'; export enum ErrorCorrectionLevelValues { - L, - M, - Q, - H + L, + M, + Q, + H } /** @@ -35,61 +35,61 @@ export enum ErrorCorrectionLevelValues { */ export default class ErrorCorrectionLevel { - private static FOR_BITS = new Map(); - private static FOR_VALUE = new Map(); + private static FOR_BITS = new Map(); + private static FOR_VALUE = new Map(); - /** L = ~7% correction */ - public static L = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.L, 'L', 0x01); - /** M = ~15% correction */ - public static M = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.M, 'M', 0x00); - /** Q = ~25% correction */ - public static Q = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.Q, 'Q', 0x03); - /** H = ~30% correction */ - public static H = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.H, 'H', 0x02); + /** L = ~7% correction */ + public static L = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.L, 'L', 0x01); + /** M = ~15% correction */ + public static M = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.M, 'M', 0x00); + /** Q = ~25% correction */ + public static Q = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.Q, 'Q', 0x03); + /** H = ~30% correction */ + public static H = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.H, 'H', 0x02); - private constructor(private value: ErrorCorrectionLevelValues, private stringValue: string, private bits: number /*int*/) { - ErrorCorrectionLevel.FOR_BITS.set(bits, this); - ErrorCorrectionLevel.FOR_VALUE.set(value, this); - } + private constructor(private value: ErrorCorrectionLevelValues, private stringValue: string, private bits: number /* int */) { + ErrorCorrectionLevel.FOR_BITS.set(bits, this); + ErrorCorrectionLevel.FOR_VALUE.set(value, this); + } - public getValue(): ErrorCorrectionLevelValues/*int*/ { - return this.value; - } + public getValue(): ErrorCorrectionLevelValues/* int */ { + return this.value; + } - public getBits(): number /*int*/ { - return this.bits; - } + public getBits(): number /* int */ { + return this.bits; + } - public static fromString(s: string): ErrorCorrectionLevel { - switch (s) { - case 'L': return ErrorCorrectionLevel.L; - case 'M': return ErrorCorrectionLevel.M; - case 'Q': return ErrorCorrectionLevel.Q; - case 'H': return ErrorCorrectionLevel.H; - default: throw new ArgumentException(s + 'not available'); - } + public static fromString(s: string): ErrorCorrectionLevel { + switch (s) { + case 'L': return ErrorCorrectionLevel.L; + case 'M': return ErrorCorrectionLevel.M; + case 'Q': return ErrorCorrectionLevel.Q; + case 'H': return ErrorCorrectionLevel.H; + default: throw new ArgumentException(s + 'not available'); } + } - public toString(): string { - return this.stringValue; - } + public toString(): string { + return this.stringValue; + } - public equals(o: any): boolean { - if (!(o instanceof ErrorCorrectionLevel)) { - return false; - } - const other = o; - return this.value === other.value; + public equals(o: any): boolean { + if (!(o instanceof ErrorCorrectionLevel)) { + return false; } - /** - * @param bits int containing the two bits encoding a QR Code's error correction level - * @return ErrorCorrectionLevel representing the encoded error correction level - */ - public static forBits(bits: number /*int*/): ErrorCorrectionLevel { - if (bits < 0 || bits >= ErrorCorrectionLevel.FOR_BITS.size) { - throw new IllegalArgumentException(); - } - return ErrorCorrectionLevel.FOR_BITS.get(bits); + const other = o; + return this.value === other.value; + } + /** + * @param bits int containing the two bits encoding a QR Code's error correction level + * @return ErrorCorrectionLevel representing the encoded error correction level + */ + public static forBits(bits: number /* int */): ErrorCorrectionLevel { + if (bits < 0 || bits >= ErrorCorrectionLevel.FOR_BITS.size) { + throw new IllegalArgumentException(); } + return ErrorCorrectionLevel.FOR_BITS.get(bits); + } } diff --git a/src/core/qrcode/decoder/FormatInformation.ts b/src/core/qrcode/decoder/FormatInformation.ts index d93f59c1..92d851fc 100644 --- a/src/core/qrcode/decoder/FormatInformation.ts +++ b/src/core/qrcode/decoder/FormatInformation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import ErrorCorrectionLevel from './ErrorCorrectionLevel'; import Integer from '../../util/Integer'; @@ -29,132 +29,132 @@ import Integer from '../../util/Integer'; */ export default class FormatInformation { - private static FORMAT_INFO_MASK_QR = 0x5412; + private static FORMAT_INFO_MASK_QR = 0x5412; - /** - * See ISO 18004:2006, Annex C, Table C.1 - */ - private static FORMAT_INFO_DECODE_LOOKUP = [ - Int32Array.from([0x5412, 0x00]), - Int32Array.from([0x5125, 0x01]), - Int32Array.from([0x5E7C, 0x02]), - Int32Array.from([0x5B4B, 0x03]), - Int32Array.from([0x45F9, 0x04]), - Int32Array.from([0x40CE, 0x05]), - Int32Array.from([0x4F97, 0x06]), - Int32Array.from([0x4AA0, 0x07]), - Int32Array.from([0x77C4, 0x08]), - Int32Array.from([0x72F3, 0x09]), - Int32Array.from([0x7DAA, 0x0A]), - Int32Array.from([0x789D, 0x0B]), - Int32Array.from([0x662F, 0x0C]), - Int32Array.from([0x6318, 0x0D]), - Int32Array.from([0x6C41, 0x0E]), - Int32Array.from([0x6976, 0x0F]), - Int32Array.from([0x1689, 0x10]), - Int32Array.from([0x13BE, 0x11]), - Int32Array.from([0x1CE7, 0x12]), - Int32Array.from([0x19D0, 0x13]), - Int32Array.from([0x0762, 0x14]), - Int32Array.from([0x0255, 0x15]), - Int32Array.from([0x0D0C, 0x16]), - Int32Array.from([0x083B, 0x17]), - Int32Array.from([0x355F, 0x18]), - Int32Array.from([0x3068, 0x19]), - Int32Array.from([0x3F31, 0x1A]), - Int32Array.from([0x3A06, 0x1B]), - Int32Array.from([0x24B4, 0x1C]), - Int32Array.from([0x2183, 0x1D]), - Int32Array.from([0x2EDA, 0x1E]), - Int32Array.from([0x2BED, 0x1F]), - ]; + /** + * See ISO 18004:2006, Annex C, Table C.1 + */ + private static FORMAT_INFO_DECODE_LOOKUP = [ + Int32Array.from([0x5412, 0x00]), + Int32Array.from([0x5125, 0x01]), + Int32Array.from([0x5E7C, 0x02]), + Int32Array.from([0x5B4B, 0x03]), + Int32Array.from([0x45F9, 0x04]), + Int32Array.from([0x40CE, 0x05]), + Int32Array.from([0x4F97, 0x06]), + Int32Array.from([0x4AA0, 0x07]), + Int32Array.from([0x77C4, 0x08]), + Int32Array.from([0x72F3, 0x09]), + Int32Array.from([0x7DAA, 0x0A]), + Int32Array.from([0x789D, 0x0B]), + Int32Array.from([0x662F, 0x0C]), + Int32Array.from([0x6318, 0x0D]), + Int32Array.from([0x6C41, 0x0E]), + Int32Array.from([0x6976, 0x0F]), + Int32Array.from([0x1689, 0x10]), + Int32Array.from([0x13BE, 0x11]), + Int32Array.from([0x1CE7, 0x12]), + Int32Array.from([0x19D0, 0x13]), + Int32Array.from([0x0762, 0x14]), + Int32Array.from([0x0255, 0x15]), + Int32Array.from([0x0D0C, 0x16]), + Int32Array.from([0x083B, 0x17]), + Int32Array.from([0x355F, 0x18]), + Int32Array.from([0x3068, 0x19]), + Int32Array.from([0x3F31, 0x1A]), + Int32Array.from([0x3A06, 0x1B]), + Int32Array.from([0x24B4, 0x1C]), + Int32Array.from([0x2183, 0x1D]), + Int32Array.from([0x2EDA, 0x1E]), + Int32Array.from([0x2BED, 0x1F]), + ]; - private errorCorrectionLevel: ErrorCorrectionLevel; - private dataMask: number; /*byte*/ + private errorCorrectionLevel: ErrorCorrectionLevel; + private dataMask: number; /* byte */ - private constructor(formatInfo: number /*int*/) { - // Bits 3,4 - this.errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03); - // Bottom 3 bits - this.dataMask = /*(byte) */(formatInfo & 0x07); - } + private constructor(formatInfo: number /* int */) { + // Bits 3,4 + this.errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03); + // Bottom 3 bits + this.dataMask = /* (byte) */(formatInfo & 0x07); + } - public static numBitsDiffering(a: number /*int*/, b: number /*int*/): number /*int*/ { - return Integer.bitCount(a ^ b); - } + public static numBitsDiffering(a: number /* int */, b: number /* int */): number /* int */ { + return Integer.bitCount(a ^ b); + } - /** - * @param maskedFormatInfo1 format info indicator, with mask still applied - * @param maskedFormatInfo2 second copy of same info; both are checked at the same time - * to establish best match - * @return information about the format it specifies, or {@code null} - * if doesn't seem to match any known pattern - */ - public static decodeFormatInformation(maskedFormatInfo1: number /*int*/, maskedFormatInfo2: number /*int*/): FormatInformation { - const formatInfo = FormatInformation.doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2); - if (formatInfo !== null) { - return formatInfo; - } - // Should return null, but, some QR codes apparently - // do not mask this info. Try again by actually masking the pattern - // first - return FormatInformation.doDecodeFormatInformation(maskedFormatInfo1 ^ FormatInformation.FORMAT_INFO_MASK_QR, - maskedFormatInfo2 ^ FormatInformation.FORMAT_INFO_MASK_QR); + /** + * @param maskedFormatInfo1 format info indicator, with mask still applied + * @param maskedFormatInfo2 second copy of same info; both are checked at the same time + * to establish best match + * @return information about the format it specifies, or {@code null} + * if doesn't seem to match any known pattern + */ + public static decodeFormatInformation(maskedFormatInfo1: number /* int */, maskedFormatInfo2: number /* int */): FormatInformation { + const formatInfo = FormatInformation.doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2); + if (formatInfo !== null) { + return formatInfo; } + // Should return null, but, some QR codes apparently + // do not mask this info. Try again by actually masking the pattern + // first + return FormatInformation.doDecodeFormatInformation(maskedFormatInfo1 ^ FormatInformation.FORMAT_INFO_MASK_QR, + maskedFormatInfo2 ^ FormatInformation.FORMAT_INFO_MASK_QR); + } - private static doDecodeFormatInformation(maskedFormatInfo1: number /*int*/, maskedFormatInfo2: number /*int*/): FormatInformation { - // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing - let bestDifference = Number.MAX_SAFE_INTEGER; - let bestFormatInfo = 0; - for (const decodeInfo of FormatInformation.FORMAT_INFO_DECODE_LOOKUP) { - const targetInfo = decodeInfo[0]; - if (targetInfo === maskedFormatInfo1 || targetInfo === maskedFormatInfo2) { - // Found an exact match - return new FormatInformation(decodeInfo[1]); - } - let bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo1, targetInfo); - if (bitsDifference < bestDifference) { - bestFormatInfo = decodeInfo[1]; - bestDifference = bitsDifference; - } - if (maskedFormatInfo1 !== maskedFormatInfo2) { - // also try the other option - bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo2, targetInfo); - if (bitsDifference < bestDifference) { - bestFormatInfo = decodeInfo[1]; - bestDifference = bitsDifference; - } - } - } - // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits - // differing means we found a match - if (bestDifference <= 3) { - return new FormatInformation(bestFormatInfo); + private static doDecodeFormatInformation(maskedFormatInfo1: number /* int */, maskedFormatInfo2: number /* int */): FormatInformation { + // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing + let bestDifference = Number.MAX_SAFE_INTEGER; + let bestFormatInfo = 0; + for (const decodeInfo of FormatInformation.FORMAT_INFO_DECODE_LOOKUP) { + const targetInfo = decodeInfo[0]; + if (targetInfo === maskedFormatInfo1 || targetInfo === maskedFormatInfo2) { + // Found an exact match + return new FormatInformation(decodeInfo[1]); + } + let bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo1, targetInfo); + if (bitsDifference < bestDifference) { + bestFormatInfo = decodeInfo[1]; + bestDifference = bitsDifference; + } + if (maskedFormatInfo1 !== maskedFormatInfo2) { + // also try the other option + bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo2, targetInfo); + if (bitsDifference < bestDifference) { + bestFormatInfo = decodeInfo[1]; + bestDifference = bitsDifference; } - return null; + } } - - public getErrorCorrectionLevel(): ErrorCorrectionLevel { - return this.errorCorrectionLevel; + // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits + // differing means we found a match + if (bestDifference <= 3) { + return new FormatInformation(bestFormatInfo); } + return null; + } - public getDataMask(): number/*byte*/ { - return this.dataMask; - } + public getErrorCorrectionLevel(): ErrorCorrectionLevel { + return this.errorCorrectionLevel; + } - /*@Override*/ - public hashCode(): number /*int*/ { - return (this.errorCorrectionLevel.getBits() << 3) | this.dataMask; - } + public getDataMask(): number/* byte */ { + return this.dataMask; + } - /*@Override*/ - public equals(o: Object): boolean { - if (!(o instanceof FormatInformation)) { - return false; - } - const other = o; - return this.errorCorrectionLevel === other.errorCorrectionLevel && - this.dataMask === other.dataMask; + /* @Override */ + public hashCode(): number /* int */ { + return (this.errorCorrectionLevel.getBits() << 3) | this.dataMask; + } + + /* @Override */ + public equals(o: Object): boolean { + if (!(o instanceof FormatInformation)) { + return false; } + const other = o; + return this.errorCorrectionLevel === other.errorCorrectionLevel && + this.dataMask === other.dataMask; + } } diff --git a/src/core/qrcode/decoder/Mode.ts b/src/core/qrcode/decoder/Mode.ts index 191024ca..50df74c7 100644 --- a/src/core/qrcode/decoder/Mode.ts +++ b/src/core/qrcode/decoder/Mode.ts @@ -14,24 +14,24 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import Version from './Version'; import IllegalArgumentException from '../../IllegalArgumentException'; export enum ModeValues { - TERMINATOR, // Not really a mode... - NUMERIC, - ALPHANUMERIC, - STRUCTURED_APPEND, // Not supported - BYTE, - ECI, // character counts don't apply - KANJI, - FNC1_FIRST_POSITION, - FNC1_SECOND_POSITION, - /** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */ - HANZI + TERMINATOR, // Not really a mode... + NUMERIC, + ALPHANUMERIC, + STRUCTURED_APPEND, // Not supported + BYTE, + ECI, // character counts don't apply + KANJI, + FNC1_FIRST_POSITION, + FNC1_SECOND_POSITION, + /** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */ + HANZI } /** @@ -42,77 +42,77 @@ export enum ModeValues { */ export default class Mode { - private static FOR_BITS = new Map(); - private static FOR_VALUE = new Map(); - - public static TERMINATOR = new Mode(ModeValues.TERMINATOR, 'TERMINATOR', Int32Array.from([0, 0, 0]), 0x00); // Not really a mode... - public static NUMERIC = new Mode(ModeValues.NUMERIC, 'NUMERIC', Int32Array.from([10, 12, 14]), 0x01); - public static ALPHANUMERIC = new Mode(ModeValues.ALPHANUMERIC, 'ALPHANUMERIC', Int32Array.from([9, 11, 13]), 0x02); - public static STRUCTURED_APPEND = new Mode(ModeValues.STRUCTURED_APPEND, 'STRUCTURED_APPEND', Int32Array.from([0, 0, 0]), 0x03); // Not supported - public static BYTE = new Mode(ModeValues.BYTE, 'BYTE', Int32Array.from([8, 16, 16]), 0x04); - public static ECI = new Mode(ModeValues.ECI, 'ECI', Int32Array.from([0, 0, 0]), 0x07); // character counts don't apply - public static KANJI = new Mode(ModeValues.KANJI, 'KANJI', Int32Array.from([8, 10, 12]), 0x08); - public static FNC1_FIRST_POSITION = new Mode(ModeValues.FNC1_FIRST_POSITION, 'FNC1_FIRST_POSITION', Int32Array.from([0, 0, 0]), 0x05); - public static FNC1_SECOND_POSITION = new Mode(ModeValues.FNC1_SECOND_POSITION, 'FNC1_SECOND_POSITION', Int32Array.from([0, 0, 0]), 0x09); - /** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */ - public static HANZI = new Mode(ModeValues.HANZI, 'HANZI', Int32Array.from([8, 10, 12]), 0x0D); - - private constructor(private value: ModeValues, private stringValue: string, private characterCountBitsForVersions: Int32Array, private bits: number /*int*/) { - Mode.FOR_BITS.set(bits, this); - Mode.FOR_VALUE.set(value, this); + private static FOR_BITS = new Map(); + private static FOR_VALUE = new Map(); + + public static TERMINATOR = new Mode(ModeValues.TERMINATOR, 'TERMINATOR', Int32Array.from([0, 0, 0]), 0x00); // Not really a mode... + public static NUMERIC = new Mode(ModeValues.NUMERIC, 'NUMERIC', Int32Array.from([10, 12, 14]), 0x01); + public static ALPHANUMERIC = new Mode(ModeValues.ALPHANUMERIC, 'ALPHANUMERIC', Int32Array.from([9, 11, 13]), 0x02); + public static STRUCTURED_APPEND = new Mode(ModeValues.STRUCTURED_APPEND, 'STRUCTURED_APPEND', Int32Array.from([0, 0, 0]), 0x03); // Not supported + public static BYTE = new Mode(ModeValues.BYTE, 'BYTE', Int32Array.from([8, 16, 16]), 0x04); + public static ECI = new Mode(ModeValues.ECI, 'ECI', Int32Array.from([0, 0, 0]), 0x07); // character counts don't apply + public static KANJI = new Mode(ModeValues.KANJI, 'KANJI', Int32Array.from([8, 10, 12]), 0x08); + public static FNC1_FIRST_POSITION = new Mode(ModeValues.FNC1_FIRST_POSITION, 'FNC1_FIRST_POSITION', Int32Array.from([0, 0, 0]), 0x05); + public static FNC1_SECOND_POSITION = new Mode(ModeValues.FNC1_SECOND_POSITION, 'FNC1_SECOND_POSITION', Int32Array.from([0, 0, 0]), 0x09); + /** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */ + public static HANZI = new Mode(ModeValues.HANZI, 'HANZI', Int32Array.from([8, 10, 12]), 0x0D); + + private constructor(private value: ModeValues, private stringValue: string, private characterCountBitsForVersions: Int32Array, private bits: number /* int */) { + Mode.FOR_BITS.set(bits, this); + Mode.FOR_VALUE.set(value, this); + } + + /** + * @param bits four bits encoding a QR Code data mode + * @return Mode encoded by these bits + * @throws IllegalArgumentException if bits do not correspond to a known mode + */ + public static forBits(bits: number /* int */): Mode { + const mode = Mode.FOR_BITS.get(bits); + if (undefined === mode) { + throw new IllegalArgumentException(); } + return mode; + } - /** - * @param bits four bits encoding a QR Code data mode - * @return Mode encoded by these bits - * @throws IllegalArgumentException if bits do not correspond to a known mode - */ - public static forBits(bits: number /*int*/): Mode { - const mode = Mode.FOR_BITS.get(bits); - if (undefined === mode) { - throw new IllegalArgumentException(); - } - return mode; - } + /** + * @param version version in question + * @return number of bits used, in this QR Code symbol {@link Version}, to encode the + * count of characters that will follow encoded in this Mode + */ + public getCharacterCountBits(version: Version): number /* int */ { + const versionNumber = version.getVersionNumber(); - /** - * @param version version in question - * @return number of bits used, in this QR Code symbol {@link Version}, to encode the - * count of characters that will follow encoded in this Mode - */ - public getCharacterCountBits(version: Version): number /*int*/ { - const versionNumber = version.getVersionNumber(); - - let offset; - - if (versionNumber <= 9) { - offset = 0; - } else if (versionNumber <= 26) { - offset = 1; - } else { - offset = 2; - } - - return this.characterCountBitsForVersions[offset]; - } + let offset; - public getValue(): ModeValues/*int*/ { - return this.value; + if (versionNumber <= 9) { + offset = 0; + } else if (versionNumber <= 26) { + offset = 1; + } else { + offset = 2; } - public getBits(): number /*int*/ { - return this.bits; - } + return this.characterCountBitsForVersions[offset]; + } - public equals(o: any): boolean { - if (!(o instanceof Mode)) { - return false; - } - const other = o; - return this.value === other.value; - } + public getValue(): ModeValues/* int */ { + return this.value; + } - public toString(): string { - return this.stringValue; + public getBits(): number /* int */ { + return this.bits; + } + + public equals(o: any): boolean { + if (!(o instanceof Mode)) { + return false; } + const other = o; + return this.value === other.value; + } + + public toString(): string { + return this.stringValue; + } } diff --git a/src/core/qrcode/decoder/QRCodeDecoderMetaData.ts b/src/core/qrcode/decoder/QRCodeDecoderMetaData.ts index d64d0be4..36038213 100644 --- a/src/core/qrcode/decoder/QRCodeDecoderMetaData.ts +++ b/src/core/qrcode/decoder/QRCodeDecoderMetaData.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import ResultPoint from '../../ResultPoint'; @@ -27,28 +27,28 @@ import ResultPoint from '../../ResultPoint'; export default class QRCodeDecoderMetaData { - public constructor(private mirrored: boolean) { } + public constructor(private mirrored: boolean) { } - /** - * @return true if the QR Code was mirrored. - */ - public isMirrored(): boolean { - return this.mirrored; - } - - /** - * Apply the result points' order correction due to mirroring. - * - * @param points Array of points to apply mirror correction to. - */ - public applyMirroredCorrection(points: Array): void { - if (!this.mirrored || points === null || points.length < 3) { - return; - } - const bottomLeft = points[0]; - points[0] = points[2]; - points[2] = bottomLeft; - // No need to 'fix' top-left and alignment pattern. + /** + * @return true if the QR Code was mirrored. + */ + public isMirrored(): boolean { + return this.mirrored; + } + + /** + * Apply the result points' order correction due to mirroring. + * + * @param points Array of points to apply mirror correction to. + */ + public applyMirroredCorrection(points: Array): void { + if (!this.mirrored || points === null || points.length < 3) { + return; } + const bottomLeft = points[0]; + points[0] = points[2]; + points[2] = bottomLeft; + // No need to 'fix' top-left and alignment pattern. + } } diff --git a/src/core/qrcode/decoder/Version.ts b/src/core/qrcode/decoder/Version.ts index f765f23e..62d3942e 100644 --- a/src/core/qrcode/decoder/Version.ts +++ b/src/core/qrcode/decoder/Version.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.decoder {*/ +/* namespace com.google.zxing.qrcode.decoder { */ import BitMatrix from '../../common/BitMatrix'; @@ -32,486 +32,486 @@ import IllegalArgumentException from '../../IllegalArgumentException'; */ export default class Version { - /** - * See ISO 18004:2006 Annex D. - * Element i represents the raw version bits that specify version i + 7 - */ - private static VERSION_DECODE_INFO = Int32Array.from([ - 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, - 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, - 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, - 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, - 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, - 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, - 0x2542E, 0x26A64, 0x27541, 0x28C69]); + /** + * See ISO 18004:2006 Annex D. + * Element i represents the raw version bits that specify version i + 7 + */ + private static VERSION_DECODE_INFO = Int32Array.from([ + 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, + 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, + 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, + 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, + 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, + 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, + 0x2542E, 0x26A64, 0x27541, 0x28C69]); - /** - * See ISO 18004:2006 6.5.1 Table 9 - */ - private static VERSIONS: Version[] = [ - new Version(1, new Int32Array(0), - new ECBlocks(7, new ECB(1, 19)), - new ECBlocks(10, new ECB(1, 16)), - new ECBlocks(13, new ECB(1, 13)), - new ECBlocks(17, new ECB(1, 9))), - new Version(2, Int32Array.from([6, 18]), - new ECBlocks(10, new ECB(1, 34)), - new ECBlocks(16, new ECB(1, 28)), - new ECBlocks(22, new ECB(1, 22)), - new ECBlocks(28, new ECB(1, 16))), - new Version(3, Int32Array.from([6, 22]), - new ECBlocks(15, new ECB(1, 55)), - new ECBlocks(26, new ECB(1, 44)), - new ECBlocks(18, new ECB(2, 17)), - new ECBlocks(22, new ECB(2, 13))), - new Version(4, Int32Array.from([6, 26]), - new ECBlocks(20, new ECB(1, 80)), - new ECBlocks(18, new ECB(2, 32)), - new ECBlocks(26, new ECB(2, 24)), - new ECBlocks(16, new ECB(4, 9))), - new Version(5, Int32Array.from([6, 30]), - new ECBlocks(26, new ECB(1, 108)), - new ECBlocks(24, new ECB(2, 43)), - new ECBlocks(18, new ECB(2, 15), - new ECB(2, 16)), - new ECBlocks(22, new ECB(2, 11), - new ECB(2, 12))), - new Version(6, Int32Array.from([6, 34]), - new ECBlocks(18, new ECB(2, 68)), - new ECBlocks(16, new ECB(4, 27)), - new ECBlocks(24, new ECB(4, 19)), - new ECBlocks(28, new ECB(4, 15))), - new Version(7, Int32Array.from([6, 22, 38]), - new ECBlocks(20, new ECB(2, 78)), - new ECBlocks(18, new ECB(4, 31)), - new ECBlocks(18, new ECB(2, 14), - new ECB(4, 15)), - new ECBlocks(26, new ECB(4, 13), - new ECB(1, 14))), - new Version(8, Int32Array.from([6, 24, 42]), - new ECBlocks(24, new ECB(2, 97)), - new ECBlocks(22, new ECB(2, 38), - new ECB(2, 39)), - new ECBlocks(22, new ECB(4, 18), - new ECB(2, 19)), - new ECBlocks(26, new ECB(4, 14), - new ECB(2, 15))), - new Version(9, Int32Array.from([6, 26, 46]), - new ECBlocks(30, new ECB(2, 116)), - new ECBlocks(22, new ECB(3, 36), - new ECB(2, 37)), - new ECBlocks(20, new ECB(4, 16), - new ECB(4, 17)), - new ECBlocks(24, new ECB(4, 12), - new ECB(4, 13))), - new Version(10, Int32Array.from([6, 28, 50]), - new ECBlocks(18, new ECB(2, 68), - new ECB(2, 69)), - new ECBlocks(26, new ECB(4, 43), - new ECB(1, 44)), - new ECBlocks(24, new ECB(6, 19), - new ECB(2, 20)), - new ECBlocks(28, new ECB(6, 15), - new ECB(2, 16))), - new Version(11, Int32Array.from([6, 30, 54]), - new ECBlocks(20, new ECB(4, 81)), - new ECBlocks(30, new ECB(1, 50), - new ECB(4, 51)), - new ECBlocks(28, new ECB(4, 22), - new ECB(4, 23)), - new ECBlocks(24, new ECB(3, 12), - new ECB(8, 13))), - new Version(12, Int32Array.from([6, 32, 58]), - new ECBlocks(24, new ECB(2, 92), - new ECB(2, 93)), - new ECBlocks(22, new ECB(6, 36), - new ECB(2, 37)), - new ECBlocks(26, new ECB(4, 20), - new ECB(6, 21)), - new ECBlocks(28, new ECB(7, 14), - new ECB(4, 15))), - new Version(13, Int32Array.from([6, 34, 62]), - new ECBlocks(26, new ECB(4, 107)), - new ECBlocks(22, new ECB(8, 37), - new ECB(1, 38)), - new ECBlocks(24, new ECB(8, 20), - new ECB(4, 21)), - new ECBlocks(22, new ECB(12, 11), - new ECB(4, 12))), - new Version(14, Int32Array.from([6, 26, 46, 66]), - new ECBlocks(30, new ECB(3, 115), - new ECB(1, 116)), - new ECBlocks(24, new ECB(4, 40), - new ECB(5, 41)), - new ECBlocks(20, new ECB(11, 16), - new ECB(5, 17)), - new ECBlocks(24, new ECB(11, 12), - new ECB(5, 13))), - new Version(15, Int32Array.from([6, 26, 48, 70]), - new ECBlocks(22, new ECB(5, 87), - new ECB(1, 88)), - new ECBlocks(24, new ECB(5, 41), - new ECB(5, 42)), - new ECBlocks(30, new ECB(5, 24), - new ECB(7, 25)), - new ECBlocks(24, new ECB(11, 12), - new ECB(7, 13))), - new Version(16, Int32Array.from([6, 26, 50, 74]), - new ECBlocks(24, new ECB(5, 98), - new ECB(1, 99)), - new ECBlocks(28, new ECB(7, 45), - new ECB(3, 46)), - new ECBlocks(24, new ECB(15, 19), - new ECB(2, 20)), - new ECBlocks(30, new ECB(3, 15), - new ECB(13, 16))), - new Version(17, Int32Array.from([6, 30, 54, 78]), - new ECBlocks(28, new ECB(1, 107), - new ECB(5, 108)), - new ECBlocks(28, new ECB(10, 46), - new ECB(1, 47)), - new ECBlocks(28, new ECB(1, 22), - new ECB(15, 23)), - new ECBlocks(28, new ECB(2, 14), - new ECB(17, 15))), - new Version(18, Int32Array.from([6, 30, 56, 82]), - new ECBlocks(30, new ECB(5, 120), - new ECB(1, 121)), - new ECBlocks(26, new ECB(9, 43), - new ECB(4, 44)), - new ECBlocks(28, new ECB(17, 22), - new ECB(1, 23)), - new ECBlocks(28, new ECB(2, 14), - new ECB(19, 15))), - new Version(19, Int32Array.from([6, 30, 58, 86]), - new ECBlocks(28, new ECB(3, 113), - new ECB(4, 114)), - new ECBlocks(26, new ECB(3, 44), - new ECB(11, 45)), - new ECBlocks(26, new ECB(17, 21), - new ECB(4, 22)), - new ECBlocks(26, new ECB(9, 13), - new ECB(16, 14))), - new Version(20, Int32Array.from([6, 34, 62, 90]), - new ECBlocks(28, new ECB(3, 107), - new ECB(5, 108)), - new ECBlocks(26, new ECB(3, 41), - new ECB(13, 42)), - new ECBlocks(30, new ECB(15, 24), - new ECB(5, 25)), - new ECBlocks(28, new ECB(15, 15), - new ECB(10, 16))), - new Version(21, Int32Array.from([6, 28, 50, 72, 94]), - new ECBlocks(28, new ECB(4, 116), - new ECB(4, 117)), - new ECBlocks(26, new ECB(17, 42)), - new ECBlocks(28, new ECB(17, 22), - new ECB(6, 23)), - new ECBlocks(30, new ECB(19, 16), - new ECB(6, 17))), - new Version(22, Int32Array.from([6, 26, 50, 74, 98]), - new ECBlocks(28, new ECB(2, 111), - new ECB(7, 112)), - new ECBlocks(28, new ECB(17, 46)), - new ECBlocks(30, new ECB(7, 24), - new ECB(16, 25)), - new ECBlocks(24, new ECB(34, 13))), - new Version(23, Int32Array.from([6, 30, 54, 78, 102]), - new ECBlocks(30, new ECB(4, 121), - new ECB(5, 122)), - new ECBlocks(28, new ECB(4, 47), - new ECB(14, 48)), - new ECBlocks(30, new ECB(11, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(16, 15), - new ECB(14, 16))), - new Version(24, Int32Array.from([6, 28, 54, 80, 106]), - new ECBlocks(30, new ECB(6, 117), - new ECB(4, 118)), - new ECBlocks(28, new ECB(6, 45), - new ECB(14, 46)), - new ECBlocks(30, new ECB(11, 24), - new ECB(16, 25)), - new ECBlocks(30, new ECB(30, 16), - new ECB(2, 17))), - new Version(25, Int32Array.from([6, 32, 58, 84, 110]), - new ECBlocks(26, new ECB(8, 106), - new ECB(4, 107)), - new ECBlocks(28, new ECB(8, 47), - new ECB(13, 48)), - new ECBlocks(30, new ECB(7, 24), - new ECB(22, 25)), - new ECBlocks(30, new ECB(22, 15), - new ECB(13, 16))), - new Version(26, Int32Array.from([6, 30, 58, 86, 114]), - new ECBlocks(28, new ECB(10, 114), - new ECB(2, 115)), - new ECBlocks(28, new ECB(19, 46), - new ECB(4, 47)), - new ECBlocks(28, new ECB(28, 22), - new ECB(6, 23)), - new ECBlocks(30, new ECB(33, 16), - new ECB(4, 17))), - new Version(27, Int32Array.from([6, 34, 62, 90, 118]), - new ECBlocks(30, new ECB(8, 122), - new ECB(4, 123)), - new ECBlocks(28, new ECB(22, 45), - new ECB(3, 46)), - new ECBlocks(30, new ECB(8, 23), - new ECB(26, 24)), - new ECBlocks(30, new ECB(12, 15), - new ECB(28, 16))), - new Version(28, Int32Array.from([6, 26, 50, 74, 98, 122]), - new ECBlocks(30, new ECB(3, 117), - new ECB(10, 118)), - new ECBlocks(28, new ECB(3, 45), - new ECB(23, 46)), - new ECBlocks(30, new ECB(4, 24), - new ECB(31, 25)), - new ECBlocks(30, new ECB(11, 15), - new ECB(31, 16))), - new Version(29, Int32Array.from([6, 30, 54, 78, 102, 126]), - new ECBlocks(30, new ECB(7, 116), - new ECB(7, 117)), - new ECBlocks(28, new ECB(21, 45), - new ECB(7, 46)), - new ECBlocks(30, new ECB(1, 23), - new ECB(37, 24)), - new ECBlocks(30, new ECB(19, 15), - new ECB(26, 16))), - new Version(30, Int32Array.from([6, 26, 52, 78, 104, 130]), - new ECBlocks(30, new ECB(5, 115), - new ECB(10, 116)), - new ECBlocks(28, new ECB(19, 47), - new ECB(10, 48)), - new ECBlocks(30, new ECB(15, 24), - new ECB(25, 25)), - new ECBlocks(30, new ECB(23, 15), - new ECB(25, 16))), - new Version(31, Int32Array.from([6, 30, 56, 82, 108, 134]), - new ECBlocks(30, new ECB(13, 115), - new ECB(3, 116)), - new ECBlocks(28, new ECB(2, 46), - new ECB(29, 47)), - new ECBlocks(30, new ECB(42, 24), - new ECB(1, 25)), - new ECBlocks(30, new ECB(23, 15), - new ECB(28, 16))), - new Version(32, Int32Array.from([6, 34, 60, 86, 112, 138]), - new ECBlocks(30, new ECB(17, 115)), - new ECBlocks(28, new ECB(10, 46), - new ECB(23, 47)), - new ECBlocks(30, new ECB(10, 24), - new ECB(35, 25)), - new ECBlocks(30, new ECB(19, 15), - new ECB(35, 16))), - new Version(33, Int32Array.from([6, 30, 58, 86, 114, 142]), - new ECBlocks(30, new ECB(17, 115), - new ECB(1, 116)), - new ECBlocks(28, new ECB(14, 46), - new ECB(21, 47)), - new ECBlocks(30, new ECB(29, 24), - new ECB(19, 25)), - new ECBlocks(30, new ECB(11, 15), - new ECB(46, 16))), - new Version(34, Int32Array.from([6, 34, 62, 90, 118, 146]), - new ECBlocks(30, new ECB(13, 115), - new ECB(6, 116)), - new ECBlocks(28, new ECB(14, 46), - new ECB(23, 47)), - new ECBlocks(30, new ECB(44, 24), - new ECB(7, 25)), - new ECBlocks(30, new ECB(59, 16), - new ECB(1, 17))), - new Version(35, Int32Array.from([6, 30, 54, 78, 102, 126, 150]), - new ECBlocks(30, new ECB(12, 121), - new ECB(7, 122)), - new ECBlocks(28, new ECB(12, 47), - new ECB(26, 48)), - new ECBlocks(30, new ECB(39, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(22, 15), - new ECB(41, 16))), - new Version(36, Int32Array.from([6, 24, 50, 76, 102, 128, 154]), - new ECBlocks(30, new ECB(6, 121), - new ECB(14, 122)), - new ECBlocks(28, new ECB(6, 47), - new ECB(34, 48)), - new ECBlocks(30, new ECB(46, 24), - new ECB(10, 25)), - new ECBlocks(30, new ECB(2, 15), - new ECB(64, 16))), - new Version(37, Int32Array.from([6, 28, 54, 80, 106, 132, 158]), - new ECBlocks(30, new ECB(17, 122), - new ECB(4, 123)), - new ECBlocks(28, new ECB(29, 46), - new ECB(14, 47)), - new ECBlocks(30, new ECB(49, 24), - new ECB(10, 25)), - new ECBlocks(30, new ECB(24, 15), - new ECB(46, 16))), - new Version(38, Int32Array.from([6, 32, 58, 84, 110, 136, 162]), - new ECBlocks(30, new ECB(4, 122), - new ECB(18, 123)), - new ECBlocks(28, new ECB(13, 46), - new ECB(32, 47)), - new ECBlocks(30, new ECB(48, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(42, 15), - new ECB(32, 16))), - new Version(39, Int32Array.from([6, 26, 54, 82, 110, 138, 166]), - new ECBlocks(30, new ECB(20, 117), - new ECB(4, 118)), - new ECBlocks(28, new ECB(40, 47), - new ECB(7, 48)), - new ECBlocks(30, new ECB(43, 24), - new ECB(22, 25)), - new ECBlocks(30, new ECB(10, 15), - new ECB(67, 16))), - new Version(40, Int32Array.from([6, 30, 58, 86, 114, 142, 170]), - new ECBlocks(30, new ECB(19, 118), - new ECB(6, 119)), - new ECBlocks(28, new ECB(18, 47), - new ECB(31, 48)), - new ECBlocks(30, new ECB(34, 24), - new ECB(34, 25)), - new ECBlocks(30, new ECB(20, 15), - new ECB(61, 16))) - ]; + /** + * See ISO 18004:2006 6.5.1 Table 9 + */ + private static VERSIONS: Version[] = [ + new Version(1, new Int32Array(0), + new ECBlocks(7, new ECB(1, 19)), + new ECBlocks(10, new ECB(1, 16)), + new ECBlocks(13, new ECB(1, 13)), + new ECBlocks(17, new ECB(1, 9))), + new Version(2, Int32Array.from([6, 18]), + new ECBlocks(10, new ECB(1, 34)), + new ECBlocks(16, new ECB(1, 28)), + new ECBlocks(22, new ECB(1, 22)), + new ECBlocks(28, new ECB(1, 16))), + new Version(3, Int32Array.from([6, 22]), + new ECBlocks(15, new ECB(1, 55)), + new ECBlocks(26, new ECB(1, 44)), + new ECBlocks(18, new ECB(2, 17)), + new ECBlocks(22, new ECB(2, 13))), + new Version(4, Int32Array.from([6, 26]), + new ECBlocks(20, new ECB(1, 80)), + new ECBlocks(18, new ECB(2, 32)), + new ECBlocks(26, new ECB(2, 24)), + new ECBlocks(16, new ECB(4, 9))), + new Version(5, Int32Array.from([6, 30]), + new ECBlocks(26, new ECB(1, 108)), + new ECBlocks(24, new ECB(2, 43)), + new ECBlocks(18, new ECB(2, 15), + new ECB(2, 16)), + new ECBlocks(22, new ECB(2, 11), + new ECB(2, 12))), + new Version(6, Int32Array.from([6, 34]), + new ECBlocks(18, new ECB(2, 68)), + new ECBlocks(16, new ECB(4, 27)), + new ECBlocks(24, new ECB(4, 19)), + new ECBlocks(28, new ECB(4, 15))), + new Version(7, Int32Array.from([6, 22, 38]), + new ECBlocks(20, new ECB(2, 78)), + new ECBlocks(18, new ECB(4, 31)), + new ECBlocks(18, new ECB(2, 14), + new ECB(4, 15)), + new ECBlocks(26, new ECB(4, 13), + new ECB(1, 14))), + new Version(8, Int32Array.from([6, 24, 42]), + new ECBlocks(24, new ECB(2, 97)), + new ECBlocks(22, new ECB(2, 38), + new ECB(2, 39)), + new ECBlocks(22, new ECB(4, 18), + new ECB(2, 19)), + new ECBlocks(26, new ECB(4, 14), + new ECB(2, 15))), + new Version(9, Int32Array.from([6, 26, 46]), + new ECBlocks(30, new ECB(2, 116)), + new ECBlocks(22, new ECB(3, 36), + new ECB(2, 37)), + new ECBlocks(20, new ECB(4, 16), + new ECB(4, 17)), + new ECBlocks(24, new ECB(4, 12), + new ECB(4, 13))), + new Version(10, Int32Array.from([6, 28, 50]), + new ECBlocks(18, new ECB(2, 68), + new ECB(2, 69)), + new ECBlocks(26, new ECB(4, 43), + new ECB(1, 44)), + new ECBlocks(24, new ECB(6, 19), + new ECB(2, 20)), + new ECBlocks(28, new ECB(6, 15), + new ECB(2, 16))), + new Version(11, Int32Array.from([6, 30, 54]), + new ECBlocks(20, new ECB(4, 81)), + new ECBlocks(30, new ECB(1, 50), + new ECB(4, 51)), + new ECBlocks(28, new ECB(4, 22), + new ECB(4, 23)), + new ECBlocks(24, new ECB(3, 12), + new ECB(8, 13))), + new Version(12, Int32Array.from([6, 32, 58]), + new ECBlocks(24, new ECB(2, 92), + new ECB(2, 93)), + new ECBlocks(22, new ECB(6, 36), + new ECB(2, 37)), + new ECBlocks(26, new ECB(4, 20), + new ECB(6, 21)), + new ECBlocks(28, new ECB(7, 14), + new ECB(4, 15))), + new Version(13, Int32Array.from([6, 34, 62]), + new ECBlocks(26, new ECB(4, 107)), + new ECBlocks(22, new ECB(8, 37), + new ECB(1, 38)), + new ECBlocks(24, new ECB(8, 20), + new ECB(4, 21)), + new ECBlocks(22, new ECB(12, 11), + new ECB(4, 12))), + new Version(14, Int32Array.from([6, 26, 46, 66]), + new ECBlocks(30, new ECB(3, 115), + new ECB(1, 116)), + new ECBlocks(24, new ECB(4, 40), + new ECB(5, 41)), + new ECBlocks(20, new ECB(11, 16), + new ECB(5, 17)), + new ECBlocks(24, new ECB(11, 12), + new ECB(5, 13))), + new Version(15, Int32Array.from([6, 26, 48, 70]), + new ECBlocks(22, new ECB(5, 87), + new ECB(1, 88)), + new ECBlocks(24, new ECB(5, 41), + new ECB(5, 42)), + new ECBlocks(30, new ECB(5, 24), + new ECB(7, 25)), + new ECBlocks(24, new ECB(11, 12), + new ECB(7, 13))), + new Version(16, Int32Array.from([6, 26, 50, 74]), + new ECBlocks(24, new ECB(5, 98), + new ECB(1, 99)), + new ECBlocks(28, new ECB(7, 45), + new ECB(3, 46)), + new ECBlocks(24, new ECB(15, 19), + new ECB(2, 20)), + new ECBlocks(30, new ECB(3, 15), + new ECB(13, 16))), + new Version(17, Int32Array.from([6, 30, 54, 78]), + new ECBlocks(28, new ECB(1, 107), + new ECB(5, 108)), + new ECBlocks(28, new ECB(10, 46), + new ECB(1, 47)), + new ECBlocks(28, new ECB(1, 22), + new ECB(15, 23)), + new ECBlocks(28, new ECB(2, 14), + new ECB(17, 15))), + new Version(18, Int32Array.from([6, 30, 56, 82]), + new ECBlocks(30, new ECB(5, 120), + new ECB(1, 121)), + new ECBlocks(26, new ECB(9, 43), + new ECB(4, 44)), + new ECBlocks(28, new ECB(17, 22), + new ECB(1, 23)), + new ECBlocks(28, new ECB(2, 14), + new ECB(19, 15))), + new Version(19, Int32Array.from([6, 30, 58, 86]), + new ECBlocks(28, new ECB(3, 113), + new ECB(4, 114)), + new ECBlocks(26, new ECB(3, 44), + new ECB(11, 45)), + new ECBlocks(26, new ECB(17, 21), + new ECB(4, 22)), + new ECBlocks(26, new ECB(9, 13), + new ECB(16, 14))), + new Version(20, Int32Array.from([6, 34, 62, 90]), + new ECBlocks(28, new ECB(3, 107), + new ECB(5, 108)), + new ECBlocks(26, new ECB(3, 41), + new ECB(13, 42)), + new ECBlocks(30, new ECB(15, 24), + new ECB(5, 25)), + new ECBlocks(28, new ECB(15, 15), + new ECB(10, 16))), + new Version(21, Int32Array.from([6, 28, 50, 72, 94]), + new ECBlocks(28, new ECB(4, 116), + new ECB(4, 117)), + new ECBlocks(26, new ECB(17, 42)), + new ECBlocks(28, new ECB(17, 22), + new ECB(6, 23)), + new ECBlocks(30, new ECB(19, 16), + new ECB(6, 17))), + new Version(22, Int32Array.from([6, 26, 50, 74, 98]), + new ECBlocks(28, new ECB(2, 111), + new ECB(7, 112)), + new ECBlocks(28, new ECB(17, 46)), + new ECBlocks(30, new ECB(7, 24), + new ECB(16, 25)), + new ECBlocks(24, new ECB(34, 13))), + new Version(23, Int32Array.from([6, 30, 54, 78, 102]), + new ECBlocks(30, new ECB(4, 121), + new ECB(5, 122)), + new ECBlocks(28, new ECB(4, 47), + new ECB(14, 48)), + new ECBlocks(30, new ECB(11, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(16, 15), + new ECB(14, 16))), + new Version(24, Int32Array.from([6, 28, 54, 80, 106]), + new ECBlocks(30, new ECB(6, 117), + new ECB(4, 118)), + new ECBlocks(28, new ECB(6, 45), + new ECB(14, 46)), + new ECBlocks(30, new ECB(11, 24), + new ECB(16, 25)), + new ECBlocks(30, new ECB(30, 16), + new ECB(2, 17))), + new Version(25, Int32Array.from([6, 32, 58, 84, 110]), + new ECBlocks(26, new ECB(8, 106), + new ECB(4, 107)), + new ECBlocks(28, new ECB(8, 47), + new ECB(13, 48)), + new ECBlocks(30, new ECB(7, 24), + new ECB(22, 25)), + new ECBlocks(30, new ECB(22, 15), + new ECB(13, 16))), + new Version(26, Int32Array.from([6, 30, 58, 86, 114]), + new ECBlocks(28, new ECB(10, 114), + new ECB(2, 115)), + new ECBlocks(28, new ECB(19, 46), + new ECB(4, 47)), + new ECBlocks(28, new ECB(28, 22), + new ECB(6, 23)), + new ECBlocks(30, new ECB(33, 16), + new ECB(4, 17))), + new Version(27, Int32Array.from([6, 34, 62, 90, 118]), + new ECBlocks(30, new ECB(8, 122), + new ECB(4, 123)), + new ECBlocks(28, new ECB(22, 45), + new ECB(3, 46)), + new ECBlocks(30, new ECB(8, 23), + new ECB(26, 24)), + new ECBlocks(30, new ECB(12, 15), + new ECB(28, 16))), + new Version(28, Int32Array.from([6, 26, 50, 74, 98, 122]), + new ECBlocks(30, new ECB(3, 117), + new ECB(10, 118)), + new ECBlocks(28, new ECB(3, 45), + new ECB(23, 46)), + new ECBlocks(30, new ECB(4, 24), + new ECB(31, 25)), + new ECBlocks(30, new ECB(11, 15), + new ECB(31, 16))), + new Version(29, Int32Array.from([6, 30, 54, 78, 102, 126]), + new ECBlocks(30, new ECB(7, 116), + new ECB(7, 117)), + new ECBlocks(28, new ECB(21, 45), + new ECB(7, 46)), + new ECBlocks(30, new ECB(1, 23), + new ECB(37, 24)), + new ECBlocks(30, new ECB(19, 15), + new ECB(26, 16))), + new Version(30, Int32Array.from([6, 26, 52, 78, 104, 130]), + new ECBlocks(30, new ECB(5, 115), + new ECB(10, 116)), + new ECBlocks(28, new ECB(19, 47), + new ECB(10, 48)), + new ECBlocks(30, new ECB(15, 24), + new ECB(25, 25)), + new ECBlocks(30, new ECB(23, 15), + new ECB(25, 16))), + new Version(31, Int32Array.from([6, 30, 56, 82, 108, 134]), + new ECBlocks(30, new ECB(13, 115), + new ECB(3, 116)), + new ECBlocks(28, new ECB(2, 46), + new ECB(29, 47)), + new ECBlocks(30, new ECB(42, 24), + new ECB(1, 25)), + new ECBlocks(30, new ECB(23, 15), + new ECB(28, 16))), + new Version(32, Int32Array.from([6, 34, 60, 86, 112, 138]), + new ECBlocks(30, new ECB(17, 115)), + new ECBlocks(28, new ECB(10, 46), + new ECB(23, 47)), + new ECBlocks(30, new ECB(10, 24), + new ECB(35, 25)), + new ECBlocks(30, new ECB(19, 15), + new ECB(35, 16))), + new Version(33, Int32Array.from([6, 30, 58, 86, 114, 142]), + new ECBlocks(30, new ECB(17, 115), + new ECB(1, 116)), + new ECBlocks(28, new ECB(14, 46), + new ECB(21, 47)), + new ECBlocks(30, new ECB(29, 24), + new ECB(19, 25)), + new ECBlocks(30, new ECB(11, 15), + new ECB(46, 16))), + new Version(34, Int32Array.from([6, 34, 62, 90, 118, 146]), + new ECBlocks(30, new ECB(13, 115), + new ECB(6, 116)), + new ECBlocks(28, new ECB(14, 46), + new ECB(23, 47)), + new ECBlocks(30, new ECB(44, 24), + new ECB(7, 25)), + new ECBlocks(30, new ECB(59, 16), + new ECB(1, 17))), + new Version(35, Int32Array.from([6, 30, 54, 78, 102, 126, 150]), + new ECBlocks(30, new ECB(12, 121), + new ECB(7, 122)), + new ECBlocks(28, new ECB(12, 47), + new ECB(26, 48)), + new ECBlocks(30, new ECB(39, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(22, 15), + new ECB(41, 16))), + new Version(36, Int32Array.from([6, 24, 50, 76, 102, 128, 154]), + new ECBlocks(30, new ECB(6, 121), + new ECB(14, 122)), + new ECBlocks(28, new ECB(6, 47), + new ECB(34, 48)), + new ECBlocks(30, new ECB(46, 24), + new ECB(10, 25)), + new ECBlocks(30, new ECB(2, 15), + new ECB(64, 16))), + new Version(37, Int32Array.from([6, 28, 54, 80, 106, 132, 158]), + new ECBlocks(30, new ECB(17, 122), + new ECB(4, 123)), + new ECBlocks(28, new ECB(29, 46), + new ECB(14, 47)), + new ECBlocks(30, new ECB(49, 24), + new ECB(10, 25)), + new ECBlocks(30, new ECB(24, 15), + new ECB(46, 16))), + new Version(38, Int32Array.from([6, 32, 58, 84, 110, 136, 162]), + new ECBlocks(30, new ECB(4, 122), + new ECB(18, 123)), + new ECBlocks(28, new ECB(13, 46), + new ECB(32, 47)), + new ECBlocks(30, new ECB(48, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(42, 15), + new ECB(32, 16))), + new Version(39, Int32Array.from([6, 26, 54, 82, 110, 138, 166]), + new ECBlocks(30, new ECB(20, 117), + new ECB(4, 118)), + new ECBlocks(28, new ECB(40, 47), + new ECB(7, 48)), + new ECBlocks(30, new ECB(43, 24), + new ECB(22, 25)), + new ECBlocks(30, new ECB(10, 15), + new ECB(67, 16))), + new Version(40, Int32Array.from([6, 30, 58, 86, 114, 142, 170]), + new ECBlocks(30, new ECB(19, 118), + new ECB(6, 119)), + new ECBlocks(28, new ECB(18, 47), + new ECB(31, 48)), + new ECBlocks(30, new ECB(34, 24), + new ECB(34, 25)), + new ECBlocks(30, new ECB(20, 15), + new ECB(61, 16))) + ]; - private ecBlocks: ECBlocks[]; - private totalCodewords: number; /*int*/ + private ecBlocks: ECBlocks[]; + private totalCodewords: number; /* int */ - private constructor(private versionNumber: number /*int*/, - private alignmentPatternCenters: Int32Array, - ...ecBlocks: ECBlocks[]) { - this.ecBlocks = ecBlocks; - let total = 0; - const ecCodewords = ecBlocks[0].getECCodewordsPerBlock(); - const ecbArray: ECB[] = ecBlocks[0].getECBlocks(); - for (const ecBlock of ecbArray) { - total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords); - } - this.totalCodewords = total; + private constructor(private versionNumber: number /* int */, + private alignmentPatternCenters: Int32Array, + ...ecBlocks: ECBlocks[]) { + this.ecBlocks = ecBlocks; + let total = 0; + const ecCodewords = ecBlocks[0].getECCodewordsPerBlock(); + const ecbArray: ECB[] = ecBlocks[0].getECBlocks(); + for (const ecBlock of ecbArray) { + total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords); } + this.totalCodewords = total; + } - public getVersionNumber(): number /*int*/ { - return this.versionNumber; - } + public getVersionNumber(): number /* int */ { + return this.versionNumber; + } - public getAlignmentPatternCenters(): Int32Array { - return this.alignmentPatternCenters; - } + public getAlignmentPatternCenters(): Int32Array { + return this.alignmentPatternCenters; + } - public getTotalCodewords(): number /*int*/ { - return this.totalCodewords; - } + public getTotalCodewords(): number /* int */ { + return this.totalCodewords; + } - public getDimensionForVersion(): number /*int*/ { - return 17 + 4 * this.versionNumber; - } + public getDimensionForVersion(): number /* int */ { + return 17 + 4 * this.versionNumber; + } - public getECBlocksForLevel(ecLevel: ErrorCorrectionLevel): ECBlocks { - return this.ecBlocks[ecLevel.getValue()]; - // TYPESCRIPTPORT: original was using ordinal, and using the order of levels as defined in ErrorCorrectionLevel enum (LMQH) - // I will use the direct value from ErrorCorrectionLevelValues enum which in typescript goes to a number - } + public getECBlocksForLevel(ecLevel: ErrorCorrectionLevel): ECBlocks { + return this.ecBlocks[ecLevel.getValue()]; + // TYPESCRIPTPORT: original was using ordinal, and using the order of levels as defined in ErrorCorrectionLevel enum (LMQH) + // I will use the direct value from ErrorCorrectionLevelValues enum which in typescript goes to a number + } - /** - *

Deduces version information purely from QR Code dimensions.

- * - * @param dimension dimension in modules - * @return Version for a QR Code of that dimension - * @throws FormatException if dimension is not 1 mod 4 - */ - public static getProvisionalVersionForDimension(dimension: number /*int*/): Version /*throws FormatException */ { - if (dimension % 4 !== 1) { - throw new FormatException(); - } - try { - return this.getVersionForNumber((dimension - 17) / 4); - } catch (ignored/*: IllegalArgumentException*/) { - throw new FormatException(); - } + /** + *

Deduces version information purely from QR Code dimensions.

+ * + * @param dimension dimension in modules + * @return Version for a QR Code of that dimension + * @throws FormatException if dimension is not 1 mod 4 + */ + public static getProvisionalVersionForDimension(dimension: number /* int */): Version /* throws FormatException */ { + if (dimension % 4 !== 1) { + throw new FormatException(); } + try { + return this.getVersionForNumber((dimension - 17) / 4); + } catch (ignored/* : IllegalArgumentException */) { + throw new FormatException(); + } + } - public static getVersionForNumber(versionNumber: number /*int*/): Version { - if (versionNumber < 1 || versionNumber > 40) { - throw new IllegalArgumentException(); - } - return Version.VERSIONS[versionNumber - 1]; + public static getVersionForNumber(versionNumber: number /* int */): Version { + if (versionNumber < 1 || versionNumber > 40) { + throw new IllegalArgumentException(); } + return Version.VERSIONS[versionNumber - 1]; + } - public static decodeVersionInformation(versionBits: number /*int*/): Version { - let bestDifference = Number.MAX_SAFE_INTEGER; - let bestVersion = 0; - for (let i = 0; i < Version.VERSION_DECODE_INFO.length; i++) { - const targetVersion = Version.VERSION_DECODE_INFO[i]; - // Do the version info bits match exactly? done. - if (targetVersion === versionBits) { - return Version.getVersionForNumber(i + 7); - } - // Otherwise see if this is the closest to a real version info bit string - // we have seen so far - const bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion); - if (bitsDifference < bestDifference) { - bestVersion = i + 7; - bestDifference = bitsDifference; - } - } - // We can tolerate up to 3 bits of error since no two version info codewords will - // differ in less than 8 bits. - if (bestDifference <= 3) { - return Version.getVersionForNumber(bestVersion); - } - // If we didn't find a close enough match, fail - return null; + public static decodeVersionInformation(versionBits: number /* int */): Version { + let bestDifference = Number.MAX_SAFE_INTEGER; + let bestVersion = 0; + for (let i = 0; i < Version.VERSION_DECODE_INFO.length; i++) { + const targetVersion = Version.VERSION_DECODE_INFO[i]; + // Do the version info bits match exactly? done. + if (targetVersion === versionBits) { + return Version.getVersionForNumber(i + 7); + } + // Otherwise see if this is the closest to a real version info bit string + // we have seen so far + const bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion); + if (bitsDifference < bestDifference) { + bestVersion = i + 7; + bestDifference = bitsDifference; + } + } + // We can tolerate up to 3 bits of error since no two version info codewords will + // differ in less than 8 bits. + if (bestDifference <= 3) { + return Version.getVersionForNumber(bestVersion); } + // If we didn't find a close enough match, fail + return null; + } - /** - * See ISO 18004:2006 Annex E - */ - public buildFunctionPattern(): BitMatrix { - const dimension = this.getDimensionForVersion(); - const bitMatrix = new BitMatrix(dimension); + /** + * See ISO 18004:2006 Annex E + */ + public buildFunctionPattern(): BitMatrix { + const dimension = this.getDimensionForVersion(); + const bitMatrix = new BitMatrix(dimension); - // Top left finder pattern + separator + format - bitMatrix.setRegion(0, 0, 9, 9); - // Top right finder pattern + separator + format - bitMatrix.setRegion(dimension - 8, 0, 8, 9); - // Bottom left finder pattern + separator + format - bitMatrix.setRegion(0, dimension - 8, 9, 8); + // Top left finder pattern + separator + format + bitMatrix.setRegion(0, 0, 9, 9); + // Top right finder pattern + separator + format + bitMatrix.setRegion(dimension - 8, 0, 8, 9); + // Bottom left finder pattern + separator + format + bitMatrix.setRegion(0, dimension - 8, 9, 8); - // Alignment patterns - const max = this.alignmentPatternCenters.length; - for (let x = 0; x < max; x++) { - const i = this.alignmentPatternCenters[x] - 2; - for (let y = 0; y < max; y++) { - if ((x === 0 && (y === 0 || y === max - 1)) || (x === max - 1 && y === 0)) { - // No alignment patterns near the three finder patterns - continue; - } - bitMatrix.setRegion(this.alignmentPatternCenters[y] - 2, i, 5, 5); - } + // Alignment patterns + const max = this.alignmentPatternCenters.length; + for (let x = 0; x < max; x++) { + const i = this.alignmentPatternCenters[x] - 2; + for (let y = 0; y < max; y++) { + if ((x === 0 && (y === 0 || y === max - 1)) || (x === max - 1 && y === 0)) { + // No alignment patterns near the three finder patterns + continue; } + bitMatrix.setRegion(this.alignmentPatternCenters[y] - 2, i, 5, 5); + } + } - // Vertical timing pattern - bitMatrix.setRegion(6, 9, 1, dimension - 17); - // Horizontal timing pattern - bitMatrix.setRegion(9, 6, dimension - 17, 1); - - if (this.versionNumber > 6) { - // Version info, top right - bitMatrix.setRegion(dimension - 11, 0, 3, 6); - // Version info, bottom left - bitMatrix.setRegion(0, dimension - 11, 6, 3); - } + // Vertical timing pattern + bitMatrix.setRegion(6, 9, 1, dimension - 17); + // Horizontal timing pattern + bitMatrix.setRegion(9, 6, dimension - 17, 1); - return bitMatrix; + if (this.versionNumber > 6) { + // Version info, top right + bitMatrix.setRegion(dimension - 11, 0, 3, 6); + // Version info, bottom left + bitMatrix.setRegion(0, dimension - 11, 6, 3); } - /*@Override*/ - public toString(): string { - return '' + this.versionNumber; - } + return bitMatrix; + } + + /* @Override */ + public toString(): string { + return '' + this.versionNumber; + } } diff --git a/src/core/qrcode/detector/AlignmentPattern.ts b/src/core/qrcode/detector/AlignmentPattern.ts index c3a896e3..108a4dc8 100644 --- a/src/core/qrcode/detector/AlignmentPattern.ts +++ b/src/core/qrcode/detector/AlignmentPattern.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.detector {*/ +/* namespace com.google.zxing.qrcode.detector { */ import ResultPoint from '../../ResultPoint'; @@ -26,31 +26,31 @@ import ResultPoint from '../../ResultPoint'; */ export default class AlignmentPattern extends ResultPoint { - public constructor(posX: number/*float*/, posY: number/*float*/, private estimatedModuleSize: number/*float*/) { - super(posX, posY); - } + public constructor(posX: number/* float */, posY: number/* float */, private estimatedModuleSize: number/* float */) { + super(posX, posY); + } - /** - *

Determines if this alignment pattern "about equals" an alignment pattern at the stated - * position and size -- meaning, it is at nearly the same center with nearly the same size.

- */ - public aboutEquals(moduleSize: number/*float*/, i: number/*float*/, j: number/*float*/): boolean { - if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) { - const moduleSizeDiff: number /*float*/ = Math.abs(moduleSize - this.estimatedModuleSize); - return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize; - } - return false; + /** + *

Determines if this alignment pattern "about equals" an alignment pattern at the stated + * position and size -- meaning, it is at nearly the same center with nearly the same size.

+ */ + public aboutEquals(moduleSize: number/* float */, i: number/* float */, j: number/* float */): boolean { + if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) { + const moduleSizeDiff: number /* float */ = Math.abs(moduleSize - this.estimatedModuleSize); + return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize; } + return false; + } - /** - * Combines this object's current estimate of a finder pattern position and module size - * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two. - */ - public combineEstimate(i: number/*float*/, j: number/*float*/, newModuleSize: number/*float*/): AlignmentPattern { - const combinedX: number /*float*/ = (this.getX() + j) / 2.0; - const combinedY: number /*float*/ = (this.getY() + i) / 2.0; - const combinedModuleSize: number /*float*/ = (this.estimatedModuleSize + newModuleSize) / 2.0; - return new AlignmentPattern(combinedX, combinedY, combinedModuleSize); - } + /** + * Combines this object's current estimate of a finder pattern position and module size + * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two. + */ + public combineEstimate(i: number/* float */, j: number/* float */, newModuleSize: number/* float */): AlignmentPattern { + const combinedX: number /* float */ = (this.getX() + j) / 2.0; + const combinedY: number /* float */ = (this.getY() + i) / 2.0; + const combinedModuleSize: number /* float */ = (this.estimatedModuleSize + newModuleSize) / 2.0; + return new AlignmentPattern(combinedX, combinedY, combinedModuleSize); + } } diff --git a/src/core/qrcode/detector/AlignmentPatternFinder.ts b/src/core/qrcode/detector/AlignmentPatternFinder.ts index 628d0831..e61f299a 100644 --- a/src/core/qrcode/detector/AlignmentPatternFinder.ts +++ b/src/core/qrcode/detector/AlignmentPatternFinder.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.detector {*/ +/* namespace com.google.zxing.qrcode.detector { */ import ResultPointCallback from '../../ResultPointCallback'; import BitMatrix from '../../common/BitMatrix'; @@ -22,8 +22,8 @@ import AlignmentPattern from './AlignmentPattern'; import NotFoundException from '../../NotFoundException'; -/*import java.util.ArrayList;*/ -/*import java.util.List;*/ +/* import java.util.ArrayList; */ +/* import java.util.List; */ /** *

This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder @@ -41,230 +41,230 @@ import NotFoundException from '../../NotFoundException'; */ export default class AlignmentPatternFinder { - private possibleCenters: AlignmentPattern[]; - private crossCheckStateCount: Int32Array; + private possibleCenters: AlignmentPattern[]; + private crossCheckStateCount: Int32Array; - /** - *

Creates a finder that will look in a portion of the whole image.

- * - * @param image image to search - * @param startX left column from which to start searching - * @param startY top row from which to start searching - * @param width width of region to search - * @param height height of region to search - * @param moduleSize estimated module size so far - */ - public constructor(private image: BitMatrix, - private startX: number /*int*/, - private startY: number /*int*/, - private width: number /*int*/, - private height: number /*int*/, - private moduleSize: number/*float*/, - private resultPointCallback: ResultPointCallback) { - this.possibleCenters = []; // new Array(5)) - // TYPESCRIPTPORT: array initialization without size as the length is checked below - this.crossCheckStateCount = new Int32Array(3); - } + /** + *

Creates a finder that will look in a portion of the whole image.

+ * + * @param image image to search + * @param startX left column from which to start searching + * @param startY top row from which to start searching + * @param width width of region to search + * @param height height of region to search + * @param moduleSize estimated module size so far + */ + public constructor(private image: BitMatrix, + private startX: number /* int */, + private startY: number /* int */, + private width: number /* int */, + private height: number /* int */, + private moduleSize: number/* float */, + private resultPointCallback: ResultPointCallback) { + this.possibleCenters = []; // new Array(5)) + // TYPESCRIPTPORT: array initialization without size as the length is checked below + this.crossCheckStateCount = new Int32Array(3); + } - /** - *

This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since - * it's pretty performance-critical and so is written to be fast foremost.

- * - * @return {@link AlignmentPattern} if found - * @throws NotFoundException if not found - */ - public find(): AlignmentPattern /*throws NotFoundException*/ { - const startX = this.startX; - const height = this.height; - const width = this.width; - const maxJ = startX + width; - const middleI = this.startY + (height / 2); - // We are looking for black/white/black modules in 1:1:1 ratio - // this tracks the number of black/white/black modules seen so far - const stateCount = new Int32Array(3); - const image = this.image; - for (let iGen = 0; iGen < height; iGen++) { - // Search from middle outwards - const i = middleI + ((iGen & 0x01) === 0 ? Math.floor((iGen + 1) / 2) : -Math.floor((iGen + 1) / 2)); + /** + *

This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since + * it's pretty performance-critical and so is written to be fast foremost.

+ * + * @return {@link AlignmentPattern} if found + * @throws NotFoundException if not found + */ + public find(): AlignmentPattern /* throws NotFoundException */ { + const startX = this.startX; + const height = this.height; + const width = this.width; + const maxJ = startX + width; + const middleI = this.startY + (height / 2); + // We are looking for black/white/black modules in 1:1:1 ratio + // this tracks the number of black/white/black modules seen so far + const stateCount = new Int32Array(3); + const image = this.image; + for (let iGen = 0; iGen < height; iGen++) { + // Search from middle outwards + const i = middleI + ((iGen & 0x01) === 0 ? Math.floor((iGen + 1) / 2) : -Math.floor((iGen + 1) / 2)); - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; + stateCount[0] = 0; + stateCount[1] = 0; + stateCount[2] = 0; - let j = startX; - // Burn off leading white pixels before anything else; if we start in the middle of - // a white run, it doesn't make sense to count its length, since we don't know if the - // white run continued to the left of the start point - while (j < maxJ && !image.get(j, i)) { - j++; - } - let currentState = 0; - while (j < maxJ) { - if (image.get(j, i)) { - // Black pixel - if (currentState === 1) { // Counting black pixels - stateCount[1]++; - } else { // Counting white pixels - if (currentState === 2) { // A winner? - if (this.foundPatternCross(stateCount)) { // Yes - const confirmed = this.handlePossibleCenter(stateCount, i, j); - if (confirmed !== null) { - return confirmed; - } - } - stateCount[0] = stateCount[2]; - stateCount[1] = 1; - stateCount[2] = 0; - currentState = 1; - } else { - stateCount[++currentState]++; - } - } - } else { // White pixel - if (currentState === 1) { // Counting black pixels - currentState++; - } - stateCount[currentState]++; - } - j++; - } - if (this.foundPatternCross(stateCount)) { - const confirmed = this.handlePossibleCenter(stateCount, i, maxJ); + let j = startX; + // Burn off leading white pixels before anything else; if we start in the middle of + // a white run, it doesn't make sense to count its length, since we don't know if the + // white run continued to the left of the start point + while (j < maxJ && !image.get(j, i)) { + j++; + } + let currentState = 0; + while (j < maxJ) { + if (image.get(j, i)) { + // Black pixel + if (currentState === 1) { // Counting black pixels + stateCount[1]++; + } else { // Counting white pixels + if (currentState === 2) { // A winner? + if (this.foundPatternCross(stateCount)) { // Yes + const confirmed = this.handlePossibleCenter(stateCount, i, j); if (confirmed !== null) { - return confirmed; + return confirmed; } + } + stateCount[0] = stateCount[2]; + stateCount[1] = 1; + stateCount[2] = 0; + currentState = 1; + } else { + stateCount[++currentState]++; } - + } + } else { // White pixel + if (currentState === 1) { // Counting black pixels + currentState++; + } + stateCount[currentState]++; } - - // Hmm, nothing we saw was observed and confirmed twice. If we had - // any guess at all, return it. - if (this.possibleCenters.length !== 0) { - return this.possibleCenters[0]; + j++; + } + if (this.foundPatternCross(stateCount)) { + const confirmed = this.handlePossibleCenter(stateCount, i, maxJ); + if (confirmed !== null) { + return confirmed; } + } - throw new NotFoundException(); } - /** - * Given a count of black/white/black pixels just seen and an end position, - * figures the location of the center of this black/white/black run. - */ - private static centerFromEnd(stateCount: Int32Array, end: number /*int*/): number/*float*/ { - return (end - stateCount[2]) - stateCount[1] / 2.0; + // Hmm, nothing we saw was observed and confirmed twice. If we had + // any guess at all, return it. + if (this.possibleCenters.length !== 0) { + return this.possibleCenters[0]; } - /** - * @param stateCount count of black/white/black pixels just read - * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios - * used by alignment patterns to be considered a match - */ - private foundPatternCross(stateCount: Int32Array): boolean { - const moduleSize: number /*float*/ = this.moduleSize; - const maxVariance: number /*float*/ = moduleSize / 2.0; - for (let i = 0; i < 3; i++) { - if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) { - return false; - } - } - return true; - } + throw new NotFoundException(); + } - /** - *

After a horizontal scan finds a potential alignment pattern, this method - * "cross-checks" by scanning down vertically through the center of the possible - * alignment pattern to see if the same proportion is detected.

- * - * @param startI row where an alignment pattern was detected - * @param centerJ center of the section that appears to cross an alignment pattern - * @param maxCount maximum reasonable number of modules that should be - * observed in any reading state, based on the results of the horizontal scan - * @return vertical center of alignment pattern, or {@link Float#NaN} if not found - */ - private crossCheckVertical(startI: number /*int*/, centerJ: number /*int*/, maxCount: number /*int*/, - originalStateCountTotal: number /*int*/): number/*float*/ { - const image = this.image; + /** + * Given a count of black/white/black pixels just seen and an end position, + * figures the location of the center of this black/white/black run. + */ + private static centerFromEnd(stateCount: Int32Array, end: number /* int */): number/* float */ { + return (end - stateCount[2]) - stateCount[1] / 2.0; + } - const maxI = image.getHeight(); - const stateCount = this.crossCheckStateCount; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; + /** + * @param stateCount count of black/white/black pixels just read + * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios + * used by alignment patterns to be considered a match + */ + private foundPatternCross(stateCount: Int32Array): boolean { + const moduleSize: number /* float */ = this.moduleSize; + const maxVariance: number /* float */ = moduleSize / 2.0; + for (let i = 0; i < 3; i++) { + if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) { + return false; + } + } + return true; + } - // Start counting up from center - let i = startI; - while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) { - stateCount[1]++; - i--; - } - // If already too many modules in this state or ran off the edge: - if (i < 0 || stateCount[1] > maxCount) { - return NaN; - } - while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) { - stateCount[0]++; - i--; - } - if (stateCount[0] > maxCount) { - return NaN; - } + /** + *

After a horizontal scan finds a potential alignment pattern, this method + * "cross-checks" by scanning down vertically through the center of the possible + * alignment pattern to see if the same proportion is detected.

+ * + * @param startI row where an alignment pattern was detected + * @param centerJ center of the section that appears to cross an alignment pattern + * @param maxCount maximum reasonable number of modules that should be + * observed in any reading state, based on the results of the horizontal scan + * @return vertical center of alignment pattern, or {@link Float#NaN} if not found + */ + private crossCheckVertical(startI: number /* int */, centerJ: number /* int */, maxCount: number /* int */, + originalStateCountTotal: number /* int */): number/* float */ { + const image = this.image; - // Now also count down from center - i = startI + 1; - while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) { - stateCount[1]++; - i++; - } - if (i === maxI || stateCount[1] > maxCount) { - return NaN; - } - while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) { - stateCount[2]++; - i++; - } - if (stateCount[2] > maxCount) { - return NaN; - } + const maxI = image.getHeight(); + const stateCount = this.crossCheckStateCount; + stateCount[0] = 0; + stateCount[1] = 0; + stateCount[2] = 0; - const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; - if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { - return NaN; - } + // Start counting up from center + let i = startI; + while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) { + stateCount[1]++; + i--; + } + // If already too many modules in this state or ran off the edge: + if (i < 0 || stateCount[1] > maxCount) { + return NaN; + } + while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) { + stateCount[0]++; + i--; + } + if (stateCount[0] > maxCount) { + return NaN; + } - return this.foundPatternCross(stateCount) ? AlignmentPatternFinder.centerFromEnd(stateCount, i) : NaN; + // Now also count down from center + i = startI + 1; + while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) { + stateCount[1]++; + i++; + } + if (i === maxI || stateCount[1] > maxCount) { + return NaN; + } + while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) { + stateCount[2]++; + i++; + } + if (stateCount[2] > maxCount) { + return NaN; } - /** - *

This is called when a horizontal scan finds a possible alignment pattern. It will - * cross check with a vertical scan, and if successful, will see if this pattern had been - * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have - * found the alignment pattern.

- * - * @param stateCount reading state module counts from horizontal scan - * @param i row where alignment pattern may be found - * @param j end of possible alignment pattern in row - * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not - */ - private handlePossibleCenter(stateCount: Int32Array, i: number /*int*/, j: number /*int*/): AlignmentPattern { - const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; - const centerJ: number /*float*/ = AlignmentPatternFinder.centerFromEnd(stateCount, j); - const centerI: number /*float*/ = this.crossCheckVertical(i, /*(int) */centerJ, 2 * stateCount[1], stateCountTotal); - if (!isNaN(centerI)) { - const estimatedModuleSize: number /*float*/ = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0; - for (const center of this.possibleCenters) { - // Look for about the same center and module size: - if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { - return center.combineEstimate(centerI, centerJ, estimatedModuleSize); - } - } - // Hadn't found this before; save it - const point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize); - this.possibleCenters.push(point); - if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) { - this.resultPointCallback.foundPossibleResultPoint(point); - } + const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; + if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { + return NaN; + } + + return this.foundPatternCross(stateCount) ? AlignmentPatternFinder.centerFromEnd(stateCount, i) : NaN; + } + + /** + *

This is called when a horizontal scan finds a possible alignment pattern. It will + * cross check with a vertical scan, and if successful, will see if this pattern had been + * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have + * found the alignment pattern.

+ * + * @param stateCount reading state module counts from horizontal scan + * @param i row where alignment pattern may be found + * @param j end of possible alignment pattern in row + * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not + */ + private handlePossibleCenter(stateCount: Int32Array, i: number /* int */, j: number /* int */): AlignmentPattern { + const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; + const centerJ: number /* float */ = AlignmentPatternFinder.centerFromEnd(stateCount, j); + const centerI: number /* float */ = this.crossCheckVertical(i, /* (int) */centerJ, 2 * stateCount[1], stateCountTotal); + if (!isNaN(centerI)) { + const estimatedModuleSize: number /* float */ = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0; + for (const center of this.possibleCenters) { + // Look for about the same center and module size: + if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { + return center.combineEstimate(centerI, centerJ, estimatedModuleSize); } - return null; + } + // Hadn't found this before; save it + const point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize); + this.possibleCenters.push(point); + if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) { + this.resultPointCallback.foundPossibleResultPoint(point); + } } + return null; + } } diff --git a/src/core/qrcode/detector/Detector.ts b/src/core/qrcode/detector/Detector.ts index 8da90249..f9e59546 100644 --- a/src/core/qrcode/detector/Detector.ts +++ b/src/core/qrcode/detector/Detector.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.detector {*/ +/* namespace com.google.zxing.qrcode.detector { */ import BitMatrix from '../../common/BitMatrix'; import MathUtils from '../../common/detector/MathUtils'; @@ -34,7 +34,7 @@ import FinderPatternFinder from './FinderPatternFinder'; import FinderPatternInfo from './FinderPatternInfo'; -/*import java.util.Map;*/ +/* import java.util.Map; */ /** *

Encapsulates logic that can detect a QR Code in an image, even if the QR Code @@ -62,8 +62,8 @@ export default class Detector { * @return {@link DetectorResult} encapsulating results of detecting a QR Code * @throws NotFoundException if QR Code cannot be found * @throws FormatException if a QR Code cannot be decoded - */ - // public detect(): DetectorResult /*throws NotFoundException, FormatException*/ { + */ + // public detect(): DetectorResult /*throws NotFoundException, FormatException */ { // return detect(null) // } @@ -74,11 +74,11 @@ export default class Detector { * @return {@link DetectorResult} encapsulating results of detecting a QR Code * @throws NotFoundException if QR Code cannot be found * @throws FormatException if a QR Code cannot be decoded - */ - public detect(hints: Map): DetectorResult /*throws NotFoundException, FormatException*/ { + */ + public detect(hints: Map): DetectorResult /* throws NotFoundException, FormatException */ { this.resultPointCallback = (hints === null || hints === undefined) ? null : - /*(ResultPointCallback) */hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); + /* (ResultPointCallback) */hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); const finder = new FinderPatternFinder(this.image, this.resultPointCallback); const info = finder.find(hints); @@ -92,7 +92,7 @@ export default class Detector { const topRight: FinderPattern = info.getTopRight(); const bottomLeft: FinderPattern = info.getBottomLeft(); - const moduleSize: number /*float*/ = this.calculateModuleSize(topLeft, topRight, bottomLeft); + const moduleSize: number /* float */ = this.calculateModuleSize(topLeft, topRight, bottomLeft); if (moduleSize < 1.0) { throw new NotFoundException('No pattern found in proccess finder.'); } @@ -105,14 +105,14 @@ export default class Detector { if (provisionalVersion.getAlignmentPatternCenters().length > 0) { // Guess where a "bottom right" finder pattern would have been - const bottomRightX: number /*float*/ = topRight.getX() - topLeft.getX() + bottomLeft.getX(); - const bottomRightY: number /*float*/ = topRight.getY() - topLeft.getY() + bottomLeft.getY(); + const bottomRightX: number /* float */ = topRight.getX() - topLeft.getX() + bottomLeft.getX(); + const bottomRightY: number /* float */ = topRight.getY() - topLeft.getY() + bottomLeft.getY(); // Estimate that alignment pattern is closer by 3 modules // from "bottom right" to known top left location - const correctionToTopLeft: number /*float*/ = 1.0 - 3.0 / modulesBetweenFPCenters; - const estAlignmentX = /*(int) */Math.floor(topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX())); - const estAlignmentY = /*(int) */Math.floor(topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY())); + const correctionToTopLeft: number /* float */ = 1.0 - 3.0 / modulesBetweenFPCenters; + const estAlignmentX = /* (int) */Math.floor(topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX())); + const estAlignmentY = /* (int) */Math.floor(topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY())); // Kind of arbitrary -- expand search radius before giving up for (let i = 4; i <= 16; i <<= 1) { @@ -122,7 +122,7 @@ export default class Detector { estAlignmentY, i); break; - } catch (re/*NotFoundException*/) { + } catch (re/* NotFoundException */) { if (!(re instanceof NotFoundException)) { throw re; } @@ -150,12 +150,12 @@ export default class Detector { topRight: ResultPoint, bottomLeft: ResultPoint, alignmentPattern: ResultPoint, - dimension: number /*int*/): PerspectiveTransform { - const dimMinusThree: number /*float*/ = dimension - 3.5; - let bottomRightX: number; /*float*/ - let bottomRightY: number; /*float*/ - let sourceBottomRightX: number; /*float*/ - let sourceBottomRightY: number; /*float*/ + dimension: number /* int */): PerspectiveTransform { + const dimMinusThree: number /* float */ = dimension - 3.5; + let bottomRightX: number; /* float */ + let bottomRightY: number; /* float */ + let sourceBottomRightX: number; /* float */ + let sourceBottomRightY: number; /* float */ if (alignmentPattern !== null) { bottomRightX = alignmentPattern.getX(); bottomRightY = alignmentPattern.getY(); @@ -190,7 +190,7 @@ export default class Detector { private static sampleGrid(image: BitMatrix, transform: PerspectiveTransform, - dimension: number /*int*/): BitMatrix /*throws NotFoundException*/ { + dimension: number /* int */): BitMatrix /* throws NotFoundException */ { const sampler = GridSamplerInstance.getInstance(); return sampler.sampleGridWithTransform(image, dimension, dimension, transform); @@ -199,11 +199,11 @@ export default class Detector { /** *

Computes the dimension (number of modules on a size) of the QR Code based on the position * of the finder patterns and estimated module size.

- */ + */ private static computeDimension(topLeft: ResultPoint, topRight: ResultPoint, bottomLeft: ResultPoint, - moduleSize: number/*float*/): number /*int*/ /*throws NotFoundException*/ { + moduleSize: number/* float */): number /* int */ /* throws NotFoundException */ { const tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize); const tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize); let dimension = Math.floor((tltrCentersDimension + tlblCentersDimension) / 2) + 7; @@ -229,10 +229,10 @@ export default class Detector { * @param topRight detected top-right finder pattern center * @param bottomLeft detected bottom-left finder pattern center * @return estimated module size - */ + */ protected calculateModuleSize(topLeft: ResultPoint, topRight: ResultPoint, - bottomLeft: ResultPoint): number/*float*/ { + bottomLeft: ResultPoint): number/* float */ { // Take the average return (this.calculateModuleSizeOneWay(topLeft, topRight) + this.calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0; @@ -242,16 +242,16 @@ export default class Detector { *

Estimates module size based on two finder patterns -- it uses * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the * width of each, measuring along the axis between their centers.

- */ - private calculateModuleSizeOneWay(pattern: ResultPoint, otherPattern: ResultPoint): number/*float*/ { - const moduleSizeEst1: number /*float*/ = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */Math.floor(pattern.getX()), - /*(int) */Math.floor(pattern.getY()), - /*(int) */Math.floor(otherPattern.getX()), - /*(int) */Math.floor(otherPattern.getY())); - const moduleSizeEst2: number /*float*/ = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */Math.floor(otherPattern.getX()), - /*(int) */Math.floor(otherPattern.getY()), - /*(int) */Math.floor(pattern.getX()), - /*(int) */Math.floor(pattern.getY())); + */ + private calculateModuleSizeOneWay(pattern: ResultPoint, otherPattern: ResultPoint): number/* float */ { + const moduleSizeEst1: number /* float */ = this.sizeOfBlackWhiteBlackRunBothWays(/* (int) */Math.floor(pattern.getX()), + /* (int) */Math.floor(pattern.getY()), + /* (int) */Math.floor(otherPattern.getX()), + /* (int) */Math.floor(otherPattern.getY())); + const moduleSizeEst2: number /* float */ = this.sizeOfBlackWhiteBlackRunBothWays(/* (int) */Math.floor(otherPattern.getX()), + /* (int) */Math.floor(otherPattern.getY()), + /* (int) */Math.floor(pattern.getX()), + /* (int) */Math.floor(pattern.getY())); if (isNaN(moduleSizeEst1)) { return moduleSizeEst2 / 7.0; } @@ -267,32 +267,32 @@ export default class Detector { * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of * a finder pattern by looking for a black-white-black run from the center in the direction * of another point (another finder pattern center), and in the opposite direction too. - */ - private sizeOfBlackWhiteBlackRunBothWays(fromX: number /*int*/, fromY: number /*int*/, toX: number /*int*/, toY: number /*int*/): number/*float*/ { + */ + private sizeOfBlackWhiteBlackRunBothWays(fromX: number /* int */, fromY: number /* int */, toX: number /* int */, toY: number /* int */): number/* float */ { - let result: number /*float*/ = this.sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY); + let result: number /* float */ = this.sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY); // Now count other way -- don't run off image though of course - let scale: number /*float*/ = 1.0; + let scale: number /* float */ = 1.0; let otherToX = fromX - (toX - fromX); if (otherToX < 0) { - scale = fromX / /*(float) */(fromX - otherToX); + scale = fromX / /* (float) */(fromX - otherToX); otherToX = 0; } else if (otherToX >= this.image.getWidth()) { - scale = (this.image.getWidth() - 1 - fromX) / /*(float) */(otherToX - fromX); + scale = (this.image.getWidth() - 1 - fromX) / /* (float) */(otherToX - fromX); otherToX = this.image.getWidth() - 1; } - let otherToY = /*(int) */Math.floor(fromY - (toY - fromY) * scale); + let otherToY = /* (int) */Math.floor(fromY - (toY - fromY) * scale); scale = 1.0; if (otherToY < 0) { - scale = fromY / /*(float) */(fromY - otherToY); + scale = fromY / /* (float) */(fromY - otherToY); otherToY = 0; } else if (otherToY >= this.image.getHeight()) { - scale = (this.image.getHeight() - 1 - fromY) / /*(float) */(otherToY - fromY); + scale = (this.image.getHeight() - 1 - fromY) / /* (float) */(otherToY - fromY); otherToY = this.image.getHeight() - 1; } - otherToX = /*(int) */Math.floor(fromX + (otherToX - fromX) * scale); + otherToX = /* (int) */Math.floor(fromX + (otherToX - fromX) * scale); result += this.sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY); @@ -307,8 +307,8 @@ export default class Detector { * *

This is used when figuring out how wide a finder pattern is, when the finder pattern * may be skewed or rotated.

- */ - private sizeOfBlackWhiteBlackRun(fromX: number /*int*/, fromY: number /*int*/, toX: number /*int*/, toY: number /*int*/): number/*float*/ { + */ + private sizeOfBlackWhiteBlackRun(fromX: number /* int */, fromY: number /* int */, toX: number /* int */, toY: number /* int */): number/* float */ { // Mild variant of Bresenham's algorithm // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm const steep: boolean = Math.abs(toY - fromY) > Math.abs(toX - fromX); @@ -374,14 +374,14 @@ export default class Detector { * @param allowanceFactor number of pixels in all directions to search from the center * @return {@link AlignmentPattern} if found, or null otherwise * @throws NotFoundException if an unexpected error occurs during detection - */ - protected findAlignmentInRegion(overallEstModuleSize: number/*float*/, - estAlignmentX: number /*int*/, - estAlignmentY: number /*int*/, - allowanceFactor: number/*float*/): AlignmentPattern { + */ + protected findAlignmentInRegion(overallEstModuleSize: number/* float */, + estAlignmentX: number /* int */, + estAlignmentY: number /* int */, + allowanceFactor: number/* float */): AlignmentPattern { // Look for an alignment pattern (3 modules in size) around where it // should be - const allowance = /*(int) */Math.floor(allowanceFactor * overallEstModuleSize); + const allowance = /* (int) */Math.floor(allowanceFactor * overallEstModuleSize); const alignmentAreaLeftX = Math.max(0, estAlignmentX - allowance); const alignmentAreaRightX = Math.min(this.image.getWidth() - 1, estAlignmentX + allowance); if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) { diff --git a/src/core/qrcode/detector/FinderPattern.ts b/src/core/qrcode/detector/FinderPattern.ts index b49bf1e7..0b182cae 100644 --- a/src/core/qrcode/detector/FinderPattern.ts +++ b/src/core/qrcode/detector/FinderPattern.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.detector {*/ +/* namespace com.google.zxing.qrcode.detector { */ import ResultPoint from '../../ResultPoint'; @@ -27,54 +27,54 @@ import ResultPoint from '../../ResultPoint'; */ export default class FinderPattern extends ResultPoint { - // FinderPattern(posX: number/*float*/, posY: number/*float*/, estimatedModuleSize: number/*float*/) { - // this(posX, posY, estimatedModuleSize, 1) - // } + // FinderPattern(posX: number/*float */, posY: number/*float */, estimatedModuleSize: number/*float */) { + // this(posX, posY, estimatedModuleSize, 1) + // } - public constructor(posX: number/*float*/, posY: number/*float*/, private estimatedModuleSize: number/*float*/, private count?: number /*int*/) { - super(posX, posY); - if (undefined === count) { - this.count = 1; - } + public constructor(posX: number/* float */, posY: number/* float */, private estimatedModuleSize: number/* float */, private count?: number /* int */) { + super(posX, posY); + if (undefined === count) { + this.count = 1; } + } - public getEstimatedModuleSize(): number/*float*/ { - return this.estimatedModuleSize; - } + public getEstimatedModuleSize(): number/* float */ { + return this.estimatedModuleSize; + } - public getCount(): number /*int*/ { - return this.count; - } + public getCount(): number /* int */ { + return this.count; + } - /* - void incrementCount() { - this.count++ - } - */ + /* + void incrementCount() { + this.count++ + } + */ - /** - *

Determines if this finder pattern "about equals" a finder pattern at the stated - * position and size -- meaning, it is at nearly the same center with nearly the same size.

- */ - public aboutEquals(moduleSize: number/*float*/, i: number/*float*/, j: number/*float*/): boolean { - if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) { - const moduleSizeDiff: number /*float*/ = Math.abs(moduleSize - this.estimatedModuleSize); - return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize; - } - return false; + /** + *

Determines if this finder pattern "about equals" a finder pattern at the stated + * position and size -- meaning, it is at nearly the same center with nearly the same size.

+ */ + public aboutEquals(moduleSize: number/* float */, i: number/* float */, j: number/* float */): boolean { + if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) { + const moduleSizeDiff: number /* float */ = Math.abs(moduleSize - this.estimatedModuleSize); + return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize; } + return false; + } - /** - * Combines this object's current estimate of a finder pattern position and module size - * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average - * based on count. - */ - public combineEstimate(i: number/*float*/, j: number/*float*/, newModuleSize: number/*float*/): FinderPattern { - const combinedCount = this.count + 1; - const combinedX: number /*float*/ = (this.count * this.getX() + j) / combinedCount; - const combinedY: number /*float*/ = (this.count * this.getY() + i) / combinedCount; - const combinedModuleSize: number /*float*/ = (this.count * this.estimatedModuleSize + newModuleSize) / combinedCount; - return new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount); - } + /** + * Combines this object's current estimate of a finder pattern position and module size + * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average + * based on count. + */ + public combineEstimate(i: number/* float */, j: number/* float */, newModuleSize: number/* float */): FinderPattern { + const combinedCount = this.count + 1; + const combinedX: number /* float */ = (this.count * this.getX() + j) / combinedCount; + const combinedY: number /* float */ = (this.count * this.getY() + i) / combinedCount; + const combinedModuleSize: number /* float */ = (this.count * this.estimatedModuleSize + newModuleSize) / combinedCount; + return new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount); + } } diff --git a/src/core/qrcode/detector/FinderPatternFinder.ts b/src/core/qrcode/detector/FinderPatternFinder.ts index 8415b19c..c987a1c9 100644 --- a/src/core/qrcode/detector/FinderPatternFinder.ts +++ b/src/core/qrcode/detector/FinderPatternFinder.ts @@ -14,25 +14,46 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.detector {*/ - +import BitMatrix from '../../common/BitMatrix'; import DecodeHintType from '../../DecodeHintType'; +import NotFoundException from '../../NotFoundException'; import ResultPoint from '../../ResultPoint'; import ResultPointCallback from '../../ResultPointCallback'; -import BitMatrix from '../../common/BitMatrix'; +import Arrays from '../../util/Arrays'; +import Comparator from '../../util/Comparator'; +import Double from '../../util/Double'; +import Float from '../../util/Float'; +import { double, float, int, List } from '../../../customTypings'; import FinderPattern from './FinderPattern'; import FinderPatternInfo from './FinderPatternInfo'; -import NotFoundException from '../../NotFoundException'; +// package com.google.zxing.qrcode.detector; -import { float } from '../../../customTypings'; +// import com.google.zxing.DecodeHintType; +// import com.google.zxing.NotFoundException; +// import com.google.zxing.ResultPoint; +// import com.google.zxing.ResultPointCallback; +// import com.google.zxing.common.BitMatrix; + +// import java.io.Serializable; +// import java.util.ArrayList; +// import java.util.Arrays; +// import java.util.Comparator; +// import java.util.List; +// import java.util.Map; + + +// TYPESCRIPTPORT: this class woudl normaly exist at the end of this file, but it's here due to ESLint. +/** + *

Orders by {@link FinderPattern#getEstimatedModuleSize()}

+ */ +/* private static final */ class EstimatedModuleComparator implements Comparator/*, Serializable*/ { + /** @override */ + public compare(center1: FinderPattern, center2: FinderPattern): int { + return Float.compare(center1.getEstimatedModuleSize(), center2.getEstimatedModuleSize()); + } +} -/*import java.io.Serializable;*/ -/*import java.util.ArrayList;*/ -/*import java.util.Collections;*/ -/*import java.util.Comparator;*/ -/*import java.util.List;*/ -/*import java.util.Map;*/ /** *

This class attempts to find finder patterns in a QR Code. Finder patterns are the square @@ -44,629 +65,644 @@ import { float } from '../../../customTypings'; */ export default class FinderPatternFinder { - private static CENTER_QUORUM = 2; - protected static MIN_SKIP = 3; // 1 pixel/module times 3 modules/center - protected static MAX_MODULES = 57; // support up to version 10 for mobile clients - - private possibleCenters: FinderPattern[]; - private hasSkipped: boolean; - private crossCheckStateCount: Int32Array; + private static /* final*/ CENTER_QUORUM: int = 2; + private static /* final*/ moduleComparator: EstimatedModuleComparator = new EstimatedModuleComparator(); + protected static /* final*/ MIN_SKIP: int = 3; // 1 pixel/module times 3 modules/center + protected static /* final*/ MAX_MODULES: int = 97; // support up to version 20 for mobile clients + + private /* final*/ image: BitMatrix; + private /* final*/ possibleCenters: List; + private hasSkipped: boolean; + private /* final*/ crossCheckStateCount: Int32Array; + private /* final*/ resultPointCallback: ResultPointCallback; + + /** + *

Creates a finder that will search the image for three finder patterns.

+ * + * @param image image to search + */ + private constructorOverload1(image: BitMatrix) { + this.constructorOverload2(image, null); + } /** - *

Creates a finder that will search the image for three finder patterns.

- * - * @param image image to search - */ - // public constructor(image: BitMatrix) { - // this(image, null) - // } - - public constructor(private image: BitMatrix, private resultPointCallback: ResultPointCallback) { - this.possibleCenters = []; - this.crossCheckStateCount = new Int32Array(5); - this.resultPointCallback = resultPointCallback; - } - - protected getImage(): BitMatrix { - return this.image; - } - - protected getPossibleCenters(): FinderPattern[] { - return this.possibleCenters; - } - - public find(hints: Map): FinderPatternInfo /*throws NotFoundException */ { - const tryHarder: boolean = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType.TRY_HARDER); - const pureBarcode: boolean = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType.PURE_BARCODE); - const image = this.image; - const maxI = image.getHeight(); - const maxJ = image.getWidth(); - // We are looking for black/white/black/white/black modules in - // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far - - // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the - // image, and then account for the center being 3 modules in size. This gives the smallest - // number of pixels the center could be, so skip this often. When trying harder, look for all - // QR versions regardless of how dense they are. - let iSkip = Math.floor((3 * maxI) / (4 * FinderPatternFinder.MAX_MODULES)); - if (iSkip < FinderPatternFinder.MIN_SKIP || tryHarder) { - iSkip = FinderPatternFinder.MIN_SKIP; - } + * @param image image to search + * @param resultPointCallback + */ + private constructorOverload2(image: BitMatrix, resultPointCallback: ResultPointCallback) { + this.image = image; + this.possibleCenters = new Array(); + this.crossCheckStateCount = Int32Array.from({ length: 5 }); + this.resultPointCallback = resultPointCallback; + } + + /** + * @param image image to search + */ + constructor(image: BitMatrix, resultPointCallback?: ResultPointCallback) { + // TYPESCRIPTPORT: this contructor only serves as entrypoint for the original Java overloads + if (resultPointCallback) { + this.constructorOverload2(image, resultPointCallback); + return; + } + this.constructorOverload1(image); + } + + protected /* final */ getImage(): BitMatrix { + return this.image; + } + + protected /* final */ getPossibleCenters(): List { + return this.possibleCenters; + } + + /** + * + * @throws NotFoundException + */ + /* final */ find(hints: Map): FinderPatternInfo { + const tryHarder: boolean = hints != null && hints.has(DecodeHintType.TRY_HARDER); + const maxI: int = this.image.getHeight(); + const maxJ: int = this.image.getWidth(); + // We are looking for black/white/black/white/black modules in + // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far + + // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the + // image, and then account for the center being 3 modules in size. This gives the smallest + // number of pixels the center could be, so skip this often. When trying harder, look for all + // QR versions regardless of how dense they are. + let iSkip: int = Math.trunc((3 * maxI) / (4 * FinderPatternFinder.MAX_MODULES)); + if (iSkip < FinderPatternFinder.MIN_SKIP || tryHarder) { + iSkip = FinderPatternFinder.MIN_SKIP; + } - let done: boolean = false; - const stateCount = new Int32Array(5); - for (let i = iSkip - 1; i < maxI && !done; i += iSkip) { - // Get a row of black/white values - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - let currentState = 0; - for (let j = 0; j < maxJ; j++) { - if (image.get(j, i)) { - // Black pixel - if ((currentState & 1) === 1) { // Counting white pixels - currentState++; - } - stateCount[currentState]++; - } else { // White pixel - if ((currentState & 1) === 0) { // Counting black pixels - if (currentState === 4) { // A winner? - if (FinderPatternFinder.foundPatternCross(stateCount)) { // Yes - const confirmed: boolean = this.handlePossibleCenter(stateCount, i, j, pureBarcode); - if (confirmed === true) { - // Start examining every other line. Checking each line turned out to be too - // expensive and didn't improve performance. - iSkip = 2; - if (this.hasSkipped === true) { - done = this.haveMultiplyConfirmedCenters(); - } else { - const rowSkip = this.findRowSkip(); - if (rowSkip > stateCount[2]) { - // Skip rows between row of lower confirmed center - // and top of presumed third confirmed center - // but back up a bit to get a full chance of detecting - // it, entire width of center of finder pattern - - // Skip by rowSkip, but back off by stateCount[2] (size of last center - // of pattern we saw) to be conservative, and also back off by iSkip which - // is about to be re-added - i += rowSkip - stateCount[2] - iSkip; - j = maxJ - 1; - } - } - } else { - stateCount[0] = stateCount[2]; - stateCount[1] = stateCount[3]; - stateCount[2] = stateCount[4]; - stateCount[3] = 1; - stateCount[4] = 0; - currentState = 3; - continue; - } - // Clear state to start looking again - currentState = 0; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - } else { // No, shift counts back by two - stateCount[0] = stateCount[2]; - stateCount[1] = stateCount[3]; - stateCount[2] = stateCount[4]; - stateCount[3] = 1; - stateCount[4] = 0; - currentState = 3; - } - } else { - stateCount[++currentState]++; - } - } else { // Counting white pixels - stateCount[currentState]++; - } - } - } - if (FinderPatternFinder.foundPatternCross(stateCount)) { - const confirmed: boolean = this.handlePossibleCenter(stateCount, i, maxJ, pureBarcode); - if (confirmed === true) { - iSkip = stateCount[0]; - if (this.hasSkipped) { - // Found a third one - done = this.haveMultiplyConfirmedCenters(); + let done: boolean = false; + const stateCount: Int32Array = Int32Array.from({ length: 5 }); + for (let i: int = iSkip - 1; i < maxI && !done; i += iSkip) { + // Get a row of black/white values + this.clearCounts(stateCount); + let currentState: int = 0; + for (let j: int = 0; j < maxJ; j++) { + if (this.image.get(j, i)) { + // Black pixel + if ((currentState & 1) === 1) { // Counting white pixels + currentState++; + } + stateCount[currentState]++; + } else { // White pixel + if ((currentState & 1) === 0) { // Counting black pixels + if (currentState === 4) { // A winner? + if (FinderPatternFinder.foundPatternCross(stateCount)) { // Yes + let confirmed: boolean = this.handlePossibleCenter(stateCount, i, j); + if (confirmed) { + // Start examining every other line. Checking each line turned out to be too + // expensive and didn't improve performance. + iSkip = 2; + if (this.hasSkipped) { + done = this.haveMultiplyConfirmedCenters(); + } else { + let rowSkip: int = this.findRowSkip(); + if (rowSkip > stateCount[2]) { + // Skip rows between row of lower confirmed center + // and top of presumed third confirmed center + // but back up a bit to get a full chance of detecting + // it, entire width of center of finder pattern + + // Skip by rowSkip, but back off by stateCount[2] (size of last center + // of pattern we saw) to be conservative, and also back off by iSkip which + // is about to be re-added + i += rowSkip - stateCount[2] - iSkip; + j = maxJ - 1; } + } + } else { + this.shiftCounts2(stateCount); + currentState = 3; + continue; } + // Clear state to start looking again + currentState = 0; + this.clearCounts(stateCount); + } else { // No, shift counts back by two + this.shiftCounts2(stateCount); + currentState = 3; + } + } else { + stateCount[++currentState]++; } - } - - const patternInfo: FinderPattern[] = this.selectBestPatterns(); - ResultPoint.orderBestPatterns(patternInfo); - - return new FinderPatternInfo(patternInfo); + } else { // Counting white pixels + stateCount[currentState]++; + } + } + } + if (FinderPatternFinder.foundPatternCross(stateCount)) { + let confirmed: boolean = this.handlePossibleCenter(stateCount, i, maxJ); + if (confirmed) { + iSkip = stateCount[0]; + if (this.hasSkipped) { + // Found a third one + done = this.haveMultiplyConfirmedCenters(); + } + } + } } - /** - * Given a count of black/white/black/white/black pixels just seen and an end position, - * figures the location of the center of this run. - */ - private static centerFromEnd(stateCount: Int32Array, end: number /*int*/): number/*float*/ { - return (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0; + const patternInfo: FinderPattern[] = this.selectBestPatterns(); + ResultPoint.orderBestPatterns(patternInfo); + + return new FinderPatternInfo(patternInfo); + } + + /** + * Given a count of black/white/black/white/black pixels just seen and an end position, + * figures the location of the center of this run. + */ + private static centerFromEnd(stateCount: Int32Array, end: int): float { + return (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0; + } + + /** + * @param stateCount count of black/white/black/white/black pixels just read + * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios + * used by finder patterns to be considered a match + */ + protected static foundPatternCross(stateCount: Int32Array): boolean { + let totalModuleSize: int = 0; + for (let i: int = 0; i < 5; i++) { + let count: int = stateCount[i]; + if (count === 0) { + return false; + } + totalModuleSize += count; } - - /** - * @param stateCount count of black/white/black/white/black pixels just read - * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios - * used by finder patterns to be considered a match - */ - protected static foundPatternCross(stateCount: Int32Array): boolean { - let totalModuleSize = 0; - for (let i = 0; i < 5; i++) { - const count = stateCount[i]; - if (count === 0) { - return false; - } - totalModuleSize += count; - } - if (totalModuleSize < 7) { - return false; - } - const moduleSize: number /*float*/ = totalModuleSize / 7.0; - const maxVariance: number /*float*/ = moduleSize / 2.0; - // Allow less than 50% variance from 1-1-3-1-1 proportions - return Math.abs(moduleSize - stateCount[0]) < maxVariance && - Math.abs(moduleSize - stateCount[1]) < maxVariance && - Math.abs(3.0 * moduleSize - stateCount[2]) < 3 * maxVariance && - Math.abs(moduleSize - stateCount[3]) < maxVariance && - Math.abs(moduleSize - stateCount[4]) < maxVariance; - } - - private getCrossCheckStateCount(): Int32Array { - const crossCheckStateCount = this.crossCheckStateCount; - crossCheckStateCount[0] = 0; - crossCheckStateCount[1] = 0; - crossCheckStateCount[2] = 0; - crossCheckStateCount[3] = 0; - crossCheckStateCount[4] = 0; - return crossCheckStateCount; + if (totalModuleSize < 7) { + return false; } - - /** - * After a vertical and horizontal scan finds a potential finder pattern, this method - * "cross-cross-cross-checks" by scanning down diagonally through the center of the possible - * finder pattern to see if the same proportion is detected. - * - * @param startI row where a finder pattern was detected - * @param centerJ center of the section that appears to cross a finder pattern - * @param maxCount maximum reasonable number of modules that should be - * observed in any reading state, based on the results of the horizontal scan - * @param originalStateCountTotal The original state count total. - * @return true if proportions are withing expected limits - */ - private crossCheckDiagonal(startI: number /*int*/, centerJ: number /*int*/, maxCount: number /*int*/, originalStateCountTotal: number /*int*/): boolean { - const stateCount: Int32Array = this.getCrossCheckStateCount(); - - // Start counting up, left from center finding black center mass - let i = 0; - const image = this.image; - while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i)) { - stateCount[2]++; - i++; - } - - if (startI < i || centerJ < i) { - return false; - } - - // Continue up, left finding white space - while (startI >= i && centerJ >= i && !image.get(centerJ - i, startI - i) && - stateCount[1] <= maxCount) { - stateCount[1]++; - i++; - } - - // If already too many modules in this state or ran off the edge: - if (startI < i || centerJ < i || stateCount[1] > maxCount) { - return false; - } - - // Continue up, left finding black border - while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i) && - stateCount[0] <= maxCount) { - stateCount[0]++; - i++; - } - if (stateCount[0] > maxCount) { - return false; - } - - const maxI = image.getHeight(); - const maxJ = image.getWidth(); - - // Now also count down, right from center - i = 1; - while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i)) { - stateCount[2]++; - i++; - } - - // Ran off the edge? - if (startI + i >= maxI || centerJ + i >= maxJ) { - return false; - } - - while (startI + i < maxI && centerJ + i < maxJ && !image.get(centerJ + i, startI + i) && - stateCount[3] < maxCount) { - stateCount[3]++; - i++; - } - - if (startI + i >= maxI || centerJ + i >= maxJ || stateCount[3] >= maxCount) { - return false; - } - - while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i) && - stateCount[4] < maxCount) { - stateCount[4]++; - i++; - } - - if (stateCount[4] >= maxCount) { - return false; - } - - // If we found a finder-pattern-like section, but its size is more than 100% different than - // the original, assume it's a false positive - const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; - return Math.abs(stateCountTotal - originalStateCountTotal) < 2 * originalStateCountTotal && - FinderPatternFinder.foundPatternCross(stateCount); + const moduleSize: float = totalModuleSize / 7.0; // TYPESCRIPTPORT: check if a precision reduction is needed + const maxVariance: float = moduleSize / 2.0; // TYPESCRIPTPORT: check if a precision reduction is needed + // Allow less than 50% variance from 1-1-3-1-1 proportions + return Math.abs(moduleSize - stateCount[0]) < maxVariance && + Math.abs(moduleSize - stateCount[1]) < maxVariance && + Math.abs(3.0 * moduleSize - stateCount[2]) < 3 * maxVariance && + Math.abs(moduleSize - stateCount[3]) < maxVariance && + Math.abs(moduleSize - stateCount[4]) < maxVariance; + } + + /** + * @param stateCount count of black/white/black/white/black pixels just read + * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios + * used by finder patterns to be considered a match + */ + protected static foundPatternDiagonal(stateCount: Int32Array): boolean { + let totalModuleSize: int = 0; + for (let i: int = 0; i < 5; i++) { + const count: int = stateCount[i]; + if (count === 0) { + return false; + } + totalModuleSize += count; + } + if (totalModuleSize < 7) { + return false; + } + const moduleSize: float = totalModuleSize / 7.0; + const maxVariance: float = moduleSize / 1.333; + // Allow less than 75% variance from 1-1-3-1-1 proportions + return Math.abs(moduleSize - stateCount[0]) < maxVariance && + Math.abs(moduleSize - stateCount[1]) < maxVariance && + Math.abs(3.0 * moduleSize - stateCount[2]) < 3 * maxVariance && + Math.abs(moduleSize - stateCount[3]) < maxVariance && + Math.abs(moduleSize - stateCount[4]) < maxVariance; + } + + private getCrossCheckStateCount(): Int32Array { + this.clearCounts(this.crossCheckStateCount); + return this.crossCheckStateCount; + } + + protected /* final */ clearCounts(counts: Int32Array): void { + Arrays.fill(counts, 0); + } + + protected /* final */ shiftCounts2(stateCount: Int32Array): void { + stateCount[0] = stateCount[2]; + stateCount[1] = stateCount[3]; + stateCount[2] = stateCount[4]; + stateCount[3] = 1; + stateCount[4] = 0; + } + + /** + * After a vertical and horizontal scan finds a potential finder pattern, this method + * "cross-cross-cross-checks" by scanning down diagonally through the center of the possible + * finder pattern to see if the same proportion is detected. + * + * @param centerI row where a finder pattern was detected + * @param centerJ center of the section that appears to cross a finder pattern + * @return true if proportions are withing expected limits + */ + private crossCheckDiagonal(centerI: int, centerJ: int): boolean { + const stateCount: Int32Array = this.getCrossCheckStateCount(); + + // Start counting up, left from center finding black center mass + let i: int = 0; + while (centerI >= i && centerJ >= i && this.image.get(centerJ - i, centerI - i)) { + stateCount[2]++; + i++; + } + if (stateCount[2] === 0) { + return false; } - /** - *

After a horizontal scan finds a potential finder pattern, this method - * "cross-checks" by scanning down vertically through the center of the possible - * finder pattern to see if the same proportion is detected.

- * - * @param startI row where a finder pattern was detected - * @param centerJ center of the section that appears to cross a finder pattern - * @param maxCount maximum reasonable number of modules that should be - * observed in any reading state, based on the results of the horizontal scan - * @return vertical center of finder pattern, or {@link Float#NaN} if not found - */ - private crossCheckVertical(startI: number /*int*/, centerJ: number /*int*/, maxCount: number /*int*/, - originalStateCountTotal: number /*int*/): number/*float*/ { - const image: BitMatrix = this.image; - - const maxI = image.getHeight(); - const stateCount: Int32Array = this.getCrossCheckStateCount(); - - // Start counting up from center - let i = startI; - while (i >= 0 && image.get(centerJ, i)) { - stateCount[2]++; - i--; - } - if (i < 0) { - return NaN; - } - while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) { - stateCount[1]++; - i--; - } - // If already too many modules in this state or ran off the edge: - if (i < 0 || stateCount[1] > maxCount) { - return NaN; - } - while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) { - stateCount[0]++; - i--; - } - if (stateCount[0] > maxCount) { - return NaN; - } + // Continue up, left finding white space + while (centerI >= i && centerJ >= i && !this.image.get(centerJ - i, centerI - i)) { + stateCount[1]++; + i++; + } + if (stateCount[1] === 0) { + return false; + } - // Now also count down from center - i = startI + 1; - while (i < maxI && image.get(centerJ, i)) { - stateCount[2]++; - i++; - } - if (i === maxI) { - return NaN; - } - while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) { - stateCount[3]++; - i++; - } - if (i === maxI || stateCount[3] >= maxCount) { - return NaN; - } - while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) { - stateCount[4]++; - i++; - } - if (stateCount[4] >= maxCount) { - return NaN; - } + // Continue up, left finding black border + while (centerI >= i && centerJ >= i && this.image.get(centerJ - i, centerI - i)) { + stateCount[0]++; + i++; + } + if (stateCount[0] === 0) { + return false; + } - // If we found a finder-pattern-like section, but its size is more than 40% different than - // the original, assume it's a false positive - const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + - stateCount[4]; - if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { - return NaN; - } + const maxI: int = this.image.getHeight(); + const maxJ: int = this.image.getWidth(); - return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, i) : NaN; + // Now also count down, right from center + i = 1; + while (centerI + i < maxI && centerJ + i < maxJ && this.image.get(centerJ + i, centerI + i)) { + stateCount[2]++; + i++; } - /** - *

Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical, - * except it reads horizontally instead of vertically. This is used to cross-cross - * check a vertical cross check and locate the real center of the alignment pattern.

- */ - private crossCheckHorizontal(startJ: number /*int*/, centerI: number /*int*/, maxCount: number /*int*/, - originalStateCountTotal: number /*int*/): number/*float*/ { - const image: BitMatrix = this.image; - - const maxJ = image.getWidth(); - const stateCount: Int32Array = this.getCrossCheckStateCount(); - - let j = startJ; - while (j >= 0 && image.get(j, centerI)) { - stateCount[2]++; - j--; - } - if (j < 0) { - return NaN; - } - while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) { - stateCount[1]++; - j--; - } - if (j < 0 || stateCount[1] > maxCount) { - return NaN; - } - while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) { - stateCount[0]++; - j--; - } - if (stateCount[0] > maxCount) { - return NaN; - } - - j = startJ + 1; - while (j < maxJ && image.get(j, centerI)) { - stateCount[2]++; - j++; - } - if (j === maxJ) { - return NaN; - } - while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) { - stateCount[3]++; - j++; - } - if (j === maxJ || stateCount[3] >= maxCount) { - return NaN; - } - while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) { - stateCount[4]++; - j++; - } - if (stateCount[4] >= maxCount) { - return NaN; - } + while (centerI + i < maxI && centerJ + i < maxJ && !this.image.get(centerJ + i, centerI + i)) { + stateCount[3]++; + i++; + } + if (stateCount[3] === 0) { + return false; + } - // If we found a finder-pattern-like section, but its size is significantly different than - // the original, assume it's a false positive - const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + - stateCount[4]; - if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) { - return NaN; - } + while (centerI + i < maxI && centerJ + i < maxJ && this.image.get(centerJ + i, centerI + i)) { + stateCount[4]++; + i++; + } + if (stateCount[4] === 0) { + return false; + } - return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, j) : NaN; + return FinderPatternFinder.foundPatternDiagonal(stateCount); + } + + /** + *

After a horizontal scan finds a potential finder pattern, this method + * "cross-checks" by scanning down vertically through the center of the possible + * finder pattern to see if the same proportion is detected.

+ * + * @param startI row where a finder pattern was detected + * @param centerJ center of the section that appears to cross a finder pattern + * @param maxCount maximum reasonable number of modules that should be + * observed in any reading state, based on the results of the horizontal scan + * @return vertical center of finder pattern, or {@link Float#NaN} if not found + */ + private crossCheckVertical(startI: int, centerJ: int, maxCount: int, + originalStateCountTotal: int): float { + const image: BitMatrix = this.image; + + const maxI: int = image.getHeight(); + let stateCount: Int32Array = this.getCrossCheckStateCount(); + + // Start counting up from center + let i: int = startI; + while (i >= 0 && image.get(centerJ, i)) { + stateCount[2]++; + i--; + } + if (i < 0) { + return Float.NaN; + } + while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) { + stateCount[1]++; + i--; + } + // If already too many modules in this state or ran off the edge: + if (i < 0 || stateCount[1] > maxCount) { + return Float.NaN; + } + while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) { + stateCount[0]++; + i--; + } + if (stateCount[0] > maxCount) { + return Float.NaN; } - /** - *

This is called when a horizontal scan finds a possible alignment pattern. It will - * cross check with a vertical scan, and if successful, will, ah, cross-cross-check - * with another horizontal scan. This is needed primarily to locate the real horizontal - * center of the pattern in cases of extreme skew. - * And then we cross-cross-cross check with another diagonal scan.

- * - *

If that succeeds the finder pattern location is added to a list that tracks - * the number of times each location has been nearly-matched as a finder pattern. - * Each additional find is more evidence that the location is in fact a finder - * pattern center - * - * @param stateCount reading state module counts from horizontal scan - * @param i row where finder pattern may be found - * @param j end of possible finder pattern in row - * @param pureBarcode true if in "pure barcode" mode - * @return true if a finder pattern candidate was found this time - */ - protected handlePossibleCenter(stateCount: Int32Array, i: number /*int*/, j: number /*int*/, pureBarcode: boolean): boolean { - const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + - stateCount[4]; - let centerJ: number /*float*/ = FinderPatternFinder.centerFromEnd(stateCount, j); - let centerI: number /*float*/ = this.crossCheckVertical(i, /*(int) */Math.floor(centerJ), stateCount[2], stateCountTotal); - if (!isNaN(centerI)) { - // Re-cross check - centerJ = this.crossCheckHorizontal(/*(int) */Math.floor(centerJ), /*(int) */Math.floor(centerI), stateCount[2], stateCountTotal); - if (!isNaN(centerJ) && - (!pureBarcode || this.crossCheckDiagonal(/*(int) */Math.floor(centerI), /*(int) */Math.floor(centerJ), stateCount[2], stateCountTotal))) { - const estimatedModuleSize: number /*float*/ = stateCountTotal / 7.0; - let found: boolean = false; - const possibleCenters = this.possibleCenters; - for (let index = 0, length = possibleCenters.length; index < length; index++) { - const center: FinderPattern = possibleCenters[index]; - // Look for about the same center and module size: - if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { - possibleCenters[index] = center.combineEstimate(centerI, centerJ, estimatedModuleSize); - found = true; - break; - } - } - if (!found) { - const point: FinderPattern = new FinderPattern(centerJ, centerI, estimatedModuleSize); - possibleCenters.push(point); - if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) { - this.resultPointCallback.foundPossibleResultPoint(point); - } - } - return true; - } - } - return false; + // Now also count down from center + i = startI + 1; + while (i < maxI && image.get(centerJ, i)) { + stateCount[2]++; + i++; + } + if (i === maxI) { + return Float.NaN; + } + while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) { + stateCount[3]++; + i++; + } + if (i === maxI || stateCount[3] >= maxCount) { + return Float.NaN; + } + while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) { + stateCount[4]++; + i++; + } + if (stateCount[4] >= maxCount) { + return Float.NaN; } - /** - * @return number of rows we could safely skip during scanning, based on the first - * two finder patterns that have been located. In some cases their position will - * allow us to infer that the third pattern must lie below a certain point farther - * down in the image. - */ - private findRowSkip(): number /*int*/ { - const max = this.possibleCenters.length; - if (max <= 1) { - return 0; - } - let firstConfirmedCenter: ResultPoint = null; - for (const center of this.possibleCenters) { - if (center.getCount() >= FinderPatternFinder.CENTER_QUORUM) { - if (firstConfirmedCenter == null) { - firstConfirmedCenter = center; - } else { - // We have two confirmed centers - // How far down can we skip before resuming looking for the next - // pattern? In the worst case, only the difference between the - // difference in the x / y coordinates of the two centers. - // This is the case where you find top left last. - this.hasSkipped = true; - return /*(int) */Math.floor((Math.abs(firstConfirmedCenter.getX() - center.getX()) - - Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2); - } - } - } - return 0; + // If we found a finder-pattern-like section, but its size is more than 40% different than + // the original, assume it's a false positive + const stateCountTotal: int = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + + stateCount[4]; + if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { + return Float.NaN; } - /** - * @return true iff we have found at least 3 finder patterns that have been detected - * at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the - * candidates is "pretty similar" - */ - private haveMultiplyConfirmedCenters(): boolean { - let confirmedCount = 0; - let totalModuleSize: number /*float*/ = 0.0; - const max = this.possibleCenters.length; - for (const pattern of this.possibleCenters) { - if (pattern.getCount() >= FinderPatternFinder.CENTER_QUORUM) { - confirmedCount++; - totalModuleSize += pattern.getEstimatedModuleSize(); - } - } - if (confirmedCount < 3) { - return false; - } - // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive" - // and that we need to keep looking. We detect this by asking if the estimated module sizes - // vary too much. We arbitrarily say that when the total deviation from average exceeds - // 5% of the total module size estimates, it's too much. - const average: number /*float*/ = totalModuleSize / max; - let totalDeviation: number /*float*/ = 0.0; - for (const pattern of this.possibleCenters) { - totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average); - } - return totalDeviation <= 0.05 * totalModuleSize; + return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, i) : Float.NaN; + } + + /** + *

Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical, + * except it reads horizontally instead of vertically. This is used to cross-cross + * check a vertical cross check and locate the real center of the alignment pattern.

+ */ + private crossCheckHorizontal(startJ: int, centerI: int, maxCount: int, + originalStateCountTotal: int): float { + const image: BitMatrix = this.image; + + const maxJ: int = image.getWidth(); + const stateCount: Int32Array = this.getCrossCheckStateCount(); + + let j: int = startJ; + while (j >= 0 && image.get(j, centerI)) { + stateCount[2]++; + j--; + } + if (j < 0) { + return Float.NaN; + } + while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) { + stateCount[1]++; + j--; + } + if (j < 0 || stateCount[1] > maxCount) { + return Float.NaN; + } + while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) { + stateCount[0]++; + j--; + } + if (stateCount[0] > maxCount) { + return Float.NaN; } - /** - * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are - * those that have been detected at least {@link #CENTER_QUORUM} times, and whose module - * size differs from the average among those patterns the least - * @throws NotFoundException if 3 such finder patterns do not exist - */ - private selectBestPatterns(): FinderPattern[] /*throws NotFoundException */ { - - const startSize = this.possibleCenters.length; - if (startSize < 3) { - // Couldn't find enough finder patterns - throw new NotFoundException(); - } + j = startJ + 1; + while (j < maxJ && image.get(j, centerI)) { + stateCount[2]++; + j++; + } + if (j === maxJ) { + return Float.NaN; + } + while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) { + stateCount[3]++; + j++; + } + if (j === maxJ || stateCount[3] >= maxCount) { + return Float.NaN; + } + while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) { + stateCount[4]++; + j++; + } + if (stateCount[4] >= maxCount) { + return Float.NaN; + } - const possibleCenters = this.possibleCenters; - - let average: float; - // Filter outlier possibilities whose module size is too different - if (startSize > 3) { - // But we can only afford to do so if we have at least 4 possibilities to choose from - let totalModuleSize: float = 0.0; - let square: float = 0.0; - for (const center of this.possibleCenters) { - const size: float = center.getEstimatedModuleSize(); - totalModuleSize += size; - square += size * size; - } - average = totalModuleSize / startSize; - let stdDev: float = Math.sqrt(square / startSize - average * average); - - possibleCenters.sort( - /** - *

Orders by furthest from average

- */ - // FurthestFromAverageComparator implements Comparator - (center1: FinderPattern, center2: FinderPattern) => { - const dA: float = Math.abs(center2.getEstimatedModuleSize() - average); - const dB: float = Math.abs(center1.getEstimatedModuleSize() - average); - return dA < dB ? -1 : dA > dB ? 1 : 0; - }); - - const limit: float = Math.max(0.2 * average, stdDev); - - for (let i = 0; i < possibleCenters.length && possibleCenters.length > 3; i++) { - const pattern: FinderPattern = possibleCenters[i]; - if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) { - possibleCenters.splice(i, 1); - i--; - } - } - } + // If we found a finder-pattern-like section, but its size is significantly different than + // the original, assume it's a false positive + const stateCountTotal: int = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + + stateCount[4]; + if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) { + return Float.NaN; + } - if (possibleCenters.length > 3) { - // Throw away all but those first size candidate points we found. + return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, j) : Float.NaN; + } + + /** + * @param stateCount reading state module counts from horizontal scan + * @param i row where finder pattern may be found + * @param j end of possible finder pattern in row + * @param pureBarcode ignored + * @return true if a finder pattern candidate was found this time + * @deprecated only exists for backwards compatibility + * @see #handlePossibleCenter(Int32Array, int, int) + * @Deprecated + */ + protected /* final */ handlePossibleCenterX(stateCount: Int32Array, i: int, j: int, pureBarcode: boolean): boolean { + return this.handlePossibleCenter(stateCount, i, j); + } + + /** + *

This is called when a horizontal scan finds a possible alignment pattern. It will + * cross check with a vertical scan, and if successful, will, ah, cross-cross-check + * with another horizontal scan. This is needed primarily to locate the real horizontal + * center of the pattern in cases of extreme skew. + * And then we cross-cross-cross check with another diagonal scan.

+ * + *

If that succeeds the finder pattern location is added to a list that tracks + * the number of times each location has been nearly-matched as a finder pattern. + * Each additional find is more evidence that the location is in fact a finder + * pattern center + * + * @param stateCount reading state module counts from horizontal scan + * @param i row where finder pattern may be found + * @param j end of possible finder pattern in row + * @return true if a finder pattern candidate was found this time + */ + protected /* final */ handlePossibleCenter(stateCount: Int32Array, i: int, j: int): boolean { + const stateCountTotal: int = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + + stateCount[4]; + let centerJ: float = FinderPatternFinder.centerFromEnd(stateCount, j); + const centerI: float = this.crossCheckVertical(i, centerJ, stateCount[2], stateCountTotal); + if (!Float.isNaN(centerI)) { + // Re-cross check + centerJ = this.crossCheckHorizontal(Math.trunc(centerJ), Math.trunc(centerI), stateCount[2], stateCountTotal); + if (!Float.isNaN(centerJ) && this.crossCheckDiagonal(Math.trunc(centerI), Math.trunc(centerJ))) { + const estimatedModuleSize: float = stateCountTotal / 7.0; + let found: boolean = false; + for (let index: int = 0; index < this.possibleCenters.length; index++) { + const center: FinderPattern = this.possibleCenters[index]; + // Look for about the same center and module size: + if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { + this.possibleCenters[index] = center.combineEstimate(centerI, centerJ, estimatedModuleSize); + found = true; + break; + } + } + if (!found) { + const point: FinderPattern = new FinderPattern(centerJ, centerI, estimatedModuleSize); + this.possibleCenters.push(point); + if (this.resultPointCallback != null) { + this.resultPointCallback.foundPossibleResultPoint(point); + } + } + return true; + } + } + return false; + } + + /** + * @return number of rows we could safely skip during scanning, based on the first + * two finder patterns that have been located. In some cases their position will + * allow us to infer that the third pattern must lie below a certain point farther + * down in the image. + */ + private findRowSkip(): int { + const max: int = this.possibleCenters.length; + if (max <= 1) { + return 0; + } + let firstConfirmedCenter: ResultPoint = null; + for (const center/*: FinderPattern*/ of this.possibleCenters) { + if (center.getCount() >= FinderPatternFinder.CENTER_QUORUM) { + if (firstConfirmedCenter == null) { + firstConfirmedCenter = center; + } else { + // We have two confirmed centers + // How far down can we skip before resuming looking for the next + // pattern? In the worst case, only the difference between the + // difference in the x / y coordinates of the two centers. + // This is the case where you find top left last. + this.hasSkipped = true; + return /* TYPESCRIPTPORT: Math.trunc here to emulate Java's `int` cast see CONTRIBUTING */ Math.trunc((Math.abs(firstConfirmedCenter.getX() - center.getX()) - + Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2); + } + } + } + return 0; + } + + /** + * @return true iff we have found at least 3 finder patterns that have been detected + * at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the + * candidates is "pretty similar" + */ + private haveMultiplyConfirmedCenters(): boolean { + let confirmedCount: int = 0; + let totalModuleSize: float = 0.0; + const max: int = this.possibleCenters.length; + for (const pattern/*: FinderPattern*/ of this.possibleCenters) { + if (pattern.getCount() >= FinderPatternFinder.CENTER_QUORUM) { + confirmedCount++; + totalModuleSize += pattern.getEstimatedModuleSize(); + } + } + if (confirmedCount < 3) { + return false; + } + // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive" + // and that we need to keep looking. We detect this by asking if the estimated module sizes + // vary too much. We arbitrarily say that when the total deviation from average exceeds + // 5% of the total module size estimates, it's too much. + const average: float = totalModuleSize / max; + let totalDeviation: float = 0.0; + for (const pattern/*: FinderPattern*/ of this.possibleCenters) { + totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average); + } + return totalDeviation <= 0.05 * totalModuleSize; + } + + /** + * Get square of distance between a and b. + */ + private static squaredDistance(a: FinderPattern, b: FinderPattern): double { + const x: double = a.getX() - b.getX(); + const y: double = a.getY() - b.getY(); + return x * x + y * y; + } + + /** + * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are + * those have similar module size and form a shape closer to a isosceles right triangle. + * @throws {@link NotFoundException} if 3 such finder patterns do not exist + */ + private selectBestPatterns(): FinderPattern[] { + + const startSize: int = this.possibleCenters.length; + if (startSize < 3) { + // Couldn't find enough finder patterns + throw NotFoundException.getNotFoundInstance(); + } - let totalModuleSize: float = 0.0; - for (const possibleCenter of possibleCenters) { - totalModuleSize += possibleCenter.getEstimatedModuleSize(); - } + this.possibleCenters.sort(FinderPatternFinder.moduleComparator.compare); + + let distortion: double = Double.MAX_VALUE; + const squares: Float64Array = Float64Array.from({ length: 3 }); + const bestPatterns: FinderPattern[] = new FinderPattern[3]; + + for (let i /*int*/ = 0; i < this.possibleCenters.length - 2; i++) { + const fpi: FinderPattern = this.possibleCenters[i]; + const minModuleSize: float = fpi.getEstimatedModuleSize(); + + for (let j /*int*/ = i + 1; j < this.possibleCenters.length - 1; j++) { + const fpj: FinderPattern = this.possibleCenters[j]; + const squares0: double = FinderPatternFinder.squaredDistance(fpi, fpj); + + for (let k /*int*/ = j + 1; k < this.possibleCenters.length; k++) { + const fpk: FinderPattern = this.possibleCenters[k]; + const maxModuleSize: float = fpk.getEstimatedModuleSize(); + if (maxModuleSize > minModuleSize * 1.4) { + // module size is not similar + continue; + } + + squares[0] = squares0; + squares[1] = FinderPatternFinder.squaredDistance(fpj, fpk); + squares[2] = FinderPatternFinder.squaredDistance(fpi, fpk); + Arrays.sort(squares); + + // a^2 + b^2 = c^2 (Pythagorean theorem), and a = b (isosceles triangle). + // Since any right triangle satisfies the formula c^2 - b^2 - a^2 = 0, + // we need to check both two equal sides separately. + // The value of |c^2 - 2 * b^2| + |c^2 - 2 * a^2| increases as dissimilarity + // from isosceles right triangle. + const d: double = Math.abs(squares[2] - 2 * squares[1]) + Math.abs(squares[2] - 2 * squares[0]); + if (d < distortion) { + distortion = d; + bestPatterns[0] = fpi; + bestPatterns[1] = fpj; + bestPatterns[2] = fpk; + } + } + } + } - average = totalModuleSize / possibleCenters.length; - - possibleCenters.sort( - /** - *

Orders by {@link FinderPattern#getCount()}, descending.

- */ - // CenterComparator implements Comparator - (center1: FinderPattern, center2: FinderPattern) => { - if (center2.getCount() === center1.getCount()) { - const dA: float = Math.abs(center2.getEstimatedModuleSize() - average); - const dB: float = Math.abs(center1.getEstimatedModuleSize() - average); - return dA < dB ? 1 : dA > dB ? -1 : 0; - } else { - return center2.getCount() - center1.getCount(); - } - }); + if (distortion === Double.MAX_VALUE) { + throw NotFoundException.getNotFoundInstance(); + } - possibleCenters.splice(3); // this is not realy necessary as we only return first 3 anyway - } + return bestPatterns; + } - return [ - possibleCenters[0], - possibleCenters[1], - possibleCenters[2] - ]; - } } diff --git a/src/core/qrcode/detector/FinderPatternInfo.ts b/src/core/qrcode/detector/FinderPatternInfo.ts index 520cbaa5..4b4ad657 100644 --- a/src/core/qrcode/detector/FinderPatternInfo.ts +++ b/src/core/qrcode/detector/FinderPatternInfo.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.detector {*/ +/* namespace com.google.zxing.qrcode.detector { */ import FinderPattern from './FinderPattern'; @@ -26,26 +26,26 @@ import FinderPattern from './FinderPattern'; */ export default class FinderPatternInfo { - private bottomLeft: FinderPattern; - private topLeft: FinderPattern; - private topRight: FinderPattern; + private bottomLeft: FinderPattern; + private topLeft: FinderPattern; + private topRight: FinderPattern; - public constructor(patternCenters: FinderPattern[]) { - this.bottomLeft = patternCenters[0]; - this.topLeft = patternCenters[1]; - this.topRight = patternCenters[2]; - } + public constructor(patternCenters: FinderPattern[]) { + this.bottomLeft = patternCenters[0]; + this.topLeft = patternCenters[1]; + this.topRight = patternCenters[2]; + } - public getBottomLeft(): FinderPattern { - return this.bottomLeft; - } + public getBottomLeft(): FinderPattern { + return this.bottomLeft; + } - public getTopLeft(): FinderPattern { - return this.topLeft; - } + public getTopLeft(): FinderPattern { + return this.topLeft; + } - public getTopRight(): FinderPattern { - return this.topRight; - } + public getTopRight(): FinderPattern { + return this.topRight; + } } diff --git a/src/core/qrcode/encoder/BlockPair.ts b/src/core/qrcode/encoder/BlockPair.ts index cc346a22..05a35ba2 100644 --- a/src/core/qrcode/encoder/BlockPair.ts +++ b/src/core/qrcode/encoder/BlockPair.ts @@ -14,18 +14,18 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.encoder {*/ +/* namespace com.google.zxing.qrcode.encoder { */ export default class BlockPair { - public constructor(private dataBytes: Uint8Array, private errorCorrectionBytes: Uint8Array) { } + public constructor(private dataBytes: Uint8Array, private errorCorrectionBytes: Uint8Array) { } - public getDataBytes(): Uint8Array { - return this.dataBytes; - } + public getDataBytes(): Uint8Array { + return this.dataBytes; + } - public getErrorCorrectionBytes(): Uint8Array { - return this.errorCorrectionBytes; - } + public getErrorCorrectionBytes(): Uint8Array { + return this.errorCorrectionBytes; + } } diff --git a/src/core/qrcode/encoder/ByteMatrix.ts b/src/core/qrcode/encoder/ByteMatrix.ts index 0fe3a401..b91e9863 100644 --- a/src/core/qrcode/encoder/ByteMatrix.ts +++ b/src/core/qrcode/encoder/ByteMatrix.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.encoder {*/ +/* namespace com.google.zxing.qrcode.encoder { */ -/*import java.util.Arrays;*/ +/* import java.util.Arrays; */ import Arrays from '../../util/Arrays'; import StringBuilder from '../../util/StringBuilder'; @@ -29,98 +29,98 @@ import StringBuilder from '../../util/StringBuilder'; */ export default class ByteMatrix { - private bytes: Array; + private bytes: Array; - public constructor(private width: number /*int*/, private height: number /*int*/) { - const bytes = new Array(height); // [height][width] - for (let i = 0; i !== height; i++) { - bytes[i] = new Uint8Array(width); - } - this.bytes = bytes; + public constructor(private width: number /* int */, private height: number /* int */) { + const bytes = new Array(height); // [height][width] + for (let i = 0; i !== height; i++) { + bytes[i] = new Uint8Array(width); } + this.bytes = bytes; + } - public getHeight(): number /*int*/ { - return this.height; - } + public getHeight(): number /* int */ { + return this.height; + } - public getWidth(): number /*int*/ { - return this.width; - } + public getWidth(): number /* int */ { + return this.width; + } - public get(x: number /*int*/, y: number /*int*/): number/*byte*/ { - return this.bytes[y][x]; - } + public get(x: number /* int */, y: number /* int */): number/* byte */ { + return this.bytes[y][x]; + } - /** - * @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y) - */ - public getArray(): Array { - return this.bytes; + /** + * @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y) + */ + public getArray(): Array { + return this.bytes; + } + + // TYPESCRIPTPORT: preffer to let two methods instead of override to avoid type comparison inside + public setNumber(x: number /* int */, y: number /* int */, value: number/* byte|int */): void { + this.bytes[y][x] = value; + } + + // public set(x: number /*int */, y: number /*int */, value: number /*int */): void { + // bytes[y][x] = (byte) value + // } + + public setBoolean(x: number /* int */, y: number /* int */, value: boolean): void { + this.bytes[y][x] = /* (byte) */(value ? 1 : 0); + } + + public clear(value: number/* byte */): void { + for (const aByte of this.bytes) { + Arrays.fill(aByte, value); } + } - // TYPESCRIPTPORT: preffer to let two methods instead of override to avoid type comparison inside - public setNumber(x: number /*int*/, y: number /*int*/, value: number/*byte|int*/): void { - this.bytes[y][x] = value; + public equals(o: any) { + if (!(o instanceof ByteMatrix)) { + return false; } - - // public set(x: number /*int*/, y: number /*int*/, value: number /*int*/): void { - // bytes[y][x] = (byte) value - // } - - public setBoolean(x: number /*int*/, y: number /*int*/, value: boolean): void { - this.bytes[y][x] = /*(byte) */(value ? 1 : 0); + const other = o; + if (this.width !== other.width) { + return false; } - - public clear(value: number/*byte*/): void { - for (const aByte of this.bytes) { - Arrays.fill(aByte, value); - } + if (this.height !== other.height) { + return false; } - - public equals(o: any) { - if (!(o instanceof ByteMatrix)) { - return false; - } - const other = o; - if (this.width !== other.width) { - return false; + for (let y = 0, height = this.height; y < height; ++y) { + const bytesY = this.bytes[y]; + const otherBytesY = other.bytes[y]; + for (let x = 0, width = this.width; x < width; ++x) { + if (bytesY[x] !== otherBytesY[x]) { + return false; } - if (this.height !== other.height) { - return false; - } - for (let y = 0, height = this.height; y < height; ++y) { - const bytesY = this.bytes[y]; - const otherBytesY = other.bytes[y]; - for (let x = 0, width = this.width; x < width; ++x) { - if (bytesY[x] !== otherBytesY[x]) { - return false; - } - } - } - return true; + } } - - /*@Override*/ - public toString(): string { - const result = new StringBuilder(); // (2 * width * height + 2) - for (let y = 0, height = this.height; y < height; ++y) { - const bytesY = this.bytes[y]; - for (let x = 0, width = this.width; x < width; ++x) { - switch (bytesY[x]) { - case 0: - result.append(' 0'); - break; - case 1: - result.append(' 1'); - break; - default: - result.append(' '); - break; - } - } - result.append('\n'); + return true; + } + + /* @Override */ + public toString(): string { + const result = new StringBuilder(); // (2 * width * height + 2) + for (let y = 0, height = this.height; y < height; ++y) { + const bytesY = this.bytes[y]; + for (let x = 0, width = this.width; x < width; ++x) { + switch (bytesY[x]) { + case 0: + result.append(' 0'); + break; + case 1: + result.append(' 1'); + break; + default: + result.append(' '); + break; } - return result.toString(); + } + result.append('\n'); } + return result.toString(); + } } diff --git a/src/core/qrcode/encoder/Encoder.ts b/src/core/qrcode/encoder/Encoder.ts index d7529a5f..6939bb18 100644 --- a/src/core/qrcode/encoder/Encoder.ts +++ b/src/core/qrcode/encoder/Encoder.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.encoder {*/ +/* namespace com.google.zxing.qrcode.encoder { */ import EncodeHintType from '../../EncodeHintType'; import BitArray from '../../common/BitArray'; @@ -34,10 +34,10 @@ import StringEncoding from '../../util/StringEncoding'; import BlockPair from './BlockPair'; import WriterException from '../../WriterException'; -/*import java.io.UnsupportedEncodingException;*/ -/*import java.util.ArrayList;*/ -/*import java.util.Collection;*/ -/*import java.util.Map;*/ +/* import java.io.UnsupportedEncodingException; */ +/* import java.util.ArrayList; */ +/* import java.util.Collection; */ +/* import java.util.Map; */ /** * @author satorux@google.com (Satoru Takabayashi) - creator @@ -45,595 +45,595 @@ import WriterException from '../../WriterException'; */ export default class Encoder { - // The original table is defined in the table 5 of JISX0510:2004 (p.19). - private static ALPHANUMERIC_TABLE = Int32Array.from([ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f - 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f - ]); - - public static DEFAULT_BYTE_MODE_ENCODING = CharacterSetECI.UTF8.getName(); // "ISO-8859-1" - // TYPESCRIPTPORT: changed to UTF8, the default for js - - private constructor() { } - - // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details. - // Basically it applies four rules and summate all penalties. - private static calculateMaskPenalty(matrix: ByteMatrix): number /*int*/ { - return MaskUtil.applyMaskPenaltyRule1(matrix) - + MaskUtil.applyMaskPenaltyRule2(matrix) - + MaskUtil.applyMaskPenaltyRule3(matrix) - + MaskUtil.applyMaskPenaltyRule4(matrix); - } - - /** - * @param content text to encode - * @param ecLevel error correction level to use - * @return {@link QRCode} representing the encoded QR code - * @throws WriterException if encoding can't succeed, because of for example invalid content - * or configuration - */ - // public static encode(content: string, ecLevel: ErrorCorrectionLevel): QRCode /*throws WriterException*/ { - // return encode(content, ecLevel, null) - // } - - public static encode(content: string, - ecLevel: ErrorCorrectionLevel, - hints: Map = null): QRCode /*throws WriterException*/ { - - // Determine what character encoding has been specified by the caller, if any - let encoding: string = Encoder.DEFAULT_BYTE_MODE_ENCODING; - const hasEncodingHint: boolean = hints !== null && undefined !== hints.get(EncodeHintType.CHARACTER_SET); - if (hasEncodingHint) { - encoding = hints.get(EncodeHintType.CHARACTER_SET).toString(); - } + // The original table is defined in the table 5 of JISX0510:2004 (p.19). + private static ALPHANUMERIC_TABLE = Int32Array.from([ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f + ]); + + public static DEFAULT_BYTE_MODE_ENCODING = CharacterSetECI.UTF8.getName(); // "ISO-8859-1" + // TYPESCRIPTPORT: changed to UTF8, the default for js + + private constructor() { } + + // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details. + // Basically it applies four rules and summate all penalties. + private static calculateMaskPenalty(matrix: ByteMatrix): number /* int */ { + return MaskUtil.applyMaskPenaltyRule1(matrix) + + MaskUtil.applyMaskPenaltyRule2(matrix) + + MaskUtil.applyMaskPenaltyRule3(matrix) + + MaskUtil.applyMaskPenaltyRule4(matrix); + } + + /** + * @param content text to encode + * @param ecLevel error correction level to use + * @return {@link QRCode} representing the encoded QR code + * @throws WriterException if encoding can't succeed, because of for example invalid content + * or configuration + */ + // public static encode(content: string, ecLevel: ErrorCorrectionLevel): QRCode /*throws WriterException */ { + // return encode(content, ecLevel, null) + // } + + public static encode(content: string, + ecLevel: ErrorCorrectionLevel, + hints: Map = null): QRCode /* throws WriterException */ { + + // Determine what character encoding has been specified by the caller, if any + let encoding: string = Encoder.DEFAULT_BYTE_MODE_ENCODING; + const hasEncodingHint: boolean = hints !== null && undefined !== hints.get(EncodeHintType.CHARACTER_SET); + if (hasEncodingHint) { + encoding = hints.get(EncodeHintType.CHARACTER_SET).toString(); + } - // Pick an encoding mode appropriate for the content. Note that this will not attempt to use - // multiple modes / segments even if that were more efficient. Twould be nice. - const mode: Mode = this.chooseMode(content, encoding); + // Pick an encoding mode appropriate for the content. Note that this will not attempt to use + // multiple modes / segments even if that were more efficient. Twould be nice. + const mode: Mode = this.chooseMode(content, encoding); - // This will store the header information, like mode and - // length, as well as "header" segments like an ECI segment. - const headerBits = new BitArray(); + // This will store the header information, like mode and + // length, as well as "header" segments like an ECI segment. + const headerBits = new BitArray(); - // Append ECI segment if applicable - if (mode === Mode.BYTE && (hasEncodingHint || Encoder.DEFAULT_BYTE_MODE_ENCODING !== encoding)) { - const eci = CharacterSetECI.getCharacterSetECIByName(encoding); - if (eci !== undefined) { - this.appendECI(eci, headerBits); - } - } + // Append ECI segment if applicable + if (mode === Mode.BYTE && (hasEncodingHint || Encoder.DEFAULT_BYTE_MODE_ENCODING !== encoding)) { + const eci = CharacterSetECI.getCharacterSetECIByName(encoding); + if (eci !== undefined) { + this.appendECI(eci, headerBits); + } + } - // (With ECI in place,) Write the mode marker - this.appendModeInfo(mode, headerBits); - - // Collect data within the main segment, separately, to count its size if needed. Don't add it to - // main payload yet. - const dataBits = new BitArray(); - this.appendBytes(content, mode, dataBits, encoding); - - let version: Version; - if (hints !== null && undefined !== hints.get(EncodeHintType.QR_VERSION)) { - const versionNumber = Number.parseInt(hints.get(EncodeHintType.QR_VERSION).toString(), 10); - version = Version.getVersionForNumber(versionNumber); - const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, version); - if (!this.willFit(bitsNeeded, version, ecLevel)) { - throw new WriterException('Data too big for requested version'); - } - } else { - version = this.recommendVersion(ecLevel, mode, headerBits, dataBits); - } + // (With ECI in place,) Write the mode marker + this.appendModeInfo(mode, headerBits); + + // Collect data within the main segment, separately, to count its size if needed. Don't add it to + // main payload yet. + const dataBits = new BitArray(); + this.appendBytes(content, mode, dataBits, encoding); + + let version: Version; + if (hints !== null && undefined !== hints.get(EncodeHintType.QR_VERSION)) { + const versionNumber = Number.parseInt(hints.get(EncodeHintType.QR_VERSION).toString(), 10); + version = Version.getVersionForNumber(versionNumber); + const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, version); + if (!this.willFit(bitsNeeded, version, ecLevel)) { + throw new WriterException('Data too big for requested version'); + } + } else { + version = this.recommendVersion(ecLevel, mode, headerBits, dataBits); + } - const headerAndDataBits = new BitArray(); - headerAndDataBits.appendBitArray(headerBits); - // Find "length" of main segment and write it - const numLetters = mode === Mode.BYTE ? dataBits.getSizeInBytes() : content.length; - this.appendLengthInfo(numLetters, version, mode, headerAndDataBits); - // Put data together into the overall payload - headerAndDataBits.appendBitArray(dataBits); - - const ecBlocks: ECBlocks = version.getECBlocksForLevel(ecLevel); - const numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords(); - - // Terminate the bits properly. - this.terminateBits(numDataBytes, headerAndDataBits); - - // Interleave data bits with error correction code. - const finalBits: BitArray = this.interleaveWithECBytes(headerAndDataBits, - version.getTotalCodewords(), - numDataBytes, - ecBlocks.getNumBlocks()); - - const qrCode = new QRCode(); - - qrCode.setECLevel(ecLevel); - qrCode.setMode(mode); - qrCode.setVersion(version); - - // Choose the mask pattern and set to "qrCode". - const dimension = version.getDimensionForVersion(); - const matrix: ByteMatrix = new ByteMatrix(dimension, dimension); - const maskPattern = this.chooseMaskPattern(finalBits, ecLevel, version, matrix); - qrCode.setMaskPattern(maskPattern); - - // Build the matrix and set it to "qrCode". - MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix); - qrCode.setMatrix(matrix); - - return qrCode; - } - - /** - * Decides the smallest version of QR code that will contain all of the provided data. - * - * @throws WriterException if the data cannot fit in any version - */ - private static recommendVersion(ecLevel: ErrorCorrectionLevel, - mode: Mode, - headerBits: BitArray, - dataBits: BitArray): Version /*throws WriterException*/ { - // Hard part: need to know version to know how many bits length takes. But need to know how many - // bits it takes to know version. First we take a guess at version by assuming version will be - // the minimum, 1: - const provisionalBitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, Version.getVersionForNumber(1)); - const provisionalVersion = this.chooseVersion(provisionalBitsNeeded, ecLevel); - - // Use that guess to calculate the right version. I am still not sure this works in 100% of cases. - const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, provisionalVersion); - return this.chooseVersion(bitsNeeded, ecLevel); - } - - private static calculateBitsNeeded(mode: Mode, - headerBits: BitArray, - dataBits: BitArray, - version: Version): number /*int*/ { - return headerBits.getSize() + mode.getCharacterCountBits(version) + dataBits.getSize(); - } - - /** - * @return the code point of the table used in alphanumeric mode or - * -1 if there is no corresponding code in the table. - */ - public static getAlphanumericCode(code: number /*int*/): number /*int*/ { - if (code < Encoder.ALPHANUMERIC_TABLE.length) { - return Encoder.ALPHANUMERIC_TABLE[code]; - } - return -1; + const headerAndDataBits = new BitArray(); + headerAndDataBits.appendBitArray(headerBits); + // Find "length" of main segment and write it + const numLetters = mode === Mode.BYTE ? dataBits.getSizeInBytes() : content.length; + this.appendLengthInfo(numLetters, version, mode, headerAndDataBits); + // Put data together into the overall payload + headerAndDataBits.appendBitArray(dataBits); + + const ecBlocks: ECBlocks = version.getECBlocksForLevel(ecLevel); + const numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords(); + + // Terminate the bits properly. + this.terminateBits(numDataBytes, headerAndDataBits); + + // Interleave data bits with error correction code. + const finalBits: BitArray = this.interleaveWithECBytes(headerAndDataBits, + version.getTotalCodewords(), + numDataBytes, + ecBlocks.getNumBlocks()); + + const qrCode = new QRCode(); + + qrCode.setECLevel(ecLevel); + qrCode.setMode(mode); + qrCode.setVersion(version); + + // Choose the mask pattern and set to "qrCode". + const dimension = version.getDimensionForVersion(); + const matrix: ByteMatrix = new ByteMatrix(dimension, dimension); + const maskPattern = this.chooseMaskPattern(finalBits, ecLevel, version, matrix); + qrCode.setMaskPattern(maskPattern); + + // Build the matrix and set it to "qrCode". + MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix); + qrCode.setMatrix(matrix); + + return qrCode; + } + + /** + * Decides the smallest version of QR code that will contain all of the provided data. + * + * @throws WriterException if the data cannot fit in any version + */ + private static recommendVersion(ecLevel: ErrorCorrectionLevel, + mode: Mode, + headerBits: BitArray, + dataBits: BitArray): Version /* throws WriterException */ { + // Hard part: need to know version to know how many bits length takes. But need to know how many + // bits it takes to know version. First we take a guess at version by assuming version will be + // the minimum, 1: + const provisionalBitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, Version.getVersionForNumber(1)); + const provisionalVersion = this.chooseVersion(provisionalBitsNeeded, ecLevel); + + // Use that guess to calculate the right version. I am still not sure this works in 100% of cases. + const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, provisionalVersion); + return this.chooseVersion(bitsNeeded, ecLevel); + } + + private static calculateBitsNeeded(mode: Mode, + headerBits: BitArray, + dataBits: BitArray, + version: Version): number /* int */ { + return headerBits.getSize() + mode.getCharacterCountBits(version) + dataBits.getSize(); + } + + /** + * @return the code point of the table used in alphanumeric mode or + * -1 if there is no corresponding code in the table. + */ + public static getAlphanumericCode(code: number /* int */): number /* int */ { + if (code < Encoder.ALPHANUMERIC_TABLE.length) { + return Encoder.ALPHANUMERIC_TABLE[code]; } + return -1; + } - // public static chooseMode(content: string): Mode { - // return chooseMode(content, null); - // } + // public static chooseMode(content: string): Mode { + // return chooseMode(content, null); + // } - /** - * Choose the best mode by examining the content. Note that 'encoding' is used as a hint; - * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}. - */ - public static chooseMode(content: string, encoding: string = null): Mode { - if (CharacterSetECI.SJIS.getName() === encoding && this.isOnlyDoubleByteKanji(content)) { - // Choose Kanji mode if all input are double-byte characters - return Mode.KANJI; - } - let hasNumeric: boolean = false; - let hasAlphanumeric: boolean = false; - for (let i = 0, length = content.length; i < length; ++i) { - const c: string = content.charAt(i); - if (Encoder.isDigit(c)) { - hasNumeric = true; - } else if (this.getAlphanumericCode(c.charCodeAt(0)) !== -1) { - hasAlphanumeric = true; - } else { - return Mode.BYTE; - } - } - if (hasAlphanumeric) { - return Mode.ALPHANUMERIC; - } - if (hasNumeric) { - return Mode.NUMERIC; - } + /** + * Choose the best mode by examining the content. Note that 'encoding' is used as a hint; + * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}. + */ + public static chooseMode(content: string, encoding: string = null): Mode { + if (CharacterSetECI.SJIS.getName() === encoding && this.isOnlyDoubleByteKanji(content)) { + // Choose Kanji mode if all input are double-byte characters + return Mode.KANJI; + } + let hasNumeric: boolean = false; + let hasAlphanumeric: boolean = false; + for (let i = 0, length = content.length; i < length; ++i) { + const c: string = content.charAt(i); + if (Encoder.isDigit(c)) { + hasNumeric = true; + } else if (this.getAlphanumericCode(c.charCodeAt(0)) !== -1) { + hasAlphanumeric = true; + } else { return Mode.BYTE; + } } - - private static isOnlyDoubleByteKanji(content: string): boolean { - let bytes: Uint8Array; - try { - bytes = StringEncoding.encode(content, CharacterSetECI.SJIS); // content.getBytes("Shift_JIS")) - } catch (ignored/*: UnsupportedEncodingException*/) { - return false; - } - const length = bytes.length; - if (length % 2 !== 0) { - return false; - } - for (let i = 0; i < length; i += 2) { - const byte1 = bytes[i] & 0xFF; - if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) { - return false; - } - } - return true; - } - - private static chooseMaskPattern(bits: BitArray, - ecLevel: ErrorCorrectionLevel, - version: Version, - matrix: ByteMatrix): number /*int*/ /*throws WriterException*/ { - - let minPenalty = Number.MAX_SAFE_INTEGER; // Lower penalty is better. - let bestMaskPattern = -1; - // We try all mask patterns to choose the best one. - for (let maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) { - MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix); - let penalty = this.calculateMaskPenalty(matrix); - if (penalty < minPenalty) { - minPenalty = penalty; - bestMaskPattern = maskPattern; - } - } - return bestMaskPattern; + if (hasAlphanumeric) { + return Mode.ALPHANUMERIC; } - - private static chooseVersion(numInputBits: number /*int*/, ecLevel: ErrorCorrectionLevel): Version /*throws WriterException*/ { - for (let versionNum = 1; versionNum <= 40; versionNum++) { - const version = Version.getVersionForNumber(versionNum); - if (Encoder.willFit(numInputBits, version, ecLevel)) { - return version; - } - } - throw new WriterException('Data too big'); - } - - /** - * @return true if the number of input bits will fit in a code with the specified version and - * error correction level. - */ - private static willFit(numInputBits: number /*int*/, version: Version, ecLevel: ErrorCorrectionLevel): boolean { - // In the following comments, we use numbers of Version 7-H. - // numBytes = 196 - const numBytes = version.getTotalCodewords(); - // getNumECBytes = 130 - const ecBlocks = version.getECBlocksForLevel(ecLevel); - const numEcBytes = ecBlocks.getTotalECCodewords(); - // getNumDataBytes = 196 - 130 = 66 - const numDataBytes = numBytes - numEcBytes; - const totalInputBytes = (numInputBits + 7) / 8; - return numDataBytes >= totalInputBytes; - } - - /** - * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). - */ - public static terminateBits(numDataBytes: number /*int*/, bits: BitArray): void /*throws WriterException*/ { - const capacity = numDataBytes * 8; - if (bits.getSize() > capacity) { - throw new WriterException('data bits cannot fit in the QR Code' + bits.getSize() + ' > ' + - capacity); - } - for (let i = 0; i < 4 && bits.getSize() < capacity; ++i) { - bits.appendBit(false); - } - // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details. - // If the last byte isn't 8-bit aligned, we'll add padding bits. - const numBitsInLastByte = bits.getSize() & 0x07; - if (numBitsInLastByte > 0) { - for (let i = numBitsInLastByte; i < 8; i++) { - bits.appendBit(false); - } - } - // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). - const numPaddingBytes = numDataBytes - bits.getSizeInBytes(); - for (let i = 0; i < numPaddingBytes; ++i) { - bits.appendBits((i & 0x01) === 0 ? 0xEC : 0x11, 8); - } - if (bits.getSize() !== capacity) { - throw new WriterException('Bits size does not equal capacity'); - } + if (hasNumeric) { + return Mode.NUMERIC; + } + return Mode.BYTE; + } + + private static isOnlyDoubleByteKanji(content: string): boolean { + let bytes: Uint8Array; + try { + bytes = StringEncoding.encode(content, CharacterSetECI.SJIS); // content.getBytes("Shift_JIS")) + } catch (ignored/* : UnsupportedEncodingException */) { + return false; + } + const length = bytes.length; + if (length % 2 !== 0) { + return false; + } + for (let i = 0; i < length; i += 2) { + const byte1 = bytes[i] & 0xFF; + if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) { + return false; + } + } + return true; + } + + private static chooseMaskPattern(bits: BitArray, + ecLevel: ErrorCorrectionLevel, + version: Version, + matrix: ByteMatrix): number /* int */ /* throws WriterException */ { + + let minPenalty = Number.MAX_SAFE_INTEGER; // Lower penalty is better. + let bestMaskPattern = -1; + // We try all mask patterns to choose the best one. + for (let maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) { + MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix); + let penalty = this.calculateMaskPenalty(matrix); + if (penalty < minPenalty) { + minPenalty = penalty; + bestMaskPattern = maskPattern; + } } + return bestMaskPattern; + } + + private static chooseVersion(numInputBits: number /* int */, ecLevel: ErrorCorrectionLevel): Version /* throws WriterException */ { + for (let versionNum = 1; versionNum <= 40; versionNum++) { + const version = Version.getVersionForNumber(versionNum); + if (Encoder.willFit(numInputBits, version, ecLevel)) { + return version; + } + } + throw new WriterException('Data too big'); + } - /** - * Get number of data bytes and number of error correction bytes for block id "blockID". Store - * the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of - * JISX0510:2004 (p.30) - */ - public static getNumDataBytesAndNumECBytesForBlockID(numTotalBytes: number /*int*/, - numDataBytes: number /*int*/, - numRSBlocks: number /*int*/, - blockID: number /*int*/, - numDataBytesInBlock: Int32Array, - numECBytesInBlock: Int32Array): void /*throws WriterException*/ { - if (blockID >= numRSBlocks) { - throw new WriterException('Block ID too large'); - } - // numRsBlocksInGroup2 = 196 % 5 = 1 - const numRsBlocksInGroup2 = numTotalBytes % numRSBlocks; - // numRsBlocksInGroup1 = 5 - 1 = 4 - const numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2; - // numTotalBytesInGroup1 = 196 / 5 = 39 - const numTotalBytesInGroup1 = Math.floor(numTotalBytes / numRSBlocks); - // numTotalBytesInGroup2 = 39 + 1 = 40 - const numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1; - // numDataBytesInGroup1 = 66 / 5 = 13 - const numDataBytesInGroup1 = Math.floor(numDataBytes / numRSBlocks); - // numDataBytesInGroup2 = 13 + 1 = 14 - const numDataBytesInGroup2 = numDataBytesInGroup1 + 1; - // numEcBytesInGroup1 = 39 - 13 = 26 - const numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; - // numEcBytesInGroup2 = 40 - 14 = 26 - const numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; - // Sanity checks. - // 26 = 26 - if (numEcBytesInGroup1 !== numEcBytesInGroup2) { - throw new WriterException('EC bytes mismatch'); - } - // 5 = 4 + 1. - if (numRSBlocks !== numRsBlocksInGroup1 + numRsBlocksInGroup2) { - throw new WriterException('RS blocks mismatch'); - } - // 196 = (13 + 26) * 4 + (14 + 26) * 1 - if (numTotalBytes !== - ((numDataBytesInGroup1 + numEcBytesInGroup1) * - numRsBlocksInGroup1) + - ((numDataBytesInGroup2 + numEcBytesInGroup2) * - numRsBlocksInGroup2)) { - throw new WriterException('Total bytes mismatch'); - } + /** + * @return true if the number of input bits will fit in a code with the specified version and + * error correction level. + */ + private static willFit(numInputBits: number /* int */, version: Version, ecLevel: ErrorCorrectionLevel): boolean { + // In the following comments, we use numbers of Version 7-H. + // numBytes = 196 + const numBytes = version.getTotalCodewords(); + // getNumECBytes = 130 + const ecBlocks = version.getECBlocksForLevel(ecLevel); + const numEcBytes = ecBlocks.getTotalECCodewords(); + // getNumDataBytes = 196 - 130 = 66 + const numDataBytes = numBytes - numEcBytes; + const totalInputBytes = (numInputBits + 7) / 8; + return numDataBytes >= totalInputBytes; + } + + /** + * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). + */ + public static terminateBits(numDataBytes: number /* int */, bits: BitArray): void /* throws WriterException */ { + const capacity = numDataBytes * 8; + if (bits.getSize() > capacity) { + throw new WriterException('data bits cannot fit in the QR Code' + bits.getSize() + ' > ' + + capacity); + } + for (let i = 0; i < 4 && bits.getSize() < capacity; ++i) { + bits.appendBit(false); + } + // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details. + // If the last byte isn't 8-bit aligned, we'll add padding bits. + const numBitsInLastByte = bits.getSize() & 0x07; + if (numBitsInLastByte > 0) { + for (let i = numBitsInLastByte; i < 8; i++) { + bits.appendBit(false); + } + } + // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). + const numPaddingBytes = numDataBytes - bits.getSizeInBytes(); + for (let i = 0; i < numPaddingBytes; ++i) { + bits.appendBits((i & 0x01) === 0 ? 0xEC : 0x11, 8); + } + if (bits.getSize() !== capacity) { + throw new WriterException('Bits size does not equal capacity'); + } + } - if (blockID < numRsBlocksInGroup1) { - numDataBytesInBlock[0] = numDataBytesInGroup1; - numECBytesInBlock[0] = numEcBytesInGroup1; - } else { - numDataBytesInBlock[0] = numDataBytesInGroup2; - numECBytesInBlock[0] = numEcBytesInGroup2; - } + /** + * Get number of data bytes and number of error correction bytes for block id "blockID". Store + * the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of + * JISX0510:2004 (p.30) + */ + public static getNumDataBytesAndNumECBytesForBlockID(numTotalBytes: number /* int */, + numDataBytes: number /* int */, + numRSBlocks: number /* int */, + blockID: number /* int */, + numDataBytesInBlock: Int32Array, + numECBytesInBlock: Int32Array): void /* throws WriterException */ { + if (blockID >= numRSBlocks) { + throw new WriterException('Block ID too large'); + } + // numRsBlocksInGroup2 = 196 % 5 = 1 + const numRsBlocksInGroup2 = numTotalBytes % numRSBlocks; + // numRsBlocksInGroup1 = 5 - 1 = 4 + const numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2; + // numTotalBytesInGroup1 = 196 / 5 = 39 + const numTotalBytesInGroup1 = Math.floor(numTotalBytes / numRSBlocks); + // numTotalBytesInGroup2 = 39 + 1 = 40 + const numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1; + // numDataBytesInGroup1 = 66 / 5 = 13 + const numDataBytesInGroup1 = Math.floor(numDataBytes / numRSBlocks); + // numDataBytesInGroup2 = 13 + 1 = 14 + const numDataBytesInGroup2 = numDataBytesInGroup1 + 1; + // numEcBytesInGroup1 = 39 - 13 = 26 + const numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; + // numEcBytesInGroup2 = 40 - 14 = 26 + const numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; + // Sanity checks. + // 26 = 26 + if (numEcBytesInGroup1 !== numEcBytesInGroup2) { + throw new WriterException('EC bytes mismatch'); + } + // 5 = 4 + 1. + if (numRSBlocks !== numRsBlocksInGroup1 + numRsBlocksInGroup2) { + throw new WriterException('RS blocks mismatch'); + } + // 196 = (13 + 26) * 4 + (14 + 26) * 1 + if (numTotalBytes !== + ((numDataBytesInGroup1 + numEcBytesInGroup1) * + numRsBlocksInGroup1) + + ((numDataBytesInGroup2 + numEcBytesInGroup2) * + numRsBlocksInGroup2)) { + throw new WriterException('Total bytes mismatch'); } - /** - * Interleave "bits" with corresponding error correction bytes. On success, store the result in - * "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details. - */ - public static interleaveWithECBytes(bits: BitArray, - numTotalBytes: number /*int*/, - numDataBytes: number /*int*/, - numRSBlocks: number /*int*/): BitArray /*throws WriterException*/ { + if (blockID < numRsBlocksInGroup1) { + numDataBytesInBlock[0] = numDataBytesInGroup1; + numECBytesInBlock[0] = numEcBytesInGroup1; + } else { + numDataBytesInBlock[0] = numDataBytesInGroup2; + numECBytesInBlock[0] = numEcBytesInGroup2; + } + } - // "bits" must have "getNumDataBytes" bytes of data. - if (bits.getSizeInBytes() !== numDataBytes) { - throw new WriterException('Number of bits and data bytes does not match'); - } + /** + * Interleave "bits" with corresponding error correction bytes. On success, store the result in + * "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details. + */ + public static interleaveWithECBytes(bits: BitArray, + numTotalBytes: number /* int */, + numDataBytes: number /* int */, + numRSBlocks: number /* int */): BitArray /* throws WriterException */ { + + // "bits" must have "getNumDataBytes" bytes of data. + if (bits.getSizeInBytes() !== numDataBytes) { + throw new WriterException('Number of bits and data bytes does not match'); + } - // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll - // store the divided data bytes blocks and error correction bytes blocks into "blocks". - let dataBytesOffset = 0; - let maxNumDataBytes = 0; - let maxNumEcBytes = 0; - - // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number. - const blocks = new Array(); // new Array(numRSBlocks) - - for (let i = 0; i < numRSBlocks; ++i) { - const numDataBytesInBlock: Int32Array = new Int32Array(1); - const numEcBytesInBlock: Int32Array = new Int32Array(1); - Encoder.getNumDataBytesAndNumECBytesForBlockID( - numTotalBytes, numDataBytes, numRSBlocks, i, - numDataBytesInBlock, numEcBytesInBlock); - - const size = numDataBytesInBlock[0]; - const dataBytes = new Uint8Array(size); - bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size); - const ecBytes: Uint8Array = Encoder.generateECBytes(dataBytes, numEcBytesInBlock[0]); - blocks.push(new BlockPair(dataBytes, ecBytes)); - - maxNumDataBytes = Math.max(maxNumDataBytes, size); - maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length); - dataBytesOffset += numDataBytesInBlock[0]; - } - if (numDataBytes !== dataBytesOffset) { - throw new WriterException('Data bytes does not match offset'); - } + // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll + // store the divided data bytes blocks and error correction bytes blocks into "blocks". + let dataBytesOffset = 0; + let maxNumDataBytes = 0; + let maxNumEcBytes = 0; + + // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number. + const blocks = new Array(); // new Array(numRSBlocks) + + for (let i = 0; i < numRSBlocks; ++i) { + const numDataBytesInBlock: Int32Array = new Int32Array(1); + const numEcBytesInBlock: Int32Array = new Int32Array(1); + Encoder.getNumDataBytesAndNumECBytesForBlockID( + numTotalBytes, numDataBytes, numRSBlocks, i, + numDataBytesInBlock, numEcBytesInBlock); + + const size = numDataBytesInBlock[0]; + const dataBytes = new Uint8Array(size); + bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size); + const ecBytes: Uint8Array = Encoder.generateECBytes(dataBytes, numEcBytesInBlock[0]); + blocks.push(new BlockPair(dataBytes, ecBytes)); + + maxNumDataBytes = Math.max(maxNumDataBytes, size); + maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length); + dataBytesOffset += numDataBytesInBlock[0]; + } + if (numDataBytes !== dataBytesOffset) { + throw new WriterException('Data bytes does not match offset'); + } - const result = new BitArray(); + const result = new BitArray(); - // First, place data blocks. - for (let i = 0; i < maxNumDataBytes; ++i) { - for (const block of blocks) { - const dataBytes = block.getDataBytes(); - if (i < dataBytes.length) { - result.appendBits(dataBytes[i], 8); - } - } - } - // Then, place error correction blocks. - for (let i = 0; i < maxNumEcBytes; ++i) { - for (const block of blocks) { - const ecBytes = block.getErrorCorrectionBytes(); - if (i < ecBytes.length) { - result.appendBits(ecBytes[i], 8); - } - } + // First, place data blocks. + for (let i = 0; i < maxNumDataBytes; ++i) { + for (const block of blocks) { + const dataBytes = block.getDataBytes(); + if (i < dataBytes.length) { + result.appendBits(dataBytes[i], 8); } - if (numTotalBytes !== result.getSizeInBytes()) { // Should be same. - throw new WriterException('Interleaving error: ' + numTotalBytes + ' and ' + - result.getSizeInBytes() + ' differ.'); - } - - return result; + } + } + // Then, place error correction blocks. + for (let i = 0; i < maxNumEcBytes; ++i) { + for (const block of blocks) { + const ecBytes = block.getErrorCorrectionBytes(); + if (i < ecBytes.length) { + result.appendBits(ecBytes[i], 8); + } + } + } + if (numTotalBytes !== result.getSizeInBytes()) { // Should be same. + throw new WriterException('Interleaving error: ' + numTotalBytes + ' and ' + + result.getSizeInBytes() + ' differ.'); } - public static generateECBytes(dataBytes: Uint8Array, numEcBytesInBlock: number /*int*/): Uint8Array { - const numDataBytes = dataBytes.length; - const toEncode: Int32Array = new Int32Array(numDataBytes + numEcBytesInBlock); // int[numDataBytes + numEcBytesInBlock] - for (let i = 0; i < numDataBytes; i++) { - toEncode[i] = dataBytes[i] & 0xFF; - } - new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock); + return result; + } - const ecBytes = new Uint8Array(numEcBytesInBlock); - for (let i = 0; i < numEcBytesInBlock; i++) { - ecBytes[i] = /*(byte) */toEncode[numDataBytes + i]; - } - return ecBytes; + public static generateECBytes(dataBytes: Uint8Array, numEcBytesInBlock: number /* int */): Uint8Array { + const numDataBytes = dataBytes.length; + const toEncode: Int32Array = new Int32Array(numDataBytes + numEcBytesInBlock); // int[numDataBytes + numEcBytesInBlock] + for (let i = 0; i < numDataBytes; i++) { + toEncode[i] = dataBytes[i] & 0xFF; } + new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock); - /** - * Append mode info. On success, store the result in "bits". - */ - public static appendModeInfo(mode: Mode, bits: BitArray): void { - bits.appendBits(mode.getBits(), 4); + const ecBytes = new Uint8Array(numEcBytesInBlock); + for (let i = 0; i < numEcBytesInBlock; i++) { + ecBytes[i] = /* (byte) */toEncode[numDataBytes + i]; } + return ecBytes; + } + /** + * Append mode info. On success, store the result in "bits". + */ + public static appendModeInfo(mode: Mode, bits: BitArray): void { + bits.appendBits(mode.getBits(), 4); + } - /** - * Append length info. On success, store the result in "bits". - */ - public static appendLengthInfo(numLetters: number /*int*/, version: Version, mode: Mode, bits: BitArray): void /*throws WriterException*/ { - const numBits = mode.getCharacterCountBits(version); - if (numLetters >= (1 << numBits)) { - throw new WriterException(numLetters + ' is bigger than ' + ((1 << numBits) - 1)); - } - bits.appendBits(numLetters, numBits); - } - - /** - * Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". - */ - public static appendBytes(content: string, - mode: Mode, - bits: BitArray, - encoding: string): void /*throws WriterException*/ { - switch (mode) { - case Mode.NUMERIC: - Encoder.appendNumericBytes(content, bits); - break; - case Mode.ALPHANUMERIC: - Encoder.appendAlphanumericBytes(content, bits); - break; - case Mode.BYTE: - Encoder.append8BitBytes(content, bits, encoding); - break; - case Mode.KANJI: - Encoder.appendKanjiBytes(content, bits); - break; - default: - throw new WriterException('Invalid mode: ' + mode); - } - } - private static getDigit(singleCharacter: string): number { - return singleCharacter.charCodeAt(0) - 48; - } - - private static isDigit(singleCharacter: string): boolean { - const cn = Encoder.getDigit(singleCharacter); - return cn >= 0 && cn <= 9; - } - - public static appendNumericBytes(content: string, bits: BitArray): void { - const length = content.length; - let i = 0; - while (i < length) { - const num1 = Encoder.getDigit(content.charAt(i)); - if (i + 2 < length) { - // Encode three numeric letters in ten bits. - const num2 = Encoder.getDigit(content.charAt(i + 1)); - const num3 = Encoder.getDigit(content.charAt(i + 2)); - bits.appendBits(num1 * 100 + num2 * 10 + num3, 10); - i += 3; - } else if (i + 1 < length) { - // Encode two numeric letters in seven bits. - const num2 = Encoder.getDigit(content.charAt(i + 1)); - bits.appendBits(num1 * 10 + num2, 7); - i += 2; - } else { - // Encode one numeric letter in four bits. - bits.appendBits(num1, 4); - i++; - } - } + /** + * Append length info. On success, store the result in "bits". + */ + public static appendLengthInfo(numLetters: number /* int */, version: Version, mode: Mode, bits: BitArray): void /* throws WriterException */ { + const numBits = mode.getCharacterCountBits(version); + if (numLetters >= (1 << numBits)) { + throw new WriterException(numLetters + ' is bigger than ' + ((1 << numBits) - 1)); } + bits.appendBits(numLetters, numBits); + } - public static appendAlphanumericBytes(content: string, bits: BitArray): void /*throws WriterException*/ { - const length = content.length; - let i = 0; - while (i < length) { - const code1 = Encoder.getAlphanumericCode(content.charCodeAt(i)); - if (code1 === -1) { - throw new WriterException(); - } - if (i + 1 < length) { - const code2 = Encoder.getAlphanumericCode(content.charCodeAt(i + 1)); - if (code2 === -1) { - throw new WriterException(); - } - // Encode two alphanumeric letters in 11 bits. - bits.appendBits(code1 * 45 + code2, 11); - i += 2; - } else { - // Encode one alphanumeric letter in six bits. - bits.appendBits(code1, 6); - i++; - } - } + /** + * Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". + */ + public static appendBytes(content: string, + mode: Mode, + bits: BitArray, + encoding: string): void /* throws WriterException */ { + switch (mode) { + case Mode.NUMERIC: + Encoder.appendNumericBytes(content, bits); + break; + case Mode.ALPHANUMERIC: + Encoder.appendAlphanumericBytes(content, bits); + break; + case Mode.BYTE: + Encoder.append8BitBytes(content, bits, encoding); + break; + case Mode.KANJI: + Encoder.appendKanjiBytes(content, bits); + break; + default: + throw new WriterException('Invalid mode: ' + mode); } - - public static append8BitBytes(content: string, bits: BitArray, encoding: string): void { - let bytes: Uint8Array; - try { - bytes = StringEncoding.encode(content, encoding); - } catch (uee/*: UnsupportedEncodingException*/) { - throw new WriterException(uee); - } - for (let i = 0, length = bytes.length; i !== length; i++) { - const b = bytes[i]; - bits.appendBits(b, 8); - } + } + + private static getDigit(singleCharacter: string): number { + return singleCharacter.charCodeAt(0) - 48; + } + + private static isDigit(singleCharacter: string): boolean { + const cn = Encoder.getDigit(singleCharacter); + return cn >= 0 && cn <= 9; + } + + public static appendNumericBytes(content: string, bits: BitArray): void { + const length = content.length; + let i = 0; + while (i < length) { + const num1 = Encoder.getDigit(content.charAt(i)); + if (i + 2 < length) { + // Encode three numeric letters in ten bits. + const num2 = Encoder.getDigit(content.charAt(i + 1)); + const num3 = Encoder.getDigit(content.charAt(i + 2)); + bits.appendBits(num1 * 100 + num2 * 10 + num3, 10); + i += 3; + } else if (i + 1 < length) { + // Encode two numeric letters in seven bits. + const num2 = Encoder.getDigit(content.charAt(i + 1)); + bits.appendBits(num1 * 10 + num2, 7); + i += 2; + } else { + // Encode one numeric letter in four bits. + bits.appendBits(num1, 4); + i++; + } + } + } + + public static appendAlphanumericBytes(content: string, bits: BitArray): void /* throws WriterException */ { + const length = content.length; + let i = 0; + while (i < length) { + const code1 = Encoder.getAlphanumericCode(content.charCodeAt(i)); + if (code1 === -1) { + throw new WriterException(); + } + if (i + 1 < length) { + const code2 = Encoder.getAlphanumericCode(content.charCodeAt(i + 1)); + if (code2 === -1) { + throw new WriterException(); + } + // Encode two alphanumeric letters in 11 bits. + bits.appendBits(code1 * 45 + code2, 11); + i += 2; + } else { + // Encode one alphanumeric letter in six bits. + bits.appendBits(code1, 6); + i++; + } + } + } + + public static append8BitBytes(content: string, bits: BitArray, encoding: string): void { + let bytes: Uint8Array; + try { + bytes = StringEncoding.encode(content, encoding); + } catch (uee/* : UnsupportedEncodingException */) { + throw new WriterException(uee); + } + for (let i = 0, length = bytes.length; i !== length; i++) { + const b = bytes[i]; + bits.appendBits(b, 8); } + } - /** - * @throws WriterException - */ - public static appendKanjiBytes(content: string, bits: BitArray): void /*throws */ { + /** + * @throws WriterException + */ + public static appendKanjiBytes(content: string, bits: BitArray): void /* throws */ { - let bytes: Uint8Array; + let bytes: Uint8Array; - try { - bytes = StringEncoding.encode(content, CharacterSetECI.SJIS); - } catch (uee/*: UnsupportedEncodingException*/) { - throw new WriterException(uee); - } + try { + bytes = StringEncoding.encode(content, CharacterSetECI.SJIS); + } catch (uee/* : UnsupportedEncodingException */) { + throw new WriterException(uee); + } - const length = bytes.length; + const length = bytes.length; - for (let i = 0; i < length; i += 2) { + for (let i = 0; i < length; i += 2) { - const byte1 = bytes[i] & 0xFF; - const byte2 = bytes[i + 1] & 0xFF; - const code = ((byte1 << 8) & 0xFFFFFFFF) | byte2; - let subtracted = -1; + const byte1 = bytes[i] & 0xFF; + const byte2 = bytes[i + 1] & 0xFF; + const code = ((byte1 << 8) & 0xFFFFFFFF) | byte2; + let subtracted = -1; - if (code >= 0x8140 && code <= 0x9ffc) { - subtracted = code - 0x8140; - } else if (code >= 0xe040 && code <= 0xebbf) { - subtracted = code - 0xc140; - } + if (code >= 0x8140 && code <= 0x9ffc) { + subtracted = code - 0x8140; + } else if (code >= 0xe040 && code <= 0xebbf) { + subtracted = code - 0xc140; + } - if (subtracted === -1) { - throw new WriterException('Invalid byte sequence'); - } + if (subtracted === -1) { + throw new WriterException('Invalid byte sequence'); + } - const encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff); + const encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff); - bits.appendBits(encoded, 13); - } + bits.appendBits(encoded, 13); } + } - private static appendECI(eci: CharacterSetECI, bits: BitArray): void { - bits.appendBits(Mode.ECI.getBits(), 4); - // This is correct for values up to 127, which is all we need now. - bits.appendBits(eci.getValue(), 8); - } + private static appendECI(eci: CharacterSetECI, bits: BitArray): void { + bits.appendBits(Mode.ECI.getBits(), 4); + // This is correct for values up to 127, which is all we need now. + bits.appendBits(eci.getValue(), 8); + } } diff --git a/src/core/qrcode/encoder/MaskUtil.ts b/src/core/qrcode/encoder/MaskUtil.ts index 6e9415d6..991df3bb 100644 --- a/src/core/qrcode/encoder/MaskUtil.ts +++ b/src/core/qrcode/encoder/MaskUtil.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.encoder {*/ +/* namespace com.google.zxing.qrcode.encoder { */ import ByteMatrix from './ByteMatrix'; @@ -27,200 +27,200 @@ import IllegalArgumentException from '../../IllegalArgumentException'; */ export default class MaskUtil { - // Penalty weights from section 6.8.2.1 - private static N1 = 3; - private static N2 = 3; - private static N3 = 40; - private static N4 = 10; + // Penalty weights from section 6.8.2.1 + private static N1 = 3; + private static N2 = 3; + private static N3 = 40; + private static N4 = 10; - private constructor() { - // do nothing - } + private constructor() { + // do nothing + } - /** - * Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and - * give penalty to them. Example: 00000 or 11111. - */ - public static applyMaskPenaltyRule1(matrix: ByteMatrix): number /*int*/ { - return MaskUtil.applyMaskPenaltyRule1Internal(matrix, true) + MaskUtil.applyMaskPenaltyRule1Internal(matrix, false); - } + /** + * Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and + * give penalty to them. Example: 00000 or 11111. + */ + public static applyMaskPenaltyRule1(matrix: ByteMatrix): number /* int */ { + return MaskUtil.applyMaskPenaltyRule1Internal(matrix, true) + MaskUtil.applyMaskPenaltyRule1Internal(matrix, false); + } - /** - * Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give - * penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a - * penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block. - */ - public static applyMaskPenaltyRule2(matrix: ByteMatrix): number /*int*/ { - let penalty = 0; - const array: Array = matrix.getArray(); - const width: number /*int*/ = matrix.getWidth(); - const height: number /*int*/ = matrix.getHeight(); - for (let y = 0; y < height - 1; y++) { - const arrayY = array[y]; - for (let x = 0; x < width - 1; x++) { - const value = arrayY[x]; - if (value === arrayY[x + 1] && value === array[y + 1][x] && value === array[y + 1][x + 1]) { - penalty++; - } - } + /** + * Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give + * penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a + * penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block. + */ + public static applyMaskPenaltyRule2(matrix: ByteMatrix): number /* int */ { + let penalty = 0; + const array: Array = matrix.getArray(); + const width: number /* int */ = matrix.getWidth(); + const height: number /* int */ = matrix.getHeight(); + for (let y = 0; y < height - 1; y++) { + const arrayY = array[y]; + for (let x = 0; x < width - 1; x++) { + const value = arrayY[x]; + if (value === arrayY[x + 1] && value === array[y + 1][x] && value === array[y + 1][x + 1]) { + penalty++; } - return MaskUtil.N2 * penalty; + } } + return MaskUtil.N2 * penalty; + } - /** - * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4 - * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we - * find patterns like 000010111010000, we give penalty once. - */ - public static applyMaskPenaltyRule3(matrix: ByteMatrix): number /*int*/ { - let numPenalties = 0; - const array: Array = matrix.getArray(); - const width: number /*int*/ = matrix.getWidth(); - const height: number /*int*/ = matrix.getHeight(); - for (let y = 0; y < height; y++) { - for (let x = 0; x < width; x++) { - const arrayY: Uint8Array = array[y]; // We can at least optimize this access - if (x + 6 < width && - arrayY[x] === 1 && - arrayY[x + 1] === 0 && - arrayY[x + 2] === 1 && - arrayY[x + 3] === 1 && - arrayY[x + 4] === 1 && - arrayY[x + 5] === 0 && - arrayY[x + 6] === 1 && - (MaskUtil.isWhiteHorizontal(arrayY, x - 4, x) || MaskUtil.isWhiteHorizontal(arrayY, x + 7, x + 11))) { - numPenalties++; - } - if (y + 6 < height && - array[y][x] === 1 && - array[y + 1][x] === 0 && - array[y + 2][x] === 1 && - array[y + 3][x] === 1 && - array[y + 4][x] === 1 && - array[y + 5][x] === 0 && - array[y + 6][x] === 1 && - (MaskUtil.isWhiteVertical(array, x, y - 4, y) || MaskUtil.isWhiteVertical(array, x, y + 7, y + 11))) { - numPenalties++; - } - } + /** + * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4 + * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we + * find patterns like 000010111010000, we give penalty once. + */ + public static applyMaskPenaltyRule3(matrix: ByteMatrix): number /* int */ { + let numPenalties = 0; + const array: Array = matrix.getArray(); + const width: number /* int */ = matrix.getWidth(); + const height: number /* int */ = matrix.getHeight(); + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const arrayY: Uint8Array = array[y]; // We can at least optimize this access + if (x + 6 < width && + arrayY[x] === 1 && + arrayY[x + 1] === 0 && + arrayY[x + 2] === 1 && + arrayY[x + 3] === 1 && + arrayY[x + 4] === 1 && + arrayY[x + 5] === 0 && + arrayY[x + 6] === 1 && + (MaskUtil.isWhiteHorizontal(arrayY, x - 4, x) || MaskUtil.isWhiteHorizontal(arrayY, x + 7, x + 11))) { + numPenalties++; + } + if (y + 6 < height && + array[y][x] === 1 && + array[y + 1][x] === 0 && + array[y + 2][x] === 1 && + array[y + 3][x] === 1 && + array[y + 4][x] === 1 && + array[y + 5][x] === 0 && + array[y + 6][x] === 1 && + (MaskUtil.isWhiteVertical(array, x, y - 4, y) || MaskUtil.isWhiteVertical(array, x, y + 7, y + 11))) { + numPenalties++; } - return numPenalties * MaskUtil.N3; + } } + return numPenalties * MaskUtil.N3; + } - private static isWhiteHorizontal(rowArray: Uint8Array, from: number /*int*/, to: number /*int*/): boolean { - from = Math.max(from, 0); - to = Math.min(to, rowArray.length); - for (let i = from; i < to; i++) { - if (rowArray[i] === 1) { - return false; - } - } - return true; + private static isWhiteHorizontal(rowArray: Uint8Array, from: number /* int */, to: number /* int */): boolean { + from = Math.max(from, 0); + to = Math.min(to, rowArray.length); + for (let i = from; i < to; i++) { + if (rowArray[i] === 1) { + return false; + } } + return true; + } - private static isWhiteVertical(array: Uint8Array[], col: number /*int*/, from: number /*int*/, to: number /*int*/): boolean { - from = Math.max(from, 0); - to = Math.min(to, array.length); - for (let i = from; i < to; i++) { - if (array[i][col] === 1) { - return false; - } - } - return true; + private static isWhiteVertical(array: Uint8Array[], col: number /* int */, from: number /* int */, to: number /* int */): boolean { + from = Math.max(from, 0); + to = Math.min(to, array.length); + for (let i = from; i < to; i++) { + if (array[i][col] === 1) { + return false; + } } + return true; + } - /** - * Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give - * penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance. - */ - public static applyMaskPenaltyRule4(matrix: ByteMatrix): number /*int*/ { - let numDarkCells = 0; - const array: Array = matrix.getArray(); - const width: number /*int*/ = matrix.getWidth(); - const height: number /*int*/ = matrix.getHeight(); - for (let y = 0; y < height; y++) { - const arrayY: Uint8Array = array[y]; - for (let x = 0; x < width; x++) { - if (arrayY[x] === 1) { - numDarkCells++; - } - } + /** + * Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give + * penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance. + */ + public static applyMaskPenaltyRule4(matrix: ByteMatrix): number /* int */ { + let numDarkCells = 0; + const array: Array = matrix.getArray(); + const width: number /* int */ = matrix.getWidth(); + const height: number /* int */ = matrix.getHeight(); + for (let y = 0; y < height; y++) { + const arrayY: Uint8Array = array[y]; + for (let x = 0; x < width; x++) { + if (arrayY[x] === 1) { + numDarkCells++; } - const numTotalCells = matrix.getHeight() * matrix.getWidth(); - const fivePercentVariances = Math.floor(Math.abs(numDarkCells * 2 - numTotalCells) * 10 / numTotalCells); - return fivePercentVariances * MaskUtil.N4; + } } + const numTotalCells = matrix.getHeight() * matrix.getWidth(); + const fivePercentVariances = Math.floor(Math.abs(numDarkCells * 2 - numTotalCells) * 10 / numTotalCells); + return fivePercentVariances * MaskUtil.N4; + } - /** - * Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask - * pattern conditions. - */ - public static getDataMaskBit(maskPattern: number /*int*/, x: number /*int*/, y: number /*int*/): boolean { - let intermediate: number; /*int*/ - let temp: number; /*int*/ - switch (maskPattern) { - case 0: - intermediate = (y + x) & 0x1; - break; - case 1: - intermediate = y & 0x1; - break; - case 2: - intermediate = x % 3; - break; - case 3: - intermediate = (y + x) % 3; - break; - case 4: - intermediate = (Math.floor(y / 2) + Math.floor(x / 3)) & 0x1; - break; - case 5: - temp = y * x; - intermediate = (temp & 0x1) + (temp % 3); - break; - case 6: - temp = y * x; - intermediate = ((temp & 0x1) + (temp % 3)) & 0x1; - break; - case 7: - temp = y * x; - intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1; - break; - default: - throw new IllegalArgumentException('Invalid mask pattern: ' + maskPattern); - } - return intermediate === 0; + /** + * Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask + * pattern conditions. + */ + public static getDataMaskBit(maskPattern: number /* int */, x: number /* int */, y: number /* int */): boolean { + let intermediate: number; /* int */ + let temp: number; /* int */ + switch (maskPattern) { + case 0: + intermediate = (y + x) & 0x1; + break; + case 1: + intermediate = y & 0x1; + break; + case 2: + intermediate = x % 3; + break; + case 3: + intermediate = (y + x) % 3; + break; + case 4: + intermediate = (Math.floor(y / 2) + Math.floor(x / 3)) & 0x1; + break; + case 5: + temp = y * x; + intermediate = (temp & 0x1) + (temp % 3); + break; + case 6: + temp = y * x; + intermediate = ((temp & 0x1) + (temp % 3)) & 0x1; + break; + case 7: + temp = y * x; + intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1; + break; + default: + throw new IllegalArgumentException('Invalid mask pattern: ' + maskPattern); } + return intermediate === 0; + } - /** - * Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both - * vertical and horizontal orders respectively. - */ - private static applyMaskPenaltyRule1Internal(matrix: ByteMatrix, isHorizontal: boolean): number /*int*/ { - let penalty = 0; - const iLimit = isHorizontal ? matrix.getHeight() : matrix.getWidth(); - const jLimit = isHorizontal ? matrix.getWidth() : matrix.getHeight(); - const array: Array = matrix.getArray(); - for (let i = 0; i < iLimit; i++) { - let numSameBitCells = 0; - let prevBit = -1; - for (let j = 0; j < jLimit; j++) { - const bit = isHorizontal ? array[i][j] : array[j][i]; - if (bit === prevBit) { - numSameBitCells++; - } else { - if (numSameBitCells >= 5) { - penalty += MaskUtil.N1 + (numSameBitCells - 5); - } - numSameBitCells = 1; // Include the cell itself. - prevBit = bit; - } - } - if (numSameBitCells >= 5) { - penalty += MaskUtil.N1 + (numSameBitCells - 5); - } + /** + * Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both + * vertical and horizontal orders respectively. + */ + private static applyMaskPenaltyRule1Internal(matrix: ByteMatrix, isHorizontal: boolean): number /* int */ { + let penalty = 0; + const iLimit = isHorizontal ? matrix.getHeight() : matrix.getWidth(); + const jLimit = isHorizontal ? matrix.getWidth() : matrix.getHeight(); + const array: Array = matrix.getArray(); + for (let i = 0; i < iLimit; i++) { + let numSameBitCells = 0; + let prevBit = -1; + for (let j = 0; j < jLimit; j++) { + const bit = isHorizontal ? array[i][j] : array[j][i]; + if (bit === prevBit) { + numSameBitCells++; + } else { + if (numSameBitCells >= 5) { + penalty += MaskUtil.N1 + (numSameBitCells - 5); + } + numSameBitCells = 1; // Include the cell itself. + prevBit = bit; } - return penalty; + } + if (numSameBitCells >= 5) { + penalty += MaskUtil.N1 + (numSameBitCells - 5); + } } + return penalty; + } } diff --git a/src/core/qrcode/encoder/MatrixUtil.ts b/src/core/qrcode/encoder/MatrixUtil.ts index 55be9f25..ef51be50 100644 --- a/src/core/qrcode/encoder/MatrixUtil.ts +++ b/src/core/qrcode/encoder/MatrixUtil.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.encoder {*/ +/* namespace com.google.zxing.qrcode.encoder { */ import BitArray from '../../common/BitArray'; import ErrorCorrectionLevel from '../decoder/ErrorCorrectionLevel'; @@ -33,450 +33,450 @@ import IllegalArgumentException from '../../IllegalArgumentException'; */ export default class MatrixUtil { - private constructor() { - // do nothing - } - - private static POSITION_DETECTION_PATTERN: Array = Array.from([ - Int32Array.from([1, 1, 1, 1, 1, 1, 1]), - Int32Array.from([1, 0, 0, 0, 0, 0, 1]), - Int32Array.from([1, 0, 1, 1, 1, 0, 1]), - Int32Array.from([1, 0, 1, 1, 1, 0, 1]), - Int32Array.from([1, 0, 1, 1, 1, 0, 1]), - Int32Array.from([1, 0, 0, 0, 0, 0, 1]), - Int32Array.from([1, 1, 1, 1, 1, 1, 1]), - ]); - - private static POSITION_ADJUSTMENT_PATTERN: Array = Array.from([ - Int32Array.from([1, 1, 1, 1, 1]), - Int32Array.from([1, 0, 0, 0, 1]), - Int32Array.from([1, 0, 1, 0, 1]), - Int32Array.from([1, 0, 0, 0, 1]), - Int32Array.from([1, 1, 1, 1, 1]), - ]); - - // From Appendix E. Table 1, JIS0510X:2004 (71: p). The table was double-checked by komatsu. - private static POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE: Array = Array.from([ - Int32Array.from([-1, -1, -1, -1, -1, -1, -1]), // Version 1 - Int32Array.from([6, 18, -1, -1, -1, -1, -1]), // Version 2 - Int32Array.from([6, 22, -1, -1, -1, -1, -1]), // Version 3 - Int32Array.from([6, 26, -1, -1, -1, -1, -1]), // Version 4 - Int32Array.from([6, 30, -1, -1, -1, -1, -1]), // Version 5 - Int32Array.from([6, 34, -1, -1, -1, -1, -1]), // Version 6 - Int32Array.from([6, 22, 38, -1, -1, -1, -1]), // Version 7 - Int32Array.from([6, 24, 42, -1, -1, -1, -1]), // Version 8 - Int32Array.from([6, 26, 46, -1, -1, -1, -1]), // Version 9 - Int32Array.from([6, 28, 50, -1, -1, -1, -1]), // Version 10 - Int32Array.from([6, 30, 54, -1, -1, -1, -1]), // Version 11 - Int32Array.from([6, 32, 58, -1, -1, -1, -1]), // Version 12 - Int32Array.from([6, 34, 62, -1, -1, -1, -1]), // Version 13 - Int32Array.from([6, 26, 46, 66, -1, -1, -1]), // Version 14 - Int32Array.from([6, 26, 48, 70, -1, -1, -1]), // Version 15 - Int32Array.from([6, 26, 50, 74, -1, -1, -1]), // Version 16 - Int32Array.from([6, 30, 54, 78, -1, -1, -1]), // Version 17 - Int32Array.from([6, 30, 56, 82, -1, -1, -1]), // Version 18 - Int32Array.from([6, 30, 58, 86, -1, -1, -1]), // Version 19 - Int32Array.from([6, 34, 62, 90, -1, -1, -1]), // Version 20 - Int32Array.from([6, 28, 50, 72, 94, -1, -1]), // Version 21 - Int32Array.from([6, 26, 50, 74, 98, -1, -1]), // Version 22 - Int32Array.from([6, 30, 54, 78, 102, -1, -1]), // Version 23 - Int32Array.from([6, 28, 54, 80, 106, -1, -1]), // Version 24 - Int32Array.from([6, 32, 58, 84, 110, -1, -1]), // Version 25 - Int32Array.from([6, 30, 58, 86, 114, -1, -1]), // Version 26 - Int32Array.from([6, 34, 62, 90, 118, -1, -1]), // Version 27 - Int32Array.from([6, 26, 50, 74, 98, 122, -1]), // Version 28 - Int32Array.from([6, 30, 54, 78, 102, 126, -1]), // Version 29 - Int32Array.from([6, 26, 52, 78, 104, 130, -1]), // Version 30 - Int32Array.from([6, 30, 56, 82, 108, 134, -1]), // Version 31 - Int32Array.from([6, 34, 60, 86, 112, 138, -1]), // Version 32 - Int32Array.from([6, 30, 58, 86, 114, 142, -1]), // Version 33 - Int32Array.from([6, 34, 62, 90, 118, 146, -1]), // Version 34 - Int32Array.from([6, 30, 54, 78, 102, 126, 150]), // Version 35 - Int32Array.from([6, 24, 50, 76, 102, 128, 154]), // Version 36 - Int32Array.from([6, 28, 54, 80, 106, 132, 158]), // Version 37 - Int32Array.from([6, 32, 58, 84, 110, 136, 162]), // Version 38 - Int32Array.from([6, 26, 54, 82, 110, 138, 166]), // Version 39 - Int32Array.from([6, 30, 58, 86, 114, 142, 170]), // Version 40 - ]); - - // Type info cells at the left top corner. - private static TYPE_INFO_COORDINATES: Array = Array.from([ - Int32Array.from([8, 0]), - Int32Array.from([8, 1]), - Int32Array.from([8, 2]), - Int32Array.from([8, 3]), - Int32Array.from([8, 4]), - Int32Array.from([8, 5]), - Int32Array.from([8, 7]), - Int32Array.from([8, 8]), - Int32Array.from([7, 8]), - Int32Array.from([5, 8]), - Int32Array.from([4, 8]), - Int32Array.from([3, 8]), - Int32Array.from([2, 8]), - Int32Array.from([1, 8]), - Int32Array.from([0, 8]), - ]); - - // From Appendix D in JISX0510:2004 (p. 67) - private static VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101 - - // From Appendix C in JISX0510:2004 (p.65). - private static TYPE_INFO_POLY = 0x537; - private static TYPE_INFO_MASK_PATTERN = 0x5412; - - // Set all cells to -1 (TYPESCRIPTPORT: 255). -1 (TYPESCRIPTPORT: 255) means that the cell is empty (not set yet). - // - // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding - // with the ByteMatrix initialized all to zero. - public static clearMatrix(matrix: ByteMatrix): void { - // TYPESCRIPTPORT: we use UintArray se changed here from -1 to 255 - matrix.clear(/*(byte) *//*-1*/255); + private constructor() { + // do nothing + } + + private static POSITION_DETECTION_PATTERN: Array = Array.from([ + Int32Array.from([1, 1, 1, 1, 1, 1, 1]), + Int32Array.from([1, 0, 0, 0, 0, 0, 1]), + Int32Array.from([1, 0, 1, 1, 1, 0, 1]), + Int32Array.from([1, 0, 1, 1, 1, 0, 1]), + Int32Array.from([1, 0, 1, 1, 1, 0, 1]), + Int32Array.from([1, 0, 0, 0, 0, 0, 1]), + Int32Array.from([1, 1, 1, 1, 1, 1, 1]), + ]); + + private static POSITION_ADJUSTMENT_PATTERN: Array = Array.from([ + Int32Array.from([1, 1, 1, 1, 1]), + Int32Array.from([1, 0, 0, 0, 1]), + Int32Array.from([1, 0, 1, 0, 1]), + Int32Array.from([1, 0, 0, 0, 1]), + Int32Array.from([1, 1, 1, 1, 1]), + ]); + + // From Appendix E. Table 1, JIS0510X:2004 (71: p). The table was double-checked by komatsu. + private static POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE: Array = Array.from([ + Int32Array.from([-1, -1, -1, -1, -1, -1, -1]), // Version 1 + Int32Array.from([6, 18, -1, -1, -1, -1, -1]), // Version 2 + Int32Array.from([6, 22, -1, -1, -1, -1, -1]), // Version 3 + Int32Array.from([6, 26, -1, -1, -1, -1, -1]), // Version 4 + Int32Array.from([6, 30, -1, -1, -1, -1, -1]), // Version 5 + Int32Array.from([6, 34, -1, -1, -1, -1, -1]), // Version 6 + Int32Array.from([6, 22, 38, -1, -1, -1, -1]), // Version 7 + Int32Array.from([6, 24, 42, -1, -1, -1, -1]), // Version 8 + Int32Array.from([6, 26, 46, -1, -1, -1, -1]), // Version 9 + Int32Array.from([6, 28, 50, -1, -1, -1, -1]), // Version 10 + Int32Array.from([6, 30, 54, -1, -1, -1, -1]), // Version 11 + Int32Array.from([6, 32, 58, -1, -1, -1, -1]), // Version 12 + Int32Array.from([6, 34, 62, -1, -1, -1, -1]), // Version 13 + Int32Array.from([6, 26, 46, 66, -1, -1, -1]), // Version 14 + Int32Array.from([6, 26, 48, 70, -1, -1, -1]), // Version 15 + Int32Array.from([6, 26, 50, 74, -1, -1, -1]), // Version 16 + Int32Array.from([6, 30, 54, 78, -1, -1, -1]), // Version 17 + Int32Array.from([6, 30, 56, 82, -1, -1, -1]), // Version 18 + Int32Array.from([6, 30, 58, 86, -1, -1, -1]), // Version 19 + Int32Array.from([6, 34, 62, 90, -1, -1, -1]), // Version 20 + Int32Array.from([6, 28, 50, 72, 94, -1, -1]), // Version 21 + Int32Array.from([6, 26, 50, 74, 98, -1, -1]), // Version 22 + Int32Array.from([6, 30, 54, 78, 102, -1, -1]), // Version 23 + Int32Array.from([6, 28, 54, 80, 106, -1, -1]), // Version 24 + Int32Array.from([6, 32, 58, 84, 110, -1, -1]), // Version 25 + Int32Array.from([6, 30, 58, 86, 114, -1, -1]), // Version 26 + Int32Array.from([6, 34, 62, 90, 118, -1, -1]), // Version 27 + Int32Array.from([6, 26, 50, 74, 98, 122, -1]), // Version 28 + Int32Array.from([6, 30, 54, 78, 102, 126, -1]), // Version 29 + Int32Array.from([6, 26, 52, 78, 104, 130, -1]), // Version 30 + Int32Array.from([6, 30, 56, 82, 108, 134, -1]), // Version 31 + Int32Array.from([6, 34, 60, 86, 112, 138, -1]), // Version 32 + Int32Array.from([6, 30, 58, 86, 114, 142, -1]), // Version 33 + Int32Array.from([6, 34, 62, 90, 118, 146, -1]), // Version 34 + Int32Array.from([6, 30, 54, 78, 102, 126, 150]), // Version 35 + Int32Array.from([6, 24, 50, 76, 102, 128, 154]), // Version 36 + Int32Array.from([6, 28, 54, 80, 106, 132, 158]), // Version 37 + Int32Array.from([6, 32, 58, 84, 110, 136, 162]), // Version 38 + Int32Array.from([6, 26, 54, 82, 110, 138, 166]), // Version 39 + Int32Array.from([6, 30, 58, 86, 114, 142, 170]), // Version 40 + ]); + + // Type info cells at the left top corner. + private static TYPE_INFO_COORDINATES: Array = Array.from([ + Int32Array.from([8, 0]), + Int32Array.from([8, 1]), + Int32Array.from([8, 2]), + Int32Array.from([8, 3]), + Int32Array.from([8, 4]), + Int32Array.from([8, 5]), + Int32Array.from([8, 7]), + Int32Array.from([8, 8]), + Int32Array.from([7, 8]), + Int32Array.from([5, 8]), + Int32Array.from([4, 8]), + Int32Array.from([3, 8]), + Int32Array.from([2, 8]), + Int32Array.from([1, 8]), + Int32Array.from([0, 8]), + ]); + + // From Appendix D in JISX0510:2004 (p. 67) + private static VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101 + + // From Appendix C in JISX0510:2004 (p.65). + private static TYPE_INFO_POLY = 0x537; + private static TYPE_INFO_MASK_PATTERN = 0x5412; + + // Set all cells to -1 (TYPESCRIPTPORT: 255). -1 (TYPESCRIPTPORT: 255) means that the cell is empty (not set yet). + // + // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding + // with the ByteMatrix initialized all to zero. + public static clearMatrix(matrix: ByteMatrix): void { + // TYPESCRIPTPORT: we use UintArray se changed here from -1 to 255 + matrix.clear(/* (byte) *//* -1 */255); + } + + // Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On + // success, store the result in "matrix" and return true. + public static buildMatrix(dataBits: BitArray, + ecLevel: ErrorCorrectionLevel, + version: Version, + maskPattern: number /* int */, + matrix: ByteMatrix): void /* throws WriterException */ { + MatrixUtil.clearMatrix(matrix); + MatrixUtil.embedBasicPatterns(version, matrix); + // Type information appear with any version. + MatrixUtil.embedTypeInfo(ecLevel, maskPattern, matrix); + // Version info appear if version >= 7. + MatrixUtil.maybeEmbedVersionInfo(version, matrix); + // Data should be embedded at end. + MatrixUtil.embedDataBits(dataBits, maskPattern, matrix); + } + + // Embed basic patterns. On success, modify the matrix and return true. + // The basic patterns are: + // - Position detection patterns + // - Timing patterns + // - Dark dot at the left bottom corner + // - Position adjustment patterns, if need be + public static embedBasicPatterns(version: Version, matrix: ByteMatrix): void /* throws WriterException */ { + // Let's get started with embedding big squares at corners. + MatrixUtil.embedPositionDetectionPatternsAndSeparators(matrix); + // Then, embed the dark dot at the left bottom corner. + MatrixUtil.embedDarkDotAtLeftBottomCorner(matrix); + + // Position adjustment patterns appear if version >= 2. + MatrixUtil.maybeEmbedPositionAdjustmentPatterns(version, matrix); + // Timing patterns should be embedded after position adj. patterns. + MatrixUtil.embedTimingPatterns(matrix); + } + + // Embed type information. On success, modify the matrix. + public static embedTypeInfo(ecLevel: ErrorCorrectionLevel, maskPattern: number /* int */, matrix: ByteMatrix): void { + const typeInfoBits: BitArray = new BitArray(); + MatrixUtil.makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits); + + for (let i = 0, size = typeInfoBits.getSize(); i < size; ++i) { + // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in + // "typeInfoBits". + const bit: boolean = typeInfoBits.get(typeInfoBits.getSize() - 1 - i); + + // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46). + const coordinates: Int32Array = MatrixUtil.TYPE_INFO_COORDINATES[i]; + const x1 = coordinates[0]; + const y1 = coordinates[1]; + matrix.setBoolean(x1, y1, bit); + + if (i < 8) { + // Right top corner. + const x2 = matrix.getWidth() - i - 1; + const y2 = 8; + matrix.setBoolean(x2, y2, bit); + } else { + // Left bottom corner. + const x2 = 8; + const y2 = matrix.getHeight() - 7 + (i - 8); + matrix.setBoolean(x2, y2, bit); + } } + } - // Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On - // success, store the result in "matrix" and return true. - public static buildMatrix(dataBits: BitArray, - ecLevel: ErrorCorrectionLevel, - version: Version, - maskPattern: number /*int*/, - matrix: ByteMatrix): void /*throws WriterException*/ { - MatrixUtil.clearMatrix(matrix); - MatrixUtil.embedBasicPatterns(version, matrix); - // Type information appear with any version. - MatrixUtil.embedTypeInfo(ecLevel, maskPattern, matrix); - // Version info appear if version >= 7. - MatrixUtil.maybeEmbedVersionInfo(version, matrix); - // Data should be embedded at end. - MatrixUtil.embedDataBits(dataBits, maskPattern, matrix); + // Embed version information if need be. On success, modify the matrix and return true. + // See 8.10 of JISX0510:2004 (p.47) for how to embed version information. + public static maybeEmbedVersionInfo(version: Version, matrix: ByteMatrix): void /* throws WriterException */ { + if (version.getVersionNumber() < 7) { // Version info is necessary if version >= 7. + return; // Don't need version info. } - - // Embed basic patterns. On success, modify the matrix and return true. - // The basic patterns are: - // - Position detection patterns - // - Timing patterns - // - Dark dot at the left bottom corner - // - Position adjustment patterns, if need be - public static embedBasicPatterns(version: Version, matrix: ByteMatrix): void /*throws WriterException*/ { - // Let's get started with embedding big squares at corners. - MatrixUtil.embedPositionDetectionPatternsAndSeparators(matrix); - // Then, embed the dark dot at the left bottom corner. - MatrixUtil.embedDarkDotAtLeftBottomCorner(matrix); - - // Position adjustment patterns appear if version >= 2. - MatrixUtil.maybeEmbedPositionAdjustmentPatterns(version, matrix); - // Timing patterns should be embedded after position adj. patterns. - MatrixUtil.embedTimingPatterns(matrix); + const versionInfoBits = new BitArray(); + MatrixUtil.makeVersionInfoBits(version, versionInfoBits); + + let bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0. + for (let i = 0; i < 6; ++i) { + for (let j = 0; j < 3; ++j) { + // Place bits in LSB (least significant bit) to MSB order. + const bit: boolean = versionInfoBits.get(bitIndex); + bitIndex--; + // Left bottom corner. + matrix.setBoolean(i, matrix.getHeight() - 11 + j, bit); + // Right bottom corner. + matrix.setBoolean(matrix.getHeight() - 11 + j, i, bit); + } } - - // Embed type information. On success, modify the matrix. - public static embedTypeInfo(ecLevel: ErrorCorrectionLevel, maskPattern: number /*int*/, matrix: ByteMatrix): void { - const typeInfoBits: BitArray = new BitArray(); - MatrixUtil.makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits); - - for (let i = 0, size = typeInfoBits.getSize(); i < size; ++i) { - // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in - // "typeInfoBits". - const bit: boolean = typeInfoBits.get(typeInfoBits.getSize() - 1 - i); - - // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46). - const coordinates: Int32Array = MatrixUtil.TYPE_INFO_COORDINATES[i]; - const x1 = coordinates[0]; - const y1 = coordinates[1]; - matrix.setBoolean(x1, y1, bit); - - if (i < 8) { - // Right top corner. - const x2 = matrix.getWidth() - i - 1; - const y2 = 8; - matrix.setBoolean(x2, y2, bit); - } else { - // Left bottom corner. - const x2 = 8; - const y2 = matrix.getHeight() - 7 + (i - 8); - matrix.setBoolean(x2, y2, bit); - } + } + + // Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true. + // For debugging purposes, it skips masking process if "getMaskPattern" is -1(TYPESCRIPTPORT: 255). + // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits. + public static embedDataBits(dataBits: BitArray, maskPattern: number /* int */, matrix: ByteMatrix): void { + let bitIndex = 0; + let direction = -1; + // Start from the right bottom cell. + let x = matrix.getWidth() - 1; + let y = matrix.getHeight() - 1; + while (x > 0) { + // Skip the vertical timing pattern. + if (x === 6) { + x -= 1; + } + while (y >= 0 && y < matrix.getHeight()) { + for (let i = 0; i < 2; ++i) { + const xx = x - i; + // Skip the cell if it's not empty. + if (!MatrixUtil.isEmpty(matrix.get(xx, y))) { + continue; + } + let bit: boolean; + if (bitIndex < dataBits.getSize()) { + bit = dataBits.get(bitIndex); + ++bitIndex; + } else { + // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described + // in 8.4.9 of JISX0510:2004 (p. 24). + bit = false; + } + + // Skip masking if mask_pattern is -1 (TYPESCRIPTPORT: 255). + if (maskPattern !== 255 && MaskUtil.getDataMaskBit(maskPattern, xx, y)) { + bit = !bit; + } + matrix.setBoolean(xx, y, bit); } + y += direction; + } + direction = -direction; // Reverse the direction. + y += direction; + x -= 2; // Move to the left. } - - // Embed version information if need be. On success, modify the matrix and return true. - // See 8.10 of JISX0510:2004 (p.47) for how to embed version information. - public static maybeEmbedVersionInfo(version: Version, matrix: ByteMatrix): void /*throws WriterException*/ { - if (version.getVersionNumber() < 7) { // Version info is necessary if version >= 7. - return; // Don't need version info. - } - const versionInfoBits = new BitArray(); - MatrixUtil.makeVersionInfoBits(version, versionInfoBits); - - let bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0. - for (let i = 0; i < 6; ++i) { - for (let j = 0; j < 3; ++j) { - // Place bits in LSB (least significant bit) to MSB order. - const bit: boolean = versionInfoBits.get(bitIndex); - bitIndex--; - // Left bottom corner. - matrix.setBoolean(i, matrix.getHeight() - 11 + j, bit); - // Right bottom corner. - matrix.setBoolean(matrix.getHeight() - 11 + j, i, bit); - } - } + // All bits should be consumed. + if (bitIndex !== dataBits.getSize()) { + throw new WriterException('Not all bits consumed: ' + bitIndex + '/' + dataBits.getSize()); } - - // Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true. - // For debugging purposes, it skips masking process if "getMaskPattern" is -1(TYPESCRIPTPORT: 255). - // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits. - public static embedDataBits(dataBits: BitArray, maskPattern: number /*int*/, matrix: ByteMatrix): void { - let bitIndex = 0; - let direction = -1; - // Start from the right bottom cell. - let x = matrix.getWidth() - 1; - let y = matrix.getHeight() - 1; - while (x > 0) { - // Skip the vertical timing pattern. - if (x === 6) { - x -= 1; - } - while (y >= 0 && y < matrix.getHeight()) { - for (let i = 0; i < 2; ++i) { - const xx = x - i; - // Skip the cell if it's not empty. - if (!MatrixUtil.isEmpty(matrix.get(xx, y))) { - continue; - } - let bit: boolean; - if (bitIndex < dataBits.getSize()) { - bit = dataBits.get(bitIndex); - ++bitIndex; - } else { - // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described - // in 8.4.9 of JISX0510:2004 (p. 24). - bit = false; - } - - // Skip masking if mask_pattern is -1 (TYPESCRIPTPORT: 255). - if (maskPattern !== 255 && MaskUtil.getDataMaskBit(maskPattern, xx, y)) { - bit = !bit; - } - matrix.setBoolean(xx, y, bit); - } - y += direction; - } - direction = -direction; // Reverse the direction. - y += direction; - x -= 2; // Move to the left. - } - // All bits should be consumed. - if (bitIndex !== dataBits.getSize()) { - throw new WriterException('Not all bits consumed: ' + bitIndex + '/' + dataBits.getSize()); - } + } + + // Return the position of the most significant bit set (one: to) in the "value". The most + // significant bit is position 32. If there is no bit set, return 0. Examples: + // - findMSBSet(0) => 0 + // - findMSBSet(1) => 1 + // - findMSBSet(255) => 8 + public static findMSBSet(value: number /* int */): number /* int */ { + return 32 - Integer.numberOfLeadingZeros(value); + } + + // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH + // code is used for encoding type information and version information. + // Example: Calculation of version information of 7. + // f(x) is created from 7. + // - 7 = 000111 in 6 bits + // - f(x) = x^2 + x^1 + x^0 + // g(x) is given by the standard (p. 67) + // - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1 + // Multiply f(x) by x^(18 - 6) + // - f'(x) = f(x) * x^(18 - 6) + // - f'(x) = x^14 + x^13 + x^12 + // Calculate the remainder of f'(x) / g(x) + // x^2 + // __________________________________________________ + // g(x) )x^14 + x^13 + x^12 + // x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2 + // -------------------------------------------------- + // x^11 + x^10 + x^7 + x^4 + x^2 + // + // The remainder is x^11 + x^10 + x^7 + x^4 + x^2 + // Encode it in binary: 110010010100 + // The return value is 0xc94 (1100 1001 0100) + // + // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit + // operations. We don't care if coefficients are positive or negative. + public static calculateBCHCode(value: number /* int */, poly: number /* int */): number /* int */ { + if (poly === 0) { + throw new IllegalArgumentException('0 polynomial'); } - - // Return the position of the most significant bit set (one: to) in the "value". The most - // significant bit is position 32. If there is no bit set, return 0. Examples: - // - findMSBSet(0) => 0 - // - findMSBSet(1) => 1 - // - findMSBSet(255) => 8 - public static findMSBSet(value: number /*int*/): number /*int*/ { - return 32 - Integer.numberOfLeadingZeros(value); + // If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1 + // from 13 to make it 12. + const msbSetInPoly = MatrixUtil.findMSBSet(poly); + value <<= msbSetInPoly - 1; + // Do the division business using exclusive-or operations. + while (MatrixUtil.findMSBSet(value) >= msbSetInPoly) { + value ^= poly << (MatrixUtil.findMSBSet(value) - msbSetInPoly); } - - // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH - // code is used for encoding type information and version information. - // Example: Calculation of version information of 7. - // f(x) is created from 7. - // - 7 = 000111 in 6 bits - // - f(x) = x^2 + x^1 + x^0 - // g(x) is given by the standard (p. 67) - // - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1 - // Multiply f(x) by x^(18 - 6) - // - f'(x) = f(x) * x^(18 - 6) - // - f'(x) = x^14 + x^13 + x^12 - // Calculate the remainder of f'(x) / g(x) - // x^2 - // __________________________________________________ - // g(x) )x^14 + x^13 + x^12 - // x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2 - // -------------------------------------------------- - // x^11 + x^10 + x^7 + x^4 + x^2 - // - // The remainder is x^11 + x^10 + x^7 + x^4 + x^2 - // Encode it in binary: 110010010100 - // The return value is 0xc94 (1100 1001 0100) - // - // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit - // operations. We don't care if coefficients are positive or negative. - public static calculateBCHCode(value: number /*int*/, poly: number /*int*/): number /*int*/ { - if (poly === 0) { - throw new IllegalArgumentException('0 polynomial'); - } - // If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1 - // from 13 to make it 12. - const msbSetInPoly = MatrixUtil.findMSBSet(poly); - value <<= msbSetInPoly - 1; - // Do the division business using exclusive-or operations. - while (MatrixUtil.findMSBSet(value) >= msbSetInPoly) { - value ^= poly << (MatrixUtil.findMSBSet(value) - msbSetInPoly); - } - // Now the "value" is the remainder (i.e. the BCH code) - return value; + // Now the "value" is the remainder (i.e. the BCH code) + return value; + } + + // Make bit vector of type information. On success, store the result in "bits" and return true. + // Encode error correction level and mask pattern. See 8.9 of + // JISX0510:2004 (p.45) for details. + public static makeTypeInfoBits(ecLevel: ErrorCorrectionLevel, maskPattern: number /* int */, bits: BitArray): void { + if (!QRCode.isValidMaskPattern(maskPattern)) { + throw new WriterException('Invalid mask pattern'); } + const typeInfo = (ecLevel.getBits() << 3) | maskPattern; + bits.appendBits(typeInfo, 5); - // Make bit vector of type information. On success, store the result in "bits" and return true. - // Encode error correction level and mask pattern. See 8.9 of - // JISX0510:2004 (p.45) for details. - public static makeTypeInfoBits(ecLevel: ErrorCorrectionLevel, maskPattern: number /*int*/, bits: BitArray): void { - if (!QRCode.isValidMaskPattern(maskPattern)) { - throw new WriterException('Invalid mask pattern'); - } - const typeInfo = (ecLevel.getBits() << 3) | maskPattern; - bits.appendBits(typeInfo, 5); + const bchCode = MatrixUtil.calculateBCHCode(typeInfo, MatrixUtil.TYPE_INFO_POLY); + bits.appendBits(bchCode, 10); - const bchCode = MatrixUtil.calculateBCHCode(typeInfo, MatrixUtil.TYPE_INFO_POLY); - bits.appendBits(bchCode, 10); + const maskBits = new BitArray(); + maskBits.appendBits(MatrixUtil.TYPE_INFO_MASK_PATTERN, 15); + bits.xor(maskBits); - const maskBits = new BitArray(); - maskBits.appendBits(MatrixUtil.TYPE_INFO_MASK_PATTERN, 15); - bits.xor(maskBits); - - if (bits.getSize() !== 15) { // Just in case. - throw new WriterException('should not happen but we got: ' + bits.getSize()); - } + if (bits.getSize() !== 15) { // Just in case. + throw new WriterException('should not happen but we got: ' + bits.getSize()); } + } - // Make bit vector of version information. On success, store the result in "bits" and return true. - // See 8.10 of JISX0510:2004 (p.45) for details. - public static makeVersionInfoBits(version: Version, bits: BitArray): void /*throws WriterException*/ { - bits.appendBits(version.getVersionNumber(), 6); - const bchCode = MatrixUtil.calculateBCHCode(version.getVersionNumber(), MatrixUtil.VERSION_INFO_POLY); - bits.appendBits(bchCode, 12); + // Make bit vector of version information. On success, store the result in "bits" and return true. + // See 8.10 of JISX0510:2004 (p.45) for details. + public static makeVersionInfoBits(version: Version, bits: BitArray): void /* throws WriterException */ { + bits.appendBits(version.getVersionNumber(), 6); + const bchCode = MatrixUtil.calculateBCHCode(version.getVersionNumber(), MatrixUtil.VERSION_INFO_POLY); + bits.appendBits(bchCode, 12); - if (bits.getSize() !== 18) { // Just in case. - throw new WriterException('should not happen but we got: ' + bits.getSize()); - } + if (bits.getSize() !== 18) { // Just in case. + throw new WriterException('should not happen but we got: ' + bits.getSize()); } - - // Check if "value" is empty. - private static isEmpty(value: number /*int*/): boolean { - return value === 255; // -1 + } + + // Check if "value" is empty. + private static isEmpty(value: number /* int */): boolean { + return value === 255; // -1 + } + + private static embedTimingPatterns(matrix: ByteMatrix): void { + // -8 is for skipping position detection patterns (7: size), and two horizontal/vertical + // separation patterns (1: size). Thus, 8 = 7 + 1. + for (let i = 8; i < matrix.getWidth() - 8; ++i) { + const bit = (i + 1) % 2; + // Horizontal line. + if (MatrixUtil.isEmpty(matrix.get(i, 6))) { + matrix.setNumber(i, 6, bit); + } + // Vertical line. + if (MatrixUtil.isEmpty(matrix.get(6, i))) { + matrix.setNumber(6, i, bit); + } } + } - private static embedTimingPatterns(matrix: ByteMatrix): void { - // -8 is for skipping position detection patterns (7: size), and two horizontal/vertical - // separation patterns (1: size). Thus, 8 = 7 + 1. - for (let i = 8; i < matrix.getWidth() - 8; ++i) { - const bit = (i + 1) % 2; - // Horizontal line. - if (MatrixUtil.isEmpty(matrix.get(i, 6))) { - matrix.setNumber(i, 6, bit); - } - // Vertical line. - if (MatrixUtil.isEmpty(matrix.get(6, i))) { - matrix.setNumber(6, i, bit); - } - } + // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46) + private static embedDarkDotAtLeftBottomCorner(matrix: ByteMatrix): void /* throws WriterException */ { + if (matrix.get(8, matrix.getHeight() - 8) === 0) { + throw new WriterException(); } - - // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46) - private static embedDarkDotAtLeftBottomCorner(matrix: ByteMatrix): void /*throws WriterException*/ { - if (matrix.get(8, matrix.getHeight() - 8) === 0) { - throw new WriterException(); - } - matrix.setNumber(8, matrix.getHeight() - 8, 1); + matrix.setNumber(8, matrix.getHeight() - 8, 1); + } + + private static embedHorizontalSeparationPattern(xStart: number /* int */, + yStart: number /* int */, + matrix: ByteMatrix): void /* throws WriterException */ { + for (let x = 0; x < 8; ++x) { + if (!MatrixUtil.isEmpty(matrix.get(xStart + x, yStart))) { + throw new WriterException(); + } + matrix.setNumber(xStart + x, yStart, 0); } - - private static embedHorizontalSeparationPattern(xStart: number /*int*/, - yStart: number /*int*/, - matrix: ByteMatrix): void /*throws WriterException*/ { - for (let x = 0; x < 8; ++x) { - if (!MatrixUtil.isEmpty(matrix.get(xStart + x, yStart))) { - throw new WriterException(); - } - matrix.setNumber(xStart + x, yStart, 0); - } + } + + private static embedVerticalSeparationPattern(xStart: number /* int */, + yStart: number /* int */, + matrix: ByteMatrix): void /* throws WriterException */ { + for (let y = 0; y < 7; ++y) { + if (!MatrixUtil.isEmpty(matrix.get(xStart, yStart + y))) { + throw new WriterException(); + } + matrix.setNumber(xStart, yStart + y, 0); } - - private static embedVerticalSeparationPattern(xStart: number /*int*/, - yStart: number /*int*/, - matrix: ByteMatrix): void /*throws WriterException*/ { - for (let y = 0; y < 7; ++y) { - if (!MatrixUtil.isEmpty(matrix.get(xStart, yStart + y))) { - throw new WriterException(); - } - matrix.setNumber(xStart, yStart + y, 0); - } + } + + private static embedPositionAdjustmentPattern(xStart: number /* int */, yStart: number /* int */, matrix: ByteMatrix): void { + for (let y = 0; y < 5; ++y) { + const patternY: Int32Array = MatrixUtil.POSITION_ADJUSTMENT_PATTERN[y]; + for (let x = 0; x < 5; ++x) { + matrix.setNumber(xStart + x, yStart + y, patternY[x]); + } } - - private static embedPositionAdjustmentPattern(xStart: number /*int*/, yStart: number /*int*/, matrix: ByteMatrix): void { - for (let y = 0; y < 5; ++y) { - const patternY: Int32Array = MatrixUtil.POSITION_ADJUSTMENT_PATTERN[y]; - for (let x = 0; x < 5; ++x) { - matrix.setNumber(xStart + x, yStart + y, patternY[x]); - } - } - } - - private static embedPositionDetectionPattern(xStart: number /*int*/, yStart: number /*int*/, matrix: ByteMatrix): void { - for (let y = 0; y < 7; ++y) { - const patternY: Int32Array = MatrixUtil.POSITION_DETECTION_PATTERN[y]; - for (let x = 0; x < 7; ++x) { - matrix.setNumber(xStart + x, yStart + y, patternY[x]); - } - } + } + + private static embedPositionDetectionPattern(xStart: number /* int */, yStart: number /* int */, matrix: ByteMatrix): void { + for (let y = 0; y < 7; ++y) { + const patternY: Int32Array = MatrixUtil.POSITION_DETECTION_PATTERN[y]; + for (let x = 0; x < 7; ++x) { + matrix.setNumber(xStart + x, yStart + y, patternY[x]); + } } - - // Embed position detection patterns and surrounding vertical/horizontal separators. - private static embedPositionDetectionPatternsAndSeparators(matrix: ByteMatrix): void /*throws WriterException*/ { - // Embed three big squares at corners. - const pdpWidth = MatrixUtil.POSITION_DETECTION_PATTERN[0].length; - // Left top corner. - MatrixUtil.embedPositionDetectionPattern(0, 0, matrix); - // Right top corner. - MatrixUtil.embedPositionDetectionPattern(matrix.getWidth() - pdpWidth, 0, matrix); - // Left bottom corner. - MatrixUtil.embedPositionDetectionPattern(0, matrix.getWidth() - pdpWidth, matrix); - - // Embed horizontal separation patterns around the squares. - const hspWidth = 8; - // Left top corner. - MatrixUtil.embedHorizontalSeparationPattern(0, hspWidth - 1, matrix); - // Right top corner. - MatrixUtil.embedHorizontalSeparationPattern(matrix.getWidth() - hspWidth, - hspWidth - 1, matrix); - // Left bottom corner. - MatrixUtil.embedHorizontalSeparationPattern(0, matrix.getWidth() - hspWidth, matrix); - - // Embed vertical separation patterns around the squares. - const vspSize = 7; - // Left top corner. - MatrixUtil.embedVerticalSeparationPattern(vspSize, 0, matrix); - // Right top corner. - MatrixUtil.embedVerticalSeparationPattern(matrix.getHeight() - vspSize - 1, 0, matrix); - // Left bottom corner. - MatrixUtil.embedVerticalSeparationPattern(vspSize, matrix.getHeight() - vspSize, - matrix); + } + + // Embed position detection patterns and surrounding vertical/horizontal separators. + private static embedPositionDetectionPatternsAndSeparators(matrix: ByteMatrix): void /* throws WriterException */ { + // Embed three big squares at corners. + const pdpWidth = MatrixUtil.POSITION_DETECTION_PATTERN[0].length; + // Left top corner. + MatrixUtil.embedPositionDetectionPattern(0, 0, matrix); + // Right top corner. + MatrixUtil.embedPositionDetectionPattern(matrix.getWidth() - pdpWidth, 0, matrix); + // Left bottom corner. + MatrixUtil.embedPositionDetectionPattern(0, matrix.getWidth() - pdpWidth, matrix); + + // Embed horizontal separation patterns around the squares. + const hspWidth = 8; + // Left top corner. + MatrixUtil.embedHorizontalSeparationPattern(0, hspWidth - 1, matrix); + // Right top corner. + MatrixUtil.embedHorizontalSeparationPattern(matrix.getWidth() - hspWidth, + hspWidth - 1, matrix); + // Left bottom corner. + MatrixUtil.embedHorizontalSeparationPattern(0, matrix.getWidth() - hspWidth, matrix); + + // Embed vertical separation patterns around the squares. + const vspSize = 7; + // Left top corner. + MatrixUtil.embedVerticalSeparationPattern(vspSize, 0, matrix); + // Right top corner. + MatrixUtil.embedVerticalSeparationPattern(matrix.getHeight() - vspSize - 1, 0, matrix); + // Left bottom corner. + MatrixUtil.embedVerticalSeparationPattern(vspSize, matrix.getHeight() - vspSize, + matrix); + } + + // Embed position adjustment patterns if need be. + private static maybeEmbedPositionAdjustmentPatterns(version: Version, matrix: ByteMatrix): void { + if (version.getVersionNumber() < 2) { // The patterns appear if version >= 2 + return; } - - // Embed position adjustment patterns if need be. - private static maybeEmbedPositionAdjustmentPatterns(version: Version, matrix: ByteMatrix): void { - if (version.getVersionNumber() < 2) { // The patterns appear if version >= 2 - return; - } - const index = version.getVersionNumber() - 1; - const coordinates: Int32Array = MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index]; - for (let i = 0, length = coordinates.length; i !== length; i++) { - const y = coordinates[i]; - if (y >= 0) { - for (let j = 0; j !== length; j++) { - const x = coordinates[j]; - if (x >= 0 && MatrixUtil.isEmpty(matrix.get(x, y))) { - // If the cell is unset, we embed the position adjustment pattern here. - // -2 is necessary since the x/y coordinates point to the center of the pattern, not the - // left top corner. - MatrixUtil.embedPositionAdjustmentPattern(x - 2, y - 2, matrix); - } - } - } + const index = version.getVersionNumber() - 1; + const coordinates: Int32Array = MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index]; + for (let i = 0, length = coordinates.length; i !== length; i++) { + const y = coordinates[i]; + if (y >= 0) { + for (let j = 0; j !== length; j++) { + const x = coordinates[j]; + if (x >= 0 && MatrixUtil.isEmpty(matrix.get(x, y))) { + // If the cell is unset, we embed the position adjustment pattern here. + // -2 is necessary since the x/y coordinates point to the center of the pattern, not the + // left top corner. + MatrixUtil.embedPositionAdjustmentPattern(x - 2, y - 2, matrix); + } } + } } + } } diff --git a/src/core/qrcode/encoder/QRCode.ts b/src/core/qrcode/encoder/QRCode.ts index 64968ae2..78e3bd07 100644 --- a/src/core/qrcode/encoder/QRCode.ts +++ b/src/core/qrcode/encoder/QRCode.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*namespace com.google.zxing.qrcode.encoder {*/ +/* namespace com.google.zxing.qrcode.encoder { */ import ErrorCorrectionLevel from '../decoder/ErrorCorrectionLevel'; import Mode from '../decoder/Mode'; @@ -28,83 +28,83 @@ import ByteMatrix from './ByteMatrix'; */ export default class QRCode { - public static NUM_MASK_PATTERNS = 8; - - private mode: Mode; - private ecLevel: ErrorCorrectionLevel; - private version: Version; - private maskPattern: number; /*int*/ - private matrix: ByteMatrix; - - public constructor() { - this.maskPattern = -1; - } - - public getMode(): Mode { - return this.mode; - } - - public getECLevel(): ErrorCorrectionLevel { - return this.ecLevel; - } - - public getVersion(): Version { - return this.version; - } - - public getMaskPattern(): number /*int*/ { - return this.maskPattern; - } - - public getMatrix(): ByteMatrix { - return this.matrix; - } - - /*@Override*/ - public toString(): string { - const result = new StringBuilder(); // (200) - result.append('<<\n'); - result.append(' mode: '); - result.append(this.mode ? this.mode.toString() : 'null'); - result.append('\n ecLevel: '); - result.append(this.ecLevel ? this.ecLevel.toString() : 'null'); - result.append('\n version: '); - result.append(this.version ? this.version.toString() : 'null'); - result.append('\n maskPattern: '); - result.append(this.maskPattern.toString()); - if (this.matrix) { - result.append('\n matrix:\n'); - result.append(this.matrix.toString()); - } else { - result.append('\n matrix: null\n'); - } - result.append('>>\n'); - return result.toString(); - } - - public setMode(value: Mode): void { - this.mode = value; - } - - public setECLevel(value: ErrorCorrectionLevel): void { - this.ecLevel = value; - } - - public setVersion(version: Version): void { - this.version = version; - } - - public setMaskPattern(value: number /*int*/): void { - this.maskPattern = value; - } - - public setMatrix(value: ByteMatrix): void { - this.matrix = value; - } - - // Check if "mask_pattern" is valid. - public static isValidMaskPattern(maskPattern: number /*int*/): boolean { - return maskPattern >= 0 && maskPattern < QRCode.NUM_MASK_PATTERNS; + public static NUM_MASK_PATTERNS = 8; + + private mode: Mode; + private ecLevel: ErrorCorrectionLevel; + private version: Version; + private maskPattern: number; /* int */ + private matrix: ByteMatrix; + + public constructor() { + this.maskPattern = -1; + } + + public getMode(): Mode { + return this.mode; + } + + public getECLevel(): ErrorCorrectionLevel { + return this.ecLevel; + } + + public getVersion(): Version { + return this.version; + } + + public getMaskPattern(): number /* int */ { + return this.maskPattern; + } + + public getMatrix(): ByteMatrix { + return this.matrix; + } + + /* @Override */ + public toString(): string { + const result = new StringBuilder(); // (200) + result.append('<<\n'); + result.append(' mode: '); + result.append(this.mode ? this.mode.toString() : 'null'); + result.append('\n ecLevel: '); + result.append(this.ecLevel ? this.ecLevel.toString() : 'null'); + result.append('\n version: '); + result.append(this.version ? this.version.toString() : 'null'); + result.append('\n maskPattern: '); + result.append(this.maskPattern.toString()); + if (this.matrix) { + result.append('\n matrix:\n'); + result.append(this.matrix.toString()); + } else { + result.append('\n matrix: null\n'); } + result.append('>>\n'); + return result.toString(); + } + + public setMode(value: Mode): void { + this.mode = value; + } + + public setECLevel(value: ErrorCorrectionLevel): void { + this.ecLevel = value; + } + + public setVersion(version: Version): void { + this.version = version; + } + + public setMaskPattern(value: number /* int */): void { + this.maskPattern = value; + } + + public setMatrix(value: ByteMatrix): void { + this.matrix = value; + } + + // Check if "mask_pattern" is valid. + public static isValidMaskPattern(maskPattern: number /* int */): boolean { + return maskPattern >= 0 && maskPattern < QRCode.NUM_MASK_PATTERNS; + } } diff --git a/src/core/util/Arrays.ts b/src/core/util/Arrays.ts index e487efaa..36f8adec 100644 --- a/src/core/util/Arrays.ts +++ b/src/core/util/Arrays.ts @@ -11,7 +11,7 @@ export default class Arrays { * * @param a the array to be filled * @param val the value to be stored in all elements of the array - */ + */ public static fill(a: Int32Array | Uint8Array | any[], val: int): void { for (let i = 0, len = a.length; i < len; i++) a[i] = val; @@ -33,7 +33,7 @@ export default class Arrays { * @throws IllegalArgumentException if {@code fromIndex > toIndex} * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > a.length} - */ + */ public static fillWithin(a: Int32Array, fromIndex: int, toIndex: int, val: int): void { Arrays.rangeCheck(a.length, fromIndex, toIndex); for (let i = fromIndex; i < toIndex; i++) @@ -43,7 +43,7 @@ export default class Arrays { /** * Checks that {@code fromIndex} and {@code toIndex} are in * the range and throws an exception if they aren't. - */ + */ static rangeCheck(arrayLength: int, fromIndex: int, toIndex: int): void { if (fromIndex > toIndex) { throw new IllegalArgumentException( @@ -152,7 +152,7 @@ export default class Arrays { * the returned value can be the index of any one of the equal elements. * * http://jsfiddle.net/aryzhov/pkfst550/ - */ + */ public static binarySearch(ar: Int32Array, el: number, comparator?: (a: number, b: number) => number): number { if (undefined === comparator) { comparator = Arrays.numberComparator; @@ -176,4 +176,8 @@ export default class Arrays { public static numberComparator(a: number, b: number) { return a - b; } + + public static sort(squares: Array | Float64Array) { + return squares.sort(); + } } diff --git a/src/core/util/BarcodeFormaHelpers.ts b/src/core/util/BarcodeFormaHelpers.ts new file mode 100644 index 00000000..86293c3f --- /dev/null +++ b/src/core/util/BarcodeFormaHelpers.ts @@ -0,0 +1,6 @@ +import BarcodeFormat from '../BarcodeFormat'; + +export function isBarcodeFormatValue(num: number) { + const values = Object.keys(BarcodeFormat).map(i => Number(i)).filter(Number.isInteger); + return values.includes(num); +} diff --git a/src/core/util/ByteArrayOutputStream.ts b/src/core/util/ByteArrayOutputStream.ts index 3d6c2dd8..f12540cb 100644 --- a/src/core/util/ByteArrayOutputStream.ts +++ b/src/core/util/ByteArrayOutputStream.ts @@ -53,22 +53,22 @@ import { int } from '../../customTypings'; * @since JDK1.0 */ -export default /*public*/ class ByteArrayOutputStream extends OutputStream { +export default /* public */ class ByteArrayOutputStream extends OutputStream { /** * The buffer where data is stored. - */ + */ protected buf: Uint8Array; /** * The number of valid bytes in the buffer. - */ + */ protected count: int = 0; /** * Creates a new byte array output stream. The buffer capacity is * initially 32 bytes, though its size increases if necessary. - */ + */ // public constructor() { // this(32); // } @@ -79,7 +79,7 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * * @param size the initial size. * @exception IllegalArgumentException if size is negative. - */ + */ public constructor(size: int = 32) { super(); if (size < 0) { @@ -98,7 +98,7 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * @throws OutOfMemoryError if {@code minCapacity < 0}. This is * interpreted as a request for the unsatisfiably large capacity * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}. - */ + */ private ensureCapacity(minCapacity: int): void { // overflow-conscious code if (minCapacity - this.buf.length > 0) @@ -110,7 +110,7 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity - */ + */ private grow(minCapacity: int): void { // overflow-conscious code let oldCapacity: int = this.buf.length; @@ -129,10 +129,10 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * Writes the specified byte to this byte array output stream. * * @param b the byte to be written. - */ - public /*synchronized*/ write(b: int): void { + */ + public /* synchronized */ write(b: int): void { this.ensureCapacity(this.count + 1); - this.buf[this.count] = /*(byte)*/ b; + this.buf[this.count] = /* (byte) */ b; this.count += 1; } @@ -143,8 +143,8 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. - */ - public /*synchronized*/ writeBytesOffset(b: Uint8Array, off: int, len: int): void { + */ + public /* synchronized */ writeBytesOffset(b: Uint8Array, off: int, len: int): void { if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) - b.length > 0)) { throw new IndexOutOfBoundsException(); @@ -161,8 +161,8 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * * @param out the output stream to which to write the data. * @exception IOException if an I/O error occurs. - */ - public /*synchronized*/ writeTo(out: OutputStream): void { + */ + public /* synchronized */ writeTo(out: OutputStream): void { out.writeBytesOffset(this.buf, 0, this.count); } @@ -173,8 +173,8 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * reusing the already allocated buffer space. * * @see java.io.ByteArrayInputStream#count - */ - public /*synchronized*/ reset(): void { + */ + public /* synchronized */ reset(): void { this.count = 0; } @@ -185,8 +185,8 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * * @return the current contents of this output stream, as a byte array. * @see java.io.ByteArrayOutputStream#size() - */ - public /*synchronized*/ toByteArray(): Uint8Array { + */ + public /* synchronized */ toByteArray(): Uint8Array { return Arrays.copyOfUint8Array(this.buf, this.count); } @@ -196,8 +196,8 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * @return the value of the count field, which is the number * of valid bytes in this output stream. * @see java.io.ByteArrayOutputStream#count - */ - public /*synchronized*/ size(): int { + */ + public /* synchronized */ size(): int { return this.count; } @@ -225,9 +225,9 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * * @return String decoded from the buffer's contents. * @since JDK1.1 - */ - public /*synchronized*/ toString_void(): string { - return new String(this.buf/*, 0, this.count*/).toString(); + */ + public /* synchronized */ toString_void(): string { + return new String(this.buf/* , 0, this.count */).toString(); } /** @@ -247,9 +247,9 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * @exception UnsupportedEncodingException * If the named charset is not supported * @since JDK1.1 - */ - public /*synchronized*/ toString_string(charsetName: string): string { - return new String(this.buf/*, 0, this.count, charsetName*/).toString(); + */ + public /* synchronized */ toString_string(charsetName: string): string { + return new String(this.buf/* , 0, this.count, charsetName */).toString(); } /** @@ -273,10 +273,10 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { * @see java.io.ByteArrayOutputStream#size() * @see java.io.ByteArrayOutputStream#toString(String) * @see java.io.ByteArrayOutputStream#toString() - */ + */ // @Deprecated - public /*synchronized*/ toString_number(hibyte: int): string { - return new String(this.buf/*, hibyte, 0, this.count*/).toString(); + public /* synchronized */ toString_number(hibyte: int): string { + return new String(this.buf/* , hibyte, 0, this.count */).toString(); } /** @@ -286,7 +286,7 @@ export default /*public*/ class ByteArrayOutputStream extends OutputStream { *

* * @throws IOException - */ + */ public close(): void { } diff --git a/src/core/util/Collections.ts b/src/core/util/Collections.ts index 67142fb7..f1945cef 100644 --- a/src/core/util/Collections.ts +++ b/src/core/util/Collections.ts @@ -1,17 +1,28 @@ -import { Collection, int } from '../../customTypings'; +import { Collection, int, List } from '../../customTypings'; +import Comparator from './Comparator'; export default class Collections { /** * The singletonList(T) method is used to return an immutable list containing only the specified object. - */ + */ static singletonList(item: T): Collection { return [item]; } /** - * The min(Collection, Comparator) method is used to return the minimum element of the given collection, according to the order induced by the specified comparator. + * Sorts the specified list according to the order induced by the specified comparator. */ + static sort( + list: List | Array | TToBeCompared[], + comparator: Comparator, + ) { + list.sort(comparator.compare); + } + + /** + * The min(Collection, Comparator) method is used to return the minimum element of the given collection, according to the order induced by the specified comparator. + */ static min(collection: Collection, comparator: (a: T, b: T) => int): T { return collection.sort(comparator)[0]; } diff --git a/src/core/util/Comparator.ts b/src/core/util/Comparator.ts new file mode 100644 index 00000000..019f087b --- /dev/null +++ b/src/core/util/Comparator.ts @@ -0,0 +1,13 @@ +import { int } from '../../customTypings'; + +/** + * Java Comparator interface polyfill. + */ +export default interface Comparator { + /** + * Compares its two arguments for order. Returns a negative integer, zero, + * or a positive integer as the first argument is less than, equal to, + * or greater than the second. + */ + compare(a: T, b: T): int; +} diff --git a/src/core/util/Double.ts b/src/core/util/Double.ts new file mode 100644 index 00000000..d911e555 --- /dev/null +++ b/src/core/util/Double.ts @@ -0,0 +1,5 @@ +import { double } from '../../customTypings'; + +export default class Double { + static MAX_VALUE: double = 1.7 * 10 ^ 308; +} diff --git a/src/core/util/Float.ts b/src/core/util/Float.ts index 86f8458d..000462a8 100644 --- a/src/core/util/Float.ts +++ b/src/core/util/Float.ts @@ -1,3 +1,5 @@ +import { float, int } from '../../customTypings'; + /** * Ponyfill for Java's Float class. */ @@ -5,14 +7,26 @@ export default class Float { /** * The float max value in JS is the number max value. - */ + */ static MAX_VALUE: number = Number.MAX_SAFE_INTEGER; + static NaN = NaN; + /** * SincTS has no difference between int and float, there's all numbers, * this is used only to polyfill Java code. - */ + */ public static floatToIntBits(f: number): number { return f; } + + public static isNaN(num: number) { + return isNaN(num); + } + + public static compare(x: float, y: float): int { + if (x === y) return 0; + if (x < y) return -1; + if (x > y) return 1; + } } diff --git a/src/core/util/Formatter.ts b/src/core/util/Formatter.ts index 701e75c7..4186381c 100644 --- a/src/core/util/Formatter.ts +++ b/src/core/util/Formatter.ts @@ -5,7 +5,7 @@ export default class Formatter { /** * The internal formatted value. - */ + */ buffer: string; constructor() { @@ -18,7 +18,7 @@ export default class Formatter { * * @param str * @param arr - */ + */ private static form(str: string, arr: any[]) { let i = -1; @@ -61,14 +61,14 @@ export default class Formatter { * * @param append The new string to append. * @param args Argumets values to be formated. - */ + */ format(append: string, ...args: any) { this.buffer += Formatter.form(append, args); } /** * Returns the Formatter string value. - */ + */ toString(): string { return this.buffer; } diff --git a/src/core/util/Integer.ts b/src/core/util/Integer.ts index 80a9c36e..b62abece 100644 --- a/src/core/util/Integer.ts +++ b/src/core/util/Integer.ts @@ -1,3 +1,5 @@ +import { int } from "../../customTypings"; + /** * Ponyfill for Java's Integer class. */ @@ -6,6 +8,21 @@ export default class Integer { static MIN_VALUE_32_BITS = -2147483648; static MAX_VALUE: number = Number.MAX_SAFE_INTEGER; + /** + * Parameter : + * x : the first int to compare + * y : the second int to compare + * Return : + * This method returns the value zero if (x==y), + * if (x < y) then it returns a value less than zero + * and if (x > y) then it returns a value greater than zero. + */ + static compare(x: int, y: int): number { + if (x === y) return 0; + if (x < y) return -1; + if (x > y) return 1; + } + public static numberOfTrailingZeros(i: number): number { let y: number; @@ -109,7 +126,7 @@ export default class Integer { * Converts A string to an integer. * @param s A string to convert into a number. * @param radix A value between 2 and 36 that specifies the base of the number in numString. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal. - */ + */ static parseInt(num: string, radix: number = undefined) { return parseInt(num, radix); } diff --git a/src/core/util/Long.ts b/src/core/util/Long.ts index be5659ee..8bab0407 100644 --- a/src/core/util/Long.ts +++ b/src/core/util/Long.ts @@ -8,7 +8,7 @@ export default class Long { * * @param num Numeric string. * @param radix Destination radix. - */ + */ static parseLong(num: string, radix: number = undefined) { return parseInt(num, radix); } diff --git a/src/core/util/OutputStream.ts b/src/core/util/OutputStream.ts index 7fdcdb2a..410a4993 100644 --- a/src/core/util/OutputStream.ts +++ b/src/core/util/OutputStream.ts @@ -46,7 +46,7 @@ import NullPointerException from '../NullPointerException'; * @see java.io.OutputStream#write(int) * @since JDK1.0 */ -export default /*public*/ abstract class OutputStream /*implements Closeable, Flushable*/ { +export default /* public */ abstract class OutputStream /* implements Closeable, Flushable */ { /** * Writes the specified byte to this output stream. The general * contract for write is that one byte is written @@ -61,8 +61,8 @@ export default /*public*/ abstract class OutputStream /*implements Closeable, Fl * @exception IOException if an I/O error occurs. In particular, * an IOException may be thrown if the * output stream has been closed. - */ - public abstract write(b: /*int*/ number): void; + */ + public abstract write(b: /* int */ number): void; /** * Writes b.length bytes from the specified byte array @@ -73,7 +73,7 @@ export default /*public*/ abstract class OutputStream /*implements Closeable, Fl * @param b the data. * @exception IOException if an I/O error occurs. * @see java.io.OutputStream#write(byte[], int, int) - */ + */ public writeBytes(b: Uint8Array): void { this.writeBytesOffset(b, 0, b.length); } @@ -105,8 +105,8 @@ export default /*public*/ abstract class OutputStream /*implements Closeable, Fl * @exception IOException if an I/O error occurs. In particular, * an IOException is thrown if the output * stream is closed. - */ - public writeBytesOffset(b: Uint8Array, off: /*int*/ number, len: /*int*/ number): void { + */ + public writeBytesOffset(b: Uint8Array, off: /* int */ number, len: /* int */ number): void { if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || @@ -137,7 +137,7 @@ export default /*public*/ abstract class OutputStream /*implements Closeable, Fl * The flush method of OutputStream does nothing. * * @exception IOException if an I/O error occurs. - */ + */ public flush(): void { } @@ -150,7 +150,7 @@ export default /*public*/ abstract class OutputStream /*implements Closeable, Fl * The close method of OutputStream does nothing. * * @exception IOException if an I/O error occurs. - */ + */ public close(): void { } diff --git a/src/core/util/StringBuilder.ts b/src/core/util/StringBuilder.ts index ca82cd6a..d254d025 100644 --- a/src/core/util/StringBuilder.ts +++ b/src/core/util/StringBuilder.ts @@ -14,15 +14,7 @@ export default class StringBuilder { } public append(s: string | number): StringBuilder { - if (typeof s === 'string') { - this.value += s.toString(); - } else if (this.encoding) { - // use passed format (fromCharCode will return UTF8 encoding) - this.value += StringUtils.castAsNonUtf8Char(s, this.encoding); - } else { - // correctly converts from UTF-8, but not other encodings - this.value += String.fromCharCode(s); - } + this.value += this.normalizeString(s); return this; } @@ -33,6 +25,12 @@ export default class StringBuilder { return this; } + public insert(n: number, s: string | number, replace = 0) { + let c = this.normalizeString(s); + this.value = this.value.substr(0, n) + c + this.value.substr(n + replace); + return this; + } + public length(): number { return this.value.length; } @@ -53,9 +51,6 @@ export default class StringBuilder { return this.value.substring(start, end); } - /** - * @note helper method for RSS Expanded - */ public setLengthToZero(): void { this.value = ''; } @@ -64,7 +59,15 @@ export default class StringBuilder { return this.value; } - public insert(n: number, c: string) { - this.value = this.value.substr(0, n) + c + this.value.substr(n + c.length); + public normalizeString(s: string | number) { + if (typeof s === 'string') { + return s; + } else if (this.encoding) { + // use passed format (fromCharCode will return UTF8 encoding) + return StringUtils.castAsNonUtf8Char(s, this.encoding); + } else { + // correctly converts from UTF-8, but not other encodings + return String.fromCharCode(s); + } } } diff --git a/src/core/util/StringEncoding.ts b/src/core/util/StringEncoding.ts index 574c1939..1589cb34 100644 --- a/src/core/util/StringEncoding.ts +++ b/src/core/util/StringEncoding.ts @@ -9,18 +9,18 @@ export default class StringEncoding { /** * Allows the user to set a custom decoding function * so more encoding formats the native ones can be supported. - */ + */ public static customDecoder: (bytes: Uint8Array, encodingName: string) => string; /** * Allows the user to set a custom encoding function * so more encoding formats the native ones can be supported. - */ + */ public static customEncoder: (s: string, encodingName: string) => Uint8Array; /** * Decodes some Uint8Array to a string format. - */ + */ public static decode(bytes: Uint8Array, encoding: string | CharacterSetECI): string { const encodingName = this.encodingName(encoding); @@ -42,14 +42,14 @@ export default class StringEncoding { * once Node TextDecoder doesn't support all encoding formats. * * @param encodingName - */ + */ private static shouldDecodeOnFallback(encodingName: string): boolean { return !StringEncoding.isBrowser() && encodingName === 'ISO-8859-1'; } /** * Encodes some string into a Uint8Array. - */ + */ public static encode(s: string, encoding: string | CharacterSetECI): Uint8Array { const encodingName = this.encodingName(encoding); @@ -73,7 +73,7 @@ export default class StringEncoding { /** * Returns the string value from some encoding character set. - */ + */ public static encodingName(encoding: string | CharacterSetECI): string { return typeof encoding === 'string' ? encoding @@ -82,7 +82,7 @@ export default class StringEncoding { /** * Returns character set from some encoding character set. - */ + */ public static encodingCharacterSet(encoding: string | CharacterSetECI): CharacterSetECI { if (encoding instanceof CharacterSetECI) { @@ -94,7 +94,7 @@ export default class StringEncoding { /** * Runs a fallback for the native decoding funcion. - */ + */ private static decodeFallback(bytes: Uint8Array, encoding: string | CharacterSetECI): string { const characterSet = this.encodingCharacterSet(encoding); @@ -134,7 +134,7 @@ export default class StringEncoding { * Runs a fallback for the native encoding funcion. * * @see https://stackoverflow.com/a/17192845/4367683 - */ + */ private static encodeFallback(s: string): Uint8Array { const encodedURIstring = btoa(unescape(encodeURIComponent(s))); diff --git a/src/core/util/System.ts b/src/core/util/System.ts index ff8586d3..4d79eb38 100644 --- a/src/core/util/System.ts +++ b/src/core/util/System.ts @@ -1,20 +1,20 @@ export default class System { - // public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) - /** - * Makes a copy of a array. - */ - public static arraycopy(src: any, srcPos: number, dest: any, destPos: number, length: number): void { - // TODO: better use split or set? - while (length--) { - dest[destPos++] = src[srcPos++]; - } + // public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) + /** + * Makes a copy of a array. + */ + public static arraycopy(src: any, srcPos: number, dest: any, destPos: number, length: number): void { + // TODO: better use split or set? + while (length--) { + dest[destPos++] = src[srcPos++]; } + } - /** - * Returns the current time in milliseconds. - */ - public static currentTimeMillis(): number { - return Date.now(); - } + /** + * Returns the current time in milliseconds. + */ + public static currentTimeMillis(): number { + return Date.now(); + } } diff --git a/src/customTypings.ts b/src/customTypings.ts index 78d284aa..68ce20ab 100644 --- a/src/customTypings.ts +++ b/src/customTypings.ts @@ -1,3 +1,6 @@ +/// +/// + /** * This file contains some types to make our * lifes easier when copy and pasting Java code. @@ -11,7 +14,9 @@ export declare type byte = number; export declare type short = number; export declare type int = number; +export declare type long = number; export declare type float = number; +export declare type double = number; // special formats export type char = number; diff --git a/src/extension/sources/ColorFormat.ts b/src/extension/sources/ColorFormat.ts new file mode 100644 index 00000000..18c4c643 --- /dev/null +++ b/src/extension/sources/ColorFormat.ts @@ -0,0 +1,21 @@ +/** Used to determine how to calculate luminance from a given source. In JavaScript `0xFF` is identical to `255`. */ +enum ColorFormat { + /** Luminance represented as a hexadecimal in the range `0x00 - 0xFF`. */ + Luminance, + /** Color is formatted as `[R, G, B]` where numeric range is `0x00 - 0xFF`. */ + RGBMatrix, + /** Color is formatted as `[R, G, B, A]` where numeric range is `0x00 - 0xFF`. */ + RGBAMatrix, + /** Color is formatted as `0xRRGGBB` where hexadecimal range is `0x00 - 0xFF`. */ + RGBHex, + /** Color is formatted as `0xAARRGGBB` where hexadecimal range is `0x00 - 0xFF`. */ + RGBAStartHex, + /** Color is formatted as `0xRRGGBBAA` where hexadecimal range is `0x00 - 0xFF`. */ + RGBAEndHex, + /** Color is formatted as `[H, S, L]` where numeric range of L is `0 - 100`. */ + HSLMatrix, + /** Color is formatted as `[H, S, L, A]` where numeric range of L is `0 - 100`. */ + HSLAMatrix, +} + +export default ColorFormat; \ No newline at end of file diff --git a/src/extension/sources/MultiFormatLuminanceSource.ts b/src/extension/sources/MultiFormatLuminanceSource.ts new file mode 100644 index 00000000..56561dcd --- /dev/null +++ b/src/extension/sources/MultiFormatLuminanceSource.ts @@ -0,0 +1,288 @@ +import ColorFormat from './ColorFormat'; +import IllegalArgumentException from '../../core/IllegalArgumentException'; +import IllegalStateException from '../../core/IllegalStateException'; +import InvertedLuminanceSource from '../../core/InvertedLuminanceSource'; +import LuminanceSource from '../../core/LuminanceSource'; + +/** + * Used instead of HTMLCanvasElementLuminanceSource in cases where DOM is not available e.g. web workers. + * @note does not currently support cropping of image buffer. + */ +export default class MultiFormatLuminanceSource extends LuminanceSource { + private luminances: Uint8ClampedArray; + + public constructor(data: Uint8ClampedArray | Int32Array | Int8Array, width: number, height: number, format: ColorFormat) { + super(width, height); + this.luminances = MultiFormatLuminanceSource.toLuminanceBuffer(data, width, height, format); + } + + private static rgbaToLuminance(r: number, g: number, b: number, a = 0xFF) { + if (a === 0) return 0xFF; + // Calculate green-favouring average cheaply + return ((r + g*2 + b) / 4) & 0xFF; + } + + private static toLuminanceBuffer( + data: Uint8ClampedArray | Int32Array | Int8Array, + width: number, + height: number, + format: ColorFormat, + ): Uint8ClampedArray { + const luminances = new Uint8ClampedArray(width * height); + let sequence = 1; + if (format === ColorFormat.RGBMatrix || format === ColorFormat.HSLMatrix) sequence = 3; + if (format === ColorFormat.RGBAMatrix || format === ColorFormat.HSLAMatrix) sequence = 4; + + for (let i = 0, j = 0, length = data.length; i < length; i += sequence, j++) { + let luminance; + switch (format) { + case ColorFormat.RGBMatrix: + luminance = MultiFormatLuminanceSource.rgbaToLuminance(data[i], data[i + 1], data[i + 2]); + break; + case ColorFormat.RGBAMatrix: + luminance = MultiFormatLuminanceSource.rgbaToLuminance(data[i], data[i + 1], data[i + 2], data[i + 3]); + break; + case ColorFormat.RGBHex: + luminance = MultiFormatLuminanceSource.rgbaToLuminance( + data[i] >> 16 & 0xff, data[i] >> 8 & 0xff, data[i] & 0xff + ); + break; + case ColorFormat.RGBAStartHex: + luminance = MultiFormatLuminanceSource.rgbaToLuminance( + data[i] >> 16 & 0xff, data[i] >> 8 & 0xff, data[i] & 0xff, data[i] >> 24 & 0xff + ); + break; + case ColorFormat.RGBAEndHex: + luminance = MultiFormatLuminanceSource.rgbaToLuminance( + data[i] >> 24 & 0xff, data[i] >> 16 & 0xff, data[i] >> 8 & 0xff, data[i] & 0xff + ); + break; + case ColorFormat.HSLMatrix: + luminance = data[i + 2] / 100 * 0xff; + break; + case ColorFormat.HSLAMatrix: + if (data[i + 3] === 0) luminance = 0xff; + else luminance = data[i + 2] / 100 * 0xff; + break; + case ColorFormat.Luminance: + luminance = data[i]; + break; + default: + throw new IllegalStateException('Color format not supported by MultiFormatLuminanceSource'); + } + luminances[j] = luminance; + } + + return luminances; + } + + /** @inheritdoc */ + public getRow(y: number, row: Uint8ClampedArray): Uint8ClampedArray { + if (y < 0 || y >= this.getHeight()) { + throw new IllegalArgumentException('Requested row is outside the image: ' + y); + } + const width = this.getWidth(); + const start = y * width; + if (row === null) { + row = this.luminances.slice(start, start + width); + } else { + if (row.length < width) { + row = new Uint8ClampedArray(width); + } + row.set(this.luminances.slice(start, start + width)); + } + + return row; + } + + /** @inheritdoc */ + public getMatrix(): Uint8ClampedArray { + return this.luminances; + } + + /** @inheritdoc */ + public isCropSupported(): boolean { + return true; + } + + /** @inheritdoc */ + public crop( + left: number, + top: number, + width: number, + height: number + ): MultiFormatLuminanceSource { + const currentWidth = this.getWidth(); + const currentHeight = this.getHeight(); + // Position can't be smaller than 0 nor larger currentWidth - 1 + // This means the smallest crop is 1x1 + left = Math.max(0, Math.min(left, currentWidth - 1)); + top = Math.max(0, Math.min(top, currentHeight - 1)); + width = Math.max(1, Math.min(width, currentWidth - left)); + height = Math.max(1, Math.min(height, currentHeight - top)); + const buffer = new Uint8ClampedArray(width * height).fill(255); + const length = buffer.length; + for (let i = 0; i < length; i++) { + const { x, y } = MultiFormatLuminanceSource.indexToCoordinate(i, width); + const currentIndex = MultiFormatLuminanceSource.coordinateToIndex( + x + left, + y + top, + currentWidth + ); + buffer[i] = this.luminances[currentIndex]; + } + + return new MultiFormatLuminanceSource(buffer, width, height, ColorFormat.Luminance); + } + + /** @inheritdoc */ + public isRotateSupported(): boolean { + return true; + } + + /** @inheritdoc */ + public rotateCounterClockwise(): MultiFormatLuminanceSource { + // Rotations of small sets of luminance become slightly damaged. + // Todo: Consider implementing a different algorithm for angles divisible by 90. + return this.rotate(-90); + } + + /** @inheritdoc */ + public rotateCounterClockwise45(): MultiFormatLuminanceSource { + // Repeated rotations of 45 degrees degrades the image each iteration. + return this.rotate(-45); + } + + /** + * Rotate the buffer by a given angle in degrees. + * @param angle rotation angle in degrees + */ + public rotate(angle: number) { + const length = this.luminances.length; + const currentWidth = this.getWidth(); + const currentHeight = this.getHeight(); + const radians = MultiFormatLuminanceSource.degreesToRadians(angle); + const { width, height } = MultiFormatLuminanceSource.expandBuffer( + currentWidth, + currentHeight, + radians + ); + const buffer = new Uint8ClampedArray(width * height).fill(255); + + // Loop through original buffer length + for (let i = 0; i < length; i++) { + // Convert index to coordinate + let { x, y } = MultiFormatLuminanceSource.indexToCoordinate( + i, + currentWidth + ); + // Translate center of image to 0,0 + x -= currentWidth / 2; + y -= currentHeight / 2; + // Rotate coordinate around 0,0 by given radians + let { x: rx, y: ry } = MultiFormatLuminanceSource.rotateCoordinate( + x, + y, + radians + ); + // Translate new coordinates back to new center + rx = Math.round(rx + width / 2); + ry = Math.round(ry + height / 2); + // Convert new coordinates to new index + const j = MultiFormatLuminanceSource.coordinateToIndex(rx, ry, width); + buffer[j] = this.luminances[i]; + } + + return new MultiFormatLuminanceSource(buffer, width, height, ColorFormat.Luminance); + } + + /** @inheritdoc */ + public invert(): MultiFormatLuminanceSource { + return new InvertedLuminanceSource(this) as any; + } + + /* HELPERS */ + + /** + * Converts degrees to radians. + * @param degrees the amount of degrees to convert to radians + */ + static degreesToRadians(degrees: number) { + return degrees * (Math.PI / 180); + } + + /** + * Converts a numeric index in the buffer to a `x` and `y` coordinate. + * @param index the numerical position in the buffer + * @param width how wide the buffer is + * @returns the `x` and `y` coordinates. + */ + static indexToCoordinate(index: number, width: number) { + return { + x: index % width, + y: (index / width) << 0 + }; + } + + /** + * Converts a `x` and `y` coordinate in the buffer to a numeric index. + * @param x horizontal coordinate in the buffer + * @param y vertical coordinate in the buffer + * @param width how wide the buffer is + */ + static coordinateToIndex(x: number, y: number, width: number) { + return x + y * width; + } + + /** + * Expands a given width and height using a radian rotation. + * @param width current width + * @param height current height + * @param radians how many radians to rotate the dimensions + */ + static expandBuffer(width: number, height: number, radians: number) { + return { + width: Math.ceil( + Math.abs(Math.cos(radians)) * width + + Math.abs(Math.sin(radians)) * height + ), + height: Math.ceil( + Math.abs(Math.sin(radians)) * width + + Math.abs(Math.cos(radians)) * height + ) + }; + } + + /** + * Rotate a given coordinate by number of radians. + * @param x horizontal coordinate in the buffer + * @param y vertical coordinate in the buffer + * @param radians how many radians to rotate the coordinates + */ + static rotateCoordinate(x: number, y: number, radians: number) { + x = MultiFormatLuminanceSource.shearHorizontal(x, y, radians); + y = MultiFormatLuminanceSource.shearVertical(x, y, radians); + x = MultiFormatLuminanceSource.shearHorizontal(x, y, radians); + return { x, y }; + } + + /** + * Shift/shear coordinates in the horizontal direction. + * @param x horizontal coordinate in the buffer + * @param y vertical coordinate in the buffer + * @param radians how many radians to shift the coordinates + */ + static shearHorizontal(x: number, y: number, radians: number) { + return Math.round(x + -y * Math.tan(radians / 2)); + } + + /** + * Shift/shear coordinates in the vertical direction. + * @param x horizontal coordinate in the buffer + * @param y vertical coordinate in the buffer + * @param radians how many radians to shift the coordinates + */ + static shearVertical(x: number, y: number, radians: number) { + return Math.round(x * Math.sin(radians) + y); + } +} diff --git a/src/index.ts b/src/index.ts index 7b045bfc..64c8d031 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,3 @@ -export * from './browser'; - // Exceptions export { default as ArgumentException } from './core/ArgumentException'; export { default as ArithmeticException } from './core/ArithmeticException'; @@ -115,6 +113,25 @@ export { default as ITFReader } from './core/oned/ITFReader'; export { default as Code39Reader } from './core/oned/Code39Reader'; export { default as RSS14Reader } from './core/oned/rss/RSS14Reader'; export { default as RSSExpandedReader } from './core/oned/rss/expanded/RSSExpandedReader'; -export { default as AbstractExpandedDecoder } from './core/oned/rss/expanded/decoders/AbstractExpandedDecoder'; export { createDecoder as createAbstractExpandedDecoder } from './core/oned/rss/expanded/decoders/AbstractExpandedDecoderComplement'; export { default as MultiFormatOneDReader } from './core/oned/MultiFormatOneDReader'; + + +// core/oned/rss/expanded +export { default as AbstractExpandedDecoder } from './core/oned/rss/expanded/decoders/AbstractExpandedDecoder'; +export { default as createDecoder } from './core/oned/rss/expanded/decoders/createDecoder'; + + +// core/multi +export { default as MultipleBarcodeReader } from './core/multi/MultipleBarcodeReader'; + + +// core/multi/qrcode +export { default as QRCodeMultiReader } from './core/multi/qrcode/QRCodeMultiReader'; +export { default as MultiDetector } from './core/multi/qrcode/detector/MultiDetector'; +export { default as MultiFinderPatternFinder } from './core/multi/qrcode/detector/MultiFinderPatternFinder'; + + +// extension/sources +export { default as ColorFormat } from './extension/sources/ColorFormat'; +export { default as MultiFormatLuminanceSource } from './extension/sources/MultiFormatLuminanceSource'; diff --git a/src/test/core/PlanarYUVLuminanceSource.spec.ts b/src/test/core/PlanarYUVLuminanceSource.spec.ts index e40bc02a..8aa5060a 100644 --- a/src/test/core/PlanarYUVLuminanceSource.spec.ts +++ b/src/test/core/PlanarYUVLuminanceSource.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing;*/ +/* package com.google.zxing; */ import * as assert from 'assert'; import AssertUtils from './util/AssertUtils'; @@ -23,56 +23,56 @@ import { ZXingSystem } from '@zxing/library'; describe('PlanarYUVLuminanceSource', () => { - const YUV: Uint8ClampedArray = Uint8ClampedArray.from([ - 0, 1, 1, 2, 3, 5, - 8, 13, 21, 34, 55, 89, - 0, -1, -1, -2, -3, -5, - -8, -13, -21, -34, -55, -89, - 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, - ]); + const YUV: Uint8ClampedArray = Uint8ClampedArray.from([ + 0, 1, 1, 2, 3, 5, + 8, 13, 21, 34, 55, 89, + 0, -1, -1, -2, -3, -5, + -8, -13, -21, -34, -55, -89, + 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, + ]); - const COLS: number /*int*/ = 6; - const ROWS: number /*int*/ = 4; - const Y = new Uint8ClampedArray(COLS * ROWS); + const COLS: number /* int */ = 6; + const ROWS: number /* int */ = 4; + const Y = new Uint8ClampedArray(COLS * ROWS); - ZXingSystem.arraycopy(YUV, 0, Y, 0, Y.length); + ZXingSystem.arraycopy(YUV, 0, Y, 0, Y.length); - it('testNoCrop', () => { - const source = new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 0, 0, COLS, ROWS, false); - assertTypedArrayEquals(Y, 0, source.getMatrix(), 0, Y.length); - for (let r: number /*int*/ = 0; r < ROWS; r++) { - assertTypedArrayEquals(Y, r * COLS, source.getRow(r, null), 0, COLS); - } - }); + it('testNoCrop', () => { + const source = new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 0, 0, COLS, ROWS, false); + assertTypedArrayEquals(Y, 0, source.getMatrix(), 0, Y.length); + for (let r: number /* int */ = 0; r < ROWS; r++) { + assertTypedArrayEquals(Y, r * COLS, source.getRow(r, null), 0, COLS); + } + }); - it('testCrop', () => { - const source = - new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 1, 1, COLS - 2, ROWS - 2, false); - assert.strictEqual(source.isCropSupported(), true); - const cropMatrix: Uint8ClampedArray = source.getMatrix(); - for (let r: number /*int*/ = 0; r < ROWS - 2; r++) { - assertTypedArrayEquals(Y, (r + 1) * COLS + 1, cropMatrix, r * (COLS - 2), COLS - 2); - } - for (let r: number /*int*/ = 0; r < ROWS - 2; r++) { - assertTypedArrayEquals(Y, (r + 1) * COLS + 1, source.getRow(r, null), 0, COLS - 2); - } - }); + it('testCrop', () => { + const source = + new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 1, 1, COLS - 2, ROWS - 2, false); + assert.strictEqual(source.isCropSupported(), true); + const cropMatrix: Uint8ClampedArray = source.getMatrix(); + for (let r: number /* int */ = 0; r < ROWS - 2; r++) { + assertTypedArrayEquals(Y, (r + 1) * COLS + 1, cropMatrix, r * (COLS - 2), COLS - 2); + } + for (let r: number /* int */ = 0; r < ROWS - 2; r++) { + assertTypedArrayEquals(Y, (r + 1) * COLS + 1, source.getRow(r, null), 0, COLS - 2); + } + }); - it('testThumbnail', () => { - const source = - new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 0, 0, COLS, ROWS, false); - AssertUtils.typedArraysAreEqual( - Int32Array.from([0xFF000000, 0xFF010101, 0xFF030303, 0xFF000000, 0xFFFFFFFF, 0xFFFDFDFD]), - source.renderThumbnail()); - }); + it('testThumbnail', () => { + const source = + new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 0, 0, COLS, ROWS, false); + AssertUtils.typedArraysAreEqual( + Int32Array.from([0xFF000000, 0xFF010101, 0xFF030303, 0xFF000000, 0xFFFFFFFF, 0xFFFDFDFD]), + source.renderThumbnail()); + }); - function assertTypedArrayEquals(expected: Uint8ClampedArray, expectedFrom: number /*int*/, - actual: Uint8ClampedArray, actualFrom: number /*int*/, - length: number /*int*/) { - for (let i: number /*int*/ = 0; i < length; i++) { - assert.strictEqual(actual[actualFrom + i], expected[expectedFrom + i]); - } + function assertTypedArrayEquals(expected: Uint8ClampedArray, expectedFrom: number /* int */, + actual: Uint8ClampedArray, actualFrom: number /* int */, + length: number /* int */) { + for (let i: number /* int */ = 0; i < length; i++) { + assert.strictEqual(actual[actualFrom + i], expected[expectedFrom + i]); } + } }); diff --git a/src/test/core/RGBLuminanceSource.spec.ts b/src/test/core/RGBLuminanceSource.spec.ts index d9f05e54..b241f438 100644 --- a/src/test/core/RGBLuminanceSource.spec.ts +++ b/src/test/core/RGBLuminanceSource.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing;*/ +/* package com.google.zxing; */ import * as assert from 'assert'; import AssertUtils from './util/AssertUtils'; @@ -23,36 +23,36 @@ import { RGBLuminanceSource } from '@zxing/library'; describe('RGBLuminanceSource', () => { - const SOURCE = new RGBLuminanceSource(Int32Array.from([ - 0x000000, 0x7F7F7F, 0xFFFFFF, - 0xFF0000, 0x00FF00, 0x0000FF, - 0x0000FF, 0x00FF00, 0xFF0000]), 3, 3); - - it('testCrop', () => { - assert.strictEqual(SOURCE.isCropSupported(), true); - const cropped: LuminanceSource = SOURCE.crop(1, 1, 1, 1); - assert.strictEqual(cropped.getHeight(), 1); - assert.strictEqual(cropped.getWidth(), 1); - assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x7F]), cropped.getRow(0, null)), true); - }); - - it('testMatrix', () => { - assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x00, 0x7F, 0xFF, 0x3F, 0x7F, 0x3F, 0x3F, 0x7F, 0x3F]), - SOURCE.getMatrix()), true); - const croppedFullWidth: LuminanceSource = SOURCE.crop(0, 1, 3, 2); - assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x3F, 0x7F, 0x3F, 0x3F, 0x7F, 0x3F]), - croppedFullWidth.getMatrix()), true); - const croppedCorner: LuminanceSource = SOURCE.crop(1, 1, 2, 2); - assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x7F, 0x3F, 0x7F, 0x3F]), - croppedCorner.getMatrix()), true); - }); - - it('testGetRow', () => { - assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x3F, 0x7F, 0x3F]), SOURCE.getRow(2, new Uint8ClampedArray(3))), true); - }); - - it('testToString', () => { - assert.strictEqual(SOURCE.toString(), '#+ \n#+#\n#+#\n'); - }); + const SOURCE = new RGBLuminanceSource(Int32Array.from([ + 0x000000, 0x7F7F7F, 0xFFFFFF, + 0xFF0000, 0x00FF00, 0x0000FF, + 0x0000FF, 0x00FF00, 0xFF0000]), 3, 3); + + it('testCrop', () => { + assert.strictEqual(SOURCE.isCropSupported(), true); + const cropped: LuminanceSource = SOURCE.crop(1, 1, 1, 1); + assert.strictEqual(cropped.getHeight(), 1); + assert.strictEqual(cropped.getWidth(), 1); + assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x7F]), cropped.getRow(0, null)), true); + }); + + it('testMatrix', () => { + assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x00, 0x7F, 0xFF, 0x3F, 0x7F, 0x3F, 0x3F, 0x7F, 0x3F]), + SOURCE.getMatrix()), true); + const croppedFullWidth: LuminanceSource = SOURCE.crop(0, 1, 3, 2); + assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x3F, 0x7F, 0x3F, 0x3F, 0x7F, 0x3F]), + croppedFullWidth.getMatrix()), true); + const croppedCorner: LuminanceSource = SOURCE.crop(1, 1, 2, 2); + assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x7F, 0x3F, 0x7F, 0x3F]), + croppedCorner.getMatrix()), true); + }); + + it('testGetRow', () => { + assert.strictEqual(AssertUtils.typedArraysAreEqual(Uint8ClampedArray.from([0x3F, 0x7F, 0x3F]), SOURCE.getRow(2, new Uint8ClampedArray(3))), true); + }); + + it('testToString', () => { + assert.strictEqual(SOURCE.toString(), '#+ \n#+#\n#+#\n'); + }); }); diff --git a/src/test/core/SharpImageLuminanceSource.ts b/src/test/core/SharpImageLuminanceSource.ts index 2f9904f2..972829fb 100644 --- a/src/test/core/SharpImageLuminanceSource.ts +++ b/src/test/core/SharpImageLuminanceSource.ts @@ -1,70 +1,23 @@ -/* -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/*package com.google.zxing;*/ - -/*import java.awt.Graphics2D;*/ -/*import java.awt.geom.AffineTransform;*/ -/*import java.awt.image.BufferedImage;*/ -/*import java.awt.image.WritableRaster;*/ - +import { IllegalArgumentException, InvertedLuminanceSource, LuminanceSource } from '@zxing/library'; import SharpImage from './util/SharpImage'; -import { LuminanceSource } from '@zxing/library'; -import { InvertedLuminanceSource } from '@zxing/library'; -import { IllegalArgumentException } from '@zxing/library'; /** - * This LuminanceSource implementation is meant for J2SE clients and our blackbox unit tests. - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Sean Owen - * @author code@elektrowolle.de (Wolfgang Jung) + * LuminanceSource used in conjunction with test implementing the sharp node package. + * @note does not currently support rotations so some try harder tests do not yet pass. */ export default class SharpImageLuminanceSource extends LuminanceSource { public constructor(private image: SharpImage) { super(image.getWidth(), image.getHeight()); - // if (undefined === width) { - // this.width = image.getWidth() - // } - // if (undefined === height) { - // this.height = image.getHeight() - // } - - // const sourceWidth: number /*int*/ = image.getWidth() - // const sourceHeight: number /*int*/ = image.getHeight() - // if (left + width > sourceWidth || top + height > sourceHeight) { - // throw new IllegalArgumentException("Crop rectangle does not fit within image data.") - // } - - // if (left > 0 || width < sourceWidth || top > 0 || height < sourceHeight) { - // image.crop(left, top, width, height) - // } - - // image.grayscale() } - public getRow(y: number /*int*/, row: Uint8ClampedArray): Uint8ClampedArray { + public getRow(y: number, row: Uint8ClampedArray): Uint8ClampedArray { if (y < 0 || y >= this.image.getHeight()) { throw new IllegalArgumentException('Requested row is outside the image: ' + y); } - const width: number /*int*/ = this.image.getWidth(); + const width: number = this.image.getWidth(); if (row === null || row.length < width) { - row = new Uint8ClampedArray(width); /*Int8Array(width)*/ + row = new Uint8ClampedArray(width); } // The underlying raster of image consists of bytes with the luminance values this.image.getRow(y, row); @@ -75,33 +28,20 @@ export default class SharpImageLuminanceSource extends LuminanceSource { return this.image.getMatrix(); } - public isCropSupported(): boolean { - return true; + public getWidth(): number { + return this.image.getWidth(); } - public crop(left: number /*int*/, top: number /*int*/, width: number /*int*/, height: number /*int*/): LuminanceSource { - super.crop(left, top, width, height); - return this; + public getHeight(): number { + return this.image.getHeight(); } - /** - * This is always true, since the image is a gray-scale image. - * - * @return true - */ - public isRotateSupported(): boolean { + public isCropSupported(): boolean { return true; } - public rotateCounterClockwise(): LuminanceSource { - // this.image.rotate(-90) - // TYPESCRIPTPORT: not used for tests, see AbstractBlackBox.spec, SharpImage.loadWithRotations - return this; - } - - public rotateCounterClockwise45(): LuminanceSource { - // this.image.rotate(-45) - // TYPESCRIPTPORT: not used for tests, see AbstractBlackBox.spec, SharpImage.loadWithRotations + public crop(left: number, top: number, width: number, height: number): LuminanceSource { + super.crop(left, top, width, height); return this; } diff --git a/src/test/core/aztec/AztecBlackBox1.spec.ts b/src/test/core/aztec/AztecBlackBox1.spec.ts index b4c5bb98..766516cd 100644 --- a/src/test/core/aztec/AztecBlackBox1.spec.ts +++ b/src/test/core/aztec/AztecBlackBox1.spec.ts @@ -26,7 +26,7 @@ import { AztecCodeReader } from '@zxing/library'; /** * @author David Olivier */ -export /*public final*/ class AztecBlackBox1TestCase extends AbstractBlackBoxSpec { +export /* public final */ class AztecBlackBox1TestCase extends AbstractBlackBoxSpec { public constructor() { super('src/test/resources/blackbox/aztec-1', new AztecCodeReader(), BarcodeFormat.AZTEC); @@ -39,8 +39,8 @@ export /*public final*/ class AztecBlackBox1TestCase extends AbstractBlackBoxSpe } describe('AztecBlackBox.1', () => { - it('testBlackBox', async () => { - const test = new AztecBlackBox1TestCase(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new AztecBlackBox1TestCase(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/aztec/AztecBlackBox2.spec.ts b/src/test/core/aztec/AztecBlackBox2.spec.ts index a650ef24..aa052533 100644 --- a/src/test/core/aztec/AztecBlackBox2.spec.ts +++ b/src/test/core/aztec/AztecBlackBox2.spec.ts @@ -28,7 +28,7 @@ import { AztecCodeReader } from '@zxing/library'; * * @author dswitkin@google.com (Daniel Switkin) */ -export /*public final*/ class AztecBlackBox2TestCase extends AbstractBlackBoxSpec { +export /* public final */ class AztecBlackBox2TestCase extends AbstractBlackBoxSpec { public constructor() { super('src/test/resources/blackbox/aztec-2', new AztecCodeReader(), BarcodeFormat.AZTEC); @@ -41,8 +41,8 @@ export /*public final*/ class AztecBlackBox2TestCase extends AbstractBlackBoxSpe } describe('AztecBlackBox.2', () => { - it('testBlackBox', async () => { - const test = new AztecBlackBox2TestCase(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new AztecBlackBox2TestCase(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/aztec/decoder/Decoder.spec.ts b/src/test/core/aztec/decoder/Decoder.spec.ts index 415d8ce7..58229479 100644 --- a/src/test/core/aztec/decoder/Decoder.spec.ts +++ b/src/test/core/aztec/decoder/Decoder.spec.ts @@ -35,152 +35,152 @@ import { FormatException } from '@zxing/library'; */ describe('DecoderTest', () => { - const NO_POINTS: ResultPoint[] = []; + const NO_POINTS: ResultPoint[] = []; - /** - * @Test - * @throws FormatException - */ - it('testAztecResult', () => { - const matrix = BitMatrix.parseFromString( - 'X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X \n' + - ' X X X X X X X X X X \n' + - ' X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X \n' + - ' X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X \n', - 'X ', ' '); - const r = new AztecDetectorResult(matrix, NO_POINTS, false, 30, 2); - const result = new AztecDecoder().decode(r); - assertEquals('88888TTTTTTTTTTTTTTTTTTTTTTTTTTTTTT', result.getText()); - assertArrayEquals( - new Uint8Array([- 11, 85, 85, 117, 107, 90, -42, -75, -83, 107, - 90, -42, -75, -83, 107, 90, -42, -75, -83, 107, - 90, -42, -80]), - result.getRawBytes()); - assertEquals(180, result.getNumBits()); - }); + /** + * @Test + * @throws FormatException + */ + it('testAztecResult', () => { + const matrix = BitMatrix.parseFromString( + 'X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X \n' + + ' X X X X X X X X X X \n' + + ' X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X \n' + + ' X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X \n', + 'X ', ' '); + const r = new AztecDetectorResult(matrix, NO_POINTS, false, 30, 2); + const result = new AztecDecoder().decode(r); + assertEquals('88888TTTTTTTTTTTTTTTTTTTTTTTTTTTTTT', result.getText()); + assertArrayEquals( + new Uint8Array([- 11, 85, 85, 117, 107, 90, -42, -75, -83, 107, + 90, -42, -75, -83, 107, 90, -42, -75, -83, 107, + 90, -42, -80]), + result.getRawBytes()); + assertEquals(180, result.getNumBits()); + }); - /** - * @Test(expected = FormatException.class) - * throws FormatException - */ - it('testDecodeTooManyErrors', () => { - const matrix = BitMatrix.parseFromString('' - + 'X X . X . . . X X . . . X . . X X X . X . X X X X X . \n' - + 'X X . . X X . . . . . X X . . . X X . . . X . X . . X \n' - + 'X . . . X X . . X X X . X X . X X X X . X X . . X . . \n' - + '. . . . X . X X . . X X . X X . X . X X X X . X . . X \n' - + 'X X X . . X X X X X . . . . . X X . . . X . X . X . X \n' - + 'X X . . . . . . . . X . . . X . X X X . X . . X . . . \n' - + 'X X . . X . . . . . X X . . . . . X . . . . X . . X X \n' - + '. . . X . X . X . . . . . X X X X X X . . . . . . X X \n' - + 'X . . . X . X X X X X X . . X X X . X . X X X X X X . \n' - + 'X . . X X X . X X X X X X X X X X X X X . . . X . X X \n' - + '. . . . X X . . . X . . . . . . . X X . . . X X . X . \n' - + '. . . X X X . . X X . X X X X X . X . . X . . . . . . \n' - + 'X . . . . X . X . X . X . . . X . X . X X . X X . X X \n' - + 'X . X . . X . X . X . X . X . X . X . . . . . X . X X \n' - + 'X . X X X . . X . X . X . . . X . X . X X X . . . X X \n' - + 'X X X X X X X X . X . X X X X X . X . X . X . X X X . \n' - + '. . . . . . . X . X . . . . . . . X X X X . . . X X X \n' - + 'X X . . X . . X . X X X X X X X X X X X X X . . X . X \n' - + 'X X X . X X X X . . X X X X . . X . . . . X . . X X X \n' - + '. . . . X . X X X . . . . X X X X . . X X X X . . . . \n' - + '. . X . . X . X . . . X . X X . X X . X . . . X . X . \n' - + 'X X . . X . . X X X X X X X . . X . X X X X X X X . . \n' - + 'X . X X . . X X . . . . . X . . . . . . X X . X X X . \n' - + 'X . . X X . . X X . X . X . . . . X . X . . X . . X . \n' - + 'X . X . X . . X . X X X X X X X X . X X X X . . X X . \n' - + 'X X X X . . . X . . X X X . X X . . X . . . . X X X . \n' - + 'X X . X . X . . . X . X . . . . X X . X . . X X . . . \n', - 'X ', '. '); - const r = new AztecDetectorResult(matrix, NO_POINTS, true, 16, 4); - assertThrow(() => new AztecDecoder().decode(r), FormatException); - }); + /** + * @Test(expected = FormatException.class) + * throws FormatException + */ + it('testDecodeTooManyErrors', () => { + const matrix = BitMatrix.parseFromString('' + + 'X X . X . . . X X . . . X . . X X X . X . X X X X X . \n' + + 'X X . . X X . . . . . X X . . . X X . . . X . X . . X \n' + + 'X . . . X X . . X X X . X X . X X X X . X X . . X . . \n' + + '. . . . X . X X . . X X . X X . X . X X X X . X . . X \n' + + 'X X X . . X X X X X . . . . . X X . . . X . X . X . X \n' + + 'X X . . . . . . . . X . . . X . X X X . X . . X . . . \n' + + 'X X . . X . . . . . X X . . . . . X . . . . X . . X X \n' + + '. . . X . X . X . . . . . X X X X X X . . . . . . X X \n' + + 'X . . . X . X X X X X X . . X X X . X . X X X X X X . \n' + + 'X . . X X X . X X X X X X X X X X X X X . . . X . X X \n' + + '. . . . X X . . . X . . . . . . . X X . . . X X . X . \n' + + '. . . X X X . . X X . X X X X X . X . . X . . . . . . \n' + + 'X . . . . X . X . X . X . . . X . X . X X . X X . X X \n' + + 'X . X . . X . X . X . X . X . X . X . . . . . X . X X \n' + + 'X . X X X . . X . X . X . . . X . X . X X X . . . X X \n' + + 'X X X X X X X X . X . X X X X X . X . X . X . X X X . \n' + + '. . . . . . . X . X . . . . . . . X X X X . . . X X X \n' + + 'X X . . X . . X . X X X X X X X X X X X X X . . X . X \n' + + 'X X X . X X X X . . X X X X . . X . . . . X . . X X X \n' + + '. . . . X . X X X . . . . X X X X . . X X X X . . . . \n' + + '. . X . . X . X . . . X . X X . X X . X . . . X . X . \n' + + 'X X . . X . . X X X X X X X . . X . X X X X X X X . . \n' + + 'X . X X . . X X . . . . . X . . . . . . X X . X X X . \n' + + 'X . . X X . . X X . X . X . . . . X . X . . X . . X . \n' + + 'X . X . X . . X . X X X X X X X X . X X X X . . X X . \n' + + 'X X X X . . . X . . X X X . X X . . X . . . . X X X . \n' + + 'X X . X . X . . . X . X . . . . X X . X . . X X . . . \n', + 'X ', '. '); + const r = new AztecDetectorResult(matrix, NO_POINTS, true, 16, 4); + assertThrow(() => new AztecDecoder().decode(r), FormatException); + }); - /** - * - * @Test(expected = FormatException.class) - * @throws FormatException - */ - it('testDecodeTooManyErrors2', () => { - const matrix = BitMatrix.parseFromString('' - + '. X X . . X . X X . . . X . . X X X . . . X X . X X . \n' - + 'X X . X X . . X . . . X X . . . X X . X X X . X . X X \n' - + '. . . . X . . . X X X . X X . X X X X . X X . . X . . \n' - + 'X . X X . . X . . . X X . X X . X . X X . . . . . X . \n' - + 'X X . X . . X . X X . . . . . X X . . . . . X . . . X \n' - + 'X . . X . . . . . . X . . . X . X X X X X X X . . . X \n' - + 'X . . X X . . X . . X X . . . . . X . . . . . X X X . \n' - + '. . X X X X . X . . . . . X X X X X X . . . . . . X X \n' - + 'X . . . X . X X X X X X . . X X X . X . X X X X X X . \n' - + 'X . . X X X . X X X X X X X X X X X X X . . . X . X X \n' - + '. . . . X X . . . X . . . . . . . X X . . . X X . X . \n' - + '. . . X X X . . X X . X X X X X . X . . X . . . . . . \n' - + 'X . . . . X . X . X . X . . . X . X . X X . X X . X X \n' - + 'X . X . . X . X . X . X . X . X . X . . . . . X . X X \n' - + 'X . X X X . . X . X . X . . . X . X . X X X . . . X X \n' - + 'X X X X X X X X . X . X X X X X . X . X . X . X X X . \n' - + '. . . . . . . X . X . . . . . . . X X X X . . . X X X \n' - + 'X X . . X . . X . X X X X X X X X X X X X X . . X . X \n' - + 'X X X . X X X X . . X X X X . . X . . . . X . . X X X \n' - + '. . X X X X X . X . . . . X X X X . . X X X . X . X . \n' - + '. . X X . X . X . . . X . X X . X X . . . . X X . . . \n' - + 'X . . . X . X . X X X X X X . . X . X X X X X . X . . \n' - + '. X . . . X X X . . . . . X . . . . . X X X X X . X . \n' - + 'X . . X . X X X X . X . X . . . . X . X X . X . . X . \n' - + 'X . . . X X . X . X X X X X X X X . X X X X . . X X . \n' - + '. X X X X . . X . . X X X . X X . . X . . . . X X X . \n' - + 'X X . . . X X . . X . X . . . . X X . X . . X . X . X \n', - 'X ', '. '); - const r = new AztecDetectorResult(matrix, NO_POINTS, true, 16, 4); - assertThrow(() => new AztecDecoder().decode(r), FormatException); - }); + /** + * + * @Test(expected = FormatException.class) + * @throws FormatException + */ + it('testDecodeTooManyErrors2', () => { + const matrix = BitMatrix.parseFromString('' + + '. X X . . X . X X . . . X . . X X X . . . X X . X X . \n' + + 'X X . X X . . X . . . X X . . . X X . X X X . X . X X \n' + + '. . . . X . . . X X X . X X . X X X X . X X . . X . . \n' + + 'X . X X . . X . . . X X . X X . X . X X . . . . . X . \n' + + 'X X . X . . X . X X . . . . . X X . . . . . X . . . X \n' + + 'X . . X . . . . . . X . . . X . X X X X X X X . . . X \n' + + 'X . . X X . . X . . X X . . . . . X . . . . . X X X . \n' + + '. . X X X X . X . . . . . X X X X X X . . . . . . X X \n' + + 'X . . . X . X X X X X X . . X X X . X . X X X X X X . \n' + + 'X . . X X X . X X X X X X X X X X X X X . . . X . X X \n' + + '. . . . X X . . . X . . . . . . . X X . . . X X . X . \n' + + '. . . X X X . . X X . X X X X X . X . . X . . . . . . \n' + + 'X . . . . X . X . X . X . . . X . X . X X . X X . X X \n' + + 'X . X . . X . X . X . X . X . X . X . . . . . X . X X \n' + + 'X . X X X . . X . X . X . . . X . X . X X X . . . X X \n' + + 'X X X X X X X X . X . X X X X X . X . X . X . X X X . \n' + + '. . . . . . . X . X . . . . . . . X X X X . . . X X X \n' + + 'X X . . X . . X . X X X X X X X X X X X X X . . X . X \n' + + 'X X X . X X X X . . X X X X . . X . . . . X . . X X X \n' + + '. . X X X X X . X . . . . X X X X . . X X X . X . X . \n' + + '. . X X . X . X . . . X . X X . X X . . . . X X . . . \n' + + 'X . . . X . X . X X X X X X . . X . X X X X X . X . . \n' + + '. X . . . X X X . . . . . X . . . . . X X X X X . X . \n' + + 'X . . X . X X X X . X . X . . . . X . X X . X . . X . \n' + + 'X . . . X X . X . X X X X X X X X . X X X X . . X X . \n' + + '. X X X X . . X . . X X X . X X . . X . . . . X X X . \n' + + 'X X . . . X X . . X . X . . . . X X . X . . X . X . X \n', + 'X ', '. '); + const r = new AztecDetectorResult(matrix, NO_POINTS, true, 16, 4); + assertThrow(() => new AztecDecoder().decode(r), FormatException); + }); - /** - * @Test - */ - it('testRawBytes', () => { - let bool0: boolean[] = []; - let bool1: boolean[] = [true]; - let bool7: boolean[] = [true, false, true, false, true, false, true]; - let bool8: boolean[] = [true, false, true, false, true, false, true, false]; - let bool9: boolean[] = [ - true, false, true, false, true, false, true, false, - true]; - let bool16: boolean[] = [ - false, true, true, false, false, false, true, true, - true, true, false, false, false, false, false, true]; - let byte0: /*byte[]*/Uint8Array = new Uint8Array([]); - let byte1: /*byte[]*/Uint8Array = new Uint8Array([-128]); - let byte7: /*byte[]*/ Uint8Array = new Uint8Array([- 86]); - let byte8: /*byte[]*/ Uint8Array = new Uint8Array([- 86]); - let byte9: /*byte[]*/ Uint8Array = new Uint8Array([- 86, -128]); - let byte16: /*byte[]*/ Uint8Array = new Uint8Array([99, - 63]); + /** + * @Test + */ + it('testRawBytes', () => { + let bool0: boolean[] = []; + let bool1: boolean[] = [true]; + let bool7: boolean[] = [true, false, true, false, true, false, true]; + let bool8: boolean[] = [true, false, true, false, true, false, true, false]; + let bool9: boolean[] = [ + true, false, true, false, true, false, true, false, + true]; + let bool16: boolean[] = [ + false, true, true, false, false, false, true, true, + true, true, false, false, false, false, false, true]; + let byte0: /* byte[] */Uint8Array = new Uint8Array([]); + let byte1: /* byte[] */Uint8Array = new Uint8Array([-128]); + let byte7: /* byte[] */ Uint8Array = new Uint8Array([- 86]); + let byte8: /* byte[] */ Uint8Array = new Uint8Array([- 86]); + let byte9: /* byte[] */ Uint8Array = new Uint8Array([- 86, -128]); + let byte16: /* byte[] */ Uint8Array = new Uint8Array([99, - 63]); - assertArrayEquals(byte0, AztecDecoder.convertBoolArrayToByteArray(bool0)); - assertArrayEquals(byte1, AztecDecoder.convertBoolArrayToByteArray(bool1)); - assertArrayEquals(byte7, AztecDecoder.convertBoolArrayToByteArray(bool7)); - assertArrayEquals(byte8, AztecDecoder.convertBoolArrayToByteArray(bool8)); - assertArrayEquals(byte9, AztecDecoder.convertBoolArrayToByteArray(bool9)); - assertArrayEquals(byte16, AztecDecoder.convertBoolArrayToByteArray(bool16)); - }); + assertArrayEquals(byte0, AztecDecoder.convertBoolArrayToByteArray(bool0)); + assertArrayEquals(byte1, AztecDecoder.convertBoolArrayToByteArray(bool1)); + assertArrayEquals(byte7, AztecDecoder.convertBoolArrayToByteArray(bool7)); + assertArrayEquals(byte8, AztecDecoder.convertBoolArrayToByteArray(bool8)); + assertArrayEquals(byte9, AztecDecoder.convertBoolArrayToByteArray(bool9)); + assertArrayEquals(byte16, AztecDecoder.convertBoolArrayToByteArray(bool16)); + }); }); diff --git a/src/test/core/aztec/detector/Detector.spec.ts b/src/test/core/aztec/detector/Detector.spec.ts index ffddf653..98c4345d 100644 --- a/src/test/core/aztec/detector/Detector.spec.ts +++ b/src/test/core/aztec/detector/Detector.spec.ts @@ -60,166 +60,166 @@ import { ZXingInteger } from '@zxing/library'; describe('DetectorTest', () => { - /** - * @Test - * @throws Exception - */ - // public void testErrorInParameterLocatorZeroZero() throws Exception { - it('testErrorInParameterLocatorZeroZero', () => { - // Layers=1, CodeWords=1. So the parameter info and its Reed-Solomon info - // will be completely zero! - testErrorInParameterLocator('X'); - }); - - /** - * @Test - * @throws Exception - */ - // public void testErrorInParameterLocatorCompact() throws Exception { - it('testErrorInParameterLocatorCompact', () => { - testErrorInParameterLocator('This is an example Aztec symbol for Wikipedia.'); - }); - - /** - * @Test - */ - // public void testErrorInParameterLocatorNotCompact() throws Exception { - it('testErrorInParameterLocatorNotCompact', () => { - const alphabet: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz'; - testErrorInParameterLocator(alphabet + alphabet + alphabet); - }); - - /** - * @throws Exception - */ - // Test that we can tolerate errors in the parameter locator bits - function testErrorInParameterLocator(data: string): void { - let aztec: AztecCode = AztecEncoder.encode(StringUtils.getBytes(data, ZXingStandardCharsets.ISO_8859_1), 25, AztecEncoder.DEFAULT_AZTEC_LAYERS); - let random: Random = new Random(aztec.getMatrix().hashCode().toString()); // pseudo-random, but deterministic - let layers: /*int*/ number = aztec.getLayers(); - let compact: boolean = aztec.isCompact(); - let orientationPoints: AztecPoint[] = getOrientationPoints(aztec); - for (const isMirror of [false, true]) { - for (const matrix of getRotations(aztec.getMatrix())) { - // Systematically try every possible 1- and 2-bit error. - for (let error1 = 0; error1 < orientationPoints.length; error1++) { - for (let error2 = error1; error2 < orientationPoints.length; error2++) { - let copy: BitMatrix = isMirror ? transpose(matrix) : clone(matrix); - copy.flip(orientationPoints[error1].getX(), orientationPoints[error1].getY()); - if (error2 > error1) { - // if error2 == error1, we only test a single error - copy.flip(orientationPoints[error2].getX(), orientationPoints[error2].getY()); - } - // The detector doesn't seem to work when matrix bits are only 1x1. So magnify. - let r: AztecDetectorResult = new AztecDetector(makeLarger(copy, 3)).detectMirror(isMirror); - assertNotNull(r); - assertEquals(r.getNbLayers(), layers); - assertEquals(r.isCompact(), compact); - let res: DecoderResult = new AztecDecoder().decode(r); - assertEquals(data, res.getText()); - } - } - // Try a few random three-bit errors; - for (let i = 0; i < 5; i++) { - let copy: BitMatrix = clone(matrix); - let errors: /* Collection */ Set = /* new TreeSet<>() */ new Set(); - while (errors.size < 3) { - // Quick and dirty way of getting three distinct integers between 1 and n. - errors.add(random.nextInt(orientationPoints.length)); - } - for (const error of errors) { - copy.flip(orientationPoints[error].getX(), orientationPoints[error].getY()); - } - try { - new AztecDetector(makeLarger(copy, 3)).detectMirror(false); - fail('Should not reach here'); - } catch (expected) { - // continue - if (!(expected instanceof NotFoundException)) { - throw expected; - } - } - } + /** + * @Test + * @throws Exception + */ + // public void testErrorInParameterLocatorZeroZero() throws Exception { + it('testErrorInParameterLocatorZeroZero', () => { + // Layers=1, CodeWords=1. So the parameter info and its Reed-Solomon info + // will be completely zero! + testErrorInParameterLocator('X'); + }); + + /** + * @Test + * @throws Exception + */ + // public void testErrorInParameterLocatorCompact() throws Exception { + it('testErrorInParameterLocatorCompact', () => { + testErrorInParameterLocator('This is an example Aztec symbol for Wikipedia.'); + }); + + /** + * @Test + */ + // public void testErrorInParameterLocatorNotCompact() throws Exception { + it('testErrorInParameterLocatorNotCompact', () => { + const alphabet: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz'; + testErrorInParameterLocator(alphabet + alphabet + alphabet); + }); + + /** + * @throws Exception + */ + // Test that we can tolerate errors in the parameter locator bits + function testErrorInParameterLocator(data: string): void { + let aztec: AztecCode = AztecEncoder.encode(StringUtils.getBytes(data, ZXingStandardCharsets.ISO_8859_1), 25, AztecEncoder.DEFAULT_AZTEC_LAYERS); + let random: Random = new Random(aztec.getMatrix().hashCode().toString()); // pseudo-random, but deterministic + let layers: /* int */ number = aztec.getLayers(); + let compact: boolean = aztec.isCompact(); + let orientationPoints: AztecPoint[] = getOrientationPoints(aztec); + for (const isMirror of [false, true]) { + for (const matrix of getRotations(aztec.getMatrix())) { + // Systematically try every possible 1- and 2-bit error. + for (let error1 = 0; error1 < orientationPoints.length; error1++) { + for (let error2 = error1; error2 < orientationPoints.length; error2++) { + let copy: BitMatrix = isMirror ? transpose(matrix) : clone(matrix); + copy.flip(orientationPoints[error1].getX(), orientationPoints[error1].getY()); + if (error2 > error1) { + // if error2 == error1, we only test a single error + copy.flip(orientationPoints[error2].getX(), orientationPoints[error2].getY()); } + // The detector doesn't seem to work when matrix bits are only 1x1. So magnify. + let r: AztecDetectorResult = new AztecDetector(makeLarger(copy, 3)).detectMirror(isMirror); + assertNotNull(r); + assertEquals(r.getNbLayers(), layers); + assertEquals(r.isCompact(), compact); + let res: DecoderResult = new AztecDecoder().decode(r); + assertEquals(data, res.getText()); + } } - } - - // Zooms a bit matrix so that each bit is factor x factor - function makeLarger(input: BitMatrix, factor: /*int*/ number): BitMatrix { - let width: number = input.getWidth(); - let output: BitMatrix = new BitMatrix(width * factor); - for (let inputY: number = 0; inputY < width; inputY++) { - for (let inputX: number = 0; inputX < width; inputX++) { - if (input.get(inputX, inputY)) { - output.setRegion(inputX * factor, inputY * factor, factor, factor); - } + // Try a few random three-bit errors; + for (let i = 0; i < 5; i++) { + let copy: BitMatrix = clone(matrix); + let errors: /* Collection */ Set = /* new TreeSet<>() */ new Set(); + while (errors.size < 3) { + // Quick and dirty way of getting three distinct integers between 1 and n. + errors.add(random.nextInt(orientationPoints.length)); + } + for (const error of errors) { + copy.flip(orientationPoints[error].getX(), orientationPoints[error].getY()); + } + try { + new AztecDetector(makeLarger(copy, 3)).detectMirror(false); + fail('Should not reach here'); + } catch (expected) { + // continue + if (!(expected instanceof NotFoundException)) { + throw expected; } + } } - return output; - } - - // Returns a list of the four rotations of the BitMatrix. - function getRotations(matrix0: BitMatrix): BitMatrix[] { - let matrix90: BitMatrix = rotateRight(matrix0); - let matrix180: BitMatrix = rotateRight(matrix90); - let matrix270: BitMatrix = rotateRight(matrix180); - return ZXingArrays.asList(matrix0, matrix90, matrix180, matrix270); + } } - - // Rotates a square BitMatrix to the right by 90 degrees - function rotateRight(input: BitMatrix): BitMatrix { - let width: number = input.getWidth(); - let result: BitMatrix = new BitMatrix(width); - for (let x /*int*/ = 0; x < width; x++) { - for (let y /*int*/ = 0; y < width; y++) { - if (input.get(x, y)) { - result.set(y, width - x - 1); - } - } + } + + // Zooms a bit matrix so that each bit is factor x factor + function makeLarger(input: BitMatrix, factor: /* int */ number): BitMatrix { + let width: number = input.getWidth(); + let output: BitMatrix = new BitMatrix(width * factor); + for (let inputY: number = 0; inputY < width; inputY++) { + for (let inputX: number = 0; inputX < width; inputX++) { + if (input.get(inputX, inputY)) { + output.setRegion(inputX * factor, inputY * factor, factor, factor); } - return result; + } } - - // Returns the transpose of a bit matrix, which is equivalent to rotating the - // matrix to the right, and then flipping it left-to-right - function transpose(input: BitMatrix): BitMatrix { - let width: number = input.getWidth(); - let result: BitMatrix = new BitMatrix(width); - for (let x: number = 0; x < width; x++) { - for (let y: number = 0; y < width; y++) { - if (input.get(x, y)) { - result.set(y, x); - } - } + return output; + } + + // Returns a list of the four rotations of the BitMatrix. + function getRotations(matrix0: BitMatrix): BitMatrix[] { + let matrix90: BitMatrix = rotateRight(matrix0); + let matrix180: BitMatrix = rotateRight(matrix90); + let matrix270: BitMatrix = rotateRight(matrix180); + return ZXingArrays.asList(matrix0, matrix90, matrix180, matrix270); + } + + // Rotates a square BitMatrix to the right by 90 degrees + function rotateRight(input: BitMatrix): BitMatrix { + let width: number = input.getWidth(); + let result: BitMatrix = new BitMatrix(width); + for (let x /* int */ = 0; x < width; x++) { + for (let y /* int */ = 0; y < width; y++) { + if (input.get(x, y)) { + result.set(y, width - x - 1); } - return result; + } } - - function clone(input: BitMatrix): BitMatrix { - let width: number = input.getWidth(); - let result: BitMatrix = new BitMatrix(width); - for (let x: number = 0; x < width; x++) { - for (let y: number = 0; y < width; y++) { - if (input.get(x, y)) { - result.set(x, y); - } - } + return result; + } + + // Returns the transpose of a bit matrix, which is equivalent to rotating the + // matrix to the right, and then flipping it left-to-right + function transpose(input: BitMatrix): BitMatrix { + let width: number = input.getWidth(); + let result: BitMatrix = new BitMatrix(width); + for (let x: number = 0; x < width; x++) { + for (let y: number = 0; y < width; y++) { + if (input.get(x, y)) { + result.set(y, x); } - return result; + } } - - function getOrientationPoints(code: AztecCode): AztecPoint[] { - let center: number = ZXingInteger.truncDivision(code.getMatrix().getWidth(), 2); - let offset: number = code.isCompact() ? 5 : 7; - let result: AztecPoint[] = []; - for (let xSign: number = -1; xSign <= 1; xSign += 2) { - for (let ySign: number = -1; ySign <= 1; ySign += 2) { - result.push(new AztecPoint(center + xSign * offset, center + ySign * offset)); - result.push(new AztecPoint(center + xSign * (offset - 1), center + ySign * offset)); - result.push(new AztecPoint(center + xSign * offset, center + ySign * (offset - 1))); - } + return result; + } + + function clone(input: BitMatrix): BitMatrix { + let width: number = input.getWidth(); + let result: BitMatrix = new BitMatrix(width); + for (let x: number = 0; x < width; x++) { + for (let y: number = 0; y < width; y++) { + if (input.get(x, y)) { + result.set(x, y); } - return result; + } + } + return result; + } + + function getOrientationPoints(code: AztecCode): AztecPoint[] { + let center: number = ZXingInteger.truncDivision(code.getMatrix().getWidth(), 2); + let offset: number = code.isCompact() ? 5 : 7; + let result: AztecPoint[] = []; + for (let xSign: number = -1; xSign <= 1; xSign += 2) { + for (let ySign: number = -1; ySign <= 1; ySign += 2) { + result.push(new AztecPoint(center + xSign * offset, center + ySign * offset)); + result.push(new AztecPoint(center + xSign * (offset - 1), center + ySign * offset)); + result.push(new AztecPoint(center + xSign * offset, center + ySign * (offset - 1))); + } } + return result; + } }); diff --git a/src/test/core/aztec/encoder/EncoderTest.spec.ts b/src/test/core/aztec/encoder/EncoderTest.spec.ts index 45d10b1f..e0d2ebf0 100644 --- a/src/test/core/aztec/encoder/EncoderTest.spec.ts +++ b/src/test/core/aztec/encoder/EncoderTest.spec.ts @@ -65,28 +65,28 @@ describe('EncoderTest', () => { true, 3, 'X X X X X X X X \n' + - 'X X X X X X X X X X \n' + - 'X X X X X X X X X X X \n' + - 'X X X X X X X X X X X \n' + - ' X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X \n' + - 'X X X X X X X X X X \n' + - ' X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X \n' + - ' X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X \n' + - ' X X X \n' + - ' X X X X X X X X X X \n' + - ' X X X X X X X X X X \n' + 'X X X X X X X X X X \n' + + 'X X X X X X X X X X X \n' + + 'X X X X X X X X X X X \n' + + ' X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X \n' + + 'X X X X X X X X X X \n' + + ' X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X \n' + + ' X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X \n' + + ' X X X \n' + + ' X X X X X X X X X X \n' + + ' X X X X X X X X X X \n' ); }); @@ -95,51 +95,51 @@ describe('EncoderTest', () => { it('testEncode2', () => { testEncode( 'Aztec Code is a public domain 2D matrix barcode symbology' + - ' of nominally square symbols built on a square grid with a ' + - 'distinctive square bullseye pattern at their center.', + ' of nominally square symbols built on a square grid with a ' + + 'distinctive square bullseye pattern at their center.', false, 6, ' X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X X X X X X X X X \n' + - ' X X X X X X X X X X X X X X X X \n' + - 'X X X X X X X X X X X X X \n' + ' X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X X X X X X X X X \n' + + ' X X X X X X X X X X X X X X X X \n' + + 'X X X X X X X X X X X X X \n' ); }); @@ -215,7 +215,7 @@ describe('EncoderTest', () => { it('testEncodeDecode5', () => { testEncodeDecode( 'http://test/~!@#*^%&)__ ;:\'"[]{}\\|-+-=`1029384756<>/?abc' + - 'Four score and seven our forefathers brought forth', + 'Four score and seven our forefathers brought forth', false, 5 ); @@ -226,11 +226,11 @@ describe('EncoderTest', () => { it('testEncodeDecode10', () => { testEncodeDecode( 'In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus quis diam' + - ' cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum' + - ' est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue' + - ' auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla' + - ' ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id' + - ' elementum sapien dolor et diam.', + ' cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum' + + ' est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue' + + ' auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla' + + ' ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id' + + ' elementum sapien dolor et diam.', false, 10 ); @@ -241,27 +241,27 @@ describe('EncoderTest', () => { it('testEncodeDecode23', () => { testEncodeDecode( 'In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus quis diam' + - ' cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum' + - ' est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue' + - ' auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla' + - ' ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id' + - ' elementum sapien dolor et diam. Donec ac nunc sodales elit placerat eleifend.' + - ' Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra fringilla, risus' + - ' justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo diam, lobortis eu' + - ' tristique ac, p.In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus' + - ' quis diam cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec' + - ' laoreet rutrum est, nec convallis mauris condimentum sit amet. Phasellus gravida,' + - ' justo et congue auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec' + - ' lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar' + - ' nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit placerat' + - ' eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra' + - ' fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo' + - ' diam, lobortis eu tristique ac, p. In ut magna vel mauris malesuada dictum. Nulla' + - ' ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum' + - ' sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet.' + - ' Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget hendrerit' + - ' felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo' + - ' erat pulvinar nisi, id elementum sapien dolor et diam.', + ' cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum' + + ' est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue' + + ' auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla' + + ' ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id' + + ' elementum sapien dolor et diam. Donec ac nunc sodales elit placerat eleifend.' + + ' Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra fringilla, risus' + + ' justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo diam, lobortis eu' + + ' tristique ac, p.In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus' + + ' quis diam cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec' + + ' laoreet rutrum est, nec convallis mauris condimentum sit amet. Phasellus gravida,' + + ' justo et congue auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec' + + ' lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar' + + ' nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit placerat' + + ' eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra' + + ' fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo' + + ' diam, lobortis eu tristique ac, p. In ut magna vel mauris malesuada dictum. Nulla' + + ' ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum' + + ' sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet.' + + ' Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget hendrerit' + + ' felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo' + + ' erat pulvinar nisi, id elementum sapien dolor et diam.', false, 23 ); @@ -272,42 +272,42 @@ describe('EncoderTest', () => { it('testEncodeDecode31', () => { testEncodeDecode( 'In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus quis diam' + - ' cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum' + - ' est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue' + - ' auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla' + - ' ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id' + - ' elementum sapien dolor et diam. Donec ac nunc sodales elit placerat eleifend.' + - ' Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra fringilla, risus' + - ' justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo diam, lobortis eu' + - ' tristique ac, p.In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus' + - ' quis diam cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec' + - ' laoreet rutrum est, nec convallis mauris condimentum sit amet. Phasellus gravida,' + - ' justo et congue auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec' + - ' lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar' + - ' nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit placerat' + - ' eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra' + - ' fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo' + - ' diam, lobortis eu tristique ac, p. In ut magna vel mauris malesuada dictum. Nulla' + - ' ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum' + - ' sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet.' + - ' Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget hendrerit' + - ' felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo' + - ' erat pulvinar nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit' + - ' placerat eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at' + - ' pharetra fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est.' + - ' Ut justo diam, lobortis eu tristique ac, p.In ut magna vel mauris malesuada' + - ' dictum. Nulla ullamcorper metus quis diam cursus facilisis. Sed mollis quam id' + - ' justo rutrum sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum' + - ' sit amet. Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat,' + - ' eget hendrerit felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet' + - ' laoreet, justo erat pulvinar nisi, id elementum sapien dolor et diam. Donec ac' + - ' nunc sodales elit placerat eleifend. Sed ornare luctus ornare. Vestibulum vehicula,' + - ' massa at pharetra fringilla, risus justo faucibus erat, nec porttitor nibh tellus' + - ' sed est. Ut justo diam, lobortis eu tris. In ut magna vel mauris malesuada dictum.' + - ' Nulla ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum' + - ' sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet.' + - ' Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget' + - ' hendrerit felis turpis nec lorem.', + ' cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum' + + ' est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue' + + ' auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla' + + ' ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id' + + ' elementum sapien dolor et diam. Donec ac nunc sodales elit placerat eleifend.' + + ' Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra fringilla, risus' + + ' justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo diam, lobortis eu' + + ' tristique ac, p.In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus' + + ' quis diam cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec' + + ' laoreet rutrum est, nec convallis mauris condimentum sit amet. Phasellus gravida,' + + ' justo et congue auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec' + + ' lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar' + + ' nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit placerat' + + ' eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra' + + ' fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo' + + ' diam, lobortis eu tristique ac, p. In ut magna vel mauris malesuada dictum. Nulla' + + ' ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum' + + ' sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet.' + + ' Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget hendrerit' + + ' felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo' + + ' erat pulvinar nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit' + + ' placerat eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at' + + ' pharetra fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est.' + + ' Ut justo diam, lobortis eu tristique ac, p.In ut magna vel mauris malesuada' + + ' dictum. Nulla ullamcorper metus quis diam cursus facilisis. Sed mollis quam id' + + ' justo rutrum sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum' + + ' sit amet. Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat,' + + ' eget hendrerit felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet' + + ' laoreet, justo erat pulvinar nisi, id elementum sapien dolor et diam. Donec ac' + + ' nunc sodales elit placerat eleifend. Sed ornare luctus ornare. Vestibulum vehicula,' + + ' massa at pharetra fringilla, risus justo faucibus erat, nec porttitor nibh tellus' + + ' sed est. Ut justo diam, lobortis eu tris. In ut magna vel mauris malesuada dictum.' + + ' Nulla ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum' + + ' sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet.' + + ' Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget' + + ' hendrerit felis turpis nec lorem.', false, 31 ); @@ -399,7 +399,7 @@ describe('EncoderTest', () => { // Found on an airline boarding pass. Several stretches of Binary shift are // necessary to keep the bitcount so low. '09 UAG ^160MEUCIQC0sYS/HpKxnBELR1uB85R20OoqqwFGa0q2uEi' + - 'Ygh6utAIgLl1aBVM4EOTQtMQQYH9M2Z3Dp4qnA/fwWuQ+M8L3V8U=', + 'Ygh6utAIgLl1aBVM4EOTQtMQQYH9M2Z3Dp4qnA/fwWuQ+M8L3V8U=', 823 ); }); @@ -476,7 +476,7 @@ describe('EncoderTest', () => { 8 * i + (i <= 31 ? 10 : i <= 62 ? 20 : i <= 2078 ? 21 : 31); // Verify that we are correct about the length. testHighLevelEncodeString(sb.substring(0, i), expectedLength); - if (i != 1 && i != 32 && i != 2079) { + if (i !== 1 && i !== 32 && i !== 2079) { // The addition of an 'a' at the beginning or end gets merged into the binary code // in those cases where adding another binary character only adds 8 or 9 bits to the result. // So we exclude the border cases i=1,32,2079 diff --git a/src/test/core/common/AbstractBlackBox.ts b/src/test/core/common/AbstractBlackBox.ts index b2a8f3fb..5b30acc2 100644 --- a/src/test/core/common/AbstractBlackBox.ts +++ b/src/test/core/common/AbstractBlackBox.ts @@ -14,48 +14,36 @@ * limitations under the License. */ -/*package com.google.zxing.common;*/ - -import { - BarcodeFormat, - BinaryBitmap, - DecodeHintType, - HybridBinarizer, - LuminanceSource, - Reader, - Result, - ResultMetadataType, - ZXingStringEncoding -} from '@zxing/library'; -import * as fs from 'fs'; +/* package com.google.zxing.common; */ + import * as path from 'path'; -import TestResult from '../common/TestResult'; -import SharpImageLuminanceSource from '../SharpImageLuminanceSource'; -import { assertEquals } from '../util/AssertUtils'; +import * as fs from 'fs'; +import * as log from 'loglevel'; +import { assertEquals, assertGreaterThanEquals, assertLessThanEquals } from '../util/AssertUtils'; import SharpImage from '../util/SharpImage'; -/*import javax.imageio.ImageIO;*/ -/*import java.awt.Graphics;*/ -/*import java.awt.geom.AffineTransform;*/ -/*import java.awt.geom.RectangularShape;*/ -/*import java.awt.image.AffineTransformOp;*/ -/*import java.awt.image.BufferedImage;*/ -/*import java.awt.image.BufferedImageOp;*/ -/*import java.io.BufferedReader;*/ -/*import java.io.IOException;*/ -/*import java.nio.charset.ZXingCharset;*/ -/*import java.nio.charset.ZXingStandardCharsets;*/ -/*import java.nio.file.DirectoryStream;*/ -/*import java.nio.file.Files;*/ -/*import java.nio.file.Path;*/ -/*import java.nio.file.Paths;*/ -/*import java.util.ArrayList;*/ -/*import java.util.EnumMap;*/ -/*import java.util.List;*/ -/*import java.util.Map;*/ -/*import java.util.Properties;*/ -/*import java.util.logging.Logger;*/ +/* import javax.imageio.ImageIO; */ +/* import java.awt.Graphics; */ +/* import java.awt.geom.AffineTransform; */ +/* import java.awt.geom.RectangularShape; */ +/* import java.awt.image.AffineTransformOp; */ +/* import java.awt.image.BufferedImage; */ +/* import java.awt.image.BufferedImageOp; */ +/* import java.io.BufferedReader; */ +/* import java.io.IOException; */ +/* import java.nio.charset.ZXingCharset; */ +/* import java.nio.charset.ZXingStandardCharsets; */ +/* import java.nio.file.DirectoryStream; */ +/* import java.nio.file.Files; */ +/* import java.nio.file.Path; */ +/* import java.nio.file.Paths; */ +/* import java.util.ArrayList; */ +/* import java.util.EnumMap; */ +/* import java.util.List; */ +/* import java.util.Map; */ +/* import java.util.Properties; */ +/* import java.util.logging.Logger; */ /** * @author Sean Owen @@ -105,7 +93,7 @@ abstract class AbstractBlackBoxSpec { * @param maxTryHarderMisreads Maximum number of images which can fail due to successfully * reading the wrong contents using the try harder flag * @param rotation The rotation in degrees clockwise to use for this test. - */ + */ protected addTestWithMax( mustPassCount: number /* int */, tryHarderCount: number /* int */, @@ -133,7 +121,7 @@ abstract class AbstractBlackBoxSpec { } if (results.length === 0) { - console.log(`No files in folder ${dir}`); + log.info(`No files in folder ${dir}`); } return results; @@ -141,7 +129,7 @@ abstract class AbstractBlackBoxSpec { /** * @throws IOException - */ + */ protected getImageFiles(): Array { assertEquals(fs.existsSync(this.testBase), true, 'Please download and install test images, and run from the \'core\' directory'); return this.walkDirectory(this.testBase); @@ -158,25 +146,20 @@ abstract class AbstractBlackBoxSpec { * @param done * * @throws IOException - */ + */ public async testBlackBox(): Promise { - try { - await this.testBlackBoxCountingResults(true); - console.log('testBlackBox finished.'); - } catch (e) { - console.log('Test ended with error: ', e); - throw e; - } + await this.testBlackBoxCountingResults(true); + log.info('testBlackBox finished.'); } /** * @throws IOException - */ + */ private async testBlackBoxCountingResults(assertOnFailure: boolean): Promise { assertEquals(this.testResults.length > 0, true); const imageFiles: Array = this.getImageFiles(); - const testCount: number /*int*/ = this.testResults.length; + const testCount: number /* int */ = this.testResults.length; const passedCounts = new Int32Array(testCount); const misreadCounts = new Int32Array(testCount); @@ -191,7 +174,6 @@ abstract class AbstractBlackBoxSpec { // and run tests in parallel testImageIterations.push(new Promise(async resolve => { - console.log(` Starting ${testImage}`); const fileBaseName: string = path.basename(testImage, path.extname(testImage)); let expectedTextFile: string = path.resolve(this.testBase, fileBaseName + '.txt'); let expectedText: string; @@ -203,6 +185,7 @@ abstract class AbstractBlackBoxSpec { assertEquals(fs.existsSync(expectedTextFile), true, 'result bin/text file should exists'); expectedText = AbstractBlackBoxSpec.readBinFileAsString(expectedTextFile); } + const truncated = AbstractBlackBoxSpec.truncate(expectedText, 32); const expectedMetadataFile: string = path.resolve(fileBaseName + '.metadata.txt'); let expectedMetadata = null; @@ -210,42 +193,59 @@ abstract class AbstractBlackBoxSpec { expectedMetadata = AbstractBlackBoxSpec.readTextFileAsMetadata(expectedMetadataFile); } - const decodeIterations: Promise[] = []; + const decodeIterations: Promise<{success: boolean; message: string}>[] = []; - for (let x: number /*int*/ = 0; x < testCount; x++) { + for (let x: number /* int */ = 0; x < testCount; x++) { // we run this in a separated scope so we can iterate faster // and run tests in parallel decodeIterations.push(new Promise(async resolve => { - - const rotation: number /*float*/ = this.testResults[x].getRotation(); + const rotation: number /* float */ = this.testResults[x].getRotation(); const rotatedImage = await SharpImage.loadWithRotation(testImage, rotation); const source: LuminanceSource = new SharpImageLuminanceSource(rotatedImage); const bitmap = new BinaryBitmap(new HybridBinarizer(source)); + + let message = ` ${rotation.toString().padStart(3, ' ')}: `; + let success = false; + let misread = false; try { - if (this.decode(bitmap, rotation, expectedText, expectedMetadata, false)) { + let { decoded, error } = this.decode(bitmap, rotation, expectedText, expectedMetadata, false); + if (decoded) { + message += 'successfully decoded'; passedCounts[x]++; + success = true; } else { + message += `misread with error ${error}`; + misread = true; misreadCounts[x]++; } } catch (e) { - console.log(` could not read at rotation ${rotation} failed with ${e.constructor.name}. Message: ${e.message}`); + message += `failed with error [${e.constructor.name}]`; } try { - if (this.decode(bitmap, rotation, expectedText, expectedMetadata, true)) { + let { decoded, error } = this.decode(bitmap, rotation, expectedText, expectedMetadata, true); + if (decoded) { + message += `${!success || misread ? ', but' : ' and'} try harder successfully decoded`; tryHarderCounts[x]++; + success = true; } else { + message += `${success || !misread ? ', but' : ' and'} try harder misread with error ${error}`; tryHarderMisreadCounts[x]++; + misread = true; } } catch (e) { - console.log(` could not read at rotation ${rotation} w/TH failed with ${e.constructor.name}.`); + message += `${success || misread ? ', but' : ' and'} try harder failed with error [${e.constructor.name}]`; } - - resolve(); + resolve({success, message}); })); } - await Promise.all(decodeIterations); + const results = await Promise.all(decodeIterations); + log.info(` Decoding ${path.relative(process.cwd(), testImage)} expecting '${truncated}' with rotations`); + results.forEach(({success, message}) => { + if (!success) log.warn(message); + else log.debug(message); + }); resolve(); })); @@ -255,70 +255,83 @@ abstract class AbstractBlackBoxSpec { // Original reference: 197. // Print the results of all tests first - let totalFound /*int*/ = 0; - let totalMustPass /*int*/ = 0; - let totalMisread /*int*/ = 0; - let totalMaxMisread /*int*/ = 0; + let totalFound /* int */ = 0; + let totalMustPass /* int */ = 0; + let totalMisread /* int */ = 0; + let totalMaxMisread /* int */ = 0; - for (let x: number /*int*/ = 0, length = this.testResults.length; x < length; x++) { + for (let x: number /* int */ = 0, length = this.testResults.length; x < length; x++) { const testResult: TestResult = this.testResults[x]; - console.log(`\n Rotation ${testResult.getRotation()} degrees:`); - console.log(` ${passedCounts[x]} of ${imageFiles.length} images passed (${testResult.getMustPassCount()} required)`); - let failed: number /*int*/ = imageFiles.length - passedCounts[x]; - console.log(` ${misreadCounts[x]} failed due to misreads, ${failed - misreadCounts[x]} not detected`); - console.log(` ${tryHarderCounts[x]} of ${imageFiles.length} images passed with try harder (${testResult.getTryHarderCount()} required)`); + log.info(` Rotation ${testResult.getRotation()} degrees:`); + log.info(` ${passedCounts[x]} of ${imageFiles.length} images passed (${testResult.getMustPassCount()} required)`); + let failed: number /* int */ = imageFiles.length - passedCounts[x]; + log.info(` ${misreadCounts[x]} failed due to misreads, ${failed - misreadCounts[x]} not detected`); + log.info(` ${tryHarderCounts[x]} of ${imageFiles.length} images passed with try harder (${testResult.getTryHarderCount()} required)`); failed = imageFiles.length - tryHarderCounts[x]; - console.log(` ${tryHarderMisreadCounts[x]} failed due to misreads, ${failed - tryHarderMisreadCounts[x]} not detected`); + log.info(` ${tryHarderMisreadCounts[x]} failed due to misreads, ${failed - tryHarderMisreadCounts[x]} not detected\n`); totalFound += passedCounts[x] + tryHarderCounts[x]; totalMustPass += testResult.getMustPassCount() + testResult.getTryHarderCount(); totalMisread += misreadCounts[x] + tryHarderMisreadCounts[x]; totalMaxMisread += testResult.getMaxMisreads() + testResult.getMaxTryHarderMisreads(); } - const totalTests: number /*int*/ = imageFiles.length * testCount * 2; + const totalTests: number /* int */ = imageFiles.length * testCount * 2; - console.log(` Decoded ${totalFound} images out of ${totalTests} (${totalFound * 100 / totalTests}%, ${totalMustPass} required)`); + log.info(` Decoded ${totalFound} images out of ${totalTests} (${totalFound * 100 / totalTests}%, ${totalMustPass} required)`); if (totalFound > totalMustPass) { - console.warn(` +++ Test too lax by ${totalFound - totalMustPass} images`); + log.warn(` +++ Test too lax by ${Math.abs(totalFound - totalMustPass)} images`); } else if (totalFound < totalMustPass) { - console.error(` --- Test failed by ${totalMustPass - totalFound} images`); + log.error(` --- Test failed by ${Math.abs(totalMustPass - totalFound)} images`); } if (totalMisread < totalMaxMisread) { - console.warn(` +++ Test expects too many misreads by ${totalMaxMisread - totalMisread} images`); + log.warn(` +++ Test expects too many misreads by ${Math.abs(totalMaxMisread - totalMisread)} images`); } else if (totalMisread > totalMaxMisread) { - console.error(` --- Test had too many misreads by ${totalMisread - totalMaxMisread} images`); + log.error(` --- Test had too many misreads by ${Math.abs(totalMisread - totalMaxMisread)} images`); } // Then run through again and assert if any failed. if (assertOnFailure) { - for (let x: number /*int*/ = 0; x < testCount; x++) { + for (let x: number /* int */ = 0; x < testCount; x++) { const testResult = this.testResults[x]; - const label = ' Rotation ' + testResult.getRotation() + ' degrees: Too many images failed.'; - - assertEquals(passedCounts[x] >= testResult.getMustPassCount(), true, label); - assertEquals(tryHarderCounts[x] >= testResult.getTryHarderCount(), true, `Try harder, ${label}`); - assertEquals(misreadCounts[x] <= testResult.getMaxMisreads(), true, label); - assertEquals(tryHarderMisreadCounts[x] <= testResult.getMaxTryHarderMisreads(), true, `Try harder, ${label}`); + const label = `Rotation ${testResult.getRotation()} degrees`; + + assertGreaterThanEquals( + passedCounts[x], + testResult.getMustPassCount(), + `${label} - ${Math.abs(testResult.getMustPassCount() - passedCounts[x])} too many images failed.` + ); + assertGreaterThanEquals( + tryHarderCounts[x], + testResult.getTryHarderCount(), + `${label} (try harder) - ${Math.abs(testResult.getTryHarderCount() - tryHarderCounts[x])} too many images failed.` + ); + assertLessThanEquals( + misreadCounts[x], + testResult.getMaxMisreads(), + `${label} - ${misreadCounts[x] - testResult.getMaxMisreads()} too many images were misread.` + ); + assertLessThanEquals( + tryHarderMisreadCounts[x], + testResult.getMaxTryHarderMisreads(), + `${label} (try harder) - ${tryHarderMisreadCounts[x] - testResult.getMaxTryHarderMisreads()} too many images were misread.` + ); } } } /** * @throws ReaderException - */ + */ private decode( source: BinaryBitmap, - rotation: number/*float*/, + rotation: number/* float */, expectedText: string, expectedMetadata: Map, tryHarder: boolean - ): boolean { - - const suffix: string = ` (${tryHarder ? 'try harder, ' : ''}rotation: ${rotation})`; - + ): { decoded: boolean; error?: string } { const hints = new Map(); if (tryHarder) { hints.set(DecodeHintType.TRY_HARDER, true); @@ -331,7 +344,7 @@ abstract class AbstractBlackBoxSpec { const pureHints = new Map(hints); pureHints.set(DecodeHintType.PURE_BARCODE, true); result = this.barcodeReader.decode(source, pureHints); - } catch (re/*ReaderException*/) { + } catch (re/* ReaderException */) { // continue } @@ -342,20 +355,24 @@ abstract class AbstractBlackBoxSpec { const resultFormat = result.getBarcodeFormat(); if (this.expectedFormat !== resultFormat) { - console.warn(`Format mismatch: expected '${this.expectedFormat}' but got '${resultFormat}'${suffix}`); - return false; + return { + decoded: false, + error: `[Format Mismatch]: expected '${this.expectedFormat}', actual '${resultFormat}'`, + }; } const resultText: string = result.getText(); - // WORKAROUND: ignore new line diferences between systems + // WORKAROUND: ignore new line differences between systems // TODO: check if a real problem or only because test result is stored in a file with modified new line chars const expectedTextR = expectedText.replace(/\r\n/g, '\n'); const resultTextR = resultText.replace(/\r\n/g, '\n'); if (expectedTextR !== resultTextR) { const expectedTextHexCodes = AbstractBlackBoxSpec.toDebugHexStringCodes(expectedTextR); const resultTextHexCodes = AbstractBlackBoxSpec.toDebugHexStringCodes(resultTextR); - console.warn(`Content mismatch: expected '${expectedTextR}' (${expectedTextHexCodes}) but got '${resultTextR}'${suffix} (${resultTextHexCodes})`); - return false; + return { + decoded: false, + error: `[Content Mismatch]: expected '${expectedTextR}' (${expectedTextHexCodes}), actual '${resultTextR}' (${resultTextHexCodes})`, + }; } const resultMetadata: Map = result.getResultMetadata(); @@ -366,15 +383,22 @@ abstract class AbstractBlackBoxSpec { const keyType: ResultMetadataType = AbstractBlackBoxSpec.valueOfResultMetadataTypeFromString(key); const actualValue: Object = resultMetadata === null ? undefined : resultMetadata.get(keyType); if (expectedValue !== actualValue) { - console.warn(`Metadata mismatch for key '${key}': expected '${expectedValue}' but got '${actualValue}'`); - return false; + return { + decoded: false, + error: `[Metadata Mismatch]: key '${key}', expected '${expectedValue}', actual '${actualValue}'`, + }; } } } - return true; + return { decoded: true }; } + private static truncate(text: string, n: number){ + text = text.replace(/(?:\r\n|\r|\n)/g, ' '); + return (text.length > n) ? text.substr(0, n-1) + '\u2026' : text; + }; + private static toDebugHexStringCodes(text: string): string { let r = ''; for (let i = 0, length = text.length; i !== length; i++) { @@ -403,11 +427,11 @@ abstract class AbstractBlackBoxSpec { /** * @throws IOException - */ + */ protected static readTextFileAsString(file: string): string { const stringContents: string = fs.readFileSync(file, { encoding: 'utf8' }); if (stringContents.endsWith('\n')) { - console.warn('contents: string of file ' + file + ' end with a newline. ' + + log.warn('contents: string of file ' + file + ' end with a newline. ' + 'This may not be intended and cause a test failure'); } return stringContents; @@ -415,12 +439,12 @@ abstract class AbstractBlackBoxSpec { /** * @throws IOException - */ + */ protected static readBinFileAsString(file: string): string { const bufferContents: Buffer = fs.readFileSync(file); const stringContents = ZXingStringEncoding.decode(new Uint8Array(bufferContents), 'iso-8859-1'); if (stringContents.endsWith('\n')) { - console.warn('contents: string of file ' + file + ' end with a newline. ' + + log.warn('contents: string of file ' + file + ' end with a newline. ' + 'This may not be intended and cause a test failure'); } return stringContents; @@ -428,7 +452,7 @@ abstract class AbstractBlackBoxSpec { /** * @throws IOException - */ + */ protected static readTextFileAsMetadata(file: string): Map { // TODO: read text-file as metadata. return null; diff --git a/src/test/core/common/BitArray.spec.ts b/src/test/core/common/BitArray.spec.ts index 8323e3d4..403903ec 100644 --- a/src/test/core/common/BitArray.spec.ts +++ b/src/test/core/common/BitArray.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.common;*/ +/* package com.google.zxing.common; */ import * as assert from 'assert'; import Random from '../util/Random'; @@ -27,220 +27,220 @@ import AssertUtils from '../util/AssertUtils'; */ describe('BitArray', () => { - it('testGetSet', () => { - const array = new BitArray(33); - for (let i = 0; i < 33; i++) { - assert.strictEqual(array.get(i), false); - array.set(i); - assert.strictEqual(array.get(i), true); - } - }); + it('testGetSet', () => { + const array = new BitArray(33); + for (let i = 0; i < 33; i++) { + assert.strictEqual(array.get(i), false); + array.set(i); + assert.strictEqual(array.get(i), true); + } + }); - it('testGetNextSet1', () => { - let array = new BitArray(32); - for (let i = 0; i < array.getSize(); i++) { - assert.strictEqual(array.getNextSet(i), 32, '' + i); - } - array = new BitArray(33); - for (let i = 0; i < array.getSize(); i++) { - assert.strictEqual(array.getNextSet(i), 33, '' + i); - } - }); + it('testGetNextSet1', () => { + let array = new BitArray(32); + for (let i = 0; i < array.getSize(); i++) { + assert.strictEqual(array.getNextSet(i), 32, '' + i); + } + array = new BitArray(33); + for (let i = 0; i < array.getSize(); i++) { + assert.strictEqual(array.getNextSet(i), 33, '' + i); + } + }); - it('testGetNextSet2', () => { - let array = new BitArray(33); - array.set(31); - for (let i = 0; i < array.getSize(); i++) { - assert.strictEqual(array.getNextSet(i), i <= 31 ? 31 : 33, '' + i); - } - array = new BitArray(33); - array.set(32); - for (let i = 0; i < array.getSize(); i++) { - assert.strictEqual(array.getNextSet(i), 32, '' + i); - } - }); - - - it('testGetNextSet3', () => { - const array = new BitArray(63); - array.set(31); - array.set(32); - for (let i = 0; i < array.getSize(); i++) { - let expected; - if (i <= 31) { - expected = 31; - } else if (i === 32) { - expected = 32; - } else { - expected = 63; - } - assert.strictEqual(array.getNextSet(i), expected, '' + i); - } - }); - - - it('testGetNextSet4', () => { - const array = new BitArray(63); - array.set(33); - array.set(40); - for (let i = 0; i < array.getSize(); i++) { - let expected; - if (i <= 33) { - expected = 33; - } else if (i <= 40) { - expected = 40; - } else { - expected = 63; - } - assert.strictEqual(array.getNextSet(i), expected, '' + i); - } - }); - - - it('testGetNextSet5', () => { - const r = new Random('0xDEADBEEF'); - for (let i = 0; i < 10; i++) { - const array = new BitArray(1 + r.next(100)); - const numSet = r.next(20); - for (let j = 0; j < numSet; j++) { - array.set(r.next(array.getSize())); - } - const numQueries = r.next(20); - for (let j = 0; j < numQueries; j++) { - const query = r.next(array.getSize()); - let expected = query; - while (expected < array.getSize() && !array.get(expected)) { - expected++; - } - const actual = array.getNextSet(query); - assert.strictEqual(actual, expected); - } - } - }); + it('testGetNextSet2', () => { + let array = new BitArray(33); + array.set(31); + for (let i = 0; i < array.getSize(); i++) { + assert.strictEqual(array.getNextSet(i), i <= 31 ? 31 : 33, '' + i); + } + array = new BitArray(33); + array.set(32); + for (let i = 0; i < array.getSize(); i++) { + assert.strictEqual(array.getNextSet(i), 32, '' + i); + } + }); + + + it('testGetNextSet3', () => { + const array = new BitArray(63); + array.set(31); + array.set(32); + for (let i = 0; i < array.getSize(); i++) { + let expected; + if (i <= 31) { + expected = 31; + } else if (i === 32) { + expected = 32; + } else { + expected = 63; + } + assert.strictEqual(array.getNextSet(i), expected, '' + i); + } + }); + + + it('testGetNextSet4', () => { + const array = new BitArray(63); + array.set(33); + array.set(40); + for (let i = 0; i < array.getSize(); i++) { + let expected; + if (i <= 33) { + expected = 33; + } else if (i <= 40) { + expected = 40; + } else { + expected = 63; + } + assert.strictEqual(array.getNextSet(i), expected, '' + i); + } + }); + + + it('testGetNextSet5', () => { + const r = new Random('0xDEADBEEF'); + for (let i = 0; i < 10; i++) { + const array = new BitArray(1 + r.next(100)); + const numSet = r.next(20); + for (let j = 0; j < numSet; j++) { + array.set(r.next(array.getSize())); + } + const numQueries = r.next(20); + for (let j = 0; j < numQueries; j++) { + const query = r.next(array.getSize()); + let expected = query; + while (expected < array.getSize() && !array.get(expected)) { + expected++; + } + const actual = array.getNextSet(query); + assert.strictEqual(actual, expected); + } + } + }); - it('testSetBulk', () => { - const array = new BitArray(64); - array.setBulk(32, 0xFFFF0000); - for (let i = 0; i < 48; i++) { - assert.strictEqual(array.get(i), false); - } - for (let i = 48; i < 64; i++) { - assert.strictEqual(array.get(i), true); - } - }); + it('testSetBulk', () => { + const array = new BitArray(64); + array.setBulk(32, 0xFFFF0000); + for (let i = 0; i < 48; i++) { + assert.strictEqual(array.get(i), false); + } + for (let i = 48; i < 64; i++) { + assert.strictEqual(array.get(i), true); + } + }); - it('testSetRange', () => { - const array = new BitArray(64); - array.setRange(28, 36); - assert.strictEqual(array.get(27), false); - for (let i = 28; i < 36; i++) { - assert.strictEqual(array.get(i), true); - } - assert.strictEqual(array.get(36), false); - }); + it('testSetRange', () => { + const array = new BitArray(64); + array.setRange(28, 36); + assert.strictEqual(array.get(27), false); + for (let i = 28; i < 36; i++) { + assert.strictEqual(array.get(i), true); + } + assert.strictEqual(array.get(36), false); + }); - it('testClear', () => { - const array = new BitArray(32); - for (let i = 0; i < 32; i++) { - array.set(i); - } - array.clear(); - for (let i = 0; i < 32; i++) { - assert.strictEqual(array.get(i), false); - } - }); - - - it('testFlip', () => { - const array = new BitArray(32); - assert.strictEqual(array.get(5), false); - array.flip(5); - assert.strictEqual(array.get(5), true); - array.flip(5); - assert.strictEqual(array.get(5), false); - }); - - - it('testGetArray', () => { - const array = new BitArray(64); - array.set(0); - array.set(63); - const ints = array.getBitArray(); - assert.strictEqual(ints[0], 1); - assert.strictEqual(ints[1], ZXingInteger.MIN_VALUE_32_BITS); // Integer.MIN_VALUE) - }); - - - it('testIsRange', () => { - const array = new BitArray(64); - assert.strictEqual(array.isRange(0, 64, false), true); - assert.strictEqual(array.isRange(0, 64, true), false); - array.set(32); - assert.strictEqual(array.isRange(32, 33, true), true); - array.set(31); - assert.strictEqual(array.isRange(31, 33, true), true); - array.set(34); - assert.strictEqual(array.isRange(31, 35, true), false); - for (let i = 0; i < 31; i++) { - array.set(i); - } - assert.strictEqual(array.isRange(0, 33, true), true); - for (let i = 33; i < 64; i++) { - array.set(i); - } - assert.strictEqual(array.isRange(0, 64, true), true); - assert.strictEqual(array.isRange(0, 64, false), false); - }); - - - it('reverseAlgorithmTest', () => { - const oldBits = Int32Array.from([128, 256, 512, 6453324, 50934953]); - for (let size = 1; size < 160; size++) { - const newBitsOriginal = reverseOriginal(oldBits.slice(), size); - const newBitArray = new BitArray(size, oldBits.slice()); - newBitArray.reverse(); - const newBitsNew = newBitArray.getBitArray(); - assert.strictEqual(AssertUtils.typedArraysAreEqual(newBitsOriginal, newBitsNew, size / 32 + 1), true); - } - }); - - - it('testClone', () => { - const array = new BitArray(32); - array.clone().set(0); - assert.strictEqual(array.get(0), false); - }); - - - it('testEquals', () => { - const a = new BitArray(32); - const b = new BitArray(32); - assert.strictEqual(a.equals(b), true); - assert.strictEqual(a.hashCode(), b.hashCode()); - assert.strictEqual(a.equals(new BitArray(31)), false); - a.set(16); - assert.strictEqual(a.equals(new BitArray(31)), false); - assert.notStrictEqual(a.hashCode(), b.hashCode()); - b.set(16); - assert.strictEqual(a.equals(b), true); - assert.strictEqual(a.hashCode(), b.hashCode()); - }); - - function reverseOriginal(oldBits: Int32Array, size: number): Int32Array { - const newBits = new Int32Array(oldBits.length); - for (let i = 0; i < size; i++) { - if (bitSet(oldBits, size - i - 1)) { - newBits[Math.floor(i / 32)] |= 1 << (i & 0x1F); - } - } - return newBits; + it('testClear', () => { + const array = new BitArray(32); + for (let i = 0; i < 32; i++) { + array.set(i); } - - function bitSet(bits: Int32Array, i: number): boolean { - return (bits[Math.floor(i / 32)] & (1 << (i & 0x1F))) !== 0; + array.clear(); + for (let i = 0; i < 32; i++) { + assert.strictEqual(array.get(i), false); + } + }); + + + it('testFlip', () => { + const array = new BitArray(32); + assert.strictEqual(array.get(5), false); + array.flip(5); + assert.strictEqual(array.get(5), true); + array.flip(5); + assert.strictEqual(array.get(5), false); + }); + + + it('testGetArray', () => { + const array = new BitArray(64); + array.set(0); + array.set(63); + const ints = array.getBitArray(); + assert.strictEqual(ints[0], 1); + assert.strictEqual(ints[1], ZXingInteger.MIN_VALUE_32_BITS); // Integer.MIN_VALUE) + }); + + + it('testIsRange', () => { + const array = new BitArray(64); + assert.strictEqual(array.isRange(0, 64, false), true); + assert.strictEqual(array.isRange(0, 64, true), false); + array.set(32); + assert.strictEqual(array.isRange(32, 33, true), true); + array.set(31); + assert.strictEqual(array.isRange(31, 33, true), true); + array.set(34); + assert.strictEqual(array.isRange(31, 35, true), false); + for (let i = 0; i < 31; i++) { + array.set(i); } + assert.strictEqual(array.isRange(0, 33, true), true); + for (let i = 33; i < 64; i++) { + array.set(i); + } + assert.strictEqual(array.isRange(0, 64, true), true); + assert.strictEqual(array.isRange(0, 64, false), false); + }); + + + it('reverseAlgorithmTest', () => { + const oldBits = Int32Array.from([128, 256, 512, 6453324, 50934953]); + for (let size = 1; size < 160; size++) { + const newBitsOriginal = reverseOriginal(oldBits.slice(), size); + const newBitArray = new BitArray(size, oldBits.slice()); + newBitArray.reverse(); + const newBitsNew = newBitArray.getBitArray(); + assert.strictEqual(AssertUtils.typedArraysAreEqual(newBitsOriginal, newBitsNew, size / 32 + 1), true); + } + }); + + + it('testClone', () => { + const array = new BitArray(32); + array.clone().set(0); + assert.strictEqual(array.get(0), false); + }); + + + it('testEquals', () => { + const a = new BitArray(32); + const b = new BitArray(32); + assert.strictEqual(a.equals(b), true); + assert.strictEqual(a.hashCode(), b.hashCode()); + assert.strictEqual(a.equals(new BitArray(31)), false); + a.set(16); + assert.strictEqual(a.equals(new BitArray(31)), false); + assert.notStrictEqual(a.hashCode(), b.hashCode()); + b.set(16); + assert.strictEqual(a.equals(b), true); + assert.strictEqual(a.hashCode(), b.hashCode()); + }); + + function reverseOriginal(oldBits: Int32Array, size: number): Int32Array { + const newBits = new Int32Array(oldBits.length); + for (let i = 0; i < size; i++) { + if (bitSet(oldBits, size - i - 1)) { + newBits[Math.floor(i / 32)] |= 1 << (i & 0x1F); + } + } + return newBits; + } + + function bitSet(bits: Int32Array, i: number): boolean { + return (bits[Math.floor(i / 32)] & (1 << (i & 0x1F))) !== 0; + } }); diff --git a/src/test/core/common/BitMatrix.spec.ts b/src/test/core/common/BitMatrix.spec.ts index a7d90082..49f29e5b 100644 --- a/src/test/core/common/BitMatrix.spec.ts +++ b/src/test/core/common/BitMatrix.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.common;*/ +/* package com.google.zxing.common; */ import * as assert from 'assert'; import AssertUtils from '../util/AssertUtils'; @@ -36,15 +36,15 @@ describe('BitMatrix', () => { it('testGetSet', () => { const matrix: BitMatrix = new BitMatrix(33); assert.strictEqual(33, matrix.getHeight()); - for (let y: number /*int*/ = 0; y < 33; y++) { - for (let x: number /*int*/ = 0; x < 33; x++) { + for (let y: number /* int */ = 0; y < 33; y++) { + for (let x: number /* int */ = 0; x < 33; x++) { if (y * x % 3 === 0) { matrix.set(x, y); } } } - for (let y: number /*int*/ = 0; y < 33; y++) { - for (let x: number /*int*/ = 0; x < 33; x++) { + for (let y: number /* int */ = 0; y < 33; y++) { + for (let x: number /* int */ = 0; x < 33; x++) { const expected = y * x % 3 === 0; const value = matrix.get(x, y); assert.strictEqual(value, expected); @@ -55,8 +55,8 @@ describe('BitMatrix', () => { it('testSetRegion', () => { const matrix: BitMatrix = new BitMatrix(5); matrix.setRegion(1, 1, 3, 3); - for (let y: number /*int*/ = 0; y < 5; y++) { - for (let x: number /*int*/ = 0; x < 5; x++) { + for (let y: number /* int */ = 0; y < 5; y++) { + for (let x: number /* int */ = 0; x < 5; x++) { assert.strictEqual(y >= 1 && y <= 3 && x >= 1 && x <= 3, matrix.get(x, y)); } } @@ -121,8 +121,8 @@ describe('BitMatrix', () => { matrix.setRegion(105, 22, 80, 12); // Only bits in the region should be on - for (let y: number /*int*/ = 0; y < 240; y++) { - for (let x: number /*int*/ = 0; x < 320; x++) { + for (let y: number /* int */ = 0; y < 240; y++) { + for (let x: number /* int */ = 0; x < 320; x++) { assert.strictEqual(y >= 22 && y < 34 && x >= 105 && x < 185, matrix.get(x, y)); } } @@ -130,7 +130,7 @@ describe('BitMatrix', () => { it('testGetRow', () => { const matrix: BitMatrix = new BitMatrix(102, 5); - for (let x: number /*int*/ = 0; x < 102; x++) { + for (let x: number /* int */ = 0; x < 102; x++) { if ((x & 0x03) === 0) { matrix.set(x, 2); } @@ -150,7 +150,7 @@ describe('BitMatrix', () => { array3 = matrix.getRow(2, array3); assert.strictEqual(array3.getSize(), 200); - for (let x: number /*int*/ = 0; x < 102; x++) { + for (let x: number /* int */ = 0; x < 102; x++) { const on: boolean = (x & 0x03) === 0; assert.strictEqual(on, array.get(x)); assert.strictEqual(on, array2.get(x)); @@ -307,7 +307,7 @@ describe('BitMatrix', () => { function matrixToString(result: BitMatrix): string { assert.strictEqual(1, result.getHeight()); const builder: ZXingStringBuilder = new ZXingStringBuilder(); // result.getWidth()) - for (let i: number /*int*/ = 0; i < result.getWidth(); i++) { + for (let i: number /* int */ = 0; i < result.getWidth(); i++) { builder.append(result.get(i, 0) ? '1' : '0'); } return builder.toString(); @@ -326,7 +326,7 @@ describe('BitMatrix', () => { // function matrixToString(result: BitMatrix): string { // assert.strictEqual(1, result.getHeight()); // const builder: StringBuilder = new StringBuilder(); // result.getWidth()) - // for (let i: number /*int*/ = 0; i < result.getWidth(); i++) { + // for (let i: number /*int */ = 0; i < result.getWidth(); i++) { // builder.append(result.get(i, 0) ? '1' : '0'); // } // return builder.toString(); @@ -338,29 +338,29 @@ describe('BitMatrix', () => { assert.strictEqual(matrix.equals(expectedMatrix), true); } - function testRotate180(width: number /*int*/, height: number /*int*/): void { + function testRotate180(width: number /* int */, height: number /* int */): void { const input: BitMatrix = getInput(width, height); input.rotate180(); const expected: BitMatrix = getExpected(width, height); - for (let y: number /*int*/ = 0; y < height; y++) { - for (let x: number /*int*/ = 0; x < width; x++) { + for (let y: number /* int */ = 0; y < height; y++) { + for (let x: number /* int */ = 0; x < width; x++) { assert.strictEqual(input.get(x, y), expected.get(x, y), '(' + x + ',' + y + ')'); } } } - function getExpected(width: number /*int*/, height: number /*int*/): BitMatrix { + function getExpected(width: number /* int */, height: number /* int */): BitMatrix { const result: BitMatrix = new BitMatrix(width, height); - for (let i: number /*int*/ = 0; i < BIT_MATRIX_POINTS.length; i += 2) { + for (let i: number /* int */ = 0; i < BIT_MATRIX_POINTS.length; i += 2) { result.set(width - 1 - BIT_MATRIX_POINTS[i], height - 1 - BIT_MATRIX_POINTS[i + 1]); } return result; } - function getInput(width: number /*int*/, height: number /*int*/): BitMatrix { + function getInput(width: number /* int */, height: number /* int */): BitMatrix { const result: BitMatrix = new BitMatrix(width, height); - for (let i: number /*int*/ = 0; i < BIT_MATRIX_POINTS.length; i += 2) { + for (let i: number /* int */ = 0; i < BIT_MATRIX_POINTS.length; i += 2) { result.set(BIT_MATRIX_POINTS[i], BIT_MATRIX_POINTS[i + 1]); } return result; diff --git a/src/test/core/common/BitSource.spec.ts b/src/test/core/common/BitSource.spec.ts index 934d3209..d38f5a19 100644 --- a/src/test/core/common/BitSource.spec.ts +++ b/src/test/core/common/BitSource.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.common;*/ +/* package com.google.zxing.common; */ import * as assert from 'assert'; import { BitSource } from '@zxing/library'; @@ -24,32 +24,32 @@ import { BitSource } from '@zxing/library'; */ describe('BitSource', () => { - it('testSource', () => { - const bytes = Uint8Array.from([ - /*(byte)*/ 1, - /*(byte)*/ 2, - /*(byte)*/ 3, - /*(byte)*/ 4, - /*(byte)*/ 5 - ]); + it('testSource', () => { + const bytes = Uint8Array.from([ + /* (byte) */ 1, + /* (byte) */ 2, + /* (byte) */ 3, + /* (byte) */ 4, + /* (byte) */ 5 + ]); - const source = new BitSource(bytes); + const source = new BitSource(bytes); - assert.strictEqual(source.available(), 40); - assert.strictEqual(source.readBits(1), 0); - assert.strictEqual(source.available(), 39); - assert.strictEqual(source.readBits(6), 0); - assert.strictEqual(source.available(), 33); - assert.strictEqual(source.readBits(1), 1); - assert.strictEqual(source.available(), 32); - assert.strictEqual(source.readBits(8), 2); - assert.strictEqual(source.available(), 24); - assert.strictEqual(source.readBits(10), 12); - assert.strictEqual(source.available(), 14); - assert.strictEqual(source.readBits(8), 16); - assert.strictEqual(source.available(), 6); - assert.strictEqual(source.readBits(6), 5); - assert.strictEqual(source.available(), 0); - }); + assert.strictEqual(source.available(), 40); + assert.strictEqual(source.readBits(1), 0); + assert.strictEqual(source.available(), 39); + assert.strictEqual(source.readBits(6), 0); + assert.strictEqual(source.available(), 33); + assert.strictEqual(source.readBits(1), 1); + assert.strictEqual(source.available(), 32); + assert.strictEqual(source.readBits(8), 2); + assert.strictEqual(source.available(), 24); + assert.strictEqual(source.readBits(10), 12); + assert.strictEqual(source.available(), 14); + assert.strictEqual(source.readBits(8), 16); + assert.strictEqual(source.available(), 6); + assert.strictEqual(source.readBits(6), 5); + assert.strictEqual(source.available(), 0); + }); }); diff --git a/src/test/core/common/BitSourceBuilder.ts b/src/test/core/common/BitSourceBuilder.ts index 265ed9d1..cf32ab54 100644 --- a/src/test/core/common/BitSourceBuilder.ts +++ b/src/test/core/common/BitSourceBuilder.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -/*package com.google.zxing.common;*/ +/* package com.google.zxing.common; */ -/*import java.io.ByteArrayOutputStream;*/ +/* import java.io.ByteArrayOutputStream; */ /** * Class that lets one easily build an array of bytes by appending bits at a time. @@ -25,42 +25,42 @@ */ export default class BitSourceBuilder { - private output: Array; - private nextByte: number; /*int*/ - private bitsLeftInNextByte: number; /*int*/ + private output: Array; + private nextByte: number; /* int */ + private bitsLeftInNextByte: number; /* int */ - public constructor() { - this.output = new Array(); + public constructor() { + this.output = new Array(); + this.nextByte = 0; + this.bitsLeftInNextByte = 8; + } + + public write(value: number /* int */, numBits: number /* int */): void { + if (numBits <= this.bitsLeftInNextByte) { + const nb = (this.nextByte << numBits) & 0xFFFFFFFF; + this.nextByte = nb | value; + this.bitsLeftInNextByte -= numBits; + if (this.bitsLeftInNextByte === 0) { + const byte = this.nextByte & 0xFF; + this.output.push(byte); this.nextByte = 0; this.bitsLeftInNextByte = 8; + } + } else { + const bitsToWriteNow: number /* int */ = this.bitsLeftInNextByte; + const numRestOfBits: number /* int */ = numBits - bitsToWriteNow; + const mask: number /* int */ = 0xFF >> (8 - bitsToWriteNow); + const valueToWriteNow: number /* int */ = (value >>> numRestOfBits) & mask; + this.write(valueToWriteNow, bitsToWriteNow); + this.write(value, numRestOfBits); } + } - public write(value: number /*int*/, numBits: number /*int*/): void { - if (numBits <= this.bitsLeftInNextByte) { - const nb = (this.nextByte << numBits) & 0xFFFFFFFF; - this.nextByte = nb | value; - this.bitsLeftInNextByte -= numBits; - if (this.bitsLeftInNextByte === 0) { - const byte = this.nextByte & 0xFF; - this.output.push(byte); - this.nextByte = 0; - this.bitsLeftInNextByte = 8; - } - } else { - const bitsToWriteNow: number /*int*/ = this.bitsLeftInNextByte; - const numRestOfBits: number /*int*/ = numBits - bitsToWriteNow; - const mask: number /*int*/ = 0xFF >> (8 - bitsToWriteNow); - const valueToWriteNow: number /*int*/ = (value >>> numRestOfBits) & mask; - this.write(valueToWriteNow, bitsToWriteNow); - this.write(value, numRestOfBits); - } - } - - public toByteArray(): Uint8Array { - if (this.bitsLeftInNextByte < 8) { - this.write(0, this.bitsLeftInNextByte); - } - return Uint8Array.from(this.output); + public toByteArray(): Uint8Array { + if (this.bitsLeftInNextByte < 8) { + this.write(0, this.bitsLeftInNextByte); } + return Uint8Array.from(this.output); + } } diff --git a/src/test/core/common/PerspectiveTransform.spec.ts b/src/test/core/common/PerspectiveTransform.spec.ts index 04b4346a..cdeafdfe 100644 --- a/src/test/core/common/PerspectiveTransform.spec.ts +++ b/src/test/core/common/PerspectiveTransform.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.common;*/ +/* package com.google.zxing.common; */ import * as assert from 'assert'; import { PerspectiveTransform } from '@zxing/library'; @@ -24,39 +24,39 @@ import { PerspectiveTransform } from '@zxing/library'; */ describe('PerspectiveTransform', () => { - const EPSILON: number /*float*/ = 1.0E-4; - - it('testSquareToQuadrilateral', () => { - const pt = PerspectiveTransform.squareToQuadrilateral(2.0, 3.0, 10.0, 4.0, 16.0, 15.0, 4.0, 9.0); - assertPointEquals(2.0, 3.0, 0.0, 0.0, pt); - assertPointEquals(10.0, 4.0, 1.0, 0.0, pt); - assertPointEquals(4.0, 9.0, 0.0, 1.0, pt); - assertPointEquals(16.0, 15.0, 1.0, 1.0, pt); - assertPointEquals(6.535211, 6.8873234, 0.5, 0.5, pt); - assertPointEquals(48.0, 42.42857, 1.5, 1.5, pt); - }); - - it('testQuadrilateralToQuadrilateral', () => { - const pt = PerspectiveTransform.quadrilateralToQuadrilateral( - 2.0, 3.0, 10.0, 4.0, 16.0, 15.0, 4.0, 9.0, - 103.0, 110.0, 300.0, 120.0, 290.0, 270.0, 150.0, 280.0); - assertPointEquals(103.0, 110.0, 2.0, 3.0, pt); - assertPointEquals(300.0, 120.0, 10.0, 4.0, pt); - assertPointEquals(290.0, 270.0, 16.0, 15.0, pt); - assertPointEquals(150.0, 280.0, 4.0, 9.0, pt); - assertPointEquals(7.1516876, -64.60185, 0.5, 0.5, pt); - assertPointEquals(328.09116, 334.16385, 50.0, 50.0, pt); - }); - - function assertPointEquals(expectedX: number/*float*/, - expectedY: number/*float*/, - sourceX: number/*float*/, - sourceY: number/*float*/, - pt: PerspectiveTransform) { - const points = Float32Array.from([sourceX, sourceY]); - pt.transformPoints(points); - assert.strictEqual(Math.abs(expectedX - points[0]) < EPSILON, true); - assert.strictEqual(Math.abs(expectedY - points[1]) < EPSILON, true); - } + const EPSILON: number /* float */ = 1.0E-4; + + it('testSquareToQuadrilateral', () => { + const pt = PerspectiveTransform.squareToQuadrilateral(2.0, 3.0, 10.0, 4.0, 16.0, 15.0, 4.0, 9.0); + assertPointEquals(2.0, 3.0, 0.0, 0.0, pt); + assertPointEquals(10.0, 4.0, 1.0, 0.0, pt); + assertPointEquals(4.0, 9.0, 0.0, 1.0, pt); + assertPointEquals(16.0, 15.0, 1.0, 1.0, pt); + assertPointEquals(6.535211, 6.8873234, 0.5, 0.5, pt); + assertPointEquals(48.0, 42.42857, 1.5, 1.5, pt); + }); + + it('testQuadrilateralToQuadrilateral', () => { + const pt = PerspectiveTransform.quadrilateralToQuadrilateral( + 2.0, 3.0, 10.0, 4.0, 16.0, 15.0, 4.0, 9.0, + 103.0, 110.0, 300.0, 120.0, 290.0, 270.0, 150.0, 280.0); + assertPointEquals(103.0, 110.0, 2.0, 3.0, pt); + assertPointEquals(300.0, 120.0, 10.0, 4.0, pt); + assertPointEquals(290.0, 270.0, 16.0, 15.0, pt); + assertPointEquals(150.0, 280.0, 4.0, 9.0, pt); + assertPointEquals(7.1516876, -64.60185, 0.5, 0.5, pt); + assertPointEquals(328.09116, 334.16385, 50.0, 50.0, pt); + }); + + function assertPointEquals(expectedX: number/* float */, + expectedY: number/* float */, + sourceX: number/* float */, + sourceY: number/* float */, + pt: PerspectiveTransform) { + const points = Float32Array.from([sourceX, sourceY]); + pt.transformPoints(points); + assert.strictEqual(Math.abs(expectedX - points[0]) < EPSILON, true); + assert.strictEqual(Math.abs(expectedY - points[1]) < EPSILON, true); + } }); diff --git a/src/test/core/common/StringUtils.spec.ts b/src/test/core/common/StringUtils.spec.ts index 52cbb442..fd413dd3 100644 --- a/src/test/core/common/StringUtils.spec.ts +++ b/src/test/core/common/StringUtils.spec.ts @@ -14,61 +14,61 @@ * limitations under the License. */ -/*package com.google.zxing.common;*/ +/* package com.google.zxing.common; */ import * as assert from 'assert'; import { StringUtils } from '@zxing/library'; import { CharacterSetECI } from '@zxing/library'; -/*import java.nio.charset.ZXingCharset;*/ +/* import java.nio.charset.ZXingCharset; */ describe('StringUtils', () => { - it('testShortShiftJIS_1', () => { - // ÈáëÈ≠ö - doTest(Uint8Array.from([/*(byte)*/ 0x8b, /*(byte)*/ 0xe0, /*(byte)*/ 0x8b, /*(byte)*/ 0x9b]), CharacterSetECI.SJIS.getName()/*"SJIS"*/); - }); + it('testShortShiftJIS_1', () => { + // ÈáëÈ≠ö + doTest(Uint8Array.from([/* (byte) */ 0x8b, /* (byte) */ 0xe0, /* (byte) */ 0x8b, /* (byte) */ 0x9b]), CharacterSetECI.SJIS.getName()/* "SJIS" */); + }); - it('testShortISO88591_1', () => { - // b√•d - doTest(Uint8Array.from([/*(byte)*/ 0x62, /*(byte)*/ 0xe5, /*(byte)*/ 0x64]), CharacterSetECI.ISO8859_1.getName()/*"ISO-8859-1"*/); - }); + it('testShortISO88591_1', () => { + // b√•d + doTest(Uint8Array.from([/* (byte) */ 0x62, /* (byte) */ 0xe5, /* (byte) */ 0x64]), CharacterSetECI.ISO8859_1.getName()/* "ISO-8859-1" */); + }); - it('testMixedShiftJIS_1', () => { - // Hello Èáë! - doTest(Uint8Array.from([/*(byte)*/ 0x48, /*(byte)*/ 0x65, /*(byte)*/ 0x6c, /*(byte)*/ 0x6c, /*(byte)*/ 0x6f, - /*(byte)*/ 0x20, /*(byte)*/ 0x8b, /*(byte)*/ 0xe0, /*(byte)*/ 0x21]), - 'SJIS'); - }); + it('testMixedShiftJIS_1', () => { + // Hello Èáë! + doTest(Uint8Array.from([/* (byte) */ 0x48, /* (byte) */ 0x65, /* (byte) */ 0x6c, /* (byte) */ 0x6c, /* (byte) */ 0x6f, + /* (byte) */ 0x20, /* (byte) */ 0x8b, /* (byte) */ 0xe0, /* (byte) */ 0x21]), + 'SJIS'); + }); - function doTest(bytes: Uint8Array, charsetName: string): void { - // const charset: ZXingCharset = ZXingCharset.forName(charsetName); - const guessedName: string = StringUtils.guessEncoding(bytes, null); - // const guessedEncoding: ZXingCharset = ZXingCharset.forName(guessedName); - // assert.strictEqual(guessedEncoding, charset) - assert.strictEqual(guessedName, charsetName); - } + function doTest(bytes: Uint8Array, charsetName: string): void { + // const charset: ZXingCharset = ZXingCharset.forName(charsetName); + const guessedName: string = StringUtils.guessEncoding(bytes, null); + // const guessedEncoding: ZXingCharset = ZXingCharset.forName(guessedName); + // assert.strictEqual(guessedEncoding, charset) + assert.strictEqual(guessedName, charsetName); + } - /** - * Utility for printing out a string in given encoding as a Java statement, since it's better - * to write that into the Java source file rather than risk character encoding issues in the - * source file itself. - * - * @param args command line arguments - */ - // funtion main(String[] args): void { - // const text: string = args[0] - // const charset: ZXingCharset = ZXingCharset.forName(args[1]); - // const declaration = new ZXingStringBuilder() - // declaration.append("Uint8Array.from([") - // for (byte b : text.getBytes(charset)) { - // declaration.append("/*(byte)*/ 0x") - // declaration.append(Integer.toHexString(b & 0xFF)) - // declaration.append(", ") - // } - // declaration.append('}') - // System.out.println(declaration) - // } + /** + * Utility for printing out a string in given encoding as a Java statement, since it's better + * to write that into the Java source file rather than risk character encoding issues in the + * source file itself. + * + * @param args command line arguments + */ + // funtion main(String[] args): void { + // const text: string = args[0] + // const charset: ZXingCharset = ZXingCharset.forName(args[1]); + // const declaration = new ZXingStringBuilder() + // declaration.append("Uint8Array.from([") + // for (byte b : text.getBytes(charset)) { + // declaration.append("/*(byte) */ 0x") + // declaration.append(Integer.toHexString(b & 0xFF)) + // declaration.append(", ") + // } + // declaration.append('}') + // System.out.println(declaration) + // } }); diff --git a/src/test/core/common/TestResult.ts b/src/test/core/common/TestResult.ts index 6f84ff06..00005e03 100644 --- a/src/test/core/common/TestResult.ts +++ b/src/test/core/common/TestResult.ts @@ -14,36 +14,36 @@ * limitations under the License. */ -/*package com.google.zxing.common;*/ +/* package com.google.zxing.common; */ export default class TestResult { - public constructor( - private mustPassCount: number /*int*/, - private tryHarderCount: number /*int*/, - private maxMisreads: number /*int*/, - private maxTryHarderMisreads: number /*int*/, - private rotation: number/*float*/) { - } - - public getMustPassCount(): number /*int*/ { - return this.mustPassCount; - } - - public getTryHarderCount(): number /*int*/ { - return this.tryHarderCount; - } - - public getMaxMisreads(): number /*int*/ { - return this.maxMisreads; - } - - public getMaxTryHarderMisreads(): number /*int*/ { - return this.maxTryHarderMisreads; - } - - public getRotation(): number/*float*/ { - return this.rotation; - } + public constructor( + private mustPassCount: number /* int */, + private tryHarderCount: number /* int */, + private maxMisreads: number /* int */, + private maxTryHarderMisreads: number /* int */, + private rotation: number/* float */) { + } + + public getMustPassCount(): number /* int */ { + return this.mustPassCount; + } + + public getTryHarderCount(): number /* int */ { + return this.tryHarderCount; + } + + public getMaxMisreads(): number /* int */ { + return this.maxMisreads; + } + + public getMaxTryHarderMisreads(): number /* int */ { + return this.maxTryHarderMisreads; + } + + public getRotation(): number/* float */ { + return this.rotation; + } } diff --git a/src/test/core/common/detector/MathUtils.spec.ts b/src/test/core/common/detector/MathUtils.spec.ts index cb08ce4f..8ce6f69d 100644 --- a/src/test/core/common/detector/MathUtils.spec.ts +++ b/src/test/core/common/detector/MathUtils.spec.ts @@ -14,52 +14,52 @@ * limitations under the License. */ -/*package com.google.zxing.common.detector;*/ +/* package com.google.zxing.common.detector; */ import * as assert from 'assert'; import { MathUtils } from '@zxing/library'; describe('MathUtils', () => { - const EPSILON: number /*float*/ = 1.0E-8; + const EPSILON: number /* float */ = 1.0E-8; - it('testRound', () => { - assert.strictEqual(MathUtils.round(-1.0), -1); - assert.strictEqual(MathUtils.round(0.0), 0); - assert.strictEqual(MathUtils.round(1.0), 1); + it('testRound', () => { + assert.strictEqual(MathUtils.round(-1.0), -1); + assert.strictEqual(MathUtils.round(0.0), 0); + assert.strictEqual(MathUtils.round(1.0), 1); - assert.strictEqual(MathUtils.round(1.9), 2); - assert.strictEqual(MathUtils.round(2.1), 2); + assert.strictEqual(MathUtils.round(1.9), 2); + assert.strictEqual(MathUtils.round(2.1), 2); - assert.strictEqual(MathUtils.round(2.5), 3); + assert.strictEqual(MathUtils.round(2.5), 3); - assert.strictEqual(MathUtils.round(-1.9), -2); - assert.strictEqual(MathUtils.round(-2.1), -2); + assert.strictEqual(MathUtils.round(-1.9), -2); + assert.strictEqual(MathUtils.round(-2.1), -2); - assert.strictEqual(MathUtils.round(-2.5), -3); // This differs from Math.round() + assert.strictEqual(MathUtils.round(-2.5), -3); // This differs from Math.round() - assert.strictEqual(MathUtils.round(Number.MAX_SAFE_INTEGER), Number.MAX_SAFE_INTEGER); - assert.strictEqual(MathUtils.round(Number.MIN_SAFE_INTEGER), Number.MIN_SAFE_INTEGER); + assert.strictEqual(MathUtils.round(Number.MAX_SAFE_INTEGER), Number.MAX_SAFE_INTEGER); + assert.strictEqual(MathUtils.round(Number.MIN_SAFE_INTEGER), Number.MIN_SAFE_INTEGER); - assert.strictEqual(MathUtils.round(Number.POSITIVE_INFINITY), Number.MAX_SAFE_INTEGER); - assert.strictEqual(MathUtils.round(Number.NEGATIVE_INFINITY), Number.MIN_SAFE_INTEGER); + assert.strictEqual(MathUtils.round(Number.POSITIVE_INFINITY), Number.MAX_SAFE_INTEGER); + assert.strictEqual(MathUtils.round(Number.NEGATIVE_INFINITY), Number.MIN_SAFE_INTEGER); - assert.strictEqual(MathUtils.round(NaN), 0); - }); + assert.strictEqual(MathUtils.round(NaN), 0); + }); - it('testDistance', () => { - assert.strictEqual(Math.abs(MathUtils.distance(1.0, 2.0, 3.0, 4.0) - /*(float) */Math.sqrt(8.0)) < EPSILON, true); - assert.strictEqual(Math.abs(MathUtils.distance(1.0, 2.0, 1.0, 2.0) - 0.0) < EPSILON, true); + it('testDistance', () => { + assert.strictEqual(Math.abs(MathUtils.distance(1.0, 2.0, 3.0, 4.0) - /* (float) */Math.sqrt(8.0)) < EPSILON, true); + assert.strictEqual(Math.abs(MathUtils.distance(1.0, 2.0, 1.0, 2.0) - 0.0) < EPSILON, true); - assert.strictEqual(Math.abs(MathUtils.distance(1, 2, 3, 4) - /*(float) */Math.sqrt(8.0)) < EPSILON, true); - assert.strictEqual(Math.abs(MathUtils.distance(1, 2, 1, 2) - 0.0) < EPSILON, true); - }); + assert.strictEqual(Math.abs(MathUtils.distance(1, 2, 3, 4) - /* (float) */Math.sqrt(8.0)) < EPSILON, true); + assert.strictEqual(Math.abs(MathUtils.distance(1, 2, 1, 2) - 0.0) < EPSILON, true); + }); - it('testSum', () => { - assert.strictEqual(MathUtils.sum(Int32Array.from([])), 0); - assert.strictEqual(MathUtils.sum(Int32Array.from([1])), 1); - assert.strictEqual(MathUtils.sum(Int32Array.from([1, 3])), 4); - assert.strictEqual(MathUtils.sum(Int32Array.from([-1, 1])), 0); - }); + it('testSum', () => { + assert.strictEqual(MathUtils.sum(Int32Array.from([])), 0); + assert.strictEqual(MathUtils.sum(Int32Array.from([1])), 1); + assert.strictEqual(MathUtils.sum(Int32Array.from([1, 3])), 4); + assert.strictEqual(MathUtils.sum(Int32Array.from([-1, 1])), 0); + }); }); diff --git a/src/test/core/common/reedsolomon/ReedSolomon.spec.ts b/src/test/core/common/reedsolomon/ReedSolomon.spec.ts index d7d76172..f45f92ac 100644 --- a/src/test/core/common/reedsolomon/ReedSolomon.spec.ts +++ b/src/test/core/common/reedsolomon/ReedSolomon.spec.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -/*package com.google.zxing.common.reedsolomon;*/ +/* package com.google.zxing.common.reedsolomon; */ import * as assert from 'assert'; import { ZXingStringBuilder } from '@zxing/library'; -import Random from '../../../core/util/Random'; +import Random from '../../../core/util/Random'; import { ZXingSystem } from '@zxing/library'; import { GenericGF } from '@zxing/library'; import { ReedSolomonEncoder } from '@zxing/library'; import { ReedSolomonDecoder } from '@zxing/library'; -/*import java.util.Random;*/ +/* import java.util.Random; */ import { corrupt } from './ReedSolomonCorrupt'; @@ -33,589 +33,589 @@ import { corrupt } from './ReedSolomonCorrupt'; */ describe('ReedSolomonSpec', () => { - it('testDataMatrix 1 - real life test case', () => { - testEncodeDecode( - GenericGF.DATA_MATRIX_FIELD_256, - Int32Array.from([142, 164, 186]), - Int32Array.from([114, 25, 5, 88, 102]) - ); - }); - - it('testDataMatrix 2 - real life test case', () => { - testEncodeDecode( - GenericGF.DATA_MATRIX_FIELD_256, - Int32Array.from([ - 0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64, - 0x70, 0x65, 0x66, 0x2F, 0x68, 0x70, 0x70, 0x68, - 0x6D, 0x66, 0x2F, 0x64, 0x70, 0x6E, 0x30, 0x71, - 0x30, 0x7B, 0x79, 0x6A, 0x6F, 0x68, 0x30, 0x81, - 0xF0, 0x88, 0x1F, 0xB5 - ]), - Int32Array.from([ - 0x1C, 0x64, 0xEE, 0xEB, 0xD0, 0x1D, 0x00, 0x03, - 0xF0, 0x1C, 0xF1, 0xD0, 0x6D, 0x00, 0x98, 0xDA, - 0x80, 0x88, 0xBE, 0xFF, 0xB7, 0xFA, 0xA9, 0x95 - ]) - ); - }); - - it('testDataMatrix 3.1 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 10, 240); - }); - - it('testDataMatrix 3.2 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 128, 127); - }); - - it('testDataMatrix 3.3 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 220, 35); - }); - - it('testQRCode 1 - from example given in ISO 18004, Annex I', () => { - - // Test case from example given in ISO 18004, Annex I - testEncodeDecode( - GenericGF.QR_CODE_FIELD_256, - Int32Array.from([ - 0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, - 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11 - ]), - Int32Array.from([ - 0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, - 0x2C, 0x55 - ]) - ); - - }); - - it('testQRCode 2 - real life test case', () => { - testEncodeDecode( - GenericGF.QR_CODE_FIELD_256, - Int32Array.from([ - 0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F, - 0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50, 0x61, 0x67, - 0x65, 0x3B, 0x3B, 0x00, 0xEC, 0x11, 0xEC, 0x11, - 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11 - ]), - Int32Array.from([ - 0xD8, 0xB8, 0xEF, 0x14, 0xEC, 0xD0, 0xCC, 0x85, - 0x73, 0x40, 0x0B, 0xB5, 0x5A, 0xB8, 0x8B, 0x2E, - 0x08, 0x62 - ]) - ); - }); - - it('testQRCode 3.1 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 10, 240); - }); - - it('testQRCode 3.2 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 128, 127); - }); - - it('testQRCode 3.3 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 220, 35); - }); - - it('testAztec 1 - real life test case', () => { - testEncodeDecode( - GenericGF.AZTEC_PARAM, - Int32Array.from([0x5, 0x6]), - Int32Array.from([0x3, 0x2, 0xB, 0xB, 0x7]) - ); - }); - - it('testAztec 2 - real life test case', () => { - testEncodeDecode( - GenericGF.AZTEC_PARAM, - Int32Array.from([0x0, 0x0, 0x0, 0x9]), - Int32Array.from([0xA, 0xD, 0x8, 0x6, 0x5, 0x6]) - ); - }); - - it('testAztec 3 - real life test case', () => { - testEncodeDecode( - GenericGF.AZTEC_PARAM, - Int32Array.from([0x2, 0x8, 0x8, 0x7]), - Int32Array.from([0xE, 0xC, 0xA, 0x9, 0x6, 0x8]) - ); - }); - - it('testAztec 4 - real life test case', () => { - testEncodeDecode( - GenericGF.AZTEC_DATA_6, - Int32Array.from([0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B]), - Int32Array.from([0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14]) - ); - }); - - it('testAztec 5 - real life test case', () => { - testEncodeDecode( - GenericGF.AZTEC_DATA_8, - Int32Array.from([ - 0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6, - 0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA, 0xF8, 0xCE, - 0xB7, 0xDE, 0x88, 0x64, 0x29, 0x8E, 0x84, 0xA9, - 0x6C, 0x6B, 0x9F, 0x08, 0xCA, 0x74, 0xAD, 0xAF, - 0x8C, 0xEB, 0x7C, 0x10, 0xC8, 0x53, 0x1D, 0x09, - 0x52, 0xD8, 0xD7, 0x3E, 0x11, 0x94, 0xE9, 0x5B, - 0x5F, 0x19, 0xD6, 0xFB, 0xD1, 0x0C, 0x85, 0x31, - 0xD0, 0x95, 0x2D, 0x8D, 0x73, 0xE1, 0x19, 0x4E, - 0x95, 0xB5, 0xF1, 0x9D, 0x6F]), - Int32Array.from([ - 0x31, 0xD7, 0x04, 0x46, 0xB2, 0xC1, 0x06, 0x94, - 0x17, 0xE5, 0x0C, 0x2B, 0xA3, 0x99, 0x15, 0x7F, - 0x16, 0x3C, 0x66, 0xBA, 0x33, 0xD9, 0xE8, 0x87, - 0x86, 0xBB, 0x4B, 0x15, 0x4E, 0x4A, 0xDE, 0xD4, - 0xED, 0xA1, 0xF8, 0x47, 0x2A, 0x50, 0xA6, 0xBC, - 0x53, 0x7D, 0x29, 0xFE, 0x06, 0x49, 0xF3, 0x73, - 0x9F, 0xC1, 0x75]) - ); - }); - - it('testAztec 6 - real life test case', () => { - testEncodeDecode( - GenericGF.AZTEC_DATA_10, - Int32Array.from([ - 0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD, - 0x02E, 0x056, 0x26A, 0x281, 0x1C2, 0x1A6, 0x296, 0x045, - 0x041, 0x0AA, 0x095, 0x2CE, 0x003, 0x38F, 0x2CD, 0x1A2, - 0x036, 0x1AD, 0x04E, 0x090, 0x271, 0x0D3, 0x02E, 0x0D5, - 0x2D4, 0x032, 0x2CA, 0x281, 0x0AA, 0x04E, 0x024, 0x2D3, - 0x296, 0x281, 0x0E2, 0x08A, 0x1AA, 0x28A, 0x280, 0x07C, - 0x286, 0x0A1, 0x1D0, 0x1AD, 0x154, 0x032, 0x2C2, 0x1C1, - 0x145, 0x02B, 0x2D4, 0x2B0, 0x033, 0x2D5, 0x276, 0x1C1, - 0x282, 0x10A, 0x2B5, 0x154, 0x003, 0x385, 0x20F, 0x0C4, - 0x02D, 0x050, 0x266, 0x0D5, 0x033, 0x2D5, 0x276, 0x1C1, - 0x0D4, 0x2A0, 0x08F, 0x0C4, 0x024, 0x20F, 0x2E2, 0x1AD, - 0x154, 0x02E, 0x056, 0x26A, 0x281, 0x090, 0x1E5, 0x14E, - 0x0CF, 0x2B6, 0x1C1, 0x28A, 0x2A1, 0x04E, 0x0D5, 0x003, - 0x391, 0x122, 0x286, 0x1AD, 0x2D4, 0x028, 0x262, 0x2EA, - 0x0A2, 0x004, 0x176, 0x295, 0x201, 0x0D5, 0x024, 0x20F, - 0x116, 0x0C1, 0x056, 0x095, 0x213, 0x004, 0x1EA, 0x28A, - 0x02A, 0x234, 0x2CE, 0x037, 0x157, 0x0D3, 0x262, 0x026, - 0x262, 0x2A0, 0x086, 0x106, 0x2A1, 0x126, 0x1E5, 0x266, - 0x26A, 0x2A1, 0x0E6, 0x1AA, 0x281, 0x2B6, 0x271, 0x154, - 0x02F, 0x0C4, 0x02D, 0x213, 0x0CE, 0x003, 0x38F, 0x2CD, - 0x1A2, 0x036, 0x1B5, 0x26A, 0x086, 0x280, 0x086, 0x1AA, - 0x2A1, 0x226, 0x1AD, 0x0CF, 0x2A6, 0x292, 0x2C6, 0x022, - 0x1AA, 0x256, 0x0D5, 0x02D, 0x050, 0x266, 0x0D5, 0x004, - 0x176, 0x295, 0x201, 0x0D3, 0x055, 0x031, 0x2CD, 0x2EA, - 0x1E2, 0x261, 0x1EA, 0x28A, 0x004, 0x145, 0x026, 0x1A6, - 0x1C6, 0x1F5, 0x2CE, 0x034, 0x051, 0x146, 0x1E1, 0x0B0, - 0x1B0, 0x261, 0x0D5, 0x025, 0x142, 0x1C0, 0x07C, 0x0B0, - 0x1E6, 0x081, 0x044, 0x02F, 0x2CF, 0x081, 0x290, 0x0A2, - 0x1A6, 0x281, 0x0CD, 0x155, 0x031, 0x1A2, 0x086, 0x262, - 0x2A1, 0x0CD, 0x0CA, 0x0E6, 0x1E5, 0x003, 0x394, 0x0C5, - 0x030, 0x26F, 0x053, 0x0C1, 0x1B6, 0x095, 0x2D4, 0x030, - 0x26F, 0x053, 0x0C0, 0x07C, 0x2E6, 0x295, 0x143, 0x2CD, - 0x2CE, 0x037, 0x0C9, 0x144, 0x2CD, 0x040, 0x08E, 0x054, - 0x282, 0x022, 0x2A1, 0x229, 0x053, 0x0D5, 0x262, 0x027, - 0x26A, 0x1E8, 0x14D, 0x1A2, 0x004, 0x26A, 0x296, 0x281, - 0x176, 0x295, 0x201, 0x0E2, 0x2C4, 0x143, 0x2D4, 0x026, - 0x262, 0x2A0, 0x08F, 0x0C4, 0x031, 0x213, 0x2B5, 0x155, - 0x213, 0x02F, 0x143, 0x121, 0x2A6, 0x1AD, 0x2D4, 0x034, - 0x0C5, 0x026, 0x295, 0x003, 0x396, 0x2A1, 0x176, 0x295, - 0x201, 0x0AA, 0x04E, 0x004, 0x1B0, 0x070, 0x275, 0x154, - 0x026, 0x2C1, 0x2B3, 0x154, 0x2AA, 0x256, 0x0C1, 0x044, - 0x004, 0x23F - ]), - Int32Array.from([ - 0x379, 0x099, 0x348, 0x010, 0x090, 0x196, 0x09C, 0x1FF, - 0x1B0, 0x32D, 0x244, 0x0DE, 0x201, 0x386, 0x163, 0x11F, - 0x39B, 0x344, 0x3FE, 0x02F, 0x188, 0x113, 0x3D9, 0x102, - 0x04A, 0x2E1, 0x1D1, 0x18E, 0x077, 0x262, 0x241, 0x20D, - 0x1B8, 0x11D, 0x0D0, 0x0A5, 0x29C, 0x24D, 0x3E7, 0x006, - 0x2D0, 0x1B7, 0x337, 0x178, 0x0F1, 0x1E0, 0x00B, 0x01E, - 0x0DA, 0x1C6, 0x2D9, 0x00D, 0x28B, 0x34A, 0x252, 0x27A, - 0x057, 0x0CA, 0x2C2, 0x2E4, 0x3A6, 0x0E3, 0x22B, 0x307, - 0x174, 0x292, 0x10C, 0x1ED, 0x2FD, 0x2D4, 0x0A7, 0x051, - 0x34F, 0x07A, 0x1D5, 0x01D, 0x22E, 0x2C2, 0x1DF, 0x08F, - 0x105, 0x3FE, 0x286, 0x2A2, 0x3B1, 0x131, 0x285, 0x362, - 0x315, 0x13C, 0x0F9, 0x1A2, 0x28D, 0x246, 0x1B3, 0x12C, - 0x2AD, 0x0F8, 0x222, 0x0EC, 0x39F, 0x358, 0x014, 0x229, - 0x0C8, 0x360, 0x1C2, 0x031, 0x098, 0x041, 0x3E4, 0x046, - 0x332, 0x318, 0x2E3, 0x24E, 0x3E2, 0x1E1, 0x0BE, 0x239, - 0x306, 0x3A5, 0x352, 0x351, 0x275, 0x0ED, 0x045, 0x229, - 0x0BF, 0x05D, 0x253, 0x1BE, 0x02E, 0x35A, 0x0E4, 0x2E9, - 0x17A, 0x166, 0x03C, 0x007 - ]) - ); - }); - - it('testAztec 7 - real life test case', () => { - testEncodeDecode( - GenericGF.AZTEC_DATA_12, - Int32Array.from([ - 0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85, - 0x69A, 0xA81, 0x709, 0xA6A, 0x584, 0x510, 0x4AA, 0x256, - 0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xAD1, 0x389, 0x09C, - 0x4D3, 0x0B8, 0xD5B, 0x503, 0x2B2, 0xA81, 0x2A8, 0x4E0, - 0x92D, 0x3A5, 0xA81, 0x388, 0x8A6, 0xAA8, 0xAA0, 0x07C, - 0xA18, 0xA17, 0x41A, 0xD55, 0x032, 0xB09, 0xC15, 0x142, - 0xBB5, 0x2B0, 0x0CE, 0xD59, 0xD9C, 0x1A0, 0x90A, 0xAD5, - 0x540, 0x0F8, 0x583, 0xCC4, 0x0B4, 0x509, 0x98D, 0x50C, - 0xED5, 0x9D9, 0xC13, 0x52A, 0x023, 0xCC4, 0x092, 0x0FB, - 0x89A, 0xD55, 0x02E, 0x15A, 0x6AA, 0x049, 0x079, 0x54E, - 0x33E, 0xB67, 0x068, 0xAA8, 0x44E, 0x354, 0x03E, 0x452, - 0x2A1, 0x9AD, 0xB50, 0x289, 0x8AE, 0xA28, 0x804, 0x5DA, - 0x958, 0x04D, 0x509, 0x20F, 0x458, 0xC11, 0x589, 0x584, - 0xC04, 0x7AA, 0x8A0, 0xAA3, 0x4B3, 0x837, 0x55C, 0xD39, - 0x882, 0x698, 0xAA0, 0x219, 0x06A, 0x852, 0x679, 0x666, - 0x9AA, 0xA13, 0x99A, 0xAA0, 0x6B6, 0x9C5, 0x540, 0xBCC, - 0x40B, 0x613, 0x338, 0x03E, 0x3EC, 0xD68, 0x836, 0x6D6, - 0x6A2, 0x1A8, 0x021, 0x9AA, 0xA86, 0x266, 0xB4C, 0xFA9, - 0xA92, 0xB18, 0x226, 0xAA5, 0x635, 0x42D, 0x142, 0x663, - 0x540, 0x45D, 0xA95, 0x804, 0xD31, 0x543, 0x1B3, 0x6EA, - 0x78A, 0x617, 0xAA8, 0xA01, 0x145, 0x099, 0xA67, 0x19F, - 0x5B3, 0x834, 0x145, 0x467, 0x84B, 0x06C, 0x261, 0x354, - 0x255, 0x09C, 0x01F, 0x0B0, 0x798, 0x811, 0x102, 0xFB3, - 0xC81, 0xA40, 0xA26, 0x9A8, 0x133, 0x555, 0x0C5, 0xA22, - 0x1A6, 0x2A8, 0x4CD, 0x328, 0xE67, 0x940, 0x3E5, 0x0C5, - 0x0C2, 0x6F1, 0x4CC, 0x16D, 0x895, 0xB50, 0x309, 0xBC5, - 0x330, 0x07C, 0xB9A, 0x955, 0x0EC, 0xDB3, 0x837, 0x325, - 0x44B, 0x344, 0x023, 0x854, 0xA08, 0x22A, 0x862, 0x914, - 0xCD5, 0x988, 0x279, 0xA9E, 0x853, 0x5A2, 0x012, 0x6AA, - 0x5A8, 0x15D, 0xA95, 0x804, 0xE2B, 0x114, 0x3B5, 0x026, - 0x98A, 0xA02, 0x3CC, 0x40C, 0x613, 0xAD5, 0x558, 0x4C2, - 0xF50, 0xD21, 0xA99, 0xADB, 0x503, 0x431, 0x426, 0xA54, - 0x03E, 0x5AA, 0x15D, 0xA95, 0x804, 0xAA1, 0x380, 0x46C, - 0x070, 0x9D5, 0x540, 0x9AC, 0x1AC, 0xD54, 0xAAA, 0x563, - 0x044, 0x401, 0x220, 0x9F1, 0x4F0, 0xDAA, 0x170, 0x90F, - 0x106, 0xE66, 0x85C, 0x2B4, 0xD54, 0x0B8, 0x4D3, 0x52C, - 0x228, 0x825, 0x512, 0xB67, 0x007, 0xC7D, 0x9AD, 0x106, - 0xCD6, 0x89C, 0x484, 0xE26, 0x985, 0xC6A, 0xDA8, 0x195, - 0x954, 0x095, 0x427, 0x049, 0x69D, 0x2D4, 0x09C, 0x445, - 0x355, 0x455, 0x003, 0xE50, 0xC50, 0xBA0, 0xD6A, 0xA81, - 0x958, 0x4E0, 0xA8A, 0x15D, 0xA95, 0x806, 0x76A, 0xCEC, - 0xE0D, 0x048, 0x556, 0xAAA, 0x007, 0xC2C, 0x1E6, 0x205, - 0xA28, 0x4CC, 0x6A8, 0x676, 0xACE, 0xCE0, 0x9A9, 0x501, - 0x1E6, 0x204, 0x907, 0xDC4, 0xD6A, 0xA81, 0x70A, 0xD35, - 0x502, 0x483, 0xCAA, 0x719, 0xF5B, 0x383, 0x455, 0x422, - 0x71A, 0xA01, 0xF22, 0x915, 0x0CD, 0x6DA, 0x814, 0x4C5, - 0x751, 0x440, 0x22E, 0xD4A, 0xC02, 0x6A8, 0x490, 0x7A2, - 0xC60, 0x8AC, 0x4AC, 0x260, 0x23D, 0x545, 0x055, 0x1A5, - 0x9C1, 0xBAA, 0xE69, 0xCC4, 0x134, 0xC55, 0x010, 0xC83, - 0x542, 0x933, 0xCB3, 0x34D, 0x550, 0x9CC, 0xD55, 0x035, - 0xB4E, 0x2AA, 0x05E, 0x620, 0x5B0, 0x999, 0xC01, 0xF1F, - 0x66B, 0x441, 0xB36, 0xB35, 0x10D, 0x401, 0x0CD, 0x554, - 0x313, 0x35A, 0x67D, 0x4D4, 0x958, 0xC11, 0x355, 0x2B1, - 0xAA1, 0x68A, 0x133, 0x1AA, 0x022, 0xED4, 0xAC0, 0x269, - 0x8AA, 0x18D, 0x9B7, 0x53C, 0x530, 0xBD5, 0x450, 0x08A, - 0x284, 0xCD3, 0x38C, 0xFAD, 0x9C1, 0xA0A, 0x2A3, 0x3C2, - 0x583, 0x613, 0x09A, 0xA12, 0xA84, 0xE00, 0xF85, 0x83C, - 0xC40, 0x888, 0x17D, 0x9E4, 0x0D2, 0x051, 0x34D, 0x409, - 0x9AA, 0xA86, 0x2D1, 0x10D, 0x315, 0x426, 0x699, 0x473, - 0x3CA, 0x01F, 0x286, 0x286, 0x137, 0x8A6, 0x60B, 0x6C4, - 0xADA, 0x818, 0x4DE, 0x299, 0x803, 0xE5C, 0xD4A, 0xA87, - 0x66D, 0x9C1, 0xB99, 0x2A2, 0x59A, 0x201, 0x1C2, 0xA50, - 0x411, 0x543, 0x148, 0xA66, 0xACC, 0x413, 0xCD4, 0xF42, - 0x9AD, 0x100, 0x935, 0x52D, 0x40A, 0xED4, 0xAC0, 0x271, - 0x588, 0xA1D, 0xA81, 0x34C, 0x550, 0x11E, 0x620, 0x630, - 0x9D6, 0xAAA, 0xC26, 0x17A, 0x869, 0x0D4, 0xCD6, 0xDA8, - 0x1A1, 0x8A1, 0x352, 0xA01, 0xF2D, 0x50A, 0xED4, 0xAC0, - 0x255, 0x09C, 0x023, 0x603, 0x84E, 0xAAA, 0x04D, 0x60D, - 0x66A, 0xA55, 0x52B, 0x182, 0x220, 0x091, 0x00F, 0x8A7, - 0x86D, 0x50B, 0x848, 0x788, 0x373, 0x342, 0xE15, 0xA6A, - 0xA05, 0xC26, 0x9A9, 0x611, 0x441, 0x2A8, 0x95B, 0x380, - 0x3E3, 0xECD, 0x688, 0x366, 0xB44, 0xE24, 0x271, 0x34C, - 0x2E3, 0x56D, 0x40C, 0xACA, 0xA04, 0xAA1, 0x382, 0x4B4, - 0xE96, 0xA04, 0xE22, 0x29A, 0xAA2, 0xA80, 0x1F2, 0x862, - 0x85D, 0x06B, 0x554, 0x0CA, 0xC27, 0x054, 0x50A, 0xED4, - 0xAC0, 0x33B, 0x567, 0x670, 0x682, 0x42A, 0xB55, 0x500, - 0x3E1, 0x60F, 0x310, 0x2D1, 0x426, 0x635, 0x433, 0xB56, - 0x767, 0x04D, 0x4A8, 0x08F, 0x310, 0x248, 0x3EE, 0x26B, - 0x554, 0x0B8, 0x569, 0xAA8, 0x124, 0x1E5, 0x538, 0xCFA, - 0xD9C, 0x1A2, 0xAA1, 0x138, 0xD50, 0x0F9, 0x148, 0xA86, - 0x6B6, 0xD40, 0xA26, 0x2BA, 0x8A2, 0x011, 0x76A, 0x560, - 0x135, 0x424, 0x83D, 0x163, 0x045, 0x625, 0x613, 0x011, - 0xEAA, 0x282, 0xA8D, 0x2CE, 0x0DD, 0x573, 0x4E6, 0x209, - 0xA62, 0xA80, 0x864, 0x1AA, 0x149, 0x9E5, 0x99A, 0x6AA, - 0x84E, 0x66A, 0xA81, 0xADA, 0x715, 0x502, 0xF31, 0x02D, - 0x84C, 0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xB59, 0xA88, - 0x6A0, 0x086, 0x6AA, 0xA18, 0x99A, 0xD33, 0xEA6, 0xA4A, - 0xC60, 0x89A, 0xA95, 0x8D5, 0x0B4, 0x509, 0x98D, 0x501, - 0x176, 0xA56, 0x013, 0x4C5, 0x50C, 0x6CD, 0xBA9, 0xE29, - 0x85E, 0xAA2, 0x804, 0x514, 0x266, 0x99C, 0x67D, 0x6CE, - 0x0D0, 0x515, 0x19E, 0x12C, 0x1B0, 0x984, 0xD50, 0x954, - 0x270, 0x07C, 0x2C1, 0xE62, 0x044, 0x40B, 0xECF, 0x206, - 0x902, 0x89A, 0x6A0, 0x4CD, 0x554, 0x316, 0x888, 0x698, - 0xAA1, 0x334, 0xCA3, 0x99E, 0x500, 0xF94, 0x314, 0x309, - 0xBC5, 0x330, 0x5B6, 0x256, 0xD40, 0xC26, 0xF14, 0xCC0, - 0x1F2, 0xE6A, 0x554, 0x3B3, 0x6CE, 0x0DC, 0xC95, 0x12C, - 0xD10, 0x08E, 0x152, 0x820, 0x8AA, 0x18A, 0x453, 0x356, - 0x620, 0x9E6, 0xA7A, 0x14D, 0x688, 0x049, 0xAA9, 0x6A0, - 0x576, 0xA56, 0x013, 0x8AC, 0x450, 0xED4, 0x09A, 0x62A, - 0x808, 0xF31, 0x031, 0x84E, 0xB55, 0x561, 0x30B, 0xD43, - 0x486, 0xA66, 0xB6D, 0x40D, 0x0C5, 0x09A, 0x950, 0x0F9, - 0x6A8, 0x576, 0xA56, 0x012, 0xA84, 0xE01, 0x1B0, 0x1C2, - 0x755, 0x502, 0x6B0, 0x6B3, 0x552, 0xAA9, 0x58C, 0x111, - 0x004, 0x882, 0x7C5, 0x3C3, 0x6A8, 0x5C2, 0x43C, 0x41B, - 0x99A, 0x170, 0xAD3, 0x550, 0x2E1, 0x34D, 0x4B0, 0x8A2, - 0x095, 0x44A, 0xD9C, 0x01F, 0x1F6, 0x6B4, 0x41B, 0x35A, - 0x271, 0x213, 0x89A, 0x617, 0x1AB, 0x6A0, 0x656, 0x550, - 0x255, 0x09C, 0x125, 0xA74, 0xB50, 0x271, 0x114, 0xD55, - 0x154, 0x00F, 0x943, 0x142, 0xE83, 0x5AA, 0xA06, 0x561, - 0x382, 0xA28, 0x576, 0xA56, 0x019, 0xDAB, 0x3B3, 0x834, - 0x121, 0x55A, 0xAA8, 0x01F, 0x0B0, 0x798, 0x816, 0x8A1, - 0x331, 0xAA1, 0x9DA, 0xB3B, 0x382, 0x6A5, 0x404, 0x798, - 0x812, 0x41F, 0x713, 0x5AA, 0xA05, 0xC2B, 0x4D5, 0x409, - 0x20F, 0x2A9, 0xC67, 0xD6C, 0xE0D, 0x155, 0x089, 0xC6A, - 0x807, 0xC8A, 0x454, 0x335, 0xB6A, 0x051, 0x315, 0xD45, - 0x100, 0x8BB, 0x52B, 0x009, 0xAA1, 0x241, 0xE8B, 0x182, - 0x2B1, 0x2B0, 0x980, 0x8F5, 0x514, 0x154, 0x696, 0x706, - 0xEAB, 0x9A7, 0x310, 0x4D3, 0x154, 0x043, 0x20D, 0x50A, - 0x4CF, 0x2CC, 0xD35, 0x542, 0x733, 0x554, 0x0D6, 0xD38, - 0xAA8, 0x179, 0x881, 0x6C2, 0x667, 0x007, 0xC7D, 0x9AD, - 0x106, 0xCDA, 0xCD4, 0x435, 0x004, 0x335, 0x550, 0xC4C, - 0xD69, 0x9F5, 0x352, 0x563, 0x044, 0xD54, 0xAC6, 0xA85, - 0xA28, 0x4CC, 0x6A8, 0x08B, 0xB52, 0xB00, 0x9A6, 0x2A8, - 0x636, 0x6DD, 0x4F1, 0x4C2, 0xF55, 0x140, 0x228, 0xA13, - 0x34C, 0xE33, 0xEB6, 0x706, 0x828, 0xA8C, 0xF09, 0x60D, - 0x84C, 0x26A, 0x84A, 0xA13, 0x803, 0xE16, 0x0F3, 0x102, - 0x220, 0x5F6, 0x790, 0x348, 0x144, 0xD35, 0x026, 0x6AA, - 0xA18, 0xB44, 0x434, 0xC55, 0x099, 0xA65, 0x1CC, 0xF28, - 0x07C, 0xA18, 0xA18, 0x4DE, 0x299, 0x82D, 0xB12, 0xB6A, - 0x061, 0x378, 0xA66, 0x00F, 0x973, 0x52A, 0xA1D, 0x9B6, - 0x706, 0xE64, 0xA89, 0x668, 0x804, 0x70A, 0x941, 0x045, - 0x50C, 0x522, 0x99A, 0xB31, 0x04F, 0x353, 0xD0A, 0x6B4, - 0x402, 0x4D5, 0x4B5, 0x02B, 0xB52, 0xB00, 0x9C5, 0x622, - 0x876, 0xA04, 0xD31, 0x540, 0x479, 0x881, 0x8C2, 0x75A, - 0xAAB, 0x098, 0x5EA, 0x1A4, 0x353, 0x35B, 0x6A0, 0x686, - 0x284, 0xD4A, 0x807, 0xCB5, 0x42B, 0xB52, 0xB00, 0x954, - 0x270, 0x08D, 0x80E, 0x13A, 0xAA8, 0x135, 0x835, 0x9AA, - 0x801, 0xF14, 0xF0D, 0xAA1, 0x709, 0x0F1, 0x06E, 0x668, - 0x5C2, 0xB4D, 0x540, 0xB84, 0xD35, 0x2C2, 0x288, 0x255, - 0x12B, 0x670, 0x07C, 0x7D9, 0xAD1, 0x06C, 0xD68, 0x9C4, - 0x84E, 0x269, 0x85C, 0x6AD, 0xA81, 0x959, 0x540, 0x954, - 0x270, 0x496, 0x9D2, 0xD40, 0x9C4, 0x453, 0x554, 0x550, - 0x03E, 0x50C, 0x50B, 0xA0D, 0x6AA, 0x819, 0x584, 0xE0A, - 0x8A1, 0x5DA, 0x958, 0x067, 0x6AC, 0xECE, 0x0D0, 0x485, - 0x56A, 0xAA0, 0x07C, 0x2C1, 0xE62, 0x05A, 0x284, 0xCC6, - 0xA86, 0x76A, 0xCEC, 0xE09, 0xA95, 0x011, 0xE62, 0x049, - 0x07D, 0xC4D, 0x6AA, 0x817, 0x0AD, 0x355, 0x024, 0x83C, - 0xAA7, 0x19F, 0x5B3, 0x834, 0x554, 0x227, 0x1AA, 0x01F, - 0x229, 0x150, 0xCD6, 0xDA8, 0x144, 0xC57, 0x514, 0x402, - 0x2ED, 0x4AC, 0x026, 0xA84, 0x907, 0xA2C, 0x608, 0xAC4, - 0xAC2, 0x602, 0x3D5, 0x450, 0x551, 0xA59, 0xC1B, 0xAAE, - 0x69C, 0xC41, 0x34C, 0x550, 0x10C, 0x835, 0x429, 0x33C, - 0xB33, 0x4D5, 0x509, 0xCCD, 0x550, 0x35B, 0x4E2, 0xAA0, - 0x5E6, 0x205, 0xB09, 0x99C, 0x09F - ]), - Int32Array.from([ - 0xD54, 0x221, 0x154, 0x7CD, 0xBF3, 0x112, 0x89B, 0xC5E, - 0x9CD, 0x07E, 0xFB6, 0x78F, 0x7FA, 0x16F, 0x377, 0x4B4, - 0x62D, 0x475, 0xBC2, 0x861, 0xB72, 0x9D0, 0x76A, 0x5A1, - 0x22A, 0xF74, 0xDBA, 0x8B1, 0x139, 0xDCD, 0x012, 0x293, - 0x705, 0xA34, 0xDD5, 0x3D2, 0x7F8, 0x0A6, 0x89A, 0x346, - 0xCE0, 0x690, 0x40E, 0xFF3, 0xC4D, 0x97F, 0x9C9, 0x016, - 0x73A, 0x923, 0xBCE, 0xFA9, 0xE6A, 0xB92, 0x02A, 0x07C, - 0x04B, 0x8D5, 0x753, 0x42E, 0x67E, 0x87C, 0xEE6, 0xD7D, - 0x2BF, 0xFB2, 0xFF8, 0x42F, 0x4CB, 0x214, 0x779, 0x02D, - 0x606, 0xA02, 0x08A, 0xD4F, 0xB87, 0xDDF, 0xC49, 0xB51, - 0x0E9, 0xF89, 0xAEF, 0xC92, 0x383, 0x98D, 0x367, 0xBD3, - 0xA55, 0x148, 0x9DB, 0x913, 0xC79, 0x6FF, 0x387, 0x6EA, - 0x7FA, 0xC1B, 0x12D, 0x303, 0xBCA, 0x503, 0x0FB, 0xB14, - 0x0D4, 0xAD1, 0xAFC, 0x9DD, 0x404, 0x145, 0x6E5, 0x8ED, - 0xF94, 0xD72, 0x645, 0xA21, 0x1A8, 0xABF, 0xC03, 0x91E, - 0xD53, 0x48C, 0x471, 0x4E4, 0x408, 0x33C, 0x5DF, 0x73D, - 0xA2A, 0x454, 0xD77, 0xC48, 0x2F5, 0x96A, 0x9CF, 0x047, - 0x611, 0xE92, 0xC2F, 0xA98, 0x56D, 0x919, 0x615, 0x535, - 0x67A, 0x8C1, 0x2E2, 0xBC4, 0xBE8, 0x328, 0x04F, 0x257, - 0x3F9, 0xFA5, 0x477, 0x12E, 0x94B, 0x116, 0xEF7, 0x65F, - 0x6B3, 0x915, 0xC64, 0x9AF, 0xB6C, 0x6A2, 0x50D, 0xEA3, - 0x26E, 0xC23, 0x817, 0xA42, 0x71A, 0x9DD, 0xDA8, 0x84D, - 0x3F3, 0x85B, 0xB00, 0x1FC, 0xB0A, 0xC2F, 0x00C, 0x095, - 0xC58, 0x0E3, 0x807, 0x962, 0xC4B, 0x29A, 0x6FC, 0x958, - 0xD29, 0x59E, 0xB14, 0x95A, 0xEDE, 0xF3D, 0xFB8, 0x0E5, - 0x348, 0x2E7, 0x38E, 0x56A, 0x410, 0x3B1, 0x4B0, 0x793, - 0xAB7, 0x0BC, 0x648, 0x719, 0xE3E, 0xFB4, 0x3B4, 0xE5C, - 0x950, 0xD2A, 0x50B, 0x76F, 0x8D2, 0x3C7, 0xECC, 0x87C, - 0x53A, 0xBA7, 0x4C3, 0x148, 0x437, 0x820, 0xECD, 0x660, - 0x095, 0x2F4, 0x661, 0x6A4, 0xB74, 0x5F3, 0x1D2, 0x7EC, - 0x8E2, 0xA40, 0xA6F, 0xFC3, 0x3BE, 0x1E9, 0x52C, 0x233, - 0x173, 0x4EF, 0xA7C, 0x40B, 0x14C, 0x88D, 0xF30, 0x8D9, - 0xBDB, 0x0A6, 0x940, 0xD46, 0xB2B, 0x03E, 0x46A, 0x641, - 0xF08, 0xAFF, 0x496, 0x68A, 0x7A4, 0x0BA, 0xD43, 0x515, - 0xB26, 0xD8F, 0x05C, 0xD6E, 0xA2C, 0xF25, 0x628, 0x4E5, - 0x81D, 0xA2A, 0x1FF, 0x302, 0xFBD, 0x6D9, 0x711, 0xD8B, - 0xE5C, 0x5CF, 0x42E, 0x008, 0x863, 0xB6F, 0x1E1, 0x3DA, - 0xACE, 0x82B, 0x2DB, 0x7EB, 0xC15, 0x79F, 0xA79, 0xDAF, - 0x00D, 0x2F6, 0x0CE, 0x370, 0x7E8, 0x9E6, 0x89F, 0xAE9, - 0x175, 0xA95, 0x06B, 0x9DF, 0xAFF, 0x45B, 0x823, 0xAA4, - 0xC79, 0x773, 0x886, 0x854, 0x0A5, 0x6D1, 0xE55, 0xEBB, - 0x518, 0xE50, 0xF8F, 0x8CC, 0x834, 0x388, 0xCD2, 0xFC1, - 0xA55, 0x1F8, 0xD1F, 0xE08, 0xF93, 0x362, 0xA22, 0x9FA, - 0xCE5, 0x3C3, 0xDD4, 0xC53, 0xB94, 0xAD0, 0x6EB, 0x68D, - 0x660, 0x8FC, 0xBCD, 0x914, 0x16F, 0x4C0, 0x134, 0xE1A, - 0x76F, 0x9CB, 0x660, 0xEA0, 0x320, 0x15A, 0xCE3, 0x7E8, - 0x03E, 0xB9A, 0xC90, 0xA14, 0x256, 0x1A8, 0x639, 0x7C6, - 0xA59, 0xA65, 0x956, 0x9E4, 0x592, 0x6A9, 0xCFF, 0x4DC, - 0xAA3, 0xD2A, 0xFDE, 0xA87, 0xBF5, 0x9F0, 0xC32, 0x94F, - 0x675, 0x9A6, 0x369, 0x648, 0x289, 0x823, 0x498, 0x574, - 0x8D1, 0xA13, 0xD1A, 0xBB5, 0xA19, 0x7F7, 0x775, 0x138, - 0x949, 0xA4C, 0xE36, 0x126, 0xC85, 0xE05, 0xFEE, 0x962, - 0x36D, 0x08D, 0xC76, 0x1E1, 0x1EC, 0x8D7, 0x231, 0xB68, - 0x03C, 0x1DE, 0x7DF, 0x2B1, 0x09D, 0xC81, 0xDA4, 0x8F7, - 0x6B9, 0x947, 0x9B0 - ]) - ); - }); - - it('testAztec 8.1 - synthetic test cases (compact mode message)', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_PARAM, 2, 5); - }); - - it('testAztec 8.2 - synthetic test cases (full mode message)', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_PARAM, 4, 6); - }); - - it('testAztec 8.3 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_DATA_6, 10, 7); - }); - - it('testAztec 8.4 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_DATA_6, 20, 12); - }); - - it('testAztec 8.5 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_DATA_8, 20, 11); - }); - - it('testAztec 8.6 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_DATA_8, 128, 127); - }); - - it('testAztec 8.7 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_DATA_10, 128, 128); - }); - - it('testAztec 8.8 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_DATA_10, 768, 255); - }); - - it('testAztec 8.9 - synthetic test cases', () => { - testEncodeDecodeRandom(GenericGF.AZTEC_DATA_12, 3072, 1023); - }); + it('testDataMatrix 1 - real life test case', () => { + testEncodeDecode( + GenericGF.DATA_MATRIX_FIELD_256, + Int32Array.from([142, 164, 186]), + Int32Array.from([114, 25, 5, 88, 102]) + ); + }); + + it('testDataMatrix 2 - real life test case', () => { + testEncodeDecode( + GenericGF.DATA_MATRIX_FIELD_256, + Int32Array.from([ + 0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64, + 0x70, 0x65, 0x66, 0x2F, 0x68, 0x70, 0x70, 0x68, + 0x6D, 0x66, 0x2F, 0x64, 0x70, 0x6E, 0x30, 0x71, + 0x30, 0x7B, 0x79, 0x6A, 0x6F, 0x68, 0x30, 0x81, + 0xF0, 0x88, 0x1F, 0xB5 + ]), + Int32Array.from([ + 0x1C, 0x64, 0xEE, 0xEB, 0xD0, 0x1D, 0x00, 0x03, + 0xF0, 0x1C, 0xF1, 0xD0, 0x6D, 0x00, 0x98, 0xDA, + 0x80, 0x88, 0xBE, 0xFF, 0xB7, 0xFA, 0xA9, 0x95 + ]) + ); + }); + + it('testDataMatrix 3.1 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 10, 240); + }); + + it('testDataMatrix 3.2 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 128, 127); + }); + + it('testDataMatrix 3.3 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 220, 35); + }); + + it('testQRCode 1 - from example given in ISO 18004, Annex I', () => { + + // Test case from example given in ISO 18004, Annex I + testEncodeDecode( + GenericGF.QR_CODE_FIELD_256, + Int32Array.from([ + 0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, + 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11 + ]), + Int32Array.from([ + 0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, + 0x2C, 0x55 + ]) + ); + + }); + + it('testQRCode 2 - real life test case', () => { + testEncodeDecode( + GenericGF.QR_CODE_FIELD_256, + Int32Array.from([ + 0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F, + 0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50, 0x61, 0x67, + 0x65, 0x3B, 0x3B, 0x00, 0xEC, 0x11, 0xEC, 0x11, + 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11 + ]), + Int32Array.from([ + 0xD8, 0xB8, 0xEF, 0x14, 0xEC, 0xD0, 0xCC, 0x85, + 0x73, 0x40, 0x0B, 0xB5, 0x5A, 0xB8, 0x8B, 0x2E, + 0x08, 0x62 + ]) + ); + }); + + it('testQRCode 3.1 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 10, 240); + }); + + it('testQRCode 3.2 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 128, 127); + }); + + it('testQRCode 3.3 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 220, 35); + }); + + it('testAztec 1 - real life test case', () => { + testEncodeDecode( + GenericGF.AZTEC_PARAM, + Int32Array.from([0x5, 0x6]), + Int32Array.from([0x3, 0x2, 0xB, 0xB, 0x7]) + ); + }); + + it('testAztec 2 - real life test case', () => { + testEncodeDecode( + GenericGF.AZTEC_PARAM, + Int32Array.from([0x0, 0x0, 0x0, 0x9]), + Int32Array.from([0xA, 0xD, 0x8, 0x6, 0x5, 0x6]) + ); + }); + + it('testAztec 3 - real life test case', () => { + testEncodeDecode( + GenericGF.AZTEC_PARAM, + Int32Array.from([0x2, 0x8, 0x8, 0x7]), + Int32Array.from([0xE, 0xC, 0xA, 0x9, 0x6, 0x8]) + ); + }); + + it('testAztec 4 - real life test case', () => { + testEncodeDecode( + GenericGF.AZTEC_DATA_6, + Int32Array.from([0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B]), + Int32Array.from([0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14]) + ); + }); + + it('testAztec 5 - real life test case', () => { + testEncodeDecode( + GenericGF.AZTEC_DATA_8, + Int32Array.from([ + 0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6, + 0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA, 0xF8, 0xCE, + 0xB7, 0xDE, 0x88, 0x64, 0x29, 0x8E, 0x84, 0xA9, + 0x6C, 0x6B, 0x9F, 0x08, 0xCA, 0x74, 0xAD, 0xAF, + 0x8C, 0xEB, 0x7C, 0x10, 0xC8, 0x53, 0x1D, 0x09, + 0x52, 0xD8, 0xD7, 0x3E, 0x11, 0x94, 0xE9, 0x5B, + 0x5F, 0x19, 0xD6, 0xFB, 0xD1, 0x0C, 0x85, 0x31, + 0xD0, 0x95, 0x2D, 0x8D, 0x73, 0xE1, 0x19, 0x4E, + 0x95, 0xB5, 0xF1, 0x9D, 0x6F]), + Int32Array.from([ + 0x31, 0xD7, 0x04, 0x46, 0xB2, 0xC1, 0x06, 0x94, + 0x17, 0xE5, 0x0C, 0x2B, 0xA3, 0x99, 0x15, 0x7F, + 0x16, 0x3C, 0x66, 0xBA, 0x33, 0xD9, 0xE8, 0x87, + 0x86, 0xBB, 0x4B, 0x15, 0x4E, 0x4A, 0xDE, 0xD4, + 0xED, 0xA1, 0xF8, 0x47, 0x2A, 0x50, 0xA6, 0xBC, + 0x53, 0x7D, 0x29, 0xFE, 0x06, 0x49, 0xF3, 0x73, + 0x9F, 0xC1, 0x75]) + ); + }); + + it('testAztec 6 - real life test case', () => { + testEncodeDecode( + GenericGF.AZTEC_DATA_10, + Int32Array.from([ + 0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD, + 0x02E, 0x056, 0x26A, 0x281, 0x1C2, 0x1A6, 0x296, 0x045, + 0x041, 0x0AA, 0x095, 0x2CE, 0x003, 0x38F, 0x2CD, 0x1A2, + 0x036, 0x1AD, 0x04E, 0x090, 0x271, 0x0D3, 0x02E, 0x0D5, + 0x2D4, 0x032, 0x2CA, 0x281, 0x0AA, 0x04E, 0x024, 0x2D3, + 0x296, 0x281, 0x0E2, 0x08A, 0x1AA, 0x28A, 0x280, 0x07C, + 0x286, 0x0A1, 0x1D0, 0x1AD, 0x154, 0x032, 0x2C2, 0x1C1, + 0x145, 0x02B, 0x2D4, 0x2B0, 0x033, 0x2D5, 0x276, 0x1C1, + 0x282, 0x10A, 0x2B5, 0x154, 0x003, 0x385, 0x20F, 0x0C4, + 0x02D, 0x050, 0x266, 0x0D5, 0x033, 0x2D5, 0x276, 0x1C1, + 0x0D4, 0x2A0, 0x08F, 0x0C4, 0x024, 0x20F, 0x2E2, 0x1AD, + 0x154, 0x02E, 0x056, 0x26A, 0x281, 0x090, 0x1E5, 0x14E, + 0x0CF, 0x2B6, 0x1C1, 0x28A, 0x2A1, 0x04E, 0x0D5, 0x003, + 0x391, 0x122, 0x286, 0x1AD, 0x2D4, 0x028, 0x262, 0x2EA, + 0x0A2, 0x004, 0x176, 0x295, 0x201, 0x0D5, 0x024, 0x20F, + 0x116, 0x0C1, 0x056, 0x095, 0x213, 0x004, 0x1EA, 0x28A, + 0x02A, 0x234, 0x2CE, 0x037, 0x157, 0x0D3, 0x262, 0x026, + 0x262, 0x2A0, 0x086, 0x106, 0x2A1, 0x126, 0x1E5, 0x266, + 0x26A, 0x2A1, 0x0E6, 0x1AA, 0x281, 0x2B6, 0x271, 0x154, + 0x02F, 0x0C4, 0x02D, 0x213, 0x0CE, 0x003, 0x38F, 0x2CD, + 0x1A2, 0x036, 0x1B5, 0x26A, 0x086, 0x280, 0x086, 0x1AA, + 0x2A1, 0x226, 0x1AD, 0x0CF, 0x2A6, 0x292, 0x2C6, 0x022, + 0x1AA, 0x256, 0x0D5, 0x02D, 0x050, 0x266, 0x0D5, 0x004, + 0x176, 0x295, 0x201, 0x0D3, 0x055, 0x031, 0x2CD, 0x2EA, + 0x1E2, 0x261, 0x1EA, 0x28A, 0x004, 0x145, 0x026, 0x1A6, + 0x1C6, 0x1F5, 0x2CE, 0x034, 0x051, 0x146, 0x1E1, 0x0B0, + 0x1B0, 0x261, 0x0D5, 0x025, 0x142, 0x1C0, 0x07C, 0x0B0, + 0x1E6, 0x081, 0x044, 0x02F, 0x2CF, 0x081, 0x290, 0x0A2, + 0x1A6, 0x281, 0x0CD, 0x155, 0x031, 0x1A2, 0x086, 0x262, + 0x2A1, 0x0CD, 0x0CA, 0x0E6, 0x1E5, 0x003, 0x394, 0x0C5, + 0x030, 0x26F, 0x053, 0x0C1, 0x1B6, 0x095, 0x2D4, 0x030, + 0x26F, 0x053, 0x0C0, 0x07C, 0x2E6, 0x295, 0x143, 0x2CD, + 0x2CE, 0x037, 0x0C9, 0x144, 0x2CD, 0x040, 0x08E, 0x054, + 0x282, 0x022, 0x2A1, 0x229, 0x053, 0x0D5, 0x262, 0x027, + 0x26A, 0x1E8, 0x14D, 0x1A2, 0x004, 0x26A, 0x296, 0x281, + 0x176, 0x295, 0x201, 0x0E2, 0x2C4, 0x143, 0x2D4, 0x026, + 0x262, 0x2A0, 0x08F, 0x0C4, 0x031, 0x213, 0x2B5, 0x155, + 0x213, 0x02F, 0x143, 0x121, 0x2A6, 0x1AD, 0x2D4, 0x034, + 0x0C5, 0x026, 0x295, 0x003, 0x396, 0x2A1, 0x176, 0x295, + 0x201, 0x0AA, 0x04E, 0x004, 0x1B0, 0x070, 0x275, 0x154, + 0x026, 0x2C1, 0x2B3, 0x154, 0x2AA, 0x256, 0x0C1, 0x044, + 0x004, 0x23F + ]), + Int32Array.from([ + 0x379, 0x099, 0x348, 0x010, 0x090, 0x196, 0x09C, 0x1FF, + 0x1B0, 0x32D, 0x244, 0x0DE, 0x201, 0x386, 0x163, 0x11F, + 0x39B, 0x344, 0x3FE, 0x02F, 0x188, 0x113, 0x3D9, 0x102, + 0x04A, 0x2E1, 0x1D1, 0x18E, 0x077, 0x262, 0x241, 0x20D, + 0x1B8, 0x11D, 0x0D0, 0x0A5, 0x29C, 0x24D, 0x3E7, 0x006, + 0x2D0, 0x1B7, 0x337, 0x178, 0x0F1, 0x1E0, 0x00B, 0x01E, + 0x0DA, 0x1C6, 0x2D9, 0x00D, 0x28B, 0x34A, 0x252, 0x27A, + 0x057, 0x0CA, 0x2C2, 0x2E4, 0x3A6, 0x0E3, 0x22B, 0x307, + 0x174, 0x292, 0x10C, 0x1ED, 0x2FD, 0x2D4, 0x0A7, 0x051, + 0x34F, 0x07A, 0x1D5, 0x01D, 0x22E, 0x2C2, 0x1DF, 0x08F, + 0x105, 0x3FE, 0x286, 0x2A2, 0x3B1, 0x131, 0x285, 0x362, + 0x315, 0x13C, 0x0F9, 0x1A2, 0x28D, 0x246, 0x1B3, 0x12C, + 0x2AD, 0x0F8, 0x222, 0x0EC, 0x39F, 0x358, 0x014, 0x229, + 0x0C8, 0x360, 0x1C2, 0x031, 0x098, 0x041, 0x3E4, 0x046, + 0x332, 0x318, 0x2E3, 0x24E, 0x3E2, 0x1E1, 0x0BE, 0x239, + 0x306, 0x3A5, 0x352, 0x351, 0x275, 0x0ED, 0x045, 0x229, + 0x0BF, 0x05D, 0x253, 0x1BE, 0x02E, 0x35A, 0x0E4, 0x2E9, + 0x17A, 0x166, 0x03C, 0x007 + ]) + ); + }); + + it('testAztec 7 - real life test case', () => { + testEncodeDecode( + GenericGF.AZTEC_DATA_12, + Int32Array.from([ + 0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85, + 0x69A, 0xA81, 0x709, 0xA6A, 0x584, 0x510, 0x4AA, 0x256, + 0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xAD1, 0x389, 0x09C, + 0x4D3, 0x0B8, 0xD5B, 0x503, 0x2B2, 0xA81, 0x2A8, 0x4E0, + 0x92D, 0x3A5, 0xA81, 0x388, 0x8A6, 0xAA8, 0xAA0, 0x07C, + 0xA18, 0xA17, 0x41A, 0xD55, 0x032, 0xB09, 0xC15, 0x142, + 0xBB5, 0x2B0, 0x0CE, 0xD59, 0xD9C, 0x1A0, 0x90A, 0xAD5, + 0x540, 0x0F8, 0x583, 0xCC4, 0x0B4, 0x509, 0x98D, 0x50C, + 0xED5, 0x9D9, 0xC13, 0x52A, 0x023, 0xCC4, 0x092, 0x0FB, + 0x89A, 0xD55, 0x02E, 0x15A, 0x6AA, 0x049, 0x079, 0x54E, + 0x33E, 0xB67, 0x068, 0xAA8, 0x44E, 0x354, 0x03E, 0x452, + 0x2A1, 0x9AD, 0xB50, 0x289, 0x8AE, 0xA28, 0x804, 0x5DA, + 0x958, 0x04D, 0x509, 0x20F, 0x458, 0xC11, 0x589, 0x584, + 0xC04, 0x7AA, 0x8A0, 0xAA3, 0x4B3, 0x837, 0x55C, 0xD39, + 0x882, 0x698, 0xAA0, 0x219, 0x06A, 0x852, 0x679, 0x666, + 0x9AA, 0xA13, 0x99A, 0xAA0, 0x6B6, 0x9C5, 0x540, 0xBCC, + 0x40B, 0x613, 0x338, 0x03E, 0x3EC, 0xD68, 0x836, 0x6D6, + 0x6A2, 0x1A8, 0x021, 0x9AA, 0xA86, 0x266, 0xB4C, 0xFA9, + 0xA92, 0xB18, 0x226, 0xAA5, 0x635, 0x42D, 0x142, 0x663, + 0x540, 0x45D, 0xA95, 0x804, 0xD31, 0x543, 0x1B3, 0x6EA, + 0x78A, 0x617, 0xAA8, 0xA01, 0x145, 0x099, 0xA67, 0x19F, + 0x5B3, 0x834, 0x145, 0x467, 0x84B, 0x06C, 0x261, 0x354, + 0x255, 0x09C, 0x01F, 0x0B0, 0x798, 0x811, 0x102, 0xFB3, + 0xC81, 0xA40, 0xA26, 0x9A8, 0x133, 0x555, 0x0C5, 0xA22, + 0x1A6, 0x2A8, 0x4CD, 0x328, 0xE67, 0x940, 0x3E5, 0x0C5, + 0x0C2, 0x6F1, 0x4CC, 0x16D, 0x895, 0xB50, 0x309, 0xBC5, + 0x330, 0x07C, 0xB9A, 0x955, 0x0EC, 0xDB3, 0x837, 0x325, + 0x44B, 0x344, 0x023, 0x854, 0xA08, 0x22A, 0x862, 0x914, + 0xCD5, 0x988, 0x279, 0xA9E, 0x853, 0x5A2, 0x012, 0x6AA, + 0x5A8, 0x15D, 0xA95, 0x804, 0xE2B, 0x114, 0x3B5, 0x026, + 0x98A, 0xA02, 0x3CC, 0x40C, 0x613, 0xAD5, 0x558, 0x4C2, + 0xF50, 0xD21, 0xA99, 0xADB, 0x503, 0x431, 0x426, 0xA54, + 0x03E, 0x5AA, 0x15D, 0xA95, 0x804, 0xAA1, 0x380, 0x46C, + 0x070, 0x9D5, 0x540, 0x9AC, 0x1AC, 0xD54, 0xAAA, 0x563, + 0x044, 0x401, 0x220, 0x9F1, 0x4F0, 0xDAA, 0x170, 0x90F, + 0x106, 0xE66, 0x85C, 0x2B4, 0xD54, 0x0B8, 0x4D3, 0x52C, + 0x228, 0x825, 0x512, 0xB67, 0x007, 0xC7D, 0x9AD, 0x106, + 0xCD6, 0x89C, 0x484, 0xE26, 0x985, 0xC6A, 0xDA8, 0x195, + 0x954, 0x095, 0x427, 0x049, 0x69D, 0x2D4, 0x09C, 0x445, + 0x355, 0x455, 0x003, 0xE50, 0xC50, 0xBA0, 0xD6A, 0xA81, + 0x958, 0x4E0, 0xA8A, 0x15D, 0xA95, 0x806, 0x76A, 0xCEC, + 0xE0D, 0x048, 0x556, 0xAAA, 0x007, 0xC2C, 0x1E6, 0x205, + 0xA28, 0x4CC, 0x6A8, 0x676, 0xACE, 0xCE0, 0x9A9, 0x501, + 0x1E6, 0x204, 0x907, 0xDC4, 0xD6A, 0xA81, 0x70A, 0xD35, + 0x502, 0x483, 0xCAA, 0x719, 0xF5B, 0x383, 0x455, 0x422, + 0x71A, 0xA01, 0xF22, 0x915, 0x0CD, 0x6DA, 0x814, 0x4C5, + 0x751, 0x440, 0x22E, 0xD4A, 0xC02, 0x6A8, 0x490, 0x7A2, + 0xC60, 0x8AC, 0x4AC, 0x260, 0x23D, 0x545, 0x055, 0x1A5, + 0x9C1, 0xBAA, 0xE69, 0xCC4, 0x134, 0xC55, 0x010, 0xC83, + 0x542, 0x933, 0xCB3, 0x34D, 0x550, 0x9CC, 0xD55, 0x035, + 0xB4E, 0x2AA, 0x05E, 0x620, 0x5B0, 0x999, 0xC01, 0xF1F, + 0x66B, 0x441, 0xB36, 0xB35, 0x10D, 0x401, 0x0CD, 0x554, + 0x313, 0x35A, 0x67D, 0x4D4, 0x958, 0xC11, 0x355, 0x2B1, + 0xAA1, 0x68A, 0x133, 0x1AA, 0x022, 0xED4, 0xAC0, 0x269, + 0x8AA, 0x18D, 0x9B7, 0x53C, 0x530, 0xBD5, 0x450, 0x08A, + 0x284, 0xCD3, 0x38C, 0xFAD, 0x9C1, 0xA0A, 0x2A3, 0x3C2, + 0x583, 0x613, 0x09A, 0xA12, 0xA84, 0xE00, 0xF85, 0x83C, + 0xC40, 0x888, 0x17D, 0x9E4, 0x0D2, 0x051, 0x34D, 0x409, + 0x9AA, 0xA86, 0x2D1, 0x10D, 0x315, 0x426, 0x699, 0x473, + 0x3CA, 0x01F, 0x286, 0x286, 0x137, 0x8A6, 0x60B, 0x6C4, + 0xADA, 0x818, 0x4DE, 0x299, 0x803, 0xE5C, 0xD4A, 0xA87, + 0x66D, 0x9C1, 0xB99, 0x2A2, 0x59A, 0x201, 0x1C2, 0xA50, + 0x411, 0x543, 0x148, 0xA66, 0xACC, 0x413, 0xCD4, 0xF42, + 0x9AD, 0x100, 0x935, 0x52D, 0x40A, 0xED4, 0xAC0, 0x271, + 0x588, 0xA1D, 0xA81, 0x34C, 0x550, 0x11E, 0x620, 0x630, + 0x9D6, 0xAAA, 0xC26, 0x17A, 0x869, 0x0D4, 0xCD6, 0xDA8, + 0x1A1, 0x8A1, 0x352, 0xA01, 0xF2D, 0x50A, 0xED4, 0xAC0, + 0x255, 0x09C, 0x023, 0x603, 0x84E, 0xAAA, 0x04D, 0x60D, + 0x66A, 0xA55, 0x52B, 0x182, 0x220, 0x091, 0x00F, 0x8A7, + 0x86D, 0x50B, 0x848, 0x788, 0x373, 0x342, 0xE15, 0xA6A, + 0xA05, 0xC26, 0x9A9, 0x611, 0x441, 0x2A8, 0x95B, 0x380, + 0x3E3, 0xECD, 0x688, 0x366, 0xB44, 0xE24, 0x271, 0x34C, + 0x2E3, 0x56D, 0x40C, 0xACA, 0xA04, 0xAA1, 0x382, 0x4B4, + 0xE96, 0xA04, 0xE22, 0x29A, 0xAA2, 0xA80, 0x1F2, 0x862, + 0x85D, 0x06B, 0x554, 0x0CA, 0xC27, 0x054, 0x50A, 0xED4, + 0xAC0, 0x33B, 0x567, 0x670, 0x682, 0x42A, 0xB55, 0x500, + 0x3E1, 0x60F, 0x310, 0x2D1, 0x426, 0x635, 0x433, 0xB56, + 0x767, 0x04D, 0x4A8, 0x08F, 0x310, 0x248, 0x3EE, 0x26B, + 0x554, 0x0B8, 0x569, 0xAA8, 0x124, 0x1E5, 0x538, 0xCFA, + 0xD9C, 0x1A2, 0xAA1, 0x138, 0xD50, 0x0F9, 0x148, 0xA86, + 0x6B6, 0xD40, 0xA26, 0x2BA, 0x8A2, 0x011, 0x76A, 0x560, + 0x135, 0x424, 0x83D, 0x163, 0x045, 0x625, 0x613, 0x011, + 0xEAA, 0x282, 0xA8D, 0x2CE, 0x0DD, 0x573, 0x4E6, 0x209, + 0xA62, 0xA80, 0x864, 0x1AA, 0x149, 0x9E5, 0x99A, 0x6AA, + 0x84E, 0x66A, 0xA81, 0xADA, 0x715, 0x502, 0xF31, 0x02D, + 0x84C, 0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xB59, 0xA88, + 0x6A0, 0x086, 0x6AA, 0xA18, 0x99A, 0xD33, 0xEA6, 0xA4A, + 0xC60, 0x89A, 0xA95, 0x8D5, 0x0B4, 0x509, 0x98D, 0x501, + 0x176, 0xA56, 0x013, 0x4C5, 0x50C, 0x6CD, 0xBA9, 0xE29, + 0x85E, 0xAA2, 0x804, 0x514, 0x266, 0x99C, 0x67D, 0x6CE, + 0x0D0, 0x515, 0x19E, 0x12C, 0x1B0, 0x984, 0xD50, 0x954, + 0x270, 0x07C, 0x2C1, 0xE62, 0x044, 0x40B, 0xECF, 0x206, + 0x902, 0x89A, 0x6A0, 0x4CD, 0x554, 0x316, 0x888, 0x698, + 0xAA1, 0x334, 0xCA3, 0x99E, 0x500, 0xF94, 0x314, 0x309, + 0xBC5, 0x330, 0x5B6, 0x256, 0xD40, 0xC26, 0xF14, 0xCC0, + 0x1F2, 0xE6A, 0x554, 0x3B3, 0x6CE, 0x0DC, 0xC95, 0x12C, + 0xD10, 0x08E, 0x152, 0x820, 0x8AA, 0x18A, 0x453, 0x356, + 0x620, 0x9E6, 0xA7A, 0x14D, 0x688, 0x049, 0xAA9, 0x6A0, + 0x576, 0xA56, 0x013, 0x8AC, 0x450, 0xED4, 0x09A, 0x62A, + 0x808, 0xF31, 0x031, 0x84E, 0xB55, 0x561, 0x30B, 0xD43, + 0x486, 0xA66, 0xB6D, 0x40D, 0x0C5, 0x09A, 0x950, 0x0F9, + 0x6A8, 0x576, 0xA56, 0x012, 0xA84, 0xE01, 0x1B0, 0x1C2, + 0x755, 0x502, 0x6B0, 0x6B3, 0x552, 0xAA9, 0x58C, 0x111, + 0x004, 0x882, 0x7C5, 0x3C3, 0x6A8, 0x5C2, 0x43C, 0x41B, + 0x99A, 0x170, 0xAD3, 0x550, 0x2E1, 0x34D, 0x4B0, 0x8A2, + 0x095, 0x44A, 0xD9C, 0x01F, 0x1F6, 0x6B4, 0x41B, 0x35A, + 0x271, 0x213, 0x89A, 0x617, 0x1AB, 0x6A0, 0x656, 0x550, + 0x255, 0x09C, 0x125, 0xA74, 0xB50, 0x271, 0x114, 0xD55, + 0x154, 0x00F, 0x943, 0x142, 0xE83, 0x5AA, 0xA06, 0x561, + 0x382, 0xA28, 0x576, 0xA56, 0x019, 0xDAB, 0x3B3, 0x834, + 0x121, 0x55A, 0xAA8, 0x01F, 0x0B0, 0x798, 0x816, 0x8A1, + 0x331, 0xAA1, 0x9DA, 0xB3B, 0x382, 0x6A5, 0x404, 0x798, + 0x812, 0x41F, 0x713, 0x5AA, 0xA05, 0xC2B, 0x4D5, 0x409, + 0x20F, 0x2A9, 0xC67, 0xD6C, 0xE0D, 0x155, 0x089, 0xC6A, + 0x807, 0xC8A, 0x454, 0x335, 0xB6A, 0x051, 0x315, 0xD45, + 0x100, 0x8BB, 0x52B, 0x009, 0xAA1, 0x241, 0xE8B, 0x182, + 0x2B1, 0x2B0, 0x980, 0x8F5, 0x514, 0x154, 0x696, 0x706, + 0xEAB, 0x9A7, 0x310, 0x4D3, 0x154, 0x043, 0x20D, 0x50A, + 0x4CF, 0x2CC, 0xD35, 0x542, 0x733, 0x554, 0x0D6, 0xD38, + 0xAA8, 0x179, 0x881, 0x6C2, 0x667, 0x007, 0xC7D, 0x9AD, + 0x106, 0xCDA, 0xCD4, 0x435, 0x004, 0x335, 0x550, 0xC4C, + 0xD69, 0x9F5, 0x352, 0x563, 0x044, 0xD54, 0xAC6, 0xA85, + 0xA28, 0x4CC, 0x6A8, 0x08B, 0xB52, 0xB00, 0x9A6, 0x2A8, + 0x636, 0x6DD, 0x4F1, 0x4C2, 0xF55, 0x140, 0x228, 0xA13, + 0x34C, 0xE33, 0xEB6, 0x706, 0x828, 0xA8C, 0xF09, 0x60D, + 0x84C, 0x26A, 0x84A, 0xA13, 0x803, 0xE16, 0x0F3, 0x102, + 0x220, 0x5F6, 0x790, 0x348, 0x144, 0xD35, 0x026, 0x6AA, + 0xA18, 0xB44, 0x434, 0xC55, 0x099, 0xA65, 0x1CC, 0xF28, + 0x07C, 0xA18, 0xA18, 0x4DE, 0x299, 0x82D, 0xB12, 0xB6A, + 0x061, 0x378, 0xA66, 0x00F, 0x973, 0x52A, 0xA1D, 0x9B6, + 0x706, 0xE64, 0xA89, 0x668, 0x804, 0x70A, 0x941, 0x045, + 0x50C, 0x522, 0x99A, 0xB31, 0x04F, 0x353, 0xD0A, 0x6B4, + 0x402, 0x4D5, 0x4B5, 0x02B, 0xB52, 0xB00, 0x9C5, 0x622, + 0x876, 0xA04, 0xD31, 0x540, 0x479, 0x881, 0x8C2, 0x75A, + 0xAAB, 0x098, 0x5EA, 0x1A4, 0x353, 0x35B, 0x6A0, 0x686, + 0x284, 0xD4A, 0x807, 0xCB5, 0x42B, 0xB52, 0xB00, 0x954, + 0x270, 0x08D, 0x80E, 0x13A, 0xAA8, 0x135, 0x835, 0x9AA, + 0x801, 0xF14, 0xF0D, 0xAA1, 0x709, 0x0F1, 0x06E, 0x668, + 0x5C2, 0xB4D, 0x540, 0xB84, 0xD35, 0x2C2, 0x288, 0x255, + 0x12B, 0x670, 0x07C, 0x7D9, 0xAD1, 0x06C, 0xD68, 0x9C4, + 0x84E, 0x269, 0x85C, 0x6AD, 0xA81, 0x959, 0x540, 0x954, + 0x270, 0x496, 0x9D2, 0xD40, 0x9C4, 0x453, 0x554, 0x550, + 0x03E, 0x50C, 0x50B, 0xA0D, 0x6AA, 0x819, 0x584, 0xE0A, + 0x8A1, 0x5DA, 0x958, 0x067, 0x6AC, 0xECE, 0x0D0, 0x485, + 0x56A, 0xAA0, 0x07C, 0x2C1, 0xE62, 0x05A, 0x284, 0xCC6, + 0xA86, 0x76A, 0xCEC, 0xE09, 0xA95, 0x011, 0xE62, 0x049, + 0x07D, 0xC4D, 0x6AA, 0x817, 0x0AD, 0x355, 0x024, 0x83C, + 0xAA7, 0x19F, 0x5B3, 0x834, 0x554, 0x227, 0x1AA, 0x01F, + 0x229, 0x150, 0xCD6, 0xDA8, 0x144, 0xC57, 0x514, 0x402, + 0x2ED, 0x4AC, 0x026, 0xA84, 0x907, 0xA2C, 0x608, 0xAC4, + 0xAC2, 0x602, 0x3D5, 0x450, 0x551, 0xA59, 0xC1B, 0xAAE, + 0x69C, 0xC41, 0x34C, 0x550, 0x10C, 0x835, 0x429, 0x33C, + 0xB33, 0x4D5, 0x509, 0xCCD, 0x550, 0x35B, 0x4E2, 0xAA0, + 0x5E6, 0x205, 0xB09, 0x99C, 0x09F + ]), + Int32Array.from([ + 0xD54, 0x221, 0x154, 0x7CD, 0xBF3, 0x112, 0x89B, 0xC5E, + 0x9CD, 0x07E, 0xFB6, 0x78F, 0x7FA, 0x16F, 0x377, 0x4B4, + 0x62D, 0x475, 0xBC2, 0x861, 0xB72, 0x9D0, 0x76A, 0x5A1, + 0x22A, 0xF74, 0xDBA, 0x8B1, 0x139, 0xDCD, 0x012, 0x293, + 0x705, 0xA34, 0xDD5, 0x3D2, 0x7F8, 0x0A6, 0x89A, 0x346, + 0xCE0, 0x690, 0x40E, 0xFF3, 0xC4D, 0x97F, 0x9C9, 0x016, + 0x73A, 0x923, 0xBCE, 0xFA9, 0xE6A, 0xB92, 0x02A, 0x07C, + 0x04B, 0x8D5, 0x753, 0x42E, 0x67E, 0x87C, 0xEE6, 0xD7D, + 0x2BF, 0xFB2, 0xFF8, 0x42F, 0x4CB, 0x214, 0x779, 0x02D, + 0x606, 0xA02, 0x08A, 0xD4F, 0xB87, 0xDDF, 0xC49, 0xB51, + 0x0E9, 0xF89, 0xAEF, 0xC92, 0x383, 0x98D, 0x367, 0xBD3, + 0xA55, 0x148, 0x9DB, 0x913, 0xC79, 0x6FF, 0x387, 0x6EA, + 0x7FA, 0xC1B, 0x12D, 0x303, 0xBCA, 0x503, 0x0FB, 0xB14, + 0x0D4, 0xAD1, 0xAFC, 0x9DD, 0x404, 0x145, 0x6E5, 0x8ED, + 0xF94, 0xD72, 0x645, 0xA21, 0x1A8, 0xABF, 0xC03, 0x91E, + 0xD53, 0x48C, 0x471, 0x4E4, 0x408, 0x33C, 0x5DF, 0x73D, + 0xA2A, 0x454, 0xD77, 0xC48, 0x2F5, 0x96A, 0x9CF, 0x047, + 0x611, 0xE92, 0xC2F, 0xA98, 0x56D, 0x919, 0x615, 0x535, + 0x67A, 0x8C1, 0x2E2, 0xBC4, 0xBE8, 0x328, 0x04F, 0x257, + 0x3F9, 0xFA5, 0x477, 0x12E, 0x94B, 0x116, 0xEF7, 0x65F, + 0x6B3, 0x915, 0xC64, 0x9AF, 0xB6C, 0x6A2, 0x50D, 0xEA3, + 0x26E, 0xC23, 0x817, 0xA42, 0x71A, 0x9DD, 0xDA8, 0x84D, + 0x3F3, 0x85B, 0xB00, 0x1FC, 0xB0A, 0xC2F, 0x00C, 0x095, + 0xC58, 0x0E3, 0x807, 0x962, 0xC4B, 0x29A, 0x6FC, 0x958, + 0xD29, 0x59E, 0xB14, 0x95A, 0xEDE, 0xF3D, 0xFB8, 0x0E5, + 0x348, 0x2E7, 0x38E, 0x56A, 0x410, 0x3B1, 0x4B0, 0x793, + 0xAB7, 0x0BC, 0x648, 0x719, 0xE3E, 0xFB4, 0x3B4, 0xE5C, + 0x950, 0xD2A, 0x50B, 0x76F, 0x8D2, 0x3C7, 0xECC, 0x87C, + 0x53A, 0xBA7, 0x4C3, 0x148, 0x437, 0x820, 0xECD, 0x660, + 0x095, 0x2F4, 0x661, 0x6A4, 0xB74, 0x5F3, 0x1D2, 0x7EC, + 0x8E2, 0xA40, 0xA6F, 0xFC3, 0x3BE, 0x1E9, 0x52C, 0x233, + 0x173, 0x4EF, 0xA7C, 0x40B, 0x14C, 0x88D, 0xF30, 0x8D9, + 0xBDB, 0x0A6, 0x940, 0xD46, 0xB2B, 0x03E, 0x46A, 0x641, + 0xF08, 0xAFF, 0x496, 0x68A, 0x7A4, 0x0BA, 0xD43, 0x515, + 0xB26, 0xD8F, 0x05C, 0xD6E, 0xA2C, 0xF25, 0x628, 0x4E5, + 0x81D, 0xA2A, 0x1FF, 0x302, 0xFBD, 0x6D9, 0x711, 0xD8B, + 0xE5C, 0x5CF, 0x42E, 0x008, 0x863, 0xB6F, 0x1E1, 0x3DA, + 0xACE, 0x82B, 0x2DB, 0x7EB, 0xC15, 0x79F, 0xA79, 0xDAF, + 0x00D, 0x2F6, 0x0CE, 0x370, 0x7E8, 0x9E6, 0x89F, 0xAE9, + 0x175, 0xA95, 0x06B, 0x9DF, 0xAFF, 0x45B, 0x823, 0xAA4, + 0xC79, 0x773, 0x886, 0x854, 0x0A5, 0x6D1, 0xE55, 0xEBB, + 0x518, 0xE50, 0xF8F, 0x8CC, 0x834, 0x388, 0xCD2, 0xFC1, + 0xA55, 0x1F8, 0xD1F, 0xE08, 0xF93, 0x362, 0xA22, 0x9FA, + 0xCE5, 0x3C3, 0xDD4, 0xC53, 0xB94, 0xAD0, 0x6EB, 0x68D, + 0x660, 0x8FC, 0xBCD, 0x914, 0x16F, 0x4C0, 0x134, 0xE1A, + 0x76F, 0x9CB, 0x660, 0xEA0, 0x320, 0x15A, 0xCE3, 0x7E8, + 0x03E, 0xB9A, 0xC90, 0xA14, 0x256, 0x1A8, 0x639, 0x7C6, + 0xA59, 0xA65, 0x956, 0x9E4, 0x592, 0x6A9, 0xCFF, 0x4DC, + 0xAA3, 0xD2A, 0xFDE, 0xA87, 0xBF5, 0x9F0, 0xC32, 0x94F, + 0x675, 0x9A6, 0x369, 0x648, 0x289, 0x823, 0x498, 0x574, + 0x8D1, 0xA13, 0xD1A, 0xBB5, 0xA19, 0x7F7, 0x775, 0x138, + 0x949, 0xA4C, 0xE36, 0x126, 0xC85, 0xE05, 0xFEE, 0x962, + 0x36D, 0x08D, 0xC76, 0x1E1, 0x1EC, 0x8D7, 0x231, 0xB68, + 0x03C, 0x1DE, 0x7DF, 0x2B1, 0x09D, 0xC81, 0xDA4, 0x8F7, + 0x6B9, 0x947, 0x9B0 + ]) + ); + }); + + it('testAztec 8.1 - synthetic test cases (compact mode message)', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_PARAM, 2, 5); + }); + + it('testAztec 8.2 - synthetic test cases (full mode message)', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_PARAM, 4, 6); + }); + + it('testAztec 8.3 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_DATA_6, 10, 7); + }); + + it('testAztec 8.4 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_DATA_6, 20, 12); + }); + + it('testAztec 8.5 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_DATA_8, 20, 11); + }); + + it('testAztec 8.6 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_DATA_8, 128, 127); + }); + + it('testAztec 8.7 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_DATA_10, 128, 128); + }); + + it('testAztec 8.8 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_DATA_10, 768, 255); + }); + + it('testAztec 8.9 - synthetic test cases', () => { + testEncodeDecodeRandom(GenericGF.AZTEC_DATA_12, 3072, 1023); + }); }); -const DECODER_RANDOM_TEST_ITERATIONS: number /*int*/ = 3; -const DECODER_TEST_ITERATIONS: number /*int*/ = 10; - -function testEncodeDecodeRandom(field: GenericGF, dataSize: number /*int*/, ecSize: number /*int*/): void { - - assert.strictEqual(dataSize > 0 && dataSize <= field.getSize() - 3, true, 'Invalid data size for ' + field); - assert.strictEqual(ecSize > 0 && ecSize + dataSize <= field.getSize(), true, 'Invalid ECC size for ' + field); - - const encoder = new ReedSolomonEncoder(field); - const message = new Int32Array(dataSize + ecSize); - const dataWords = new Int32Array(dataSize); /*Int32Array(dataSize)*/ - const ecWords = new Int32Array(ecSize); /*Int32Array(ecSize)*/ - const random: Random = getPseudoRandom(); - const iterations: number /*int*/ = field.getSize() > 256 ? 1 : DECODER_RANDOM_TEST_ITERATIONS; - - for (let i: number /*int*/ = 0; i < iterations; i++) { - // generate random data - for (let k: number /*int*/ = 0; k < dataSize; k++) { - dataWords[k] = random.next(field.getSize()); - } - // generate ECC words - ZXingSystem.arraycopy(dataWords, 0, message, 0, dataWords.length); - encoder.encode(message, ecWords.length); - ZXingSystem.arraycopy(message, dataSize, ecWords, 0, ecSize); - // check to see if Decoder can fix up to ecWords/2 random errors - testDecoder(field, dataWords, ecWords); +const DECODER_RANDOM_TEST_ITERATIONS: number /* int */ = 3; +const DECODER_TEST_ITERATIONS: number /* int */ = 10; + +function testEncodeDecodeRandom(field: GenericGF, dataSize: number /* int */, ecSize: number /* int */): void { + + assert.strictEqual(dataSize > 0 && dataSize <= field.getSize() - 3, true, 'Invalid data size for ' + field); + assert.strictEqual(ecSize > 0 && ecSize + dataSize <= field.getSize(), true, 'Invalid ECC size for ' + field); + + const encoder = new ReedSolomonEncoder(field); + const message = new Int32Array(dataSize + ecSize); + const dataWords = new Int32Array(dataSize); /* Int32Array(dataSize) */ + const ecWords = new Int32Array(ecSize); /* Int32Array(ecSize) */ + const random: Random = getPseudoRandom(); + const iterations: number /* int */ = field.getSize() > 256 ? 1 : DECODER_RANDOM_TEST_ITERATIONS; + + for (let i: number /* int */ = 0; i < iterations; i++) { + // generate random data + for (let k: number /* int */ = 0; k < dataSize; k++) { + dataWords[k] = random.next(field.getSize()); } + // generate ECC words + ZXingSystem.arraycopy(dataWords, 0, message, 0, dataWords.length); + encoder.encode(message, ecWords.length); + ZXingSystem.arraycopy(message, dataSize, ecWords, 0, ecSize); + // check to see if Decoder can fix up to ecWords/2 random errors + testDecoder(field, dataWords, ecWords); + } } function testEncodeDecode(field: GenericGF, dataWords: Int32Array, ecWords: Int32Array): void { - testEncoder(field, dataWords, ecWords); - testDecoder(field, dataWords, ecWords); + testEncoder(field, dataWords, ecWords); + testDecoder(field, dataWords, ecWords); } function testEncoder(field: GenericGF, dataWords: Int32Array, ecWords: Int32Array): void { - const encoder = new ReedSolomonEncoder(field); - const messageExpected = new Int32Array(dataWords.length + ecWords.length); - const message = new Int32Array(dataWords.length + ecWords.length); + const encoder = new ReedSolomonEncoder(field); + const messageExpected = new Int32Array(dataWords.length + ecWords.length); + const message = new Int32Array(dataWords.length + ecWords.length); - ZXingSystem.arraycopy(dataWords, 0, messageExpected, 0, dataWords.length); - ZXingSystem.arraycopy(ecWords, 0, messageExpected, dataWords.length, ecWords.length); - ZXingSystem.arraycopy(dataWords, 0, message, 0, dataWords.length); + ZXingSystem.arraycopy(dataWords, 0, messageExpected, 0, dataWords.length); + ZXingSystem.arraycopy(ecWords, 0, messageExpected, dataWords.length, ecWords.length); + ZXingSystem.arraycopy(dataWords, 0, message, 0, dataWords.length); - encoder.encode(message, ecWords.length); + encoder.encode(message, ecWords.length); - assertDataEquals(message, messageExpected, 'Encode in ' + field + ' (' + dataWords.length + ',' + ecWords.length + ') failed'); + assertDataEquals(message, messageExpected, 'Encode in ' + field + ' (' + dataWords.length + ',' + ecWords.length + ') failed'); } function testDecoder(field: GenericGF, dataWords: Int32Array, ecWords: Int32Array): void { - const decoder = new ReedSolomonDecoder(field); - const message = new Int32Array(dataWords.length + ecWords.length); - const maxErrors: number /*int*/ = Math.floor(ecWords.length / 2); - const random: Random = getPseudoRandom(); - const iterations: number /*int*/ = field.getSize() > 256 ? 1 : DECODER_TEST_ITERATIONS; - - for (let j: number /*int*/ = 0; j < iterations; j++) { - for (let i: number /*int*/ = 0; i < ecWords.length; i++) { - - if (i > 10 && i < Math.floor(ecWords.length / 2) - 10) { - // performance improvement - skip intermediate cases in long-running tests - i += Math.floor(ecWords.length / 10); - } - - ZXingSystem.arraycopy(dataWords, 0, message, 0, dataWords.length); - ZXingSystem.arraycopy(ecWords, 0, message, dataWords.length, ecWords.length); - - corrupt(message, i, random, field.getSize()); - - try { - decoder.decode(message, ecWords.length); - } catch (e/*ReedSolomonException e*/) { - // fail only if maxErrors exceeded - assert.strictEqual(i > maxErrors, true, - 'Decode in ' + field + ' (' + dataWords.length + ',' + ecWords.length + ') failed at ' + i + ' errors: ' + e); - // else stop - break; - } - - if (i < maxErrors) { - assertDataEquals(message, - dataWords, - 'Decode in ' + field + ' (' + dataWords.length + ',' + ecWords.length + ') failed at ' + i + ' errors'); - } - } + const decoder = new ReedSolomonDecoder(field); + const message = new Int32Array(dataWords.length + ecWords.length); + const maxErrors: number /* int */ = Math.floor(ecWords.length / 2); + const random: Random = getPseudoRandom(); + const iterations: number /* int */ = field.getSize() > 256 ? 1 : DECODER_TEST_ITERATIONS; + + for (let j: number /* int */ = 0; j < iterations; j++) { + for (let i: number /* int */ = 0; i < ecWords.length; i++) { + + if (i > 10 && i < Math.floor(ecWords.length / 2) - 10) { + // performance improvement - skip intermediate cases in long-running tests + i += Math.floor(ecWords.length / 10); + } + + ZXingSystem.arraycopy(dataWords, 0, message, 0, dataWords.length); + ZXingSystem.arraycopy(ecWords, 0, message, dataWords.length, ecWords.length); + + corrupt(message, i, random, field.getSize()); + + try { + decoder.decode(message, ecWords.length); + } catch (e/* ReedSolomonException e */) { + // fail only if maxErrors exceeded + assert.strictEqual(i > maxErrors, true, + 'Decode in ' + field + ' (' + dataWords.length + ',' + ecWords.length + ') failed at ' + i + ' errors: ' + e); + // else stop + break; + } + + if (i < maxErrors) { + assertDataEquals(message, + dataWords, + 'Decode in ' + field + ' (' + dataWords.length + ',' + ecWords.length + ') failed at ' + i + ' errors'); + } } + } } function assertDataEquals(received: Int32Array, expected: Int32Array, message: string): void { - for (let i: number /*int*/ = 0; i < expected.length; i++) { - if (expected[i] !== received[i]) { + for (let i: number /* int */ = 0; i < expected.length; i++) { + if (expected[i] !== received[i]) { - const receivedToString = arrayToString(Int32Array.from(received.subarray(0, expected.length))); + const receivedToString = arrayToString(Int32Array.from(received.subarray(0, expected.length))); - assert.ok(false, `${message}. Mismatch at ${i}. Expected ${arrayToString(expected)}, got ${receivedToString}`); - } + assert.ok(false, `${message}. Mismatch at ${i}. Expected ${arrayToString(expected)}, got ${receivedToString}`); } + } } function arrayToString(data: Int32Array): String { - const sb = new ZXingStringBuilder(); + const sb = new ZXingStringBuilder(); - sb.append('{'); + sb.append('{'); - for (let i: number /*int*/ = 0; i < data.length; i++) { - if (i > 0) { - sb.append(','); - } - sb.append(data[i].toString(16)); + for (let i: number /* int */ = 0; i < data.length; i++) { + if (i > 0) { + sb.append(','); } + sb.append(data[i].toString(16)); + } - return sb.append('}').toString(); + return sb.append('}').toString(); } function getPseudoRandom(): Random { - return new Random('0xDEADBEEF'); + return new Random('0xDEADBEEF'); } diff --git a/src/test/core/common/reedsolomon/ReedSolomonCorrupt.ts b/src/test/core/common/reedsolomon/ReedSolomonCorrupt.ts index d874fada..3aeeb363 100644 --- a/src/test/core/common/reedsolomon/ReedSolomonCorrupt.ts +++ b/src/test/core/common/reedsolomon/ReedSolomonCorrupt.ts @@ -11,15 +11,14 @@ import BitSet from '../../../core/util/BitSet'; * @param random * @param max */ -export function corrupt(received: Int32Array, howMany: number /*int*/, random: Random, max: number /*int*/): void { - const corrupted: BitSet = new Map( /*received.length*/); - for (let j: number /*int*/ = 0; j < howMany; j++) { - const location: number /*int*/ = random.next(received.length); - const value: number /*int*/ = random.next(max); +export function corrupt(received: Int32Array, howMany: number /* int */, random: Random, max: number /* int */): void { + const corrupted: BitSet = new Map( /* received.length */); + for (let j: number /* int */ = 0; j < howMany; j++) { + const location: number /* int */ = random.next(received.length); + const value: number /* int */ = random.next(max); if (corrupted.get(location) === true || received[location] === value) { j--; - } - else { + } else { corrupted.set(location, true); received[location] = value; } diff --git a/src/test/core/datamatrix/DataMatrixBlackBox.1.spec.ts b/src/test/core/datamatrix/DataMatrixBlackBox.1.spec.ts index 7210f2ae..b1f971d4 100644 --- a/src/test/core/datamatrix/DataMatrixBlackBox.1.spec.ts +++ b/src/test/core/datamatrix/DataMatrixBlackBox.1.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import { BarcodeFormat } from '@zxing/library'; import { MultiFormatReader } from '@zxing/library'; @@ -25,19 +25,19 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ class DataMatrixBlackBox1Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/datamatrix-1', new MultiFormatReader(), BarcodeFormat.DATA_MATRIX); - this.addTest(21, 21, 0.0); - this.addTest(21, 21, 90.0); - this.addTest(21, 21, 180.0); - this.addTest(21, 21, 270.0); - } + public constructor() { + super('src/test/resources/blackbox/datamatrix-1', new MultiFormatReader(), BarcodeFormat.DATA_MATRIX); + this.addTest(21, 21, 0.0); + this.addTest(21, 21, 90.0); + this.addTest(21, 21, 180.0); + this.addTest(21, 21, 270.0); + } } describe('DataMatrixBlackBox.1', () => { - it('testBlackBox', async () => { - const test = new DataMatrixBlackBox1Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new DataMatrixBlackBox1Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/datamatrix/decoder/DecodedBitStreamParser.spec.ts b/src/test/core/datamatrix/decoder/DecodedBitStreamParser.spec.ts index e7a09385..87ae2502 100644 --- a/src/test/core/datamatrix/decoder/DecodedBitStreamParser.spec.ts +++ b/src/test/core/datamatrix/decoder/DecodedBitStreamParser.spec.ts @@ -3,27 +3,27 @@ import { DataMatrixDecodedBitStreamParser } from '@zxing/library'; describe('QRCodeDecodedBitStreamParser', () => { - it('testAsciiStandardDecode', () => { + it('testAsciiStandardDecode', () => { // ASCII characters 0-127 are encoded as the value + 1 - const bytes: Uint8Array = new Uint8Array(6); - bytes[0] = 'a'.charCodeAt(0) + 1; - bytes[1] = 'b'.charCodeAt(0) + 1; - bytes[2] = 'c'.charCodeAt(0) + 1; - bytes[3] = 'A'.charCodeAt(0) + 1; - bytes[4] = 'B'.charCodeAt(0) + 1; - bytes[5] = 'C'.charCodeAt(0) + 1; - const decodedString = DataMatrixDecodedBitStreamParser.decode(bytes).getText(); - assert.strictEqual(decodedString, 'abcABC'); - }); + const bytes: Uint8Array = new Uint8Array(6); + bytes[0] = 'a'.charCodeAt(0) + 1; + bytes[1] = 'b'.charCodeAt(0) + 1; + bytes[2] = 'c'.charCodeAt(0) + 1; + bytes[3] = 'A'.charCodeAt(0) + 1; + bytes[4] = 'B'.charCodeAt(0) + 1; + bytes[5] = 'C'.charCodeAt(0) + 1; + const decodedString = DataMatrixDecodedBitStreamParser.decode(bytes).getText(); + assert.strictEqual(decodedString, 'abcABC'); + }); - it('testAsciiDoubleDigitDecode', () => { - const bytes: Uint8Array = new Uint8Array(4); - bytes[0] = 130; - bytes[1] = 1 + 130; - bytes[2] = 98 + 130; - bytes[3] = 99 + 130; - const decodedString = DataMatrixDecodedBitStreamParser.decode(bytes).getText(); - assert.strictEqual(decodedString, '00019899'); - }); + it('testAsciiDoubleDigitDecode', () => { + const bytes: Uint8Array = new Uint8Array(4); + bytes[0] = 130; + bytes[1] = 1 + 130; + bytes[2] = 98 + 130; + bytes[3] = 99 + 130; + const decodedString = DataMatrixDecodedBitStreamParser.decode(bytes).getText(); + assert.strictEqual(decodedString, '00019899'); + }); }); diff --git a/src/test/core/multi/qrcode/MultiQRCode.spec.ts b/src/test/core/multi/qrcode/MultiQRCode.spec.ts new file mode 100644 index 00000000..612a60ab --- /dev/null +++ b/src/test/core/multi/qrcode/MultiQRCode.spec.ts @@ -0,0 +1,122 @@ +/* + * Copyright 2016 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BarcodeFormat, + BinaryBitmap, + HybridBinarizer, + LuminanceSource, + MultipleBarcodeReader, + QRCodeMultiReader, + Result, + ResultMetadataType +} from '@zxing/library'; +import * as path from 'path'; +import Arrays from '../../../../core/util/Arrays'; +import { Collection, List } from '../../../../customTypings'; +import AbstractBlackBoxSpec from '../../common/AbstractBlackBox'; +import SharpImageLuminanceSource from '../../SharpImageLuminanceSource'; +import { assertArrayEquals, assertEquals, assertNotNull } from '../../util/AssertUtils'; +import SharpImage from '../../util/SharpImage'; + +// package com.google.zxing.multi.qrcode; + +// import javax.imageio.ImageIO; +// import java.awt.image.BufferedImage; +// import java.nio.file.Path; +// import java.util.Arrays; +// import java.util.Collection; +// import java.util.HashSet; +// import java.util.List; + +// import com.google.zxing.BarcodeFormat; +// import com.google.zxing.BinaryBitmap; +// import com.google.zxing.BufferedImageLuminanceSource; +// import com.google.zxing.LuminanceSource; +// import com.google.zxing.Result; +// import com.google.zxing.ResultMetadataType; +// import com.google.zxing.ResultPoint; +// import com.google.zxing.common.AbstractBlackBoxTestCase; +// import com.google.zxing.common.HybridBinarizer; +// import com.google.zxing.multi.MultipleBarcodeReader; +// import org.junit.Assert; +// import org.junit.Test; + +/** + * Tests {@link QRCodeMultiReader}. + */ +describe('MultiQRCodeTestCase', () => { + + it('testMultiQRCodes', async () => { + // Very basic test for now + const testBase: string = AbstractBlackBoxSpec.buildTestBase('src/test/resources/blackbox/multi-qrcode-1'); + + const testImage: string = path.resolve(testBase, '1.png'); + const image: SharpImage = await SharpImage.loadWithRotation(testImage, 0); + const source: LuminanceSource = new SharpImageLuminanceSource(image); + const bitmap: BinaryBitmap = new BinaryBitmap(new HybridBinarizer(source)); + + const reader: MultipleBarcodeReader = new QRCodeMultiReader(); + const results: Result[] = reader.decodeMultiple(bitmap); + assertNotNull(results); + assertEquals(4, results.length); + + const barcodeContents: Collection = []; + for (const result of results) { + barcodeContents.push(result.getText()); + assertEquals(BarcodeFormat.QR_CODE, result.getBarcodeFormat()); + assertNotNull(result.getResultMetadata()); + } + const expectedContents: Collection = []; + // TYPESCRIPTPORT: following lines are in different order from Java because JavaScript's push works in a different way HashSet<>.add, but the results are actually the same + expectedContents.push('You get to CREATE OUR JOURNAL PROMPT FOR THE DAY! Yay! Way to go! '); + expectedContents.push('You earned the class 5 EXTRA MINUTES OF RECESS!! Fabulous!! Way to go!!'); + expectedContents.push('You earned the class a 5 MINUTE DANCE PARTY!! Awesome! Way to go! Let\'s boogie!'); + expectedContents.push('You get to SIT AT MRS. SIGMON\'S DESK FOR A DAY!! Awesome!! Way to go!! Guess I better clean up! :)'); + assertArrayEquals(expectedContents, barcodeContents); + }); + + it('testProcessStructuredAppend', () => { + const sa1: Result = new Result('SA1', new Uint8Array(0), [], BarcodeFormat.QR_CODE); + const sa2: Result = new Result('SA2', new Uint8Array(0), [], BarcodeFormat.QR_CODE); + const sa3: Result = new Result('SA3', new Uint8Array(0), [], BarcodeFormat.QR_CODE); + sa1.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, 2); + sa1.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, 'L'); + sa2.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, (1 << 4) + 2); + sa2.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, 'L'); + sa3.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, (2 << 4) + 2); + sa3.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, 'L'); + + const nsa: Result = new Result('NotSA', new Uint8Array(0), [], BarcodeFormat.QR_CODE); + nsa.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, 'L'); + + const inputs: List = Arrays.asList(sa3, sa1, nsa, sa2); + + const results: List = QRCodeMultiReader.processStructuredAppend(inputs); + assertNotNull(results); + assertEquals(2, results.length); + + const barcodeContents: Collection = []; + for (const result of results) { + barcodeContents.push(result.getText()); + } + const expectedContents: Collection = []; + // TYPESCRIPTPORT: following lines are in different order from Java because JavaScript's push works in a different way HashSet<>.add, but the results are actually the same + expectedContents.push('NotSA'); + expectedContents.push('SA1SA2SA3'); + assertArrayEquals(expectedContents, barcodeContents); + }); +}); diff --git a/src/test/core/oned/Code128BlackBox1.spec.ts b/src/test/core/oned/Code128BlackBox1.spec.ts index 85d7da2c..2b7bcafb 100644 --- a/src/test/core/oned/Code128BlackBox1.spec.ts +++ b/src/test/core/oned/Code128BlackBox1.spec.ts @@ -25,16 +25,16 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; * @author Sean Owen */ class Code128BlackBox1Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/code128-1', new MultiFormatReader(), BarcodeFormat.CODE_128); - this.addTest(6, 6, 0.0); - this.addTest(6, 6, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/code128-1', new MultiFormatReader(), BarcodeFormat.CODE_128); + this.addTest(6, 6, 0.0); + this.addTest(6, 6, 180.0); + } } describe('Code128BlackBox.1', () => { - it('testBlackBox', async () => { - const test = new Code128BlackBox1Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new Code128BlackBox1Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/Code39BlackBox1.spec.ts b/src/test/core/oned/Code39BlackBox1.spec.ts index 1d04426a..dcb0e6bf 100644 --- a/src/test/core/oned/Code39BlackBox1.spec.ts +++ b/src/test/core/oned/Code39BlackBox1.spec.ts @@ -25,16 +25,16 @@ import AbstractBlackBoxSpec from './../common/AbstractBlackBox'; * @author Sean Owen */ class Code39BlackBox1Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/code39-1', new MultiFormatReader(), BarcodeFormat.CODE_39); - this.addTest(4, 4, 0.0); - this.addTest(4, 4, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/code39-1', new MultiFormatReader(), BarcodeFormat.CODE_39); + this.addTest(4, 4, 0.0); + this.addTest(4, 4, 180.0); + } } describe('Code39BlackBox.1', () => { - it('testBlackBox', async () => { - const test = new Code39BlackBox1Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new Code39BlackBox1Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/Code39BlackBox3.spec.ts b/src/test/core/oned/Code39BlackBox3.spec.ts index c13898bf..066780d9 100644 --- a/src/test/core/oned/Code39BlackBox3.spec.ts +++ b/src/test/core/oned/Code39BlackBox3.spec.ts @@ -25,16 +25,16 @@ import AbstractBlackBoxSpec from './../common/AbstractBlackBox'; * @author Sean Owen */ class Code39BlackBox3Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/code39-3', new MultiFormatReader(), BarcodeFormat.CODE_39); - this.addTest(17, 17, 0.0); - this.addTest(17, 17, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/code39-3', new MultiFormatReader(), BarcodeFormat.CODE_39); + this.addTest(17, 17, 0.0); + this.addTest(17, 17, 180.0); + } } describe('Code39BlackBox.3', () => { - it('testBlackBox', async () => { - const test = new Code39BlackBox3Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new Code39BlackBox3Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/Code39ExtendedBlackBox2.spec.ts b/src/test/core/oned/Code39ExtendedBlackBox2.spec.ts index f681c687..f1fcbc28 100644 --- a/src/test/core/oned/Code39ExtendedBlackBox2.spec.ts +++ b/src/test/core/oned/Code39ExtendedBlackBox2.spec.ts @@ -25,16 +25,16 @@ import { Code39Reader } from '@zxing/library'; * @author Sean Owen */ class Code39ExtendedBlackBox2Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/code39-2', new Code39Reader(false, true), BarcodeFormat.CODE_39); - this.addTest(2, 2, 0.0); - this.addTest(2, 2, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/code39-2', new Code39Reader(false, true), BarcodeFormat.CODE_39); + this.addTest(2, 2, 0.0); + this.addTest(2, 2, 180.0); + } } describe('Code39ExtendedBlackBox.2', () => { - it('testBlackBox', async () => { - const test = new Code39ExtendedBlackBox2Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new Code39ExtendedBlackBox2Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/Code39ExtendedMode.spec.ts b/src/test/core/oned/Code39ExtendedMode.spec.ts index 71c57253..519a93c3 100644 --- a/src/test/core/oned/Code39ExtendedMode.spec.ts +++ b/src/test/core/oned/Code39ExtendedMode.spec.ts @@ -23,29 +23,29 @@ import { BitMatrix } from '@zxing/library'; import { BitArray } from '@zxing/library'; function doTest(expectedResult: string, encodedResult: string): void { - const sut = new Code39Reader(false, true); - const matrix = BitMatrix.parseFromString(encodedResult, '1', '0'); - const row = new BitArray(matrix.getWidth()); - matrix.getRow(0, row); - const result = sut.decodeRow(0, row, null); - assert.strictEqual(expectedResult, result.getText()); - } + const sut = new Code39Reader(false, true); + const matrix = BitMatrix.parseFromString(encodedResult, '1', '0'); + const row = new BitArray(matrix.getWidth()); + matrix.getRow(0, row); + const result = sut.decodeRow(0, row, null); + assert.strictEqual(expectedResult, result.getText()); +} describe('Code39ExtendedMode', () => { - it('test 1', () => { - doTest('\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f', - '000001001011011010101001001001011001010101101001001001010110101001011010010010010101011010010110100100100101011011010010101001001001010101011001011010010010010101101011001010100100100101010110110010101001001001010101010011011010010010010101101010011010100100100101010110100110101001001001010101011001101010010010010101101010100110100100100101010110101001101001001001010110110101001010010010010101010110100110100100100101011010110100101001001001010101101101001010010010010101010101100110100100100101011010101100101001001001010101101011001010010010010101010110110010100100100101011001010101101001001001010100110101011010010010010101100110101010100100100101010010110101101001001001010110010110101010010010010101001101101010101001001001011010100101101010010010010101101001011010100100100101101101001010101001001001010101100101101010010010010110101100101010010110110100000'); - }); - it('test 2', () => { - doTest(' !"#$%&\'()*+,-./0123456789:;<=>?', - '00000100101101101010011010110101001001010010110101001011010010010100101011010010110100100101001011011010010101001001010010101011001011010010010100101101011001010100100101001010110110010101001001010010101010011011010010010100101101010011010100100101001010110100110101001001010010101011001101010010010100101101010100110100100101001010110101001101001010110110110010101101010010010100101101011010010101001101101011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010101100101101010010010100101001101101010101001001001010110110010101010010010010101010011011010100100100101101010011010101001001001010110100110101010010010010101011001101010010110110100000'); - }); - it('test 3', () => { - doTest('@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_', - '000010010110110101010010010010100110101011011010100101101011010010110110110100101010101100101101101011001010101101100101010101001101101101010011010101101001101010101100110101101010100110101101010011011011010100101010110100110110101101001010110110100101010101100110110101011001010110101100101010110110010110010101011010011010101101100110101010100101101011011001011010101001101101010101001001001011010101001101010010010010101101010011010100100100101101101010010101001001001010101101001101010010010010110101101001010010110110100000'); - }); - it('test 4', () => { - doTest('`abcdefghijklmnopqrstuvwxyz{|}~', - '000001001011011010101001001001011001101010101001010010010110101001011010010100100101011010010110100101001001011011010010101001010010010101011001011010010100100101101011001010100101001001010110110010101001010010010101010011011010010100100101101010011010100101001001010110100110101001010010010101011001101010010100100101101010100110100101001001010110101001101001010010010110110101001010010100100101010110100110100101001001011010110100101001010010010101101101001010010100100101010101100110100101001001011010101100101001010010010101101011001010010100100101010110110010100101001001011001010101101001010010010100110101011010010100100101100110101010100101001001010010110101101001010010010110010110101010010100100101001101101010101001001001010110110100101010010010010101010110011010100100100101101010110010101001001001010110101100101010010010010101011011001010010110110100000'); - }); + it('test 1', () => { + doTest('\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f', + '000001001011011010101001001001011001010101101001001001010110101001011010010010010101011010010110100100100101011011010010101001001001010101011001011010010010010101101011001010100100100101010110110010101001001001010101010011011010010010010101101010011010100100100101010110100110101001001001010101011001101010010010010101101010100110100100100101010110101001101001001001010110110101001010010010010101010110100110100100100101011010110100101001001001010101101101001010010010010101010101100110100100100101011010101100101001001001010101101011001010010010010101010110110010100100100101011001010101101001001001010100110101011010010010010101100110101010100100100101010010110101101001001001010110010110101010010010010101001101101010101001001001011010100101101010010010010101101001011010100100100101101101001010101001001001010101100101101010010010010110101100101010010110110100000'); + }); + it('test 2', () => { + doTest(' !"#$%&\'()*+,-./0123456789:;<=>?', + '00000100101101101010011010110101001001010010110101001011010010010100101011010010110100100101001011011010010101001001010010101011001011010010010100101101011001010100100101001010110110010101001001010010101010011011010010010100101101010011010100100101001010110100110101001001010010101011001101010010010100101101010100110100100101001010110101001101001010110110110010101101010010010100101101011010010101001101101011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010101100101101010010010100101001101101010101001001001010110110010101010010010010101010011011010100100100101101010011010101001001001010110100110101010010010010101011001101010010110110100000'); + }); + it('test 3', () => { + doTest('@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_', + '000010010110110101010010010010100110101011011010100101101011010010110110110100101010101100101101101011001010101101100101010101001101101101010011010101101001101010101100110101101010100110101101010011011011010100101010110100110110101101001010110110100101010101100110110101011001010110101100101010110110010110010101011010011010101101100110101010100101101011011001011010101001101101010101001001001011010101001101010010010010101101010011010100100100101101101010010101001001001010101101001101010010010010110101101001010010110110100000'); + }); + it('test 4', () => { + doTest('`abcdefghijklmnopqrstuvwxyz{|}~', + '000001001011011010101001001001011001101010101001010010010110101001011010010100100101011010010110100101001001011011010010101001010010010101011001011010010100100101101011001010100101001001010110110010101001010010010101010011011010010100100101101010011010100101001001010110100110101001010010010101011001101010010100100101101010100110100101001001010110101001101001010010010110110101001010010100100101010110100110100101001001011010110100101001010010010101101101001010010100100101010101100110100101001001011010101100101001010010010101101011001010010100100101010110110010100101001001011001010101101001010010010100110101011010010100100101100110101010100101001001010010110101101001010010010110010110101010010100100101001101101010101001001001010110110100101010010010010101010110011010100100100101101010110010101001001001010110101100101010010010010101011011001010010110110100000'); + }); }); diff --git a/src/test/core/oned/Ean13BlackBox1.spec.ts b/src/test/core/oned/Ean13BlackBox1.spec.ts index a03405be..527429dc 100644 --- a/src/test/core/oned/Ean13BlackBox1.spec.ts +++ b/src/test/core/oned/Ean13BlackBox1.spec.ts @@ -22,16 +22,16 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ class Ean13BlackBox1Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/ean13-1', new MultiFormatReader(), BarcodeFormat.EAN_13); - this.addTest(30, 31, 0.0); - this.addTest(27, 31, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/ean13-1', new MultiFormatReader(), BarcodeFormat.EAN_13); + this.addTest(30, 31, 0.0); + this.addTest(27, 31, 180.0); + } } describe('Ean13BlackBox1Spec.1', () => { - it('testBlackBox', async () => { - const test = new Ean13BlackBox1Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new Ean13BlackBox1Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/Ean8BlackBox1.spec.ts b/src/test/core/oned/Ean8BlackBox1.spec.ts index 85aa324c..6e7f0521 100644 --- a/src/test/core/oned/Ean8BlackBox1.spec.ts +++ b/src/test/core/oned/Ean8BlackBox1.spec.ts @@ -23,16 +23,16 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ class Ean8BlackBox1Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/ean8-1', new MultiFormatReader(), BarcodeFormat.EAN_8); - this.addTest(8, 8, 0.0); - this.addTest(8, 8, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/ean8-1', new MultiFormatReader(), BarcodeFormat.EAN_8); + this.addTest(8, 8, 0.0); + this.addTest(8, 8, 180.0); + } } describe('Ean8BlackBox1Spec.1', () => { - it('testBlackBox', async () => { - const test = new Ean8BlackBox1Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new Ean8BlackBox1Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/ITFBlackBox.spec.ts b/src/test/core/oned/ITFBlackBox.spec.ts index b7ae37b7..168bedfb 100644 --- a/src/test/core/oned/ITFBlackBox.spec.ts +++ b/src/test/core/oned/ITFBlackBox.spec.ts @@ -27,17 +27,17 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; class ITFBlackBoxSpec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/itf', new MultiFormatReader(), BarcodeFormat.ITF); - this.addTest(1, 1, 0.0); - this.addTest(1, 1, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/itf', new MultiFormatReader(), BarcodeFormat.ITF); + this.addTest(1, 1, 0.0); + this.addTest(1, 1, 180.0); + } } describe('ITFBlackBox', () => { - it('testBlackBox', async () => { - const test = new ITFBlackBoxSpec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new ITFBlackBoxSpec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/rss/RSS14BlackBox1.spec.ts b/src/test/core/oned/rss/RSS14BlackBox1.spec.ts index 8e31d0dc..11d48d19 100644 --- a/src/test/core/oned/rss/RSS14BlackBox1.spec.ts +++ b/src/test/core/oned/rss/RSS14BlackBox1.spec.ts @@ -27,17 +27,17 @@ import AbstractBlackBoxSpec from '../../common/AbstractBlackBox'; class RSS14BlackBox1Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/rss14-1', new MultiFormatReader(), BarcodeFormat.RSS_14); - this.addTest(6, 6, 0.0); - this.addTest(6, 6, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/rss14-1', new MultiFormatReader(), BarcodeFormat.RSS_14); + this.addTest(6, 6, 0.0); + this.addTest(6, 6, 180.0); + } } describe('RSS14BlackBox.1', () => { - it('testBlackBox', async () => { - const test = new RSS14BlackBox1Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new RSS14BlackBox1Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/rss/RSS14BlackBox2.spec.ts b/src/test/core/oned/rss/RSS14BlackBox2.spec.ts index e837a056..9b8519e2 100644 --- a/src/test/core/oned/rss/RSS14BlackBox2.spec.ts +++ b/src/test/core/oned/rss/RSS14BlackBox2.spec.ts @@ -27,17 +27,17 @@ import AbstractBlackBoxSpec from '../../common/AbstractBlackBox'; class RSS14BlackBox2Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/rss14-2', new MultiFormatReader(), BarcodeFormat.RSS_14); - this.addTestWithMax(4, 8, 1, 1, 0.0); - this.addTestWithMax(2, 8, 0, 1, 180.0); - } + public constructor() { + super('src/test/resources/blackbox/rss14-2', new MultiFormatReader(), BarcodeFormat.RSS_14); + this.addTestWithMax(4, 8, 1, 1, 0.0); + this.addTestWithMax(2, 8, 0, 1, 180.0); + } } describe('RSS14BlackBox.2', () => { - it('testBlackBox', async () => { - const test = new RSS14BlackBox2Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new RSS14BlackBox2Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/oned/rss/expanded/BinaryUtil.ts b/src/test/core/oned/rss/expanded/BinaryUtil.ts index 7fb0bdc7..f5e171a9 100644 --- a/src/test/core/oned/rss/expanded/BinaryUtil.ts +++ b/src/test/core/oned/rss/expanded/BinaryUtil.ts @@ -1,6 +1,7 @@ import { BitArray, IllegalStateException } from '@zxing/library'; import StringBuilder from '../../../../../core/util/StringBuilder'; + /* * Copyright (C) 2010 ZXing authors * @@ -34,9 +35,9 @@ import StringBuilder from '../../../../../core/util/StringBuilder'; // import java.util.regex.Pattern; -const /*private static /*final*/ ONE: RegExp = RegExp('1'); -const /*private static /*final*/ ZERO: RegExp = RegExp('0'); -const /*private static /*final*/ SPACE: RegExp = RegExp(' '); +const /* private static /*final */ ONE: RegExp = RegExp('1'); +const /* private static /*final */ ZERO: RegExp = RegExp('0'); +const /* private static /*final */ SPACE: RegExp = RegExp(' '); /** * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) @@ -48,13 +49,13 @@ export default class BinaryUtil { /* * Constructs a BitArray from a String like the one returned from BitArray.toString() - */ + */ public static buildBitArrayFromString(data: string): BitArray { let dotsAndXs: string = data.replace(ONE, 'X').replace(ZERO, '.'); let binary: BitArray = new BitArray(dotsAndXs.replace(SPACE, '').length); - let counter: /*int*/ number = 0; + let counter: /* int */ number = 0; - for (let i /*int*/ = 0; i < dotsAndXs.length; ++i) { + for (let i /* int */ = 0; i < dotsAndXs.length; ++i) { if (i % 9 === 0) { // spaces if (dotsAndXs.charAt(i) !== ' ') { throw new IllegalStateException('space expected'); @@ -74,10 +75,10 @@ export default class BinaryUtil { public static buildBitArrayFromStringWithoutSpaces(data: string): BitArray { let sb: StringBuilder = new StringBuilder(); let dotsAndXs: string = data.replace(ONE, 'X').replace(ZERO, '.'); - let current: /*int*/ number = 0; + let current: /* int */ number = 0; while (current < dotsAndXs.length) { sb.append(' '); - for (let i /*int*/ = 0; i < 8 && current < dotsAndXs.length; ++i) { + for (let i /* int */ = 0; i < 8 && current < dotsAndXs.length; ++i) { sb.append(dotsAndXs.charAt(current)); current++; } diff --git a/src/test/core/oned/rss/expanded/TestCaseUtil.ts b/src/test/core/oned/rss/expanded/TestCaseUtil.ts index 0a596030..902c89ee 100644 --- a/src/test/core/oned/rss/expanded/TestCaseUtil.ts +++ b/src/test/core/oned/rss/expanded/TestCaseUtil.ts @@ -48,7 +48,7 @@ export default class TestCaseUtil { /** * @throws IOException - */ + */ private static getBufferedImage(path: string): SharpImage { let file = AbstractBlackBoxSpec.buildTestBase(path); return SharpImage.load(file, 0); @@ -56,7 +56,7 @@ export default class TestCaseUtil { /** * @throws IOException - */ + */ static getBinaryBitmap(path: string): BinaryBitmap { let bufferedImage: SharpImage = TestCaseUtil.getBufferedImage(path); let luminanceSource: SharpImageLuminanceSource = new SharpImageLuminanceSource(bufferedImage); diff --git a/src/test/core/oned/rss/expanded/decoders/AI013103DecoderTest.java b/src/test/core/oned/rss/expanded/decoders/AI013103DecoderTest.java index 28e3c30f..03ca1419 100644 --- a/src/test/core/oned/rss/expanded/decoders/AI013103DecoderTest.java +++ b/src/test/core/oned/rss/expanded/decoders/AI013103DecoderTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -/* +/* * These authors would like to acknowledge the Spanish Ministry of Industry, * Tourism and Trade, for the support in the project TSI020301-2008-2 * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled diff --git a/src/test/core/oned/rss/expanded/decoders/AnyAIDecoderTest.java b/src/test/core/oned/rss/expanded/decoders/AnyAIDecoderTest.java index 1036c692..ea7e7ab9 100644 --- a/src/test/core/oned/rss/expanded/decoders/AnyAIDecoderTest.java +++ b/src/test/core/oned/rss/expanded/decoders/AnyAIDecoderTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -/* +/* * These authors would like to acknowledge the Spanish Ministry of Industry, * Tourism and Trade, for the support in the project TSI020301-2008-2 * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled diff --git a/src/test/core/oned/rss/expanded/expanded/RSSExpandedBlackBox3TestCase.java b/src/test/core/oned/rss/expanded/expanded/RSSExpandedBlackBox3TestCase.java index 002ce697..0e573721 100644 --- a/src/test/core/oned/rss/expanded/expanded/RSSExpandedBlackBox3TestCase.java +++ b/src/test/core/oned/rss/expanded/expanded/RSSExpandedBlackBox3TestCase.java @@ -34,11 +34,11 @@ * A test of {@link RSSExpandedReader} against a fixed test set of images. */ public final class RSSExpandedBlackBox3TestCase extends AbstractBlackBoxTestCase { - + public RSSExpandedBlackBox3TestCase() { super("src/test/resources/blackbox/rssexpanded-3", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED); addTest(117, 117, 0.0f); addTest(117, 117, 180.0f); } } - + diff --git a/src/test/core/oned/rss/expanded/expanded/RSSExpandedStackedBlackBox1TestCase.java b/src/test/core/oned/rss/expanded/expanded/RSSExpandedStackedBlackBox1TestCase.java index dabe8b13..aa261c49 100644 --- a/src/test/core/oned/rss/expanded/expanded/RSSExpandedStackedBlackBox1TestCase.java +++ b/src/test/core/oned/rss/expanded/expanded/RSSExpandedStackedBlackBox1TestCase.java @@ -35,7 +35,7 @@ * stacked RSS barcodes. */ public final class RSSExpandedStackedBlackBox1TestCase extends AbstractBlackBoxTestCase { - + public RSSExpandedStackedBlackBox1TestCase() { super("src/test/resources/blackbox/rssexpandedstacked-1", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED); addTest(59, 64, 0.0f); @@ -43,4 +43,4 @@ public RSSExpandedStackedBlackBox1TestCase() { } } - + diff --git a/src/test/core/oned/rss/expanded/expanded/RSSExpandedStackedBlackBox2TestCase.java b/src/test/core/oned/rss/expanded/expanded/RSSExpandedStackedBlackBox2TestCase.java index ee0e008c..9f0bf7c6 100644 --- a/src/test/core/oned/rss/expanded/expanded/RSSExpandedStackedBlackBox2TestCase.java +++ b/src/test/core/oned/rss/expanded/expanded/RSSExpandedStackedBlackBox2TestCase.java @@ -35,7 +35,7 @@ * stacked RSS barcodes. */ public final class RSSExpandedStackedBlackBox2TestCase extends AbstractBlackBoxTestCase { - + public RSSExpandedStackedBlackBox2TestCase() { super("src/test/resources/blackbox/rssexpandedstacked-2", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED); addTest(2, 7, 0.0f); @@ -43,4 +43,4 @@ public RSSExpandedStackedBlackBox2TestCase() { } } - + diff --git a/src/test/core/oned/rss/expanded/expanded/decoders/AI013103DecoderTest.java b/src/test/core/oned/rss/expanded/expanded/decoders/AI013103DecoderTest.java index 28e3c30f..03ca1419 100644 --- a/src/test/core/oned/rss/expanded/expanded/decoders/AI013103DecoderTest.java +++ b/src/test/core/oned/rss/expanded/expanded/decoders/AI013103DecoderTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -/* +/* * These authors would like to acknowledge the Spanish Ministry of Industry, * Tourism and Trade, for the support in the project TSI020301-2008-2 * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled diff --git a/src/test/core/oned/rss/expanded/expanded/decoders/AnyAIDecoderTest.java b/src/test/core/oned/rss/expanded/expanded/decoders/AnyAIDecoderTest.java index 1036c692..ea7e7ab9 100644 --- a/src/test/core/oned/rss/expanded/expanded/decoders/AnyAIDecoderTest.java +++ b/src/test/core/oned/rss/expanded/expanded/decoders/AnyAIDecoderTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -/* +/* * These authors would like to acknowledge the Spanish Ministry of Industry, * Tourism and Trade, for the support in the project TSI020301-2008-2 * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled diff --git a/src/test/core/pdf417/decoder/PDF417Decoder.spec.ts b/src/test/core/pdf417/decoder/PDF417Decoder.spec.ts index da0ccb61..234dd923 100644 --- a/src/test/core/pdf417/decoder/PDF417Decoder.spec.ts +++ b/src/test/core/pdf417/decoder/PDF417Decoder.spec.ts @@ -34,7 +34,7 @@ describe('PDF417DecoderTestCase', () => { /** * Tests the first sample given in ISO/IEC 15438:2015(E) - Annex H.4 - */ + */ // @Test // public void testStandardSample1() throws FormatException { it('testStandardSample1', () => { @@ -63,7 +63,7 @@ describe('PDF417DecoderTestCase', () => { /** * Tests the second given in ISO/IEC 15438:2015(E) - Annex H.4 - */ + */ // @Test // public void testStandardSample2() throws FormatException { it('testStandardSample2', () => { diff --git a/src/test/core/pdf417/decoder/ec/AbstractErrorCorrection.spec.ts b/src/test/core/pdf417/decoder/ec/AbstractErrorCorrection.spec.ts index cd8268f3..a9cfaf6e 100644 --- a/src/test/core/pdf417/decoder/ec/AbstractErrorCorrection.spec.ts +++ b/src/test/core/pdf417/decoder/ec/AbstractErrorCorrection.spec.ts @@ -29,31 +29,31 @@ import { corrupt } from '../../../common/reedsolomon/ReedSolomonCorrupt'; */ export default abstract class AbstractErrorCorrectionSpec { - static corrupt(received: Int32Array, howMany: /*int*/number, random: Random): void { - corrupt(received, howMany, random, 929); + static corrupt(received: Int32Array, howMany: /* int */number, random: Random): void { + corrupt(received, howMany, random, 929); + } + + static erase(received: Int32Array, howMany: /* int */number, random: Random): Int32Array { + const erased: BitSet = new Map(/* received.length */); + const erasures = new Int32Array(howMany); + + let erasureOffset = 0; + + for (let j = 0; j < howMany; j++) { + const location = random.next(received.length); + if (erased.get(location)) { + j--; + } else { + erased.set(location, true); + received[location] = 0; + erasures[erasureOffset++] = location; + } } + return erasures; + } - static erase(received: Int32Array, howMany: /*int*/number, random: Random): Int32Array { - const erased: BitSet = new Map(/*received.length*/); - const erasures = new Int32Array(howMany); - - let erasureOffset = 0; - - for (let j = 0; j < howMany; j++) { - const location = random.next(received.length); - if (erased.get(location)) { - j--; - } else { - erased.set(location, true); - received[location] = 0; - erasures[erasureOffset++] = location; - } - } - return erasures; - } - - static getRandom(): Random { - return new Random('0xDEADBEEF'); - } + static getRandom(): Random { + return new Random('0xDEADBEEF'); + } } diff --git a/src/test/core/pdf417/decoder/ec/ErrorCorrection.spec.ts b/src/test/core/pdf417/decoder/ec/ErrorCorrection.spec.ts index 8c9de10e..200c1f4e 100644 --- a/src/test/core/pdf417/decoder/ec/ErrorCorrection.spec.ts +++ b/src/test/core/pdf417/decoder/ec/ErrorCorrection.spec.ts @@ -37,131 +37,131 @@ import AbstractErrorCorrectionSpec from './AbstractErrorCorrection.spec'; // class ErrorCorrectionTestCase extends AbstractErrorCorrectionSpec { describe('ErrorCorrectionTestCase', () => { - // @Test - // public void testNoError() throws ChecksumException { - it('testNoError', () => { - - const received = Int32Array.from(PDF417_TEST_WITH_EC); - // no errors - checkDecode(received); - }); - // } - - // @Test - // public void testOneError() throws ChecksumException { - it('testOneError', () => { - - const random = AbstractErrorCorrectionSpec.getRandom(); - for (let i: number /*int*/ = 0; i < PDF417_TEST_WITH_EC.length; i++) { - const received: Int32Array = Int32Array.from(PDF417_TEST_WITH_EC); - received[i] = random.nextInt(256); - checkDecode(received); - } - }); - // } - - // @Test - // public void testMaxErrors() throws ChecksumException { - it('testMaxErrors', () => { - - const random: Random = AbstractErrorCorrectionSpec.getRandom(); - - for (let testIterations /*int*/ = 0; testIterations < 100; testIterations++) { // # iterations is kind of arbitrary - const received: Int32Array = Int32Array.from(PDF417_TEST_WITH_EC); - AbstractErrorCorrectionSpec.corrupt(received, MAX_ERRORS, random); - checkDecode(received); - } - }); - // } - - // @Test - // public void testTooManyErrors() { - it('testTooManyErrors', () => { - - const received: Int32Array = Int32Array.from(PDF417_TEST_WITH_EC); - const random: Random = AbstractErrorCorrectionSpec.getRandom(); - AbstractErrorCorrectionSpec.corrupt(received, MAX_ERRORS + 1, random); - try { - checkDecode(received); - assert.fail('Should not have decoded'); - } catch (ce) { - if (ce instanceof ChecksumException) { - // good - return; - } - throw ce; - } - }); - // } - - // @Ignore("Erasures not implemented yet") - // @Test - // public void testMaxErasures() throws ChecksumException { - it('testMaxErasures', () => { - - // ignored as Java version - return; + // @Test + // public void testNoError() throws ChecksumException { + it('testNoError', () => { + + const received = Int32Array.from(PDF417_TEST_WITH_EC); + // no errors + checkDecode(received); + }); + // } + + // @Test + // public void testOneError() throws ChecksumException { + it('testOneError', () => { + + const random = AbstractErrorCorrectionSpec.getRandom(); + for (let i: number /* int */ = 0; i < PDF417_TEST_WITH_EC.length; i++) { + const received: Int32Array = Int32Array.from(PDF417_TEST_WITH_EC); + received[i] = random.nextInt(256); + checkDecode(received); + } + }); + // } + + // @Test + // public void testMaxErrors() throws ChecksumException { + it('testMaxErrors', () => { - const random: Random = AbstractErrorCorrectionSpec.getRandom(); - for (const test /*int*/ of PDF417_TEST) { // # iterations is kind of arbitrary - const received = Int32Array.from(PDF417_TEST_WITH_EC); - const erasures = AbstractErrorCorrectionSpec.erase(received, MAX_ERASURES, random); - checkDecode(received, erasures); - } - }); - // } - - // @Ignore("Erasures not implemented yet") - // @Test - // public void testTooManyErasures() { - it('testTooManyErasures', () => { - - const random: Random = AbstractErrorCorrectionSpec.getRandom(); - const received: Int32Array = Int32Array.from(PDF417_TEST_WITH_EC); - const erasures: Int32Array = AbstractErrorCorrectionSpec.erase(received, MAX_ERASURES + 1, random); - try { - checkDecode(received, erasures); - assert.fail('Should not have decoded'); - } catch (ce) { - if (ce instanceof ChecksumException) { - // good - return; - } - throw ce; - } - }); - // } + const random: Random = AbstractErrorCorrectionSpec.getRandom(); + + for (let testIterations /* int */ = 0; testIterations < 100; testIterations++) { // # iterations is kind of arbitrary + const received: Int32Array = Int32Array.from(PDF417_TEST_WITH_EC); + AbstractErrorCorrectionSpec.corrupt(received, MAX_ERRORS, random); + checkDecode(received); + } + }); + // } + + // @Test + // public void testTooManyErrors() { + it('testTooManyErrors', () => { + + const received: Int32Array = Int32Array.from(PDF417_TEST_WITH_EC); + const random: Random = AbstractErrorCorrectionSpec.getRandom(); + AbstractErrorCorrectionSpec.corrupt(received, MAX_ERRORS + 1, random); + try { + checkDecode(received); + assert.fail('Should not have decoded'); + } catch (ce) { + if (ce instanceof ChecksumException) { + // good + return; + } + throw ce; + } + }); + // } + + // @Ignore("Erasures not implemented yet") + // @Test + // public void testMaxErasures() throws ChecksumException { + it('testMaxErasures', () => { + + // ignored as Java version + return; + + const random: Random = AbstractErrorCorrectionSpec.getRandom(); + for (const test /* int */ of PDF417_TEST) { // # iterations is kind of arbitrary + const received = Int32Array.from(PDF417_TEST_WITH_EC); + const erasures = AbstractErrorCorrectionSpec.erase(received, MAX_ERASURES, random); + checkDecode(received, erasures); + } + }); + // } + + // @Ignore("Erasures not implemented yet") + // @Test + // public void testTooManyErasures() { + it('testTooManyErasures', () => { + + const random: Random = AbstractErrorCorrectionSpec.getRandom(); + const received: Int32Array = Int32Array.from(PDF417_TEST_WITH_EC); + const erasures: Int32Array = AbstractErrorCorrectionSpec.erase(received, MAX_ERASURES + 1, random); + try { + checkDecode(received, erasures); + assert.fail('Should not have decoded'); + } catch (ce) { + if (ce instanceof ChecksumException) { + // good + return; + } + throw ce; + } + }); + // } }); -const /*private static final int[]*/ PDF417_TEST = Int32Array.from([ - 48, 901, 56, 141, 627, 856, 330, 69, 244, 900, 852, 169, 843, 895, 852, 895, 913, 154, 845, 778, 387, 89, 869, - 901, 219, 474, 543, 650, 169, 201, 9, 160, 35, 70, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - 900, 900 +const /* private static final int[] */ PDF417_TEST = Int32Array.from([ + 48, 901, 56, 141, 627, 856, 330, 69, 244, 900, 852, 169, 843, 895, 852, 895, 913, 154, 845, 778, 387, 89, 869, + 901, 219, 474, 543, 650, 169, 201, 9, 160, 35, 70, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, + 900, 900 ]); -const /*private static final int[]*/ PDF417_TEST_WITH_EC = Int32Array.from([ - 48, 901, 56, 141, 627, 856, 330, 69, 244, 900, 852, 169, 843, 895, 852, 895, 913, 154, 845, 778, 387, 89, 869, - 901, 219, 474, 543, 650, 169, 201, 9, 160, 35, 70, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - 900, 900, 769, 843, 591, 910, 605, 206, 706, 917, 371, 469, 79, 718, 47, 777, 249, 262, 193, 620, 597, 477, 450, - 806, 908, 309, 153, 871, 686, 838, 185, 674, 68, 679, 691, 794, 497, 479, 234, 250, 496, 43, 347, 582, 882, 536, - 322, 317, 273, 194, 917, 237, 420, 859, 340, 115, 222, 808, 866, 836, 417, 121, 833, 459, 64, 159 +const /* private static final int[] */ PDF417_TEST_WITH_EC = Int32Array.from([ + 48, 901, 56, 141, 627, 856, 330, 69, 244, 900, 852, 169, 843, 895, 852, 895, 913, 154, 845, 778, 387, 89, 869, + 901, 219, 474, 543, 650, 169, 201, 9, 160, 35, 70, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, + 900, 900, 769, 843, 591, 910, 605, 206, 706, 917, 371, 469, 79, 718, 47, 777, 249, 262, 193, 620, 597, 477, 450, + 806, 908, 309, 153, 871, 686, 838, 185, 674, 68, 679, 691, 794, 497, 479, 234, 250, 496, 43, 347, 582, 882, 536, + 322, 317, 273, 194, 917, 237, 420, 859, 340, 115, 222, 808, 866, 836, 417, 121, 833, 459, 64, 159 ]); -const /*private static final int*/ ECC_BYTES: number = PDF417_TEST_WITH_EC.length - PDF417_TEST.length; -const /*private static final int*/ ERROR_LIMIT: number = ECC_BYTES; -const /*private static final int*/ MAX_ERRORS: number = ERROR_LIMIT / 2; -const /*private static final int*/ MAX_ERASURES: number = ERROR_LIMIT; +const /* private static final int */ ECC_BYTES: number = PDF417_TEST_WITH_EC.length - PDF417_TEST.length; +const /* private static final int */ ERROR_LIMIT: number = ECC_BYTES; +const /* private static final int */ MAX_ERRORS: number = ERROR_LIMIT / 2; +const /* private static final int */ MAX_ERASURES: number = ERROR_LIMIT; -const /*private final ErrorCorrection*/ ec = new PDF417DecoderErrorCorrection(); +const /* private final ErrorCorrection */ ec = new PDF417DecoderErrorCorrection(); /** * * @throws ChecksumException */ -function /*private void*/ checkDecode(received: Int32Array, erasures?: Int32Array) { - ec.decode(received, ECC_BYTES, erasures || Int32Array.from([0])); - for (let /*int*/ i = 0; i < PDF417_TEST.length; i++) { - assert.strictEqual(received[i], PDF417_TEST[i]); - } +function /* private void */ checkDecode(received: Int32Array, erasures?: Int32Array) { + ec.decode(received, ECC_BYTES, erasures || Int32Array.from([0])); + for (let /* int */ i = 0; i < PDF417_TEST.length; i++) { + assert.strictEqual(received[i], PDF417_TEST[i]); + } } diff --git a/src/test/core/qrcode/HybridBinarizer.spec.ts b/src/test/core/qrcode/HybridBinarizer.spec.ts index 9adca8e9..ce736bac 100644 --- a/src/test/core/qrcode/HybridBinarizer.spec.ts +++ b/src/test/core/qrcode/HybridBinarizer.spec.ts @@ -6,17 +6,17 @@ import SharpImage from '../util/SharpImage'; const path = require('path'); describe('HybridBinarizer', () => { - it('testHybridBinarizer', async () => { + it('testHybridBinarizer', async () => { - const pathString = path.resolve('src/test/resources/blackbox/common/simple.png'); + const pathString = path.resolve('src/test/resources/blackbox/common/simple.png'); - const image = await SharpImage.loadWithRotation(pathString, 0); + const image = await SharpImage.loadWithRotation(pathString, 0); - const source = new SharpImageLuminanceSource(image); - const test = new HybridBinarizer(source); - const matrix = test.getBlackMatrix(); + const source = new SharpImageLuminanceSource(image); + const test = new HybridBinarizer(source); + const matrix = test.getBlackMatrix(); - assert.equal(0, matrix.get(13, 12)); - assert.equal(1, matrix.get(13, 13)); - }); + assert.equal(0, matrix.get(13, 12)); + assert.equal(1, matrix.get(13, 13)); + }); }); diff --git a/src/test/core/qrcode/QRCodeBlackBox.1.spec.ts b/src/test/core/qrcode/QRCodeBlackBox.1.spec.ts index 52f0b7cd..66630552 100644 --- a/src/test/core/qrcode/QRCodeBlackBox.1.spec.ts +++ b/src/test/core/qrcode/QRCodeBlackBox.1.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import { BarcodeFormat } from '@zxing/library'; import { MultiFormatReader } from '@zxing/library'; @@ -25,19 +25,19 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ class QRCodeBlackBox1Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/qrcode-1', new MultiFormatReader(), BarcodeFormat.QR_CODE); - this.addTest(17, 17, 0.0); - this.addTest(14, 14, 90.0); - this.addTest(17, 17, 180.0); - this.addTest(14, 14, 270.0); - } + public constructor() { + super('src/test/resources/blackbox/qrcode-1', new MultiFormatReader(), BarcodeFormat.QR_CODE); + this.addTest(17, 17, 0.0); + this.addTest(14, 14, 90.0); + this.addTest(17, 17, 180.0); + this.addTest(14, 14, 270.0); + } } describe('QRCodeBlackBox.1', () => { - it('testBlackBox', async () => { - const test = new QRCodeBlackBox1Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new QRCodeBlackBox1Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/qrcode/QRCodeBlackBox.2.spec.ts b/src/test/core/qrcode/QRCodeBlackBox.2.spec.ts index 8a0f2586..b3b2d0f1 100644 --- a/src/test/core/qrcode/QRCodeBlackBox.2.spec.ts +++ b/src/test/core/qrcode/QRCodeBlackBox.2.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import { BarcodeFormat } from '@zxing/library'; import { MultiFormatReader } from '@zxing/library'; @@ -30,20 +30,20 @@ ZXingStringEncoding.customEncoder = (b, e) => new TextEncoder(e, { NONSTANDARD_a */ export default class QRCodeBlackBox2Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/qrcode-2', new MultiFormatReader(), BarcodeFormat.QR_CODE); - this.addTest(31, 31, 0.0); - this.addTest(29, 29, 90.0); - this.addTest(30, 30, 180.0); - this.addTest(29, 29, 270.0); - } + public constructor() { + super('src/test/resources/blackbox/qrcode-2', new MultiFormatReader(), BarcodeFormat.QR_CODE); + this.addTest(31, 31, 0.0); + this.addTest(29, 29, 90.0); + this.addTest(30, 30, 180.0); + this.addTest(29, 29, 270.0); + } } describe('QRCodeBlackBox.2', () => { - it.skip('testBlackBox', async () => { - const test = new QRCodeBlackBox2Spec(); - await test.testBlackBox(); - }); + it.skip('testBlackBox', async () => { + const test = new QRCodeBlackBox2Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/qrcode/QRCodeBlackBox.3.spec.ts b/src/test/core/qrcode/QRCodeBlackBox.3.spec.ts index 4dac318a..60353ae4 100644 --- a/src/test/core/qrcode/QRCodeBlackBox.3.spec.ts +++ b/src/test/core/qrcode/QRCodeBlackBox.3.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import { BarcodeFormat } from '@zxing/library'; import { MultiFormatReader } from '@zxing/library'; @@ -25,19 +25,19 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ export default class QRCodeBlackBox3Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/qrcode-3', new MultiFormatReader(), BarcodeFormat.QR_CODE); - this.addTest(38, 38, 0.0); - this.addTest(38, 38, 90.0); - this.addTest(36, 36, 180.0); - this.addTest(39, 39, 270.0); - } + public constructor() { + super('src/test/resources/blackbox/qrcode-3', new MultiFormatReader(), BarcodeFormat.QR_CODE); + this.addTest(38, 38, 0.0); + this.addTest(38, 38, 90.0); + this.addTest(36, 36, 180.0); + this.addTest(39, 39, 270.0); + } } describe('QRCodeBlackBox.3', () => { - it('testBlackBox', async () => { - const test = new QRCodeBlackBox3Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new QRCodeBlackBox3Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/qrcode/QRCodeBlackBox.4.spec.ts b/src/test/core/qrcode/QRCodeBlackBox.4.spec.ts index 4f03358d..a04d661d 100644 --- a/src/test/core/qrcode/QRCodeBlackBox.4.spec.ts +++ b/src/test/core/qrcode/QRCodeBlackBox.4.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import { BarcodeFormat } from '@zxing/library'; import { MultiFormatReader } from '@zxing/library'; @@ -27,19 +27,19 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ export default class QRCodeBlackBox4Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/qrcode-4', new MultiFormatReader(), BarcodeFormat.QR_CODE); - this.addTest(36, 36, 0.0); - this.addTest(35, 35, 90.0); - this.addTest(35, 35, 180.0); - this.addTest(35, 35, 270.0); - } + public constructor() { + super('src/test/resources/blackbox/qrcode-4', new MultiFormatReader(), BarcodeFormat.QR_CODE); + this.addTest(36, 36, 0.0); + this.addTest(35, 35, 90.0); + this.addTest(35, 35, 180.0); + this.addTest(35, 35, 270.0); + } } describe('QRCodeBlackBox.4', () => { - it('testBlackBox', async () => { - const test = new QRCodeBlackBox4Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new QRCodeBlackBox4Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/qrcode/QRCodeBlackBox.5.spec.ts b/src/test/core/qrcode/QRCodeBlackBox.5.spec.ts index d57b2447..2da6545d 100644 --- a/src/test/core/qrcode/QRCodeBlackBox.5.spec.ts +++ b/src/test/core/qrcode/QRCodeBlackBox.5.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import { BarcodeFormat } from '@zxing/library'; import { MultiFormatReader } from '@zxing/library'; @@ -29,19 +29,19 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ export default class QRCodeBlackBox5Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/qrcode-5', new MultiFormatReader(), BarcodeFormat.QR_CODE); - this.addTest(19, 19, 0.0); - this.addTest(19, 19, 90.0); - this.addTest(19, 19, 180.0); - this.addTest(18, 18, 270.0); - } + public constructor() { + super('src/test/resources/blackbox/qrcode-5', new MultiFormatReader(), BarcodeFormat.QR_CODE); + this.addTest(19, 19, 0.0); + this.addTest(19, 19, 90.0); + this.addTest(19, 19, 180.0); + this.addTest(18, 18, 270.0); + } } describe('QRCodeBlackBox.5', () => { - it('testBlackBox', async () => { - const test = new QRCodeBlackBox5Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new QRCodeBlackBox5Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/qrcode/QRCodeBlackBox.6.spec.ts b/src/test/core/qrcode/QRCodeBlackBox.6.spec.ts index 9e81f1e9..9a0e9c3f 100644 --- a/src/test/core/qrcode/QRCodeBlackBox.6.spec.ts +++ b/src/test/core/qrcode/QRCodeBlackBox.6.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import { BarcodeFormat } from '@zxing/library'; import { MultiFormatReader } from '@zxing/library'; @@ -26,19 +26,19 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ export default class QRCodeBlackBox6Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/qrcode-6', new MultiFormatReader(), BarcodeFormat.QR_CODE); - this.addTest(15, 15, 0.0); - this.addTest(14, 14, 90.0); - this.addTest(12, 13, 180.0); - this.addTest(14, 14, 270.0); - } + public constructor() { + super('src/test/resources/blackbox/qrcode-6', new MultiFormatReader(), BarcodeFormat.QR_CODE); + this.addTest(15, 15, 0.0); + this.addTest(14, 14, 90.0); + this.addTest(12, 13, 180.0); + this.addTest(14, 14, 270.0); + } } describe('QRCodeBlackBox.6', () => { - it('testBlackBox', async () => { - const test = new QRCodeBlackBox6Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new QRCodeBlackBox6Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/qrcode/QRCodeBlackBox.7.spec.ts b/src/test/core/qrcode/QRCodeBlackBox.7.spec.ts index 7a67a7d5..45c8e5c0 100644 --- a/src/test/core/qrcode/QRCodeBlackBox.7.spec.ts +++ b/src/test/core/qrcode/QRCodeBlackBox.7.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import { BarcodeFormat } from '@zxing/library'; import { MultiFormatReader } from '@zxing/library'; @@ -26,19 +26,19 @@ import AbstractBlackBoxSpec from '../common/AbstractBlackBox'; */ export default class QRCodeBlackBox7Spec extends AbstractBlackBoxSpec { - public constructor() { - super('src/test/resources/blackbox/qrcode-7', new MultiFormatReader(), BarcodeFormat.QR_CODE); - this.addTest(4, 4, 0.0); - this.addTest(4, 4, 90.0); - this.addTest(4, 4, 180.0); - this.addTest(4, 4, 270.0); - } + public constructor() { + super('src/test/resources/blackbox/qrcode-7', new MultiFormatReader(), BarcodeFormat.QR_CODE); + this.addTest(4, 4, 0.0); + this.addTest(4, 4, 90.0); + this.addTest(4, 4, 180.0); + this.addTest(4, 4, 270.0); + } } describe('QRCodeBlackBox.7', () => { - it('testBlackBox', async () => { - const test = new QRCodeBlackBox7Spec(); - await test.testBlackBox(); - }); + it('testBlackBox', async () => { + const test = new QRCodeBlackBox7Spec(); + await test.testBlackBox(); + }); }); diff --git a/src/test/core/qrcode/QRCodeWriter.spec.ts b/src/test/core/qrcode/QRCodeWriter.spec.ts index 183b56e0..3f400ac2 100644 --- a/src/test/core/qrcode/QRCodeWriter.spec.ts +++ b/src/test/core/qrcode/QRCodeWriter.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode;*/ +/* package com.google.zxing.qrcode; */ import * as assert from 'assert'; @@ -30,110 +30,110 @@ import { createCustomEncoder } from '../util/textEncodingFactory'; const path = require('path'); -/*import javax.imageio.ImageIO;*/ -/*import java.awt.image.BufferedImage;*/ -/*import java.io.IOException;*/ -/*import java.nio.file.Files;*/ -/*import java.nio.file.Path;*/ -/*import java.nio.file.Paths;*/ -/*import java.util.EnumMap;*/ -/*import java.util.Map;*/ +/* import javax.imageio.ImageIO; */ +/* import java.awt.image.BufferedImage; */ +/* import java.io.IOException; */ +/* import java.nio.file.Files; */ +/* import java.nio.file.Path; */ +/* import java.nio.file.Paths; */ +/* import java.util.EnumMap; */ +/* import java.util.Map; */ /** * @author satorux@google.com (Satoru Takabayashi) - creator * @author dswitkin@google.com (Daniel Switkin) - ported and expanded from C++ */ describe('QRCodeWriter', () => { - ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); - - const BASE_IMAGE_PATH = 'src/test/resources/golden/qrcode/'; - - it('testQRCodeWriter', () => { - // The QR should be multiplied up to fit, with extra padding if necessary - const bigEnough: number /*int*/ = 256; - const writer: Writer = new QRCodeWriter(); - let matrix: BitMatrix = writer.encode( - 'http://www.google.com/', - BarcodeFormat.QR_CODE, - bigEnough, - bigEnough, - null - ); - assert.strictEqual(matrix !== null, true); - assert.strictEqual(matrix.getWidth(), bigEnough); - assert.strictEqual(matrix.getHeight(), bigEnough); - - // The QR will not fit in this size, so the matrix should come back bigger - const tooSmall: number /* int */ = 20; - matrix = writer.encode( - 'http://www.google.com/', - BarcodeFormat.QR_CODE, - tooSmall, - tooSmall, - null - ); - assert.strictEqual(matrix !== null, true); - assert.strictEqual(tooSmall < matrix.getWidth(), true); - assert.strictEqual(tooSmall < matrix.getHeight(), true); - - // We should also be able to handle non-square requests by padding them - const strangeWidth: number /*int*/ = 500; - const strangeHeight: number /*int*/ = 100; - matrix = writer.encode( - 'http://www.google.com/', - BarcodeFormat.QR_CODE, - strangeWidth, - strangeHeight, - null - ); - assert.strictEqual(matrix !== null, true); - assert.strictEqual(matrix.getWidth(), strangeWidth); - assert.strictEqual(matrix.getHeight(), strangeHeight); - }); - - async function compareToGoldenFile( - contents: string, - ecLevel: QRCodeDecoderErrorCorrectionLevel, - resolution: number /*int*/, - fileName: string - ): Promise { - - const filePath = path.resolve(BASE_IMAGE_PATH, fileName); - - let goldenResult: BitMatrix; - - try { - goldenResult = await SharpImage.loadAsBitMatrix(filePath); - } catch (err) { - assert.ok(false, err); - } - - const hints = new Map(); - hints.set(EncodeHintType.ERROR_CORRECTION, ecLevel); - const writer: Writer = new QRCodeWriter(); - const generatedResult: BitMatrix = writer.encode( - contents, - BarcodeFormat.QR_CODE, - resolution, - resolution, - hints - ); - - assert.strictEqual(generatedResult.getWidth(), resolution); - assert.strictEqual(generatedResult.getHeight(), resolution); - assert.strictEqual(generatedResult.equals(goldenResult), true); + ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); + + const BASE_IMAGE_PATH = 'src/test/resources/golden/qrcode/'; + + it('testQRCodeWriter', () => { + // The QR should be multiplied up to fit, with extra padding if necessary + const bigEnough: number /* int */ = 256; + const writer: Writer = new QRCodeWriter(); + let matrix: BitMatrix = writer.encode( + 'http://www.google.com/', + BarcodeFormat.QR_CODE, + bigEnough, + bigEnough, + null + ); + assert.strictEqual(matrix !== null, true); + assert.strictEqual(matrix.getWidth(), bigEnough); + assert.strictEqual(matrix.getHeight(), bigEnough); + + // The QR will not fit in this size, so the matrix should come back bigger + const tooSmall: number /* int */ = 20; + matrix = writer.encode( + 'http://www.google.com/', + BarcodeFormat.QR_CODE, + tooSmall, + tooSmall, + null + ); + assert.strictEqual(matrix !== null, true); + assert.strictEqual(tooSmall < matrix.getWidth(), true); + assert.strictEqual(tooSmall < matrix.getHeight(), true); + + // We should also be able to handle non-square requests by padding them + const strangeWidth: number /* int */ = 500; + const strangeHeight: number /* int */ = 100; + matrix = writer.encode( + 'http://www.google.com/', + BarcodeFormat.QR_CODE, + strangeWidth, + strangeHeight, + null + ); + assert.strictEqual(matrix !== null, true); + assert.strictEqual(matrix.getWidth(), strangeWidth); + assert.strictEqual(matrix.getHeight(), strangeHeight); + }); + + async function compareToGoldenFile( + contents: string, + ecLevel: QRCodeDecoderErrorCorrectionLevel, + resolution: number /* int */, + fileName: string + ): Promise { + + const filePath = path.resolve(BASE_IMAGE_PATH, fileName); + + let goldenResult: BitMatrix; + + try { + goldenResult = await SharpImage.loadAsBitMatrix(filePath); + } catch (err) { + assert.ok(false, err); } - // Golden images are generated with "qrcode_sample.cc". The images are checked with both eye balls - // and cell phones. We expect pixel-perfect results, because the error correction level is known, - // and the pixel dimensions matches exactly. - it('testRegressionTest', () => { - compareToGoldenFile( - 'http://www.google.com/', - QRCodeDecoderErrorCorrectionLevel.M, - 99, - 'renderer-test-01.png' - ); - }); + const hints = new Map(); + hints.set(EncodeHintType.ERROR_CORRECTION, ecLevel); + const writer: Writer = new QRCodeWriter(); + const generatedResult: BitMatrix = writer.encode( + contents, + BarcodeFormat.QR_CODE, + resolution, + resolution, + hints + ); + + assert.strictEqual(generatedResult.getWidth(), resolution); + assert.strictEqual(generatedResult.getHeight(), resolution); + assert.strictEqual(generatedResult.equals(goldenResult), true); + } + + // Golden images are generated with "qrcode_sample.cc". The images are checked with both eye balls + // and cell phones. We expect pixel-perfect results, because the error correction level is known, + // and the pixel dimensions matches exactly. + it('testRegressionTest', () => { + compareToGoldenFile( + 'http://www.google.com/', + QRCodeDecoderErrorCorrectionLevel.M, + 99, + 'renderer-test-01.png' + ); + }); }); diff --git a/src/test/core/qrcode/decoder/DataMask.spec.ts b/src/test/core/qrcode/decoder/DataMask.spec.ts index 294510ce..5ebd35bc 100644 --- a/src/test/core/qrcode/decoder/DataMask.spec.ts +++ b/src/test/core/qrcode/decoder/DataMask.spec.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.decoder;*/ +/* package com.google.zxing.qrcode.decoder; */ import * as assert from 'assert'; import { BitMatrix } from '@zxing/library'; import { QRCodeDataMask } from '@zxing/library'; interface MaskCondition { - isMasked(i: number /*int*/, j: number /*int*/): boolean; + isMasked(i: number /* int */, j: number /* int */): boolean; } /** @@ -29,89 +29,89 @@ interface MaskCondition { */ describe('DataMask', () => { - it('testMask0', () => { - testMaskAcrossDimensions(0, { - isMasked(i: number /*int*/, j: number /*int*/): boolean { - return (i + j) % 2 === 0; - } - }); + it('testMask0', () => { + testMaskAcrossDimensions(0, { + isMasked(i: number /* int */, j: number /* int */): boolean { + return (i + j) % 2 === 0; + } }); + }); - it('testMask1', () => { - testMaskAcrossDimensions(1, { - isMasked(i: number /*int*/, j: number /*int*/): boolean { - return i % 2 === 0; - } - }); + it('testMask1', () => { + testMaskAcrossDimensions(1, { + isMasked(i: number /* int */, j: number /* int */): boolean { + return i % 2 === 0; + } }); + }); - it('testMask2', () => { - testMaskAcrossDimensions(2, { - isMasked(i: number /*int*/, j: number /*int*/): boolean { - return j % 3 === 0; - } - }); + it('testMask2', () => { + testMaskAcrossDimensions(2, { + isMasked(i: number /* int */, j: number /* int */): boolean { + return j % 3 === 0; + } }); + }); - it('testMask3', () => { - testMaskAcrossDimensions(3, { - isMasked(i: number /*int*/, j: number /*int*/): boolean { - return (i + j) % 3 === 0; - } - }); + it('testMask3', () => { + testMaskAcrossDimensions(3, { + isMasked(i: number /* int */, j: number /* int */): boolean { + return (i + j) % 3 === 0; + } }); + }); - it('testMask4', () => { - testMaskAcrossDimensions(4, { - isMasked(i: number /*int*/, j: number /*int*/): boolean { - return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0; - } - }); + it('testMask4', () => { + testMaskAcrossDimensions(4, { + isMasked(i: number /* int */, j: number /* int */): boolean { + return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0; + } }); + }); - it('testMask5', () => { - testMaskAcrossDimensions(5, { - isMasked(i: number /*int*/, j: number /*int*/): boolean { - return (i * j) % 2 + (i * j) % 3 === 0; - } - }); + it('testMask5', () => { + testMaskAcrossDimensions(5, { + isMasked(i: number /* int */, j: number /* int */): boolean { + return (i * j) % 2 + (i * j) % 3 === 0; + } }); + }); - it('testMask6', () => { - testMaskAcrossDimensions(6, { - isMasked(i: number /*int*/, j: number /*int*/): boolean { - return ((i * j) % 2 + (i * j) % 3) % 2 === 0; - } - }); + it('testMask6', () => { + testMaskAcrossDimensions(6, { + isMasked(i: number /* int */, j: number /* int */): boolean { + return ((i * j) % 2 + (i * j) % 3) % 2 === 0; + } }); + }); - it('testMask7', () => { - testMaskAcrossDimensions(7, { - isMasked(i: number /*int*/, j: number /*int*/): boolean { - return ((i + j) % 2 + (i * j) % 3) % 2 === 0; - } - }); + it('testMask7', () => { + testMaskAcrossDimensions(7, { + isMasked(i: number /* int */, j: number /* int */): boolean { + return ((i + j) % 2 + (i * j) % 3) % 2 === 0; + } }); + }); - function testMaskAcrossDimensions(reference: number /*int*/, condition: MaskCondition): void { - const mask = QRCodeDataMask.values.get(reference); - for (let version: number /*int*/ = 1; version <= 40; version++) { - const dimension: number /*int*/ = 17 + 4 * version; - testMask(mask, dimension, condition); - } + function testMaskAcrossDimensions(reference: number /* int */, condition: MaskCondition): void { + const mask = QRCodeDataMask.values.get(reference); + for (let version: number /* int */ = 1; version <= 40; version++) { + const dimension: number /* int */ = 17 + 4 * version; + testMask(mask, dimension, condition); } + } - function testMask(mask: QRCodeDataMask, dimension: number /*int*/, condition: MaskCondition): void { - const bits = new BitMatrix(dimension); - mask.unmaskBitMatrix(bits, dimension); - for (let i: number /*int*/ = 0; i < dimension; i++) { - for (let j: number /*int*/ = 0; j < dimension; j++) { - assert.strictEqual( - bits.get(j, i), - condition.isMasked(i, j), - '(' + i + ',' + j + ')'); - } - } + function testMask(mask: QRCodeDataMask, dimension: number /* int */, condition: MaskCondition): void { + const bits = new BitMatrix(dimension); + mask.unmaskBitMatrix(bits, dimension); + for (let i: number /* int */ = 0; i < dimension; i++) { + for (let j: number /* int */ = 0; j < dimension; j++) { + assert.strictEqual( + bits.get(j, i), + condition.isMasked(i, j), + '(' + i + ',' + j + ')'); + } } + } }); diff --git a/src/test/core/qrcode/decoder/DecodedBitStreamParser.spec.ts b/src/test/core/qrcode/decoder/DecodedBitStreamParser.spec.ts index a412fcf9..4436ae5f 100644 --- a/src/test/core/qrcode/decoder/DecodedBitStreamParser.spec.ts +++ b/src/test/core/qrcode/decoder/DecodedBitStreamParser.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.decoder;*/ +/* package com.google.zxing.qrcode.decoder; */ import * as assert from 'assert'; import { QRCodeDecodedBitStreamParser } from '@zxing/library'; @@ -33,144 +33,144 @@ ZXingStringEncoding.customDecoder = (b, e) => new TextDecoder(e).decode(b); */ describe('QRCodeDecodedBitStreamParser', () => { - it('testSimpleByteMode', () => {/*throws Exception*/ - const builder = new BitSourceBuilder(); - builder.write(0x04, 4); // Byte mode - builder.write(0x03, 8); // 3 bytes - builder.write(0xF1, 8); - builder.write(0xF2, 8); - builder.write(0xF3, 8); - const result: string = QRCodeDecodedBitStreamParser.decode(builder.toByteArray(), - QRCodeVersion.getVersionForNumber(1), null, null).getText(); - assert.strictEqual(result, '\u00f1\u00f2\u00f3'); - }); + it('testSimpleByteMode', () => {/* throws Exception */ + const builder = new BitSourceBuilder(); + builder.write(0x04, 4); // Byte mode + builder.write(0x03, 8); // 3 bytes + builder.write(0xF1, 8); + builder.write(0xF2, 8); + builder.write(0xF3, 8); + const result: string = QRCodeDecodedBitStreamParser.decode(builder.toByteArray(), + QRCodeVersion.getVersionForNumber(1), null, null).getText(); + assert.strictEqual(result, '\u00f1\u00f2\u00f3'); + }); - it('testSimpleSJIS', () => {/*throws Exception*/ - const builder = new BitSourceBuilder(); - builder.write(0x04, 4); // Byte mode - builder.write(0x04, 8); // 4 bytes - builder.write(0xA1, 8); - builder.write(0xA2, 8); - builder.write(0xA3, 8); - builder.write(0xD0, 8); - const result: string = QRCodeDecodedBitStreamParser.decode(builder.toByteArray(), - QRCodeVersion.getVersionForNumber(1), null, null).getText(); - assert.strictEqual(result, '\uff61\uff62\uff63\uff90'); - }); + it('testSimpleSJIS', () => {/* throws Exception */ + const builder = new BitSourceBuilder(); + builder.write(0x04, 4); // Byte mode + builder.write(0x04, 8); // 4 bytes + builder.write(0xA1, 8); + builder.write(0xA2, 8); + builder.write(0xA3, 8); + builder.write(0xD0, 8); + const result: string = QRCodeDecodedBitStreamParser.decode(builder.toByteArray(), + QRCodeVersion.getVersionForNumber(1), null, null).getText(); + assert.strictEqual(result, '\uff61\uff62\uff63\uff90'); + }); - // TYPESCRIPTPORT: CP437 not supported by TextEncoding. TODO: search for an alternative - // See here for a possibility: https://github.com/SheetJS/js-codepage - it.skip('testECI', () => {/*throws Exception*/ - const builder = new BitSourceBuilder(); - builder.write(0x07, 4); // ECI mode - builder.write(0x02, 8); // ECI 2 = CP437 encoding - builder.write(0x04, 4); // Byte mode - builder.write(0x03, 8); // 3 bytes - builder.write(0xA1, 8); - builder.write(0xA2, 8); - builder.write(0xA3, 8); - const byteArray = builder.toByteArray(); - const result: string = QRCodeDecodedBitStreamParser.decode(byteArray, - QRCodeVersion.getVersionForNumber(1), null, null).getText(); - assert.strictEqual(result, '\u00ed\u00f3\u00fa'); - }); + // TYPESCRIPTPORT: CP437 not supported by TextEncoding. TODO: search for an alternative + // See here for a possibility: https://github.com/SheetJS/js-codepage + it.skip('testECI', () => {/* throws Exception */ + const builder = new BitSourceBuilder(); + builder.write(0x07, 4); // ECI mode + builder.write(0x02, 8); // ECI 2 = CP437 encoding + builder.write(0x04, 4); // Byte mode + builder.write(0x03, 8); // 3 bytes + builder.write(0xA1, 8); + builder.write(0xA2, 8); + builder.write(0xA3, 8); + const byteArray = builder.toByteArray(); + const result: string = QRCodeDecodedBitStreamParser.decode(byteArray, + QRCodeVersion.getVersionForNumber(1), null, null).getText(); + assert.strictEqual(result, '\u00ed\u00f3\u00fa'); + }); - const eciTestData = [ - // label, eciBits, byte1, byte2, byte3, expected - ['ISO8859_1', 0x03, 0xA1, 0xA2, 0xA3, '\u00A1\u00A2\u00A3'], - ['ISO8859_2', 0x04, 0xA1, 0xA2, 0xA3, '\u0104\u02D8\u0141'], - ['ISO8859_3', 0x05, 0xA1, 0xA2, 0xA3, '\u0126\u02D8\u00A3'], - ['ISO8859_4', 0x06, 0xA1, 0xA2, 0xA3, '\u0104\u0138\u0156'], - ['ISO8859_5', 0x07, 0xA1, 0xA2, 0xA3, '\u0401\u0402\u0403'], - ['ISO8859_6', 0x08, 0xE1, 0xE2, 0xE3, '\u0641\u0642\u0643'], - ['ISO8859_7', 0x09, 0xA1, 0xA2, 0xA3, '\u2018\u2019\u00A3'], - ['ISO8859_8', 0x0A, 0xE1, 0xE2, 0xE3, '\u05D1\u05D2\u05D3'], - ['ISO8859_9', 0x0B, 0xD0, 0xDD, 0xDE, '\u011E\u0130\u015E'], - ['ISO8859_10', 0x0C, 0xA1, 0xA2, 0xA3, '\u0104\u0112\u0122'], - ['ISO8859_11', 0x0D, 0xA1, 0xA2, 0xA3, '\u0E01\u0E02\u0E03'], - ['ISO8859_13', 0x0F, 0xD1, 0xD2, 0xD3, '\u0143\u0145\u00D3'], - ['ISO8859_14', 0x10, 0xA1, 0xA2, 0xA3, '\u1E02\u1E03\u00A3'], - ['ISO8859_15', 0x11, 0xBC, 0xBD, 0xBE, '\u0152\u0153\u0178'], - ['ISO8859_16', 0x12, 0xA1, 0xA2, 0xA3, '\u0104\u0105\u0141'], - ['windows-1250', 0x15, 0xA1, 0xA2, 0xA3, '\u02C7\u02D8\u0141'], - ['windows-1251', 0x16, 0xA1, 0xA2, 0xA3, '\u040E\u045E\u0408'], - ['windows-1252', 0x17, 0x91, 0x92, 0x93, '\u2018\u2019\u201C'], - ['windows-1256', 0x18, 0xE1, 0xE2, 0xE3, '\u0644\u00E2\u0645'], - ]; + const eciTestData = [ + // label, eciBits, byte1, byte2, byte3, expected + ['ISO8859_1', 0x03, 0xA1, 0xA2, 0xA3, '\u00A1\u00A2\u00A3'], + ['ISO8859_2', 0x04, 0xA1, 0xA2, 0xA3, '\u0104\u02D8\u0141'], + ['ISO8859_3', 0x05, 0xA1, 0xA2, 0xA3, '\u0126\u02D8\u00A3'], + ['ISO8859_4', 0x06, 0xA1, 0xA2, 0xA3, '\u0104\u0138\u0156'], + ['ISO8859_5', 0x07, 0xA1, 0xA2, 0xA3, '\u0401\u0402\u0403'], + ['ISO8859_6', 0x08, 0xE1, 0xE2, 0xE3, '\u0641\u0642\u0643'], + ['ISO8859_7', 0x09, 0xA1, 0xA2, 0xA3, '\u2018\u2019\u00A3'], + ['ISO8859_8', 0x0A, 0xE1, 0xE2, 0xE3, '\u05D1\u05D2\u05D3'], + ['ISO8859_9', 0x0B, 0xD0, 0xDD, 0xDE, '\u011E\u0130\u015E'], + ['ISO8859_10', 0x0C, 0xA1, 0xA2, 0xA3, '\u0104\u0112\u0122'], + ['ISO8859_11', 0x0D, 0xA1, 0xA2, 0xA3, '\u0E01\u0E02\u0E03'], + ['ISO8859_13', 0x0F, 0xD1, 0xD2, 0xD3, '\u0143\u0145\u00D3'], + ['ISO8859_14', 0x10, 0xA1, 0xA2, 0xA3, '\u1E02\u1E03\u00A3'], + ['ISO8859_15', 0x11, 0xBC, 0xBD, 0xBE, '\u0152\u0153\u0178'], + ['ISO8859_16', 0x12, 0xA1, 0xA2, 0xA3, '\u0104\u0105\u0141'], + ['windows-1250', 0x15, 0xA1, 0xA2, 0xA3, '\u02C7\u02D8\u0141'], + ['windows-1251', 0x16, 0xA1, 0xA2, 0xA3, '\u040E\u045E\u0408'], + ['windows-1252', 0x17, 0x91, 0x92, 0x93, '\u2018\u2019\u201C'], + ['windows-1256', 0x18, 0xE1, 0xE2, 0xE3, '\u0644\u00E2\u0645'], + ]; - describe('testECIISOEach', () => { - for (const d of eciTestData) { - it('testECIISOEach ' + d[0], () => { - testEciOneEncoding(d[0], d[1], d[2], d[3], d[4], d[5]); - }); - } - }); - - function testEciOneEncoding(encodingLabel: string, eciBits: number, b1: number, b2: number, b3: number, expected: string) { - const builder = new BitSourceBuilder(); - builder.write(0x07, 4); // ECI mode - builder.write(eciBits, 8); // ECI bits - builder.write(0x04, 4); // Byte mode - builder.write(0x03, 8); // 3 bytes - builder.write(b1, 8); - builder.write(b2, 8); - builder.write(b3, 8); - const byteArray = builder.toByteArray(); - const result: string = QRCodeDecodedBitStreamParser.decode(byteArray, - QRCodeVersion.getVersionForNumber(1), null, null).getText(); - assert.strictEqual(result, expected, encodingLabel); + describe('testECIISOEach', () => { + for (const d of eciTestData) { + it('testECIISOEach ' + d[0], () => { + testEciOneEncoding(d[0], d[1], d[2], d[3], d[4], d[5]); + }); } + }); - describe('testECIISOCombine', () => { - const r = new Random('ECIISO'); - for (let i = 0; i !== 10; i++) { - let id1 = r.next(eciTestData.length); - let id2 = r.next(eciTestData.length); - let d1 = eciTestData[id1]; - let d2 = eciTestData[id2]; - it('testECIISOCombine ' + d1[0] + ' & ' + d2[0], () => { - testEciComboned( - d1[0], d1[1], d1[2], d1[3], d1[4], d1[5], - d2[0], d2[1], d2[2], d2[3], d2[4], d2[5]); - }); - } - }); + function testEciOneEncoding(encodingLabel: string, eciBits: number, b1: number, b2: number, b3: number, expected: string) { + const builder = new BitSourceBuilder(); + builder.write(0x07, 4); // ECI mode + builder.write(eciBits, 8); // ECI bits + builder.write(0x04, 4); // Byte mode + builder.write(0x03, 8); // 3 bytes + builder.write(b1, 8); + builder.write(b2, 8); + builder.write(b3, 8); + const byteArray = builder.toByteArray(); + const result: string = QRCodeDecodedBitStreamParser.decode(byteArray, + QRCodeVersion.getVersionForNumber(1), null, null).getText(); + assert.strictEqual(result, expected, encodingLabel); + } - function testEciComboned( - encodingLabel1: string, eciBits1: number, b1: number, b2: number, b3: number, expected1: string, - encodingLabel2: string, eciBits2: number, b4: number, b5: number, b6: number, expected2: string) { - const builder = new BitSourceBuilder(); - builder.write(0x07, 4); // ECI mode - builder.write(eciBits1, 8); // ECI bits - builder.write(0x04, 4); // Byte mode - builder.write(0x03, 8); // 3 bytes - builder.write(b1, 8); - builder.write(b2, 8); - builder.write(b3, 8); - builder.write(0x07, 4); // ECI mode - builder.write(eciBits2, 8); // ECI bits - builder.write(0x04, 4); // Byte mode - builder.write(0x03, 8); // 3 bytes - builder.write(b4, 8); - builder.write(b5, 8); - builder.write(b6, 8); - const byteArray = builder.toByteArray(); - const result: string = QRCodeDecodedBitStreamParser.decode(byteArray, - QRCodeVersion.getVersionForNumber(1), null, null).getText(); - assert.strictEqual(result, expected1 + expected2, encodingLabel1 + ' & ' + encodingLabel2); + describe('testECIISOCombine', () => { + const r = new Random('ECIISO'); + for (let i = 0; i !== 10; i++) { + let id1 = r.next(eciTestData.length); + let id2 = r.next(eciTestData.length); + let d1 = eciTestData[id1]; + let d2 = eciTestData[id2]; + it('testECIISOCombine ' + d1[0] + ' & ' + d2[0], () => { + testEciComboned( + d1[0], d1[1], d1[2], d1[3], d1[4], d1[5], + d2[0], d2[1], d2[2], d2[3], d2[4], d2[5]); + }); } + }); + + function testEciComboned( + encodingLabel1: string, eciBits1: number, b1: number, b2: number, b3: number, expected1: string, + encodingLabel2: string, eciBits2: number, b4: number, b5: number, b6: number, expected2: string) { + const builder = new BitSourceBuilder(); + builder.write(0x07, 4); // ECI mode + builder.write(eciBits1, 8); // ECI bits + builder.write(0x04, 4); // Byte mode + builder.write(0x03, 8); // 3 bytes + builder.write(b1, 8); + builder.write(b2, 8); + builder.write(b3, 8); + builder.write(0x07, 4); // ECI mode + builder.write(eciBits2, 8); // ECI bits + builder.write(0x04, 4); // Byte mode + builder.write(0x03, 8); // 3 bytes + builder.write(b4, 8); + builder.write(b5, 8); + builder.write(b6, 8); + const byteArray = builder.toByteArray(); + const result: string = QRCodeDecodedBitStreamParser.decode(byteArray, + QRCodeVersion.getVersionForNumber(1), null, null).getText(); + assert.strictEqual(result, expected1 + expected2, encodingLabel1 + ' & ' + encodingLabel2); + } - it('testHanzi', () => {/*throws Exception*/ - const builder = new BitSourceBuilder(); - builder.write(0x0D, 4); // Hanzi mode - builder.write(0x01, 4); // Subset 1 = GB2312 encoding - builder.write(0x01, 8); // 1 characters - builder.write(0x03C1, 13); - const result: string = QRCodeDecodedBitStreamParser.decode(builder.toByteArray(), - QRCodeVersion.getVersionForNumber(1), null, null).getText(); - assert.strictEqual(result, '\u963f'); - }); + it('testHanzi', () => {/* throws Exception */ + const builder = new BitSourceBuilder(); + builder.write(0x0D, 4); // Hanzi mode + builder.write(0x01, 4); // Subset 1 = GB2312 encoding + builder.write(0x01, 8); // 1 characters + builder.write(0x03C1, 13); + const result: string = QRCodeDecodedBitStreamParser.decode(builder.toByteArray(), + QRCodeVersion.getVersionForNumber(1), null, null).getText(); + assert.strictEqual(result, '\u963f'); + }); - // TODO definitely need more tests here + // TODO definitely need more tests here }); diff --git a/src/test/core/qrcode/decoder/ErrorCorrectionLevel.spec.ts b/src/test/core/qrcode/decoder/ErrorCorrectionLevel.spec.ts index ca5ca5fb..0b6a5508 100644 --- a/src/test/core/qrcode/decoder/ErrorCorrectionLevel.spec.ts +++ b/src/test/core/qrcode/decoder/ErrorCorrectionLevel.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.decoder;*/ +/* package com.google.zxing.qrcode.decoder; */ import * as assert from 'assert'; @@ -25,18 +25,18 @@ import { QRCodeDecoderErrorCorrectionLevel } from '@zxing/library'; */ describe('QRCodeDecoderErrorCorrectionLevel', () => { - it('testForBits', () => { - assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.M.equals(QRCodeDecoderErrorCorrectionLevel.forBits(0)), true); - assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.L.equals(QRCodeDecoderErrorCorrectionLevel.forBits(1)), true); - assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.H.equals(QRCodeDecoderErrorCorrectionLevel.forBits(2)), true); - assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.Q.equals(QRCodeDecoderErrorCorrectionLevel.forBits(3)), true); - try { - QRCodeDecoderErrorCorrectionLevel.forBits(4); - assert.ok(false, 'Should have thrown an exception'); - } catch (ex) { - // good for IllegalArgumentException - } - }); + it('testForBits', () => { + assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.M.equals(QRCodeDecoderErrorCorrectionLevel.forBits(0)), true); + assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.L.equals(QRCodeDecoderErrorCorrectionLevel.forBits(1)), true); + assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.H.equals(QRCodeDecoderErrorCorrectionLevel.forBits(2)), true); + assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.Q.equals(QRCodeDecoderErrorCorrectionLevel.forBits(3)), true); + try { + QRCodeDecoderErrorCorrectionLevel.forBits(4); + assert.ok(false, 'Should have thrown an exception'); + } catch (ex) { + // good for IllegalArgumentException + } + }); }); diff --git a/src/test/core/qrcode/decoder/FormatInformation.spec.ts b/src/test/core/qrcode/decoder/FormatInformation.spec.ts index c856603d..b0de99a9 100644 --- a/src/test/core/qrcode/decoder/FormatInformation.spec.ts +++ b/src/test/core/qrcode/decoder/FormatInformation.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.decoder;*/ +/* package com.google.zxing.qrcode.decoder; */ import * as assert from 'assert'; @@ -26,46 +26,46 @@ import { QRCodeDecoderFormatInformation } from '@zxing/library'; */ describe('QRCodeDecoderFormatInformation', () => { - const MASKED_TEST_FORMAT_INFO: number /*int*/ = 0x2BED; - const UNMASKED_TEST_FORMAT_INFO: number /*int*/ = MASKED_TEST_FORMAT_INFO ^ 0x5412; + const MASKED_TEST_FORMAT_INFO: number /* int */ = 0x2BED; + const UNMASKED_TEST_FORMAT_INFO: number /* int */ = MASKED_TEST_FORMAT_INFO ^ 0x5412; - it('testBitsDiffering', () => { - assert.strictEqual(QRCodeDecoderFormatInformation.numBitsDiffering(1, 1), 0); - assert.strictEqual(QRCodeDecoderFormatInformation.numBitsDiffering(0, 2), 1); - assert.strictEqual(QRCodeDecoderFormatInformation.numBitsDiffering(1, 2), 2); - assert.strictEqual(QRCodeDecoderFormatInformation.numBitsDiffering(-1, 0), 32); - }); + it('testBitsDiffering', () => { + assert.strictEqual(QRCodeDecoderFormatInformation.numBitsDiffering(1, 1), 0); + assert.strictEqual(QRCodeDecoderFormatInformation.numBitsDiffering(0, 2), 1); + assert.strictEqual(QRCodeDecoderFormatInformation.numBitsDiffering(1, 2), 2); + assert.strictEqual(QRCodeDecoderFormatInformation.numBitsDiffering(-1, 0), 32); + }); - it('testDecode', () => { - // Normal case - const expected = - QRCodeDecoderFormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO); - assert.strictEqual(null !== expected, true); - assert.strictEqual(expected.getDataMask(), /*(byte)*/ 0x07); - assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.Q.equals(expected.getErrorCorrectionLevel()), true); - // where the code forgot the mask! - assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation(UNMASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO).equals(expected), true); - }); + it('testDecode', () => { + // Normal case + const expected = + QRCodeDecoderFormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO); + assert.strictEqual(null !== expected, true); + assert.strictEqual(expected.getDataMask(), /* (byte) */ 0x07); + assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.Q.equals(expected.getErrorCorrectionLevel()), true); + // where the code forgot the mask! + assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation(UNMASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO).equals(expected), true); + }); - it('testDecodeWithBitDifference', () => { - const expected = - QRCodeDecoderFormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO); - // 1,2,3,4 bits difference - assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation( - MASKED_TEST_FORMAT_INFO ^ 0x01, MASKED_TEST_FORMAT_INFO ^ 0x01).equals(expected), true); - assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation( - MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x03).equals(expected), true); - assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation( - MASKED_TEST_FORMAT_INFO ^ 0x07, MASKED_TEST_FORMAT_INFO ^ 0x07).equals(expected), true); - assert.strictEqual(null === QRCodeDecoderFormatInformation.decodeFormatInformation( - MASKED_TEST_FORMAT_INFO ^ 0x0F, MASKED_TEST_FORMAT_INFO ^ 0x0F), true); - }); + it('testDecodeWithBitDifference', () => { + const expected = + QRCodeDecoderFormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO); + // 1,2,3,4 bits difference + assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation( + MASKED_TEST_FORMAT_INFO ^ 0x01, MASKED_TEST_FORMAT_INFO ^ 0x01).equals(expected), true); + assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation( + MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x03).equals(expected), true); + assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation( + MASKED_TEST_FORMAT_INFO ^ 0x07, MASKED_TEST_FORMAT_INFO ^ 0x07).equals(expected), true); + assert.strictEqual(null === QRCodeDecoderFormatInformation.decodeFormatInformation( + MASKED_TEST_FORMAT_INFO ^ 0x0F, MASKED_TEST_FORMAT_INFO ^ 0x0F), true); + }); - it('testDecodeWithMisread', () => { - const expected = - QRCodeDecoderFormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO); - assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation( - MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x0F).equals(expected), true); - }); + it('testDecodeWithMisread', () => { + const expected = + QRCodeDecoderFormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO); + assert.strictEqual(QRCodeDecoderFormatInformation.decodeFormatInformation( + MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x0F).equals(expected), true); + }); }); diff --git a/src/test/core/qrcode/decoder/Mode.spec.ts b/src/test/core/qrcode/decoder/Mode.spec.ts index 05c14953..1cb594d5 100644 --- a/src/test/core/qrcode/decoder/Mode.spec.ts +++ b/src/test/core/qrcode/decoder/Mode.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.decoder;*/ +/* package com.google.zxing.qrcode.decoder; */ import * as assert from 'assert'; @@ -26,28 +26,28 @@ import { QRCodeMode } from '@zxing/library'; */ describe('Mode', () => { - it('testForBits', () => { - assert.strictEqual(QRCodeMode.TERMINATOR.equals(QRCodeMode.forBits(0x00)), true); - assert.strictEqual(QRCodeMode.NUMERIC.equals(QRCodeMode.forBits(0x01)), true); - assert.strictEqual(QRCodeMode.ALPHANUMERIC.equals(QRCodeMode.forBits(0x02)), true); - assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeMode.forBits(0x04)), true); - assert.strictEqual(QRCodeMode.KANJI.equals(QRCodeMode.forBits(0x08)), true); - try { - QRCodeMode.forBits(0x10); - assert.ok(false, 'Should have thrown an exception'); - } catch (ex) { - // good for InvalidArgumentException - } - }); + it('testForBits', () => { + assert.strictEqual(QRCodeMode.TERMINATOR.equals(QRCodeMode.forBits(0x00)), true); + assert.strictEqual(QRCodeMode.NUMERIC.equals(QRCodeMode.forBits(0x01)), true); + assert.strictEqual(QRCodeMode.ALPHANUMERIC.equals(QRCodeMode.forBits(0x02)), true); + assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeMode.forBits(0x04)), true); + assert.strictEqual(QRCodeMode.KANJI.equals(QRCodeMode.forBits(0x08)), true); + try { + QRCodeMode.forBits(0x10); + assert.ok(false, 'Should have thrown an exception'); + } catch (ex) { + // good for InvalidArgumentException + } + }); - it('testCharacterCount', () => { - // Spot check a few values - assert.strictEqual(QRCodeMode.NUMERIC.getCharacterCountBits(QRCodeVersion.getVersionForNumber(5)), 10); - assert.strictEqual(QRCodeMode.NUMERIC.getCharacterCountBits(QRCodeVersion.getVersionForNumber(26)), 12); - assert.strictEqual(QRCodeMode.NUMERIC.getCharacterCountBits(QRCodeVersion.getVersionForNumber(40)), 14); - assert.strictEqual(QRCodeMode.ALPHANUMERIC.getCharacterCountBits(QRCodeVersion.getVersionForNumber(6)), 9); - assert.strictEqual(QRCodeMode.BYTE.getCharacterCountBits(QRCodeVersion.getVersionForNumber(7)), 8); - assert.strictEqual(QRCodeMode.KANJI.getCharacterCountBits(QRCodeVersion.getVersionForNumber(8)), 8); - }); + it('testCharacterCount', () => { + // Spot check a few values + assert.strictEqual(QRCodeMode.NUMERIC.getCharacterCountBits(QRCodeVersion.getVersionForNumber(5)), 10); + assert.strictEqual(QRCodeMode.NUMERIC.getCharacterCountBits(QRCodeVersion.getVersionForNumber(26)), 12); + assert.strictEqual(QRCodeMode.NUMERIC.getCharacterCountBits(QRCodeVersion.getVersionForNumber(40)), 14); + assert.strictEqual(QRCodeMode.ALPHANUMERIC.getCharacterCountBits(QRCodeVersion.getVersionForNumber(6)), 9); + assert.strictEqual(QRCodeMode.BYTE.getCharacterCountBits(QRCodeVersion.getVersionForNumber(7)), 8); + assert.strictEqual(QRCodeMode.KANJI.getCharacterCountBits(QRCodeVersion.getVersionForNumber(8)), 8); + }); }); diff --git a/src/test/core/qrcode/decoder/Version.spec.ts b/src/test/core/qrcode/decoder/Version.spec.ts index 8411a636..4564caf3 100644 --- a/src/test/core/qrcode/decoder/Version.spec.ts +++ b/src/test/core/qrcode/decoder/Version.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.decoder;*/ +/* package com.google.zxing.qrcode.decoder; */ import * as assert from 'assert'; @@ -26,56 +26,56 @@ import { QRCodeVersion } from '@zxing/library'; */ describe('Version', () => { - it('testVersionForNumber', () => { - try { - QRCodeVersion.getVersionForNumber(0); - assert.ok(false, 'Should have thrown an exception'); - } catch (ex) { - // good for IllegalArgumentException - } - for (let i: number /*int*/ = 1; i <= 40; i++) { - checkVersion(QRCodeVersion.getVersionForNumber(i), i, 4 * i + 17); - } - }); - - function checkVersion(version: QRCodeVersion, versionNumber: number /*int*/, dimension: number /*int*/): void { + it('testVersionForNumber', () => { + try { + QRCodeVersion.getVersionForNumber(0); + assert.ok(false, 'Should have thrown an exception'); + } catch (ex) { + // good for IllegalArgumentException + } + for (let i: number /* int */ = 1; i <= 40; i++) { + checkVersion(QRCodeVersion.getVersionForNumber(i), i, 4 * i + 17); + } + }); - assert.strictEqual(null !== version, true); - assert.strictEqual(version.getVersionNumber(), versionNumber); - assert.strictEqual(null !== version.getAlignmentPatternCenters(), true); + function checkVersion(version: QRCodeVersion, versionNumber: number /* int */, dimension: number /* int */): void { - if (versionNumber > 1) { - assert.strictEqual(version.getAlignmentPatternCenters().length > 0, true); - } + assert.strictEqual(null !== version, true); + assert.strictEqual(version.getVersionNumber(), versionNumber); + assert.strictEqual(null !== version.getAlignmentPatternCenters(), true); - assert.strictEqual(version.getDimensionForVersion(), dimension); - assert.strictEqual(null !== version.getECBlocksForLevel(QRCodeDecoderErrorCorrectionLevel.H), true); - assert.strictEqual(null !== version.getECBlocksForLevel(QRCodeDecoderErrorCorrectionLevel.L), true); - assert.strictEqual(null !== version.getECBlocksForLevel(QRCodeDecoderErrorCorrectionLevel.M), true); - assert.strictEqual(null !== version.getECBlocksForLevel(QRCodeDecoderErrorCorrectionLevel.Q), true); - assert.strictEqual(null !== version.buildFunctionPattern(), true); + if (versionNumber > 1) { + assert.strictEqual(version.getAlignmentPatternCenters().length > 0, true); } - it('testGetProvisionalVersionForDimension', () => { - for (let i: number /*int*/ = 1; i <= 40; i++) { - assert.strictEqual(QRCodeVersion.getProvisionalVersionForDimension(4 * i + 17).getVersionNumber(), i); - } - }); + assert.strictEqual(version.getDimensionForVersion(), dimension); + assert.strictEqual(null !== version.getECBlocksForLevel(QRCodeDecoderErrorCorrectionLevel.H), true); + assert.strictEqual(null !== version.getECBlocksForLevel(QRCodeDecoderErrorCorrectionLevel.L), true); + assert.strictEqual(null !== version.getECBlocksForLevel(QRCodeDecoderErrorCorrectionLevel.M), true); + assert.strictEqual(null !== version.getECBlocksForLevel(QRCodeDecoderErrorCorrectionLevel.Q), true); + assert.strictEqual(null !== version.buildFunctionPattern(), true); + } - it('testDecodeVersionInformation', () => { - // Spot check - doTestVersion(7, 0x07C94); - doTestVersion(12, 0x0C762); - doTestVersion(17, 0x1145D); - doTestVersion(22, 0x168C9); - doTestVersion(27, 0x1B08E); - doTestVersion(32, 0x209D5); - }); - - function doTestVersion(expectedVersion: number /*int*/, mask: number /*int*/): void { - const version: QRCodeVersion = QRCodeVersion.decodeVersionInformation(mask); - assert.strictEqual(null !== version, true); - assert.strictEqual(version.getVersionNumber(), expectedVersion); + it('testGetProvisionalVersionForDimension', () => { + for (let i: number /* int */ = 1; i <= 40; i++) { + assert.strictEqual(QRCodeVersion.getProvisionalVersionForDimension(4 * i + 17).getVersionNumber(), i); } + }); + + it('testDecodeVersionInformation', () => { + // Spot check + doTestVersion(7, 0x07C94); + doTestVersion(12, 0x0C762); + doTestVersion(17, 0x1145D); + doTestVersion(22, 0x168C9); + doTestVersion(27, 0x1B08E); + doTestVersion(32, 0x209D5); + }); + + function doTestVersion(expectedVersion: number /* int */, mask: number /* int */): void { + const version: QRCodeVersion = QRCodeVersion.decodeVersionInformation(mask); + assert.strictEqual(null !== version, true); + assert.strictEqual(version.getVersionNumber(), expectedVersion); + } }); diff --git a/src/test/core/qrcode/encoder/BitVector.spec.ts b/src/test/core/qrcode/encoder/BitVector.spec.ts index 9acd32f9..3bd64a8b 100644 --- a/src/test/core/qrcode/encoder/BitVector.spec.ts +++ b/src/test/core/qrcode/encoder/BitVector.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.encoder;*/ +/* package com.google.zxing.qrcode.encoder; */ import * as assert from 'assert'; import { BitArray } from '@zxing/library'; @@ -25,155 +25,155 @@ import { BitArray } from '@zxing/library'; */ describe('BitVector', () => { - // TYPESCRIPTPORT: cannot use long (64 bits) as we only have 53 bits in number so I will just use a string for testing purposes - // function getUnsignedInt(v: BitArray, index: number /*int*/): number/*long*/ { - // let result: number = 0 - // for (let i: number /*int*/ = 0, offset = index * 8; i < 32; i++) { - // if (v.get(offset + i)) { - // result |= 1 << (31 - i) - // } - // } - // return result - // } - function getUnsignedIntAsString(v: BitArray, index: number /*int*/): string/*long*/ { - let result = ''; - for (let i: number /*int*/ = 0, offset = index * 8; i < 32; i++) { - result = result + (v.get(offset + i) ? '1' : '0'); - } - return ('00000000000000000000000000000000' + result).substring(result.length); + // TYPESCRIPTPORT: cannot use long (64 bits) as we only have 53 bits in number so I will just use a string for testing purposes + // function getUnsignedInt(v: BitArray, index: number /*int */): number/*long */ { + // let result: number = 0 + // for (let i: number /*int */ = 0, offset = index * 8; i < 32; i++) { + // if (v.get(offset + i)) { + // result |= 1 << (31 - i) + // } + // } + // return result + // } + function getUnsignedIntAsString(v: BitArray, index: number /* int */): string/* long */ { + let result = ''; + for (let i: number /* int */ = 0, offset = index * 8; i < 32; i++) { + result = result + (v.get(offset + i) ? '1' : '0'); } - - it('testAppendBit', () => { - const v = new BitArray(); - assert.strictEqual(v.getSizeInBytes(), 0); - // 1 - v.appendBit(true); - assert.strictEqual(v.getSize(), 1); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0x80000000.toString(2)); - // 10 - v.appendBit(false); - assert.strictEqual(v.getSize(), 2); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0x80000000.toString(2)); - // 101 - v.appendBit(true); - assert.strictEqual(v.getSize(), 3); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xa0000000.toString(2)); - // 1010 - v.appendBit(false); - assert.strictEqual(v.getSize(), 4); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xa0000000.toString(2)); - // 10101 - v.appendBit(true); - assert.strictEqual(v.getSize(), 5); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xa8000000.toString(2)); - // 101010 - v.appendBit(false); - assert.strictEqual(v.getSize(), 6); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xa8000000.toString(2)); - // 1010101 - v.appendBit(true); - assert.strictEqual(v.getSize(), 7); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xaa000000.toString(2)); - // 10101010 - v.appendBit(false); - assert.strictEqual(v.getSize(), 8); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xaa000000.toString(2)); - // 10101010 1 - v.appendBit(true); - assert.strictEqual(v.getSize(), 9); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xaa800000.toString(2)); - // 10101010 10 - v.appendBit(false); - assert.strictEqual(v.getSize(), 10); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xaa800000.toString(2)); - }); - - it('testAppendBits', () => { - let v = new BitArray(); - v.appendBits(0x1, 1); - assert.strictEqual(v.getSize(), 1); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0x80000000.toString(2)); - v = new BitArray(); - v.appendBits(0xff, 8); - assert.strictEqual(v.getSize(), 8); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xff000000.toString(2)); - v = new BitArray(); - v.appendBits(0xff7, 12); - assert.strictEqual(v.getSize(), 12); - assert.strictEqual(getUnsignedIntAsString(v, 0), 0xff700000.toString(2)); - }); - - it('testNumBytes', () => { - const v = new BitArray(); - assert.strictEqual(v.getSizeInBytes(), 0); - v.appendBit(false); - // 1 bit was added in the vector, so 1 byte should be consumed. - assert.strictEqual(v.getSizeInBytes(), 1); - v.appendBits(0, 7); - assert.strictEqual(v.getSizeInBytes(), 1); - v.appendBits(0, 8); - assert.strictEqual(v.getSizeInBytes(), 2); - v.appendBits(0, 1); - // We now have 17 bits, so 3 bytes should be consumed. - assert.strictEqual(v.getSizeInBytes(), 3); - }); - - it('testAppendBitVector', () => { - const v1 = new BitArray(); - v1.appendBits(0xbe, 8); - const v2 = new BitArray(); - v2.appendBits(0xef, 8); - v1.appendBitArray(v2); - // beef = 1011 1110 1110 1111 - assert.strictEqual(v1.toString(), ' X.XXXXX. XXX.XXXX'); - }); - - it('testXOR', () => { - const v1 = new BitArray(); - v1.appendBits(0x5555aaaa, 32); - const v2 = new BitArray(); - v2.appendBits(0xaaaa5555, 32); - v1.xor(v2); - assert.strictEqual(getUnsignedIntAsString(v1, 0), 0xffffffff.toString(2)); - }); - - it('testXOR2', () => { - const v1 = new BitArray(); - v1.appendBits(0x2a, 7); // 010 1010 - const v2 = new BitArray(); - v2.appendBits(0x55, 7); // 101 0101 - v1.xor(v2); - assert.strictEqual(getUnsignedIntAsString(v1, 0), 0xfe000000.toString(2)); // 1111 1110 - }); - - it('testAt', () => { - const v = new BitArray(); - v.appendBits(0xdead, 16); // 1101 1110 1010 1101 - assert.strictEqual(v.get(0), true); - assert.strictEqual(v.get(1), true); - assert.strictEqual(v.get(2), false); - assert.strictEqual(v.get(3), true); - - assert.strictEqual(v.get(4), true); - assert.strictEqual(v.get(5), true); - assert.strictEqual(v.get(6), true); - assert.strictEqual(v.get(7), false); - - assert.strictEqual(v.get(8), true); - assert.strictEqual(v.get(9), false); - assert.strictEqual(v.get(10), true); - assert.strictEqual(v.get(11), false); - - assert.strictEqual(v.get(12), true); - assert.strictEqual(v.get(13), true); - assert.strictEqual(v.get(14), false); - assert.strictEqual(v.get(15), true); - }); - - it('testToString', () => { - const v = new BitArray(); - v.appendBits(0xdead, 16); // 1101 1110 1010 1101 - assert.strictEqual(v.toString(), ' XX.XXXX. X.X.XX.X'); - }); + return ('00000000000000000000000000000000' + result).substring(result.length); + } + + it('testAppendBit', () => { + const v = new BitArray(); + assert.strictEqual(v.getSizeInBytes(), 0); + // 1 + v.appendBit(true); + assert.strictEqual(v.getSize(), 1); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0x80000000.toString(2)); + // 10 + v.appendBit(false); + assert.strictEqual(v.getSize(), 2); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0x80000000.toString(2)); + // 101 + v.appendBit(true); + assert.strictEqual(v.getSize(), 3); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xa0000000.toString(2)); + // 1010 + v.appendBit(false); + assert.strictEqual(v.getSize(), 4); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xa0000000.toString(2)); + // 10101 + v.appendBit(true); + assert.strictEqual(v.getSize(), 5); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xa8000000.toString(2)); + // 101010 + v.appendBit(false); + assert.strictEqual(v.getSize(), 6); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xa8000000.toString(2)); + // 1010101 + v.appendBit(true); + assert.strictEqual(v.getSize(), 7); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xaa000000.toString(2)); + // 10101010 + v.appendBit(false); + assert.strictEqual(v.getSize(), 8); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xaa000000.toString(2)); + // 10101010 1 + v.appendBit(true); + assert.strictEqual(v.getSize(), 9); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xaa800000.toString(2)); + // 10101010 10 + v.appendBit(false); + assert.strictEqual(v.getSize(), 10); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xaa800000.toString(2)); + }); + + it('testAppendBits', () => { + let v = new BitArray(); + v.appendBits(0x1, 1); + assert.strictEqual(v.getSize(), 1); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0x80000000.toString(2)); + v = new BitArray(); + v.appendBits(0xff, 8); + assert.strictEqual(v.getSize(), 8); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xff000000.toString(2)); + v = new BitArray(); + v.appendBits(0xff7, 12); + assert.strictEqual(v.getSize(), 12); + assert.strictEqual(getUnsignedIntAsString(v, 0), 0xff700000.toString(2)); + }); + + it('testNumBytes', () => { + const v = new BitArray(); + assert.strictEqual(v.getSizeInBytes(), 0); + v.appendBit(false); + // 1 bit was added in the vector, so 1 byte should be consumed. + assert.strictEqual(v.getSizeInBytes(), 1); + v.appendBits(0, 7); + assert.strictEqual(v.getSizeInBytes(), 1); + v.appendBits(0, 8); + assert.strictEqual(v.getSizeInBytes(), 2); + v.appendBits(0, 1); + // We now have 17 bits, so 3 bytes should be consumed. + assert.strictEqual(v.getSizeInBytes(), 3); + }); + + it('testAppendBitVector', () => { + const v1 = new BitArray(); + v1.appendBits(0xbe, 8); + const v2 = new BitArray(); + v2.appendBits(0xef, 8); + v1.appendBitArray(v2); + // beef = 1011 1110 1110 1111 + assert.strictEqual(v1.toString(), ' X.XXXXX. XXX.XXXX'); + }); + + it('testXOR', () => { + const v1 = new BitArray(); + v1.appendBits(0x5555aaaa, 32); + const v2 = new BitArray(); + v2.appendBits(0xaaaa5555, 32); + v1.xor(v2); + assert.strictEqual(getUnsignedIntAsString(v1, 0), 0xffffffff.toString(2)); + }); + + it('testXOR2', () => { + const v1 = new BitArray(); + v1.appendBits(0x2a, 7); // 010 1010 + const v2 = new BitArray(); + v2.appendBits(0x55, 7); // 101 0101 + v1.xor(v2); + assert.strictEqual(getUnsignedIntAsString(v1, 0), 0xfe000000.toString(2)); // 1111 1110 + }); + + it('testAt', () => { + const v = new BitArray(); + v.appendBits(0xdead, 16); // 1101 1110 1010 1101 + assert.strictEqual(v.get(0), true); + assert.strictEqual(v.get(1), true); + assert.strictEqual(v.get(2), false); + assert.strictEqual(v.get(3), true); + + assert.strictEqual(v.get(4), true); + assert.strictEqual(v.get(5), true); + assert.strictEqual(v.get(6), true); + assert.strictEqual(v.get(7), false); + + assert.strictEqual(v.get(8), true); + assert.strictEqual(v.get(9), false); + assert.strictEqual(v.get(10), true); + assert.strictEqual(v.get(11), false); + + assert.strictEqual(v.get(12), true); + assert.strictEqual(v.get(13), true); + assert.strictEqual(v.get(14), false); + assert.strictEqual(v.get(15), true); + }); + + it('testToString', () => { + const v = new BitArray(); + v.appendBits(0xdead, 16); // 1101 1110 1010 1101 + assert.strictEqual(v.toString(), ' XX.XXXX. X.X.XX.X'); + }); }); diff --git a/src/test/core/qrcode/encoder/Encoder.spec.ts b/src/test/core/qrcode/encoder/Encoder.spec.ts index 497e8247..20d89091 100644 --- a/src/test/core/qrcode/encoder/Encoder.spec.ts +++ b/src/test/core/qrcode/encoder/Encoder.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.encoder;*/ +/* package com.google.zxing.qrcode.encoder; */ import * as assert from 'assert'; @@ -37,585 +37,585 @@ import { createCustomEncoder, createCustomDecoder } from '../../util/textEncodin */ describe('QRCodeEncoder', () => { - it('testGetAlphanumericCode', () => { - // The first ten code points are numbers. - for (let i: number /*int*/ = 0; i < 10; ++i) { - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('0'.charCodeAt(0) + i), i); - } - - // The next 26 code points are capital alphabet letters. - for (let i: number /*int*/ = 10; i < 36; ++i) { - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('A'.charCodeAt(0) + i - 10), i); - } - - // Others are symbol letters - assert.strictEqual(QRCodeEncoder.getAlphanumericCode(' '.charCodeAt(0)), 36); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('$'.charCodeAt(0)), 37); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('%'.charCodeAt(0)), 38); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('*'.charCodeAt(0)), 39); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('+'.charCodeAt(0)), 40); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('-'.charCodeAt(0)), 41); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('.'.charCodeAt(0)), 42); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('/'.charCodeAt(0)), 43); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode(':'.charCodeAt(0)), 44); - - // Should return -1 for other letters; - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('a'.charCodeAt(0)), -1); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('#'.charCodeAt(0)), -1); - assert.strictEqual(QRCodeEncoder.getAlphanumericCode('\0'.charCodeAt(0)), -1); - }); - - it('testChooseMode', () => { - - ZXingStringEncoding.customDecoder = (b, e) => createCustomDecoder(e).decode(b); - - // Numeric mode. - assert.strictEqual(QRCodeMode.NUMERIC.equals(QRCodeEncoder.chooseMode('0')), true); - assert.strictEqual(QRCodeMode.NUMERIC.equals(QRCodeEncoder.chooseMode('0123456789')), true); - // Alphanumeric mode. - assert.strictEqual(QRCodeMode.ALPHANUMERIC.equals(QRCodeEncoder.chooseMode('A')), true); - assert.strictEqual(QRCodeMode.ALPHANUMERIC.equals(QRCodeEncoder.chooseMode('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:')), true); - // 8-bit byte mode. - assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode('a')), true); - assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode('#')), true); - assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode('')), true); - // Kanji mode. We used to use MODE_KANJI for these, but we stopped - // doing that as we cannot distinguish Shift_JIS from other encodings - // from data bytes alone. See also comments in qrcode_encoder.h. - - // AIUE in Hiragana in Shift_JIS - assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode(shiftJISString(Uint8Array.from([0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6])))), true); - - // Nihon in Kanji in Shift_JIS. - assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode(shiftJISString(Uint8Array.from([0x9, 0xf, 0x9, 0x7b])))), true); - - // Sou-Utsu-Byou in Kanji in Shift_JIS. - assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode(shiftJISString(Uint8Array.from([0xe, 0x4, 0x9, 0x5, 0x9, 0x61])))), true); - - ZXingStringEncoding.customDecoder = undefined; - }); - - it('testEncode', () => { - const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('ABCDEF', QRCodeDecoderErrorCorrectionLevel.H); - const expected: string = - '<<\n' + - ' mode: ALPHANUMERIC\n' + - ' ecLevel: H\n' + - ' version: 1\n' + - ' maskPattern: 4\n' + - ' matrix:\n' + - ' 1 1 1 1 1 1 1 0 0 1 0 1 0 0 1 1 1 1 1 1 1\n' + - ' 1 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 0 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 1 0 0 1 1 0 1 0 0 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0\n' + - ' 0 0 0 0 1 1 1 1 0 1 1 0 1 0 1 1 0 0 0 1 0\n' + - ' 0 0 0 0 1 1 0 1 1 1 0 0 1 1 1 1 0 1 1 0 1\n' + - ' 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 1 1 1 0 1 1\n' + - ' 1 0 0 1 1 1 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0\n' + - ' 0 1 1 1 1 1 1 0 1 0 1 0 1 1 1 0 0 1 1 0 0\n' + - ' 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 0\n' + - ' 1 0 0 0 0 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 1\n' + - ' 1 0 1 1 1 0 1 0 1 0 0 1 0 0 0 1 1 0 0 1 1\n' + - ' 1 0 1 1 1 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0\n' + - ' 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0 1 1 1\n' + - '>>\n'; - assert.strictEqual(qrCode.toString(), expected); - }); - - it('testEncodeWithVersion', () => { - const hints = new Map(); // EncodeHintType.class) - hints.set(EncodeHintType.QR_VERSION, 7); - const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('ABCDEF', QRCodeDecoderErrorCorrectionLevel.H, hints); - assert.strictEqual(qrCode.toString().indexOf(' version: 7\n') !== -1, true); - }); - - // @Test(expected = WriterException.class) - it('testEncodeWithVersionTooSmall', () => { - assert.throws( - () => { - const hints = new Map(); // EncodeHintType.class) - hints.set(EncodeHintType.QR_VERSION, 3); - QRCodeEncoder.encode('THISMESSAGEISTOOLONGFORAQRCODEVERSION3', QRCodeDecoderErrorCorrectionLevel.H, hints); - }, - WriterException, - 'unexpected exception thrown' - ); - }); - - it('testSimpleUTF8ECI', () => { - const hints = new Map(); // EncodeHintType.class) - hints.set(EncodeHintType.CHARACTER_SET, 'UTF8'); - const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('hello', QRCodeDecoderErrorCorrectionLevel.H, hints); - const expected: string = - '<<\n' + - ' mode: BYTE\n' + - ' ecLevel: H\n' + - ' version: 1\n' + - ' maskPattern: 6\n' + - ' matrix:\n' + - ' 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1\n' + - ' 1 0 1 1 1 0 1 0 1 0 0 1 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0\n' + - ' 0 0 0 1 1 0 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0\n' + - ' 0 0 0 0 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1\n' + - ' 1 1 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 1 0 1 1\n' + - ' 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 1 0 0 0\n' + - ' 0 1 1 0 0 1 1 0 0 1 1 1 0 1 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 0 0 1 0 0 0 0 0 0\n' + - ' 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 0 0\n' + - ' 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 0\n' + - ' 1 0 1 1 1 0 1 0 1 1 1 1 0 1 0 0 1 0 1 1 0\n' + - ' 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 0 0 1 0 1 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1 1 0 0 0\n' + - ' 1 1 1 1 1 1 1 0 0 0 0 1 0 1 0 0 1 0 1 0 0\n' + - '>>\n'; - assert.strictEqual(qrCode.toString(), expected); - }); - - it('testEncodeKanjiMode', () => { - - ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); + it('testGetAlphanumericCode', () => { + // The first ten code points are numbers. + for (let i: number /* int */ = 0; i < 10; ++i) { + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('0'.charCodeAt(0) + i), i); + } + // The next 26 code points are capital alphabet letters. + for (let i: number /* int */ = 10; i < 36; ++i) { + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('A'.charCodeAt(0) + i - 10), i); + } + + // Others are symbol letters + assert.strictEqual(QRCodeEncoder.getAlphanumericCode(' '.charCodeAt(0)), 36); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('$'.charCodeAt(0)), 37); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('%'.charCodeAt(0)), 38); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('*'.charCodeAt(0)), 39); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('+'.charCodeAt(0)), 40); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('-'.charCodeAt(0)), 41); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('.'.charCodeAt(0)), 42); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('/'.charCodeAt(0)), 43); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode(':'.charCodeAt(0)), 44); + + // Should return -1 for other letters; + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('a'.charCodeAt(0)), -1); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('#'.charCodeAt(0)), -1); + assert.strictEqual(QRCodeEncoder.getAlphanumericCode('\0'.charCodeAt(0)), -1); + }); + + it('testChooseMode', () => { + + ZXingStringEncoding.customDecoder = (b, e) => createCustomDecoder(e).decode(b); + + // Numeric mode. + assert.strictEqual(QRCodeMode.NUMERIC.equals(QRCodeEncoder.chooseMode('0')), true); + assert.strictEqual(QRCodeMode.NUMERIC.equals(QRCodeEncoder.chooseMode('0123456789')), true); + // Alphanumeric mode. + assert.strictEqual(QRCodeMode.ALPHANUMERIC.equals(QRCodeEncoder.chooseMode('A')), true); + assert.strictEqual(QRCodeMode.ALPHANUMERIC.equals(QRCodeEncoder.chooseMode('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:')), true); + // 8-bit byte mode. + assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode('a')), true); + assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode('#')), true); + assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode('')), true); + // Kanji mode. We used to use MODE_KANJI for these, but we stopped + // doing that as we cannot distinguish Shift_JIS from other encodings + // from data bytes alone. See also comments in qrcode_encoder.h. + + // AIUE in Hiragana in Shift_JIS + assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode(shiftJISString(Uint8Array.from([0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6])))), true); + + // Nihon in Kanji in Shift_JIS. + assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode(shiftJISString(Uint8Array.from([0x9, 0xf, 0x9, 0x7b])))), true); + + // Sou-Utsu-Byou in Kanji in Shift_JIS. + assert.strictEqual(QRCodeMode.BYTE.equals(QRCodeEncoder.chooseMode(shiftJISString(Uint8Array.from([0xe, 0x4, 0x9, 0x5, 0x9, 0x61])))), true); + + ZXingStringEncoding.customDecoder = undefined; + }); + + it('testEncode', () => { + const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('ABCDEF', QRCodeDecoderErrorCorrectionLevel.H); + const expected: string = + '<<\n' + + ' mode: ALPHANUMERIC\n' + + ' ecLevel: H\n' + + ' version: 1\n' + + ' maskPattern: 4\n' + + ' matrix:\n' + + ' 1 1 1 1 1 1 1 0 0 1 0 1 0 0 1 1 1 1 1 1 1\n' + + ' 1 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 0 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 1 0 0 1 1 0 1 0 0 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0\n' + + ' 0 0 0 0 1 1 1 1 0 1 1 0 1 0 1 1 0 0 0 1 0\n' + + ' 0 0 0 0 1 1 0 1 1 1 0 0 1 1 1 1 0 1 1 0 1\n' + + ' 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 1 1 1 0 1 1\n' + + ' 1 0 0 1 1 1 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0\n' + + ' 0 1 1 1 1 1 1 0 1 0 1 0 1 1 1 0 0 1 1 0 0\n' + + ' 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 0\n' + + ' 1 0 0 0 0 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 1\n' + + ' 1 0 1 1 1 0 1 0 1 0 0 1 0 0 0 1 1 0 0 1 1\n' + + ' 1 0 1 1 1 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0\n' + + ' 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0 1 1 1\n' + + '>>\n'; + assert.strictEqual(qrCode.toString(), expected); + }); + + it('testEncodeWithVersion', () => { + const hints = new Map(); // EncodeHintType.class) + hints.set(EncodeHintType.QR_VERSION, 7); + const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('ABCDEF', QRCodeDecoderErrorCorrectionLevel.H, hints); + assert.strictEqual(qrCode.toString().indexOf(' version: 7\n') !== -1, true); + }); + + // @Test(expected = WriterException.class) + it('testEncodeWithVersionTooSmall', () => { + assert.throws( + () => { const hints = new Map(); // EncodeHintType.class) - hints.set(EncodeHintType.CHARACTER_SET, CharacterSetECI.SJIS.getName()); - // Nihon in Kanji - const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('\u65e5\u672c', QRCodeDecoderErrorCorrectionLevel.M, hints); - const expected: string = - '<<\n' + - ' mode: KANJI\n' + - ' ecLevel: M\n' + - ' version: 1\n' + - ' maskPattern: 0\n' + - ' matrix:\n' + - ' 1 1 1 1 1 1 1 0 0 1 0 1 0 0 1 1 1 1 1 1 1\n' + - ' 1 0 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 0 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1 0\n' + - ' 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 0 1 0 0 0\n' + - ' 0 1 0 0 0 0 1 1 1 1 1 1 0 1 1 1 0 1 0 1 0\n' + - ' 1 1 1 0 0 1 0 1 0 0 0 1 1 1 0 1 1 0 1 0 0\n' + - ' 0 1 1 0 0 1 1 0 1 1 0 1 0 1 1 1 0 1 0 0 1\n' + - ' 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1\n' + - ' 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 1 0 0 1 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 1 1\n' + - ' 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 1 1 0 1 0 1 0 1 1 0 1 1 1 0 0 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0\n' + - ' 1 1 1 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 0 0\n' + - '>>\n'; - assert.strictEqual(qrCode.toString(), expected); - - ZXingStringEncoding.customEncoder = undefined; - }); - - it('testEncodeShiftjisNumeric', () => { - const hints = new Map(); // EncodeHintType.class) - hints.set(EncodeHintType.CHARACTER_SET, CharacterSetECI.SJIS.getName()); - const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('0123', QRCodeDecoderErrorCorrectionLevel.M, hints); - const expected: string = - '<<\n' + - ' mode: NUMERIC\n' + - ' ecLevel: M\n' + - ' version: 1\n' + - ' maskPattern: 2\n' + - ' matrix:\n' + - ' 1 1 1 1 1 1 1 0 0 1 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 1 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 0 1\n' + - ' 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0\n' + - ' 1 0 1 1 1 1 1 0 0 1 1 0 1 0 1 1 1 1 1 0 0\n' + - ' 1 1 0 0 0 1 0 0 1 0 1 0 1 0 0 1 0 0 1 0 0\n' + - ' 0 1 1 0 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1\n' + - ' 1 0 1 1 0 1 0 1 0 0 1 0 0 0 0 1 1 0 1 0 0\n' + - ' 0 0 1 0 0 1 1 1 0 0 0 1 0 1 0 0 1 0 1 0 0\n' + - ' 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 0 0 1 0 0 0\n' + - ' 1 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 0\n' + - ' 1 0 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0\n' + - ' 1 0 1 1 1 0 1 0 1 0 1 0 1 0 0 1 0 0 1 0 0\n' + - ' 1 0 1 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 1 0 0\n' + - ' 1 0 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 1 1 0 0\n' + - ' 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 1 1 0\n' + - ' 1 1 1 1 1 1 1 0 1 1 0 1 0 1 0 0 1 1 1 0 0\n' + - '>>\n'; - assert.strictEqual(qrCode.toString(), expected); - }); - - it('testAppendModeInfo', () => { - const bits = new BitArray(); - QRCodeEncoder.appendModeInfo(QRCodeMode.NUMERIC, bits); - assert.strictEqual(bits.toString(), ' ...X'); - }); - - it('testAppendLengthInfo', () => { - let bits = new BitArray(); - QRCodeEncoder.appendLengthInfo(1, // 1 letter (1/1). - QRCodeVersion.getVersionForNumber(1), - QRCodeMode.NUMERIC, - bits); - assert.strictEqual(bits.toString(), ' ........ .X'); // 10 bits. - bits = new BitArray(); - QRCodeEncoder.appendLengthInfo(2, // 2 letters (2/1). - QRCodeVersion.getVersionForNumber(10), - QRCodeMode.ALPHANUMERIC, - bits); - assert.strictEqual(bits.toString(), ' ........ .X.'); // 11 bits. - bits = new BitArray(); - QRCodeEncoder.appendLengthInfo(255, // 255 letter (255/1). - QRCodeVersion.getVersionForNumber(27), - QRCodeMode.BYTE, - bits); - assert.strictEqual(bits.toString(), ' ........ XXXXXXXX'); // 16 bits. - bits = new BitArray(); - QRCodeEncoder.appendLengthInfo(512, // 512 letters (1024/2). - QRCodeVersion.getVersionForNumber(40), - QRCodeMode.KANJI, - bits); - assert.strictEqual(bits.toString(), ' ..X..... ....'); // 12 bits. - }); - - it('testAppendBytes', () => { - ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); - ZXingStringEncoding.customDecoder = (b, e) => createCustomDecoder(e).decode(b); - - // Should use appendNumericBytes. - // 1 = 01 = 0001 in 4 bits. - let bits = new BitArray(); - QRCodeEncoder.appendBytes('1', QRCodeMode.NUMERIC, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); - assert.strictEqual(bits.toString(), ' ...X'); - // Should use appendAlphanumericBytes. - // A = 10 = 0xa = 001010 in 6 bits - bits = new BitArray(); - QRCodeEncoder.appendBytes('A', QRCodeMode.ALPHANUMERIC, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); - assert.strictEqual(bits.toString(), ' ..X.X.'); - // Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC. - try { - QRCodeEncoder.appendBytes('a', QRCodeMode.ALPHANUMERIC, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); - } catch (we/*WriterException*/) { - if (we instanceof WriterException) { - // good - } else { - throw we; - } - } - // Should use append8BitBytes. - // 0x61, 0x62, 0x63 - bits = new BitArray(); - QRCodeEncoder.appendBytes('abc', QRCodeMode.BYTE, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); - assert.strictEqual(bits.toString(), ' .XX....X .XX...X. .XX...XX'); - // Anything can be encoded in QRCodeEncoderQRCode.MODE_8BIT_BYTE. - // TYPESCRIPTPORT: this seems to be unused: QRCodeEncoder.appendBytes("\0", QRCodeMode.BYTE, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING) - - // Should use appendKanjiBytes. - // 0x93, 0x5f - bits = new BitArray(); - QRCodeEncoder.appendBytes(shiftJISString(Uint8Array.from([0x93, 0x5f])), QRCodeMode.KANJI, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); - assert.strictEqual(bits.toString(), ' .XX.XX.. XXXXX'); - - ZXingStringEncoding.customEncoder = undefined; - ZXingStringEncoding.customDecoder = undefined; - }); - - it('testTerminateBits', () => { - let v = new BitArray(); - QRCodeEncoder.terminateBits(0, v); - assert.strictEqual(v.toString(), ''); - v = new BitArray(); - QRCodeEncoder.terminateBits(1, v); - assert.strictEqual(v.toString(), ' ........'); - v = new BitArray(); - v.appendBits(0, 3); // Append 000 - QRCodeEncoder.terminateBits(1, v); - assert.strictEqual(v.toString(), ' ........'); - v = new BitArray(); - v.appendBits(0, 5); // Append 00000 - QRCodeEncoder.terminateBits(1, v); - assert.strictEqual(v.toString(), ' ........'); - v = new BitArray(); - v.appendBits(0, 8); // Append 00000000 - QRCodeEncoder.terminateBits(1, v); - assert.strictEqual(v.toString(), ' ........'); - v = new BitArray(); - QRCodeEncoder.terminateBits(2, v); - assert.strictEqual(v.toString(), ' ........ XXX.XX..'); - v = new BitArray(); - v.appendBits(0, 1); // Append 0 - QRCodeEncoder.terminateBits(3, v); - assert.strictEqual(v.toString(), ' ........ XXX.XX.. ...X...X'); - }); - - it('testGetNumDataBytesAndNumECBytesForBlockID', () => { - const numDataBytes = new Int32Array(1); /*Int32Array(1)*/ - const numEcBytes = new Int32Array(1); /*Int32Array(1)*/ - // Version 1-H. - QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, numDataBytes, numEcBytes); - assert.strictEqual(numDataBytes[0], 9); - assert.strictEqual(numEcBytes[0], 17); - - // Version 3-H. 2 blocks. - QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0, numDataBytes, numEcBytes); - assert.strictEqual(numDataBytes[0], 13); - assert.strictEqual(numEcBytes[0], 22); - QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, numDataBytes, numEcBytes); - assert.strictEqual(numDataBytes[0], 13); - assert.strictEqual(numEcBytes[0], 22); - - // Version 7-H. (4 + 1) blocks. - QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0, numDataBytes, numEcBytes); - assert.strictEqual(numDataBytes[0], 13); - assert.strictEqual(numEcBytes[0], 26); - QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, numDataBytes, numEcBytes); - assert.strictEqual(numDataBytes[0], 14); - assert.strictEqual(numEcBytes[0], 26); - - // Version 40-H. (20 + 61) blocks. - QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0, numDataBytes, numEcBytes); - assert.strictEqual(numDataBytes[0], 15); - assert.strictEqual(numEcBytes[0], 30); - QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, numDataBytes, numEcBytes); - assert.strictEqual(numDataBytes[0], 16); - assert.strictEqual(numEcBytes[0], 30); - QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, numDataBytes, numEcBytes); - assert.strictEqual(numDataBytes[0], 16); - assert.strictEqual(numEcBytes[0], 30); - }); - - it('testInterleaveWithECBytes', () => { - let dataBytes = Uint8Array.from([32, 65, 205, 69, 41, 220, 46, 128, 236]); - let input = new BitArray(); - for (let i = 0, length = dataBytes.length; i !== length; i++) { - const dataByte = dataBytes[i]; - input.appendBits(dataByte, 8); - } - let out: BitArray = QRCodeEncoder.interleaveWithECBytes(input, 26, 9, 1); - let expected = Uint8Array.from([ - // Data bytes. - 32, 65, 205, 69, 41, 220, 46, 128, 236, - // Error correction bytes. - 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, - 237, 85, 224, 96, 74, 219, 61, - ]); - assert.strictEqual(out.getSizeInBytes(), expected.length); - let outArray = new Uint8Array(expected.length); - out.toBytes(0, outArray, 0, expected.length); - // Can't use ZXingArrays.equals(), because outArray may be longer than out.sizeInBytes() - for (let x: number /*int*/ = 0; x < expected.length; x++) { - assert.strictEqual(outArray[x], expected[x]); - } - // Numbers are from http://www.swetake.com/qr/qr8.html - dataBytes = Uint8Array.from([ - 67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, - 198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, 135, - 151, 166, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, - 182, 198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, - 135, 151, 160, 236, 17, 236, 17, 236, 17, 236, - 17 - ]); - input = new BitArray(); - for (let i = 0, length = dataBytes.length; i !== length; i++) { - const dataByte = dataBytes[i]; - input.appendBits(dataByte, 8); - } - - out = QRCodeEncoder.interleaveWithECBytes(input, 134, 62, 4); - expected = Uint8Array.from([ - // Data bytes. - 67, 230, 54, 55, 70, 247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39, - 118, 119, 70, 55, 134, 135, 86, 71, 150, 151, 102, 87, 166, - 160, 118, 103, 182, 236, 134, 119, 198, 17, 150, - 135, 214, 236, 166, 151, 230, 17, 182, - 166, 247, 236, 198, 22, 7, 17, 214, 38, 23, 236, 39, - 17, - // Error correction bytes. - 175, 155, 245, 236, 80, 146, 56, 74, 155, 165, - 133, 142, 64, 183, 132, 13, 178, 54, 132, 108, 45, - 113, 53, 50, 214, 98, 193, 152, 233, 147, 50, 71, 65, - 190, 82, 51, 209, 199, 171, 54, 12, 112, 57, 113, 155, 117, - 211, 164, 117, 30, 158, 225, 31, 190, 242, 38, - 140, 61, 179, 154, 214, 138, 147, 87, 27, 96, 77, 47, - 187, 49, 156, 214, - ]); - assert.strictEqual(out.getSizeInBytes(), expected.length); - outArray = new Uint8Array(expected.length); - out.toBytes(0, outArray, 0, expected.length); - for (let x: number /*int*/ = 0; x < expected.length; x++) { - assert.strictEqual(outArray[x], expected[x]); - } - }); - - it('testAppendNumericBytes', () => { - // 1 = 01 = 0001 in 4 bits. - let bits = new BitArray(); - QRCodeEncoder.appendNumericBytes('1', bits); - assert.strictEqual(bits.toString(), ' ...X'); - // 12 = 0xc = 0001100 in 7 bits. - bits = new BitArray(); - QRCodeEncoder.appendNumericBytes('12', bits); - assert.strictEqual(bits.toString(), ' ...XX..'); - // 123 = 0x7b = 0001111011 in 10 bits. - bits = new BitArray(); - QRCodeEncoder.appendNumericBytes('123', bits); - assert.strictEqual(bits.toString(), ' ...XXXX. XX'); - // 1234 = "123" + "4" = 0001111011 + 0100 - bits = new BitArray(); - QRCodeEncoder.appendNumericBytes('1234', bits); - assert.strictEqual(bits.toString(), ' ...XXXX. XX.X..'); - // Empty. - bits = new BitArray(); - QRCodeEncoder.appendNumericBytes('', bits); - assert.strictEqual(bits.toString(), ''); - }); - - it('testAppendAlphanumericBytes', () => { - // A = 10 = 0xa = 001010 in 6 bits - let bits = new BitArray(); - QRCodeEncoder.appendAlphanumericBytes('A', bits); - assert.strictEqual(bits.toString(), ' ..X.X.'); - // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits - bits = new BitArray(); - QRCodeEncoder.appendAlphanumericBytes('AB', bits); - assert.strictEqual(bits.toString(), ' ..XXX..X X.X'); - // ABC = "AB" + "C" = 00111001101 + 001100 - bits = new BitArray(); - QRCodeEncoder.appendAlphanumericBytes('ABC', bits); - assert.strictEqual(bits.toString(), ' ..XXX..X X.X..XX. .'); - // Empty. - bits = new BitArray(); - QRCodeEncoder.appendAlphanumericBytes('', bits); - assert.strictEqual(bits.toString(), ''); - // Invalid data. - try { - QRCodeEncoder.appendAlphanumericBytes('abc', new BitArray()); - } catch (we/*WriterException*/) { - // good - } - }); - - it('testAppend8BitBytes', () => { - ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); - // 0x61, 0x62, 0x63 - let bits = new BitArray(); - QRCodeEncoder.append8BitBytes('abc', bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); - assert.strictEqual(bits.toString(), ' .XX....X .XX...X. .XX...XX'); - // Empty. - bits = new BitArray(); - QRCodeEncoder.append8BitBytes('', bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); - assert.strictEqual(bits.toString(), ''); - }); - - // Numbers are from page 21 of JISX0510:2004 - it('testAppendKanjiBytes', () => { - ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); - ZXingStringEncoding.customDecoder = (b, e) => createCustomDecoder(e).decode(b); - - const bits = new BitArray(); - QRCodeEncoder.appendKanjiBytes(shiftJISString(Uint8Array.from([0x93, 0x5f])), bits); - assert.strictEqual(bits.toString(), ' .XX.XX.. XXXXX'); - QRCodeEncoder.appendKanjiBytes(shiftJISString(Uint8Array.from([0xe4, 0xaa])), bits); - assert.strictEqual(bits.toString(), ' .XX.XX.. XXXXXXX. X.X.X.X. X.'); - - ZXingStringEncoding.customEncoder = undefined; - ZXingStringEncoding.customDecoder = undefined; - }); - - // Numbers are from http://www.swetake.com/qr/qr3.html and - // http://www.swetake.com/qr/qr9.html - it('testGenerateECBytes', () => { - let dataBytes = Uint8Array.from([32, 65, 205, 69, 41, 220, 46, 128, 236]); - let ecBytes: Uint8Array = QRCodeEncoder.generateECBytes(dataBytes, 17); - let expected = Int32Array.from([ - 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61 - ]); - assert.strictEqual(ecBytes.length, expected.length); - for (let x: number /*int*/ = 0; x < expected.length; x++) { - assert.strictEqual(ecBytes[x] & 0xFF, expected[x]); - } - dataBytes = Uint8Array.from([67, 70, 22, 38, 54, 70, 86, 102, 118, - 134, 150, 166, 182, 198, 214]); - ecBytes = QRCodeEncoder.generateECBytes(dataBytes, 18); - expected = Int32Array.from([ - 175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187 - ]); - assert.strictEqual(ecBytes.length, expected.length); - for (let x: number /*int*/ = 0; x < expected.length; x++) { - assert.strictEqual(ecBytes[x] & 0xFF, expected[x]); - } - // High-order zero coefficient case. - dataBytes = Uint8Array.from([32, 49, 205, 69, 42, 20, 0, 236, 17]); - ecBytes = QRCodeEncoder.generateECBytes(dataBytes, 17); - expected = Int32Array.from([ - 0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213 - ]); - assert.strictEqual(ecBytes.length, expected.length); - for (let x: number /*int*/ = 0; x < expected.length; x++) { - assert.strictEqual(ecBytes[x] & 0xFF, expected[x]); - } - }); - - it('testBugInBitVectorNumBytes', () => { - // There was a bug in BitVector.sizeInBytes() that caused it to return a - // smaller-by-one value (ex. 1465 instead of 1466) if the number of bits - // in the vector is not 8-bit aligned. In QRCodeEncoder::InitQRCode(), - // BitVector::sizeInBytes() is used for finding the smallest QR Code - // version that can fit the given data. Hence there were corner cases - // where we chose a wrong QR Code version that cannot fit the given - // data. Note that the issue did not occur with MODE_8BIT_BYTE, as the - // bits in the bit vector are always 8-bit aligned. - // - // Before the bug was fixed, the following test didn't pass, because: - // - // - MODE_NUMERIC is chosen as all bytes in the data are '0' - // - The 3518-byte numeric data needs 1466 bytes - // - 3518 / 3 * 10 + 7 = 11727 bits = 1465.875 bytes - // - 3 numeric bytes are encoded in 10 bits, hence the first - // 3516 bytes are encoded in 3516 / 3 * 10 = 11720 bits. - // - 2 numeric bytes can be encoded in 7 bits, hence the last - // 2 bytes are encoded in 7 bits. - // - The version 27 QR Code with the EC level L has 1468 bytes for data. - // - 1828 - 360 = 1468 - // - In InitQRCode(), 3 bytes are reserved for a header. Hence 1465 bytes - // (1468 -3) are left for data. - // - Because of the bug in BitVector::sizeInBytes(), InitQRCode() determines - // the given data can fit in 1465 bytes, despite it needs 1466 bytes. - // - Hence QRCodeEncoder.encode() failed and returned false. - // - To be precise, it needs 11727 + 4 (getMode info) + 14 (length info) = - // 11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468 - // bytes). - const builder = new ZXingStringBuilder(); // 3518) - for (let x: number /*int*/ = 0; x < 3518; x++) { - builder.append('0'); - } - QRCodeEncoder.encode(builder.toString(), QRCodeDecoderErrorCorrectionLevel.L); - }); - - function shiftJISString(bytes: Uint8Array): string { - try { - return ZXingStringEncoding.decode(bytes, CharacterSetECI.SJIS.getName()); - } catch (uee/*UnsupportedEncodingException*/) { - throw new WriterException(uee.toString()); - } + hints.set(EncodeHintType.QR_VERSION, 3); + QRCodeEncoder.encode('THISMESSAGEISTOOLONGFORAQRCODEVERSION3', QRCodeDecoderErrorCorrectionLevel.H, hints); + }, + WriterException, + 'unexpected exception thrown' + ); + }); + + it('testSimpleUTF8ECI', () => { + const hints = new Map(); // EncodeHintType.class) + hints.set(EncodeHintType.CHARACTER_SET, 'UTF8'); + const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('hello', QRCodeDecoderErrorCorrectionLevel.H, hints); + const expected: string = + '<<\n' + + ' mode: BYTE\n' + + ' ecLevel: H\n' + + ' version: 1\n' + + ' maskPattern: 6\n' + + ' matrix:\n' + + ' 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1\n' + + ' 1 0 1 1 1 0 1 0 1 0 0 1 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0\n' + + ' 0 0 0 1 1 0 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0\n' + + ' 0 0 0 0 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1\n' + + ' 1 1 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 1 0 1 1\n' + + ' 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 1 0 0 0\n' + + ' 0 1 1 0 0 1 1 0 0 1 1 1 0 1 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 0 0 1 0 0 0 0 0 0\n' + + ' 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 0 0\n' + + ' 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 0\n' + + ' 1 0 1 1 1 0 1 0 1 1 1 1 0 1 0 0 1 0 1 1 0\n' + + ' 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 0 0 1 0 1 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1 1 0 0 0\n' + + ' 1 1 1 1 1 1 1 0 0 0 0 1 0 1 0 0 1 0 1 0 0\n' + + '>>\n'; + assert.strictEqual(qrCode.toString(), expected); + }); + + it('testEncodeKanjiMode', () => { + + ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); + + const hints = new Map(); // EncodeHintType.class) + hints.set(EncodeHintType.CHARACTER_SET, CharacterSetECI.SJIS.getName()); + // Nihon in Kanji + const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('\u65e5\u672c', QRCodeDecoderErrorCorrectionLevel.M, hints); + const expected: string = + '<<\n' + + ' mode: KANJI\n' + + ' ecLevel: M\n' + + ' version: 1\n' + + ' maskPattern: 0\n' + + ' matrix:\n' + + ' 1 1 1 1 1 1 1 0 0 1 0 1 0 0 1 1 1 1 1 1 1\n' + + ' 1 0 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 0 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1 0\n' + + ' 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 0 1 0 0 0\n' + + ' 0 1 0 0 0 0 1 1 1 1 1 1 0 1 1 1 0 1 0 1 0\n' + + ' 1 1 1 0 0 1 0 1 0 0 0 1 1 1 0 1 1 0 1 0 0\n' + + ' 0 1 1 0 0 1 1 0 1 1 0 1 0 1 1 1 0 1 0 0 1\n' + + ' 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1\n' + + ' 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 1 0 0 1 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 1 1\n' + + ' 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 1 1 0 1 0 1 0 1 1 0 1 1 1 0 0 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0\n' + + ' 1 1 1 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 0 0\n' + + '>>\n'; + assert.strictEqual(qrCode.toString(), expected); + + ZXingStringEncoding.customEncoder = undefined; + }); + + it('testEncodeShiftjisNumeric', () => { + const hints = new Map(); // EncodeHintType.class) + hints.set(EncodeHintType.CHARACTER_SET, CharacterSetECI.SJIS.getName()); + const qrCode: QRCodeEncoderQRCode = QRCodeEncoder.encode('0123', QRCodeDecoderErrorCorrectionLevel.M, hints); + const expected: string = + '<<\n' + + ' mode: NUMERIC\n' + + ' ecLevel: M\n' + + ' version: 1\n' + + ' maskPattern: 2\n' + + ' matrix:\n' + + ' 1 1 1 1 1 1 1 0 0 1 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 1 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 0 1\n' + + ' 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0\n' + + ' 1 0 1 1 1 1 1 0 0 1 1 0 1 0 1 1 1 1 1 0 0\n' + + ' 1 1 0 0 0 1 0 0 1 0 1 0 1 0 0 1 0 0 1 0 0\n' + + ' 0 1 1 0 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1\n' + + ' 1 0 1 1 0 1 0 1 0 0 1 0 0 0 0 1 1 0 1 0 0\n' + + ' 0 0 1 0 0 1 1 1 0 0 0 1 0 1 0 0 1 0 1 0 0\n' + + ' 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 0 0 1 0 0 0\n' + + ' 1 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 0\n' + + ' 1 0 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0\n' + + ' 1 0 1 1 1 0 1 0 1 0 1 0 1 0 0 1 0 0 1 0 0\n' + + ' 1 0 1 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 1 0 0\n' + + ' 1 0 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 1 1 0 0\n' + + ' 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 1 1 0\n' + + ' 1 1 1 1 1 1 1 0 1 1 0 1 0 1 0 0 1 1 1 0 0\n' + + '>>\n'; + assert.strictEqual(qrCode.toString(), expected); + }); + + it('testAppendModeInfo', () => { + const bits = new BitArray(); + QRCodeEncoder.appendModeInfo(QRCodeMode.NUMERIC, bits); + assert.strictEqual(bits.toString(), ' ...X'); + }); + + it('testAppendLengthInfo', () => { + let bits = new BitArray(); + QRCodeEncoder.appendLengthInfo(1, // 1 letter (1/1). + QRCodeVersion.getVersionForNumber(1), + QRCodeMode.NUMERIC, + bits); + assert.strictEqual(bits.toString(), ' ........ .X'); // 10 bits. + bits = new BitArray(); + QRCodeEncoder.appendLengthInfo(2, // 2 letters (2/1). + QRCodeVersion.getVersionForNumber(10), + QRCodeMode.ALPHANUMERIC, + bits); + assert.strictEqual(bits.toString(), ' ........ .X.'); // 11 bits. + bits = new BitArray(); + QRCodeEncoder.appendLengthInfo(255, // 255 letter (255/1). + QRCodeVersion.getVersionForNumber(27), + QRCodeMode.BYTE, + bits); + assert.strictEqual(bits.toString(), ' ........ XXXXXXXX'); // 16 bits. + bits = new BitArray(); + QRCodeEncoder.appendLengthInfo(512, // 512 letters (1024/2). + QRCodeVersion.getVersionForNumber(40), + QRCodeMode.KANJI, + bits); + assert.strictEqual(bits.toString(), ' ..X..... ....'); // 12 bits. + }); + + it('testAppendBytes', () => { + ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); + ZXingStringEncoding.customDecoder = (b, e) => createCustomDecoder(e).decode(b); + + // Should use appendNumericBytes. + // 1 = 01 = 0001 in 4 bits. + let bits = new BitArray(); + QRCodeEncoder.appendBytes('1', QRCodeMode.NUMERIC, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); + assert.strictEqual(bits.toString(), ' ...X'); + // Should use appendAlphanumericBytes. + // A = 10 = 0xa = 001010 in 6 bits + bits = new BitArray(); + QRCodeEncoder.appendBytes('A', QRCodeMode.ALPHANUMERIC, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); + assert.strictEqual(bits.toString(), ' ..X.X.'); + // Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC. + try { + QRCodeEncoder.appendBytes('a', QRCodeMode.ALPHANUMERIC, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); + } catch (we/* WriterException */) { + if (we instanceof WriterException) { + // good + } else { + throw we; + } + } + // Should use append8BitBytes. + // 0x61, 0x62, 0x63 + bits = new BitArray(); + QRCodeEncoder.appendBytes('abc', QRCodeMode.BYTE, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); + assert.strictEqual(bits.toString(), ' .XX....X .XX...X. .XX...XX'); + // Anything can be encoded in QRCodeEncoderQRCode.MODE_8BIT_BYTE. + // TYPESCRIPTPORT: this seems to be unused: QRCodeEncoder.appendBytes("\0", QRCodeMode.BYTE, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING) + + // Should use appendKanjiBytes. + // 0x93, 0x5f + bits = new BitArray(); + QRCodeEncoder.appendBytes(shiftJISString(Uint8Array.from([0x93, 0x5f])), QRCodeMode.KANJI, bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); + assert.strictEqual(bits.toString(), ' .XX.XX.. XXXXX'); + + ZXingStringEncoding.customEncoder = undefined; + ZXingStringEncoding.customDecoder = undefined; + }); + + it('testTerminateBits', () => { + let v = new BitArray(); + QRCodeEncoder.terminateBits(0, v); + assert.strictEqual(v.toString(), ''); + v = new BitArray(); + QRCodeEncoder.terminateBits(1, v); + assert.strictEqual(v.toString(), ' ........'); + v = new BitArray(); + v.appendBits(0, 3); // Append 000 + QRCodeEncoder.terminateBits(1, v); + assert.strictEqual(v.toString(), ' ........'); + v = new BitArray(); + v.appendBits(0, 5); // Append 00000 + QRCodeEncoder.terminateBits(1, v); + assert.strictEqual(v.toString(), ' ........'); + v = new BitArray(); + v.appendBits(0, 8); // Append 00000000 + QRCodeEncoder.terminateBits(1, v); + assert.strictEqual(v.toString(), ' ........'); + v = new BitArray(); + QRCodeEncoder.terminateBits(2, v); + assert.strictEqual(v.toString(), ' ........ XXX.XX..'); + v = new BitArray(); + v.appendBits(0, 1); // Append 0 + QRCodeEncoder.terminateBits(3, v); + assert.strictEqual(v.toString(), ' ........ XXX.XX.. ...X...X'); + }); + + it('testGetNumDataBytesAndNumECBytesForBlockID', () => { + const numDataBytes = new Int32Array(1); /* Int32Array(1) */ + const numEcBytes = new Int32Array(1); /* Int32Array(1) */ + // Version 1-H. + QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, numDataBytes, numEcBytes); + assert.strictEqual(numDataBytes[0], 9); + assert.strictEqual(numEcBytes[0], 17); + + // Version 3-H. 2 blocks. + QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0, numDataBytes, numEcBytes); + assert.strictEqual(numDataBytes[0], 13); + assert.strictEqual(numEcBytes[0], 22); + QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, numDataBytes, numEcBytes); + assert.strictEqual(numDataBytes[0], 13); + assert.strictEqual(numEcBytes[0], 22); + + // Version 7-H. (4 + 1) blocks. + QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0, numDataBytes, numEcBytes); + assert.strictEqual(numDataBytes[0], 13); + assert.strictEqual(numEcBytes[0], 26); + QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, numDataBytes, numEcBytes); + assert.strictEqual(numDataBytes[0], 14); + assert.strictEqual(numEcBytes[0], 26); + + // Version 40-H. (20 + 61) blocks. + QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0, numDataBytes, numEcBytes); + assert.strictEqual(numDataBytes[0], 15); + assert.strictEqual(numEcBytes[0], 30); + QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, numDataBytes, numEcBytes); + assert.strictEqual(numDataBytes[0], 16); + assert.strictEqual(numEcBytes[0], 30); + QRCodeEncoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, numDataBytes, numEcBytes); + assert.strictEqual(numDataBytes[0], 16); + assert.strictEqual(numEcBytes[0], 30); + }); + + it('testInterleaveWithECBytes', () => { + let dataBytes = Uint8Array.from([32, 65, 205, 69, 41, 220, 46, 128, 236]); + let input = new BitArray(); + for (let i = 0, length = dataBytes.length; i !== length; i++) { + const dataByte = dataBytes[i]; + input.appendBits(dataByte, 8); + } + let out: BitArray = QRCodeEncoder.interleaveWithECBytes(input, 26, 9, 1); + let expected = Uint8Array.from([ + // Data bytes. + 32, 65, 205, 69, 41, 220, 46, 128, 236, + // Error correction bytes. + 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, + 237, 85, 224, 96, 74, 219, 61, + ]); + assert.strictEqual(out.getSizeInBytes(), expected.length); + let outArray = new Uint8Array(expected.length); + out.toBytes(0, outArray, 0, expected.length); + // Can't use ZXingArrays.equals(), because outArray may be longer than out.sizeInBytes() + for (let x: number /* int */ = 0; x < expected.length; x++) { + assert.strictEqual(outArray[x], expected[x]); + } + // Numbers are from http://www.swetake.com/qr/qr8.html + dataBytes = Uint8Array.from([ + 67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, + 198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, 135, + 151, 166, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, + 182, 198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, + 135, 151, 160, 236, 17, 236, 17, 236, 17, 236, + 17 + ]); + input = new BitArray(); + for (let i = 0, length = dataBytes.length; i !== length; i++) { + const dataByte = dataBytes[i]; + input.appendBits(dataByte, 8); + } + + out = QRCodeEncoder.interleaveWithECBytes(input, 134, 62, 4); + expected = Uint8Array.from([ + // Data bytes. + 67, 230, 54, 55, 70, 247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39, + 118, 119, 70, 55, 134, 135, 86, 71, 150, 151, 102, 87, 166, + 160, 118, 103, 182, 236, 134, 119, 198, 17, 150, + 135, 214, 236, 166, 151, 230, 17, 182, + 166, 247, 236, 198, 22, 7, 17, 214, 38, 23, 236, 39, + 17, + // Error correction bytes. + 175, 155, 245, 236, 80, 146, 56, 74, 155, 165, + 133, 142, 64, 183, 132, 13, 178, 54, 132, 108, 45, + 113, 53, 50, 214, 98, 193, 152, 233, 147, 50, 71, 65, + 190, 82, 51, 209, 199, 171, 54, 12, 112, 57, 113, 155, 117, + 211, 164, 117, 30, 158, 225, 31, 190, 242, 38, + 140, 61, 179, 154, 214, 138, 147, 87, 27, 96, 77, 47, + 187, 49, 156, 214, + ]); + assert.strictEqual(out.getSizeInBytes(), expected.length); + outArray = new Uint8Array(expected.length); + out.toBytes(0, outArray, 0, expected.length); + for (let x: number /* int */ = 0; x < expected.length; x++) { + assert.strictEqual(outArray[x], expected[x]); + } + }); + + it('testAppendNumericBytes', () => { + // 1 = 01 = 0001 in 4 bits. + let bits = new BitArray(); + QRCodeEncoder.appendNumericBytes('1', bits); + assert.strictEqual(bits.toString(), ' ...X'); + // 12 = 0xc = 0001100 in 7 bits. + bits = new BitArray(); + QRCodeEncoder.appendNumericBytes('12', bits); + assert.strictEqual(bits.toString(), ' ...XX..'); + // 123 = 0x7b = 0001111011 in 10 bits. + bits = new BitArray(); + QRCodeEncoder.appendNumericBytes('123', bits); + assert.strictEqual(bits.toString(), ' ...XXXX. XX'); + // 1234 = "123" + "4" = 0001111011 + 0100 + bits = new BitArray(); + QRCodeEncoder.appendNumericBytes('1234', bits); + assert.strictEqual(bits.toString(), ' ...XXXX. XX.X..'); + // Empty. + bits = new BitArray(); + QRCodeEncoder.appendNumericBytes('', bits); + assert.strictEqual(bits.toString(), ''); + }); + + it('testAppendAlphanumericBytes', () => { + // A = 10 = 0xa = 001010 in 6 bits + let bits = new BitArray(); + QRCodeEncoder.appendAlphanumericBytes('A', bits); + assert.strictEqual(bits.toString(), ' ..X.X.'); + // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits + bits = new BitArray(); + QRCodeEncoder.appendAlphanumericBytes('AB', bits); + assert.strictEqual(bits.toString(), ' ..XXX..X X.X'); + // ABC = "AB" + "C" = 00111001101 + 001100 + bits = new BitArray(); + QRCodeEncoder.appendAlphanumericBytes('ABC', bits); + assert.strictEqual(bits.toString(), ' ..XXX..X X.X..XX. .'); + // Empty. + bits = new BitArray(); + QRCodeEncoder.appendAlphanumericBytes('', bits); + assert.strictEqual(bits.toString(), ''); + // Invalid data. + try { + QRCodeEncoder.appendAlphanumericBytes('abc', new BitArray()); + } catch (we/* WriterException */) { + // good + } + }); + + it('testAppend8BitBytes', () => { + ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); + // 0x61, 0x62, 0x63 + let bits = new BitArray(); + QRCodeEncoder.append8BitBytes('abc', bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); + assert.strictEqual(bits.toString(), ' .XX....X .XX...X. .XX...XX'); + // Empty. + bits = new BitArray(); + QRCodeEncoder.append8BitBytes('', bits, QRCodeEncoder.DEFAULT_BYTE_MODE_ENCODING); + assert.strictEqual(bits.toString(), ''); + }); + + // Numbers are from page 21 of JISX0510:2004 + it('testAppendKanjiBytes', () => { + ZXingStringEncoding.customEncoder = (b, e) => createCustomEncoder(e).encode(b); + ZXingStringEncoding.customDecoder = (b, e) => createCustomDecoder(e).decode(b); + + const bits = new BitArray(); + QRCodeEncoder.appendKanjiBytes(shiftJISString(Uint8Array.from([0x93, 0x5f])), bits); + assert.strictEqual(bits.toString(), ' .XX.XX.. XXXXX'); + QRCodeEncoder.appendKanjiBytes(shiftJISString(Uint8Array.from([0xe4, 0xaa])), bits); + assert.strictEqual(bits.toString(), ' .XX.XX.. XXXXXXX. X.X.X.X. X.'); + + ZXingStringEncoding.customEncoder = undefined; + ZXingStringEncoding.customDecoder = undefined; + }); + + // Numbers are from http://www.swetake.com/qr/qr3.html and + // http://www.swetake.com/qr/qr9.html + it('testGenerateECBytes', () => { + let dataBytes = Uint8Array.from([32, 65, 205, 69, 41, 220, 46, 128, 236]); + let ecBytes: Uint8Array = QRCodeEncoder.generateECBytes(dataBytes, 17); + let expected = Int32Array.from([ + 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61 + ]); + assert.strictEqual(ecBytes.length, expected.length); + for (let x: number /* int */ = 0; x < expected.length; x++) { + assert.strictEqual(ecBytes[x] & 0xFF, expected[x]); + } + dataBytes = Uint8Array.from([67, 70, 22, 38, 54, 70, 86, 102, 118, + 134, 150, 166, 182, 198, 214]); + ecBytes = QRCodeEncoder.generateECBytes(dataBytes, 18); + expected = Int32Array.from([ + 175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187 + ]); + assert.strictEqual(ecBytes.length, expected.length); + for (let x: number /* int */ = 0; x < expected.length; x++) { + assert.strictEqual(ecBytes[x] & 0xFF, expected[x]); + } + // High-order zero coefficient case. + dataBytes = Uint8Array.from([32, 49, 205, 69, 42, 20, 0, 236, 17]); + ecBytes = QRCodeEncoder.generateECBytes(dataBytes, 17); + expected = Int32Array.from([ + 0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213 + ]); + assert.strictEqual(ecBytes.length, expected.length); + for (let x: number /* int */ = 0; x < expected.length; x++) { + assert.strictEqual(ecBytes[x] & 0xFF, expected[x]); + } + }); + + it('testBugInBitVectorNumBytes', () => { + // There was a bug in BitVector.sizeInBytes() that caused it to return a + // smaller-by-one value (ex. 1465 instead of 1466) if the number of bits + // in the vector is not 8-bit aligned. In QRCodeEncoder::InitQRCode(), + // BitVector::sizeInBytes() is used for finding the smallest QR Code + // version that can fit the given data. Hence there were corner cases + // where we chose a wrong QR Code version that cannot fit the given + // data. Note that the issue did not occur with MODE_8BIT_BYTE, as the + // bits in the bit vector are always 8-bit aligned. + // + // Before the bug was fixed, the following test didn't pass, because: + // + // - MODE_NUMERIC is chosen as all bytes in the data are '0' + // - The 3518-byte numeric data needs 1466 bytes + // - 3518 / 3 * 10 + 7 = 11727 bits = 1465.875 bytes + // - 3 numeric bytes are encoded in 10 bits, hence the first + // 3516 bytes are encoded in 3516 / 3 * 10 = 11720 bits. + // - 2 numeric bytes can be encoded in 7 bits, hence the last + // 2 bytes are encoded in 7 bits. + // - The version 27 QR Code with the EC level L has 1468 bytes for data. + // - 1828 - 360 = 1468 + // - In InitQRCode(), 3 bytes are reserved for a header. Hence 1465 bytes + // (1468 -3) are left for data. + // - Because of the bug in BitVector::sizeInBytes(), InitQRCode() determines + // the given data can fit in 1465 bytes, despite it needs 1466 bytes. + // - Hence QRCodeEncoder.encode() failed and returned false. + // - To be precise, it needs 11727 + 4 (getMode info) + 14 (length info) = + // 11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468 + // bytes). + const builder = new ZXingStringBuilder(); // 3518) + for (let x: number /* int */ = 0; x < 3518; x++) { + builder.append('0'); + } + QRCodeEncoder.encode(builder.toString(), QRCodeDecoderErrorCorrectionLevel.L); + }); + + function shiftJISString(bytes: Uint8Array): string { + try { + return ZXingStringEncoding.decode(bytes, CharacterSetECI.SJIS.getName()); + } catch (uee/* UnsupportedEncodingException */) { + throw new WriterException(uee.toString()); } + } }); diff --git a/src/test/core/qrcode/encoder/MaskUtil.spec.ts b/src/test/core/qrcode/encoder/MaskUtil.spec.ts index f360207b..6185b190 100644 --- a/src/test/core/qrcode/encoder/MaskUtil.spec.ts +++ b/src/test/core/qrcode/encoder/MaskUtil.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.encoder;*/ +/* package com.google.zxing.qrcode.encoder; */ import * as assert from 'assert'; import { QRCodeByteMatrix } from '@zxing/library'; @@ -26,231 +26,231 @@ import { QRCodeMaskUtil } from '@zxing/library'; */ describe('QRCodeMaskUtil', () => { - it('testApplyMaskPenaltyRule1', () => { - let matrix = new QRCodeByteMatrix(4, 1); - matrix.setNumber(0, 0, 0); - matrix.setNumber(1, 0, 0); - matrix.setNumber(2, 0, 0); - matrix.setNumber(3, 0, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 0); - // Horizontal. - matrix = new QRCodeByteMatrix(6, 1); - matrix.setNumber(0, 0, 0); - matrix.setNumber(1, 0, 0); - matrix.setNumber(2, 0, 0); - matrix.setNumber(3, 0, 0); - matrix.setNumber(4, 0, 0); - matrix.setNumber(5, 0, 1); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 3); - matrix.setNumber(5, 0, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 4); - // Vertical. - matrix = new QRCodeByteMatrix(1, 6); - matrix.setNumber(0, 0, 0); - matrix.setNumber(0, 1, 0); - matrix.setNumber(0, 2, 0); - matrix.setNumber(0, 3, 0); - matrix.setNumber(0, 4, 0); - matrix.setNumber(0, 5, 1); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 3); - matrix.setNumber(0, 5, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 4); - }); + it('testApplyMaskPenaltyRule1', () => { + let matrix = new QRCodeByteMatrix(4, 1); + matrix.setNumber(0, 0, 0); + matrix.setNumber(1, 0, 0); + matrix.setNumber(2, 0, 0); + matrix.setNumber(3, 0, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 0); + // Horizontal. + matrix = new QRCodeByteMatrix(6, 1); + matrix.setNumber(0, 0, 0); + matrix.setNumber(1, 0, 0); + matrix.setNumber(2, 0, 0); + matrix.setNumber(3, 0, 0); + matrix.setNumber(4, 0, 0); + matrix.setNumber(5, 0, 1); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 3); + matrix.setNumber(5, 0, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 4); + // Vertical. + matrix = new QRCodeByteMatrix(1, 6); + matrix.setNumber(0, 0, 0); + matrix.setNumber(0, 1, 0); + matrix.setNumber(0, 2, 0); + matrix.setNumber(0, 3, 0); + matrix.setNumber(0, 4, 0); + matrix.setNumber(0, 5, 1); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 3); + matrix.setNumber(0, 5, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule1(matrix), 4); + }); - it('testApplyMaskPenaltyRule2', () => { - let matrix = new QRCodeByteMatrix(1, 1); - matrix.setNumber(0, 0, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule2(matrix), 0); - matrix = new QRCodeByteMatrix(2, 2); - matrix.setNumber(0, 0, 0); - matrix.setNumber(1, 0, 0); - matrix.setNumber(0, 1, 0); - matrix.setNumber(1, 1, 1); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule2(matrix), 0); - matrix = new QRCodeByteMatrix(2, 2); - matrix.setNumber(0, 0, 0); - matrix.setNumber(1, 0, 0); - matrix.setNumber(0, 1, 0); - matrix.setNumber(1, 1, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule2(matrix), 3); - matrix = new QRCodeByteMatrix(3, 3); - matrix.setNumber(0, 0, 0); - matrix.setNumber(1, 0, 0); - matrix.setNumber(2, 0, 0); - matrix.setNumber(0, 1, 0); - matrix.setNumber(1, 1, 0); - matrix.setNumber(2, 1, 0); - matrix.setNumber(0, 2, 0); - matrix.setNumber(1, 2, 0); - matrix.setNumber(2, 2, 0); - // Four instances of 2x2 blocks. - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule2(matrix), 3 * 4); - }); + it('testApplyMaskPenaltyRule2', () => { + let matrix = new QRCodeByteMatrix(1, 1); + matrix.setNumber(0, 0, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule2(matrix), 0); + matrix = new QRCodeByteMatrix(2, 2); + matrix.setNumber(0, 0, 0); + matrix.setNumber(1, 0, 0); + matrix.setNumber(0, 1, 0); + matrix.setNumber(1, 1, 1); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule2(matrix), 0); + matrix = new QRCodeByteMatrix(2, 2); + matrix.setNumber(0, 0, 0); + matrix.setNumber(1, 0, 0); + matrix.setNumber(0, 1, 0); + matrix.setNumber(1, 1, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule2(matrix), 3); + matrix = new QRCodeByteMatrix(3, 3); + matrix.setNumber(0, 0, 0); + matrix.setNumber(1, 0, 0); + matrix.setNumber(2, 0, 0); + matrix.setNumber(0, 1, 0); + matrix.setNumber(1, 1, 0); + matrix.setNumber(2, 1, 0); + matrix.setNumber(0, 2, 0); + matrix.setNumber(1, 2, 0); + matrix.setNumber(2, 2, 0); + // Four instances of 2x2 blocks. + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule2(matrix), 3 * 4); + }); - it('testApplyMaskPenaltyRule3', () => { - // Horizontal 00001011101. - let matrix = new QRCodeByteMatrix(11, 1); - matrix.setNumber(0, 0, 0); - matrix.setNumber(1, 0, 0); - matrix.setNumber(2, 0, 0); - matrix.setNumber(3, 0, 0); - matrix.setNumber(4, 0, 1); - matrix.setNumber(5, 0, 0); - matrix.setNumber(6, 0, 1); - matrix.setNumber(7, 0, 1); - matrix.setNumber(8, 0, 1); - matrix.setNumber(9, 0, 0); - matrix.setNumber(10, 0, 1); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule3(matrix), 40); - // Horizontal 10111010000. - matrix = new QRCodeByteMatrix(11, 1); - matrix.setNumber(0, 0, 1); - matrix.setNumber(1, 0, 0); - matrix.setNumber(2, 0, 1); - matrix.setNumber(3, 0, 1); - matrix.setNumber(4, 0, 1); - matrix.setNumber(5, 0, 0); - matrix.setNumber(6, 0, 1); - matrix.setNumber(7, 0, 0); - matrix.setNumber(8, 0, 0); - matrix.setNumber(9, 0, 0); - matrix.setNumber(10, 0, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule3(matrix), 40); - // Vertical 00001011101. - matrix = new QRCodeByteMatrix(1, 11); - matrix.setNumber(0, 0, 0); - matrix.setNumber(0, 1, 0); - matrix.setNumber(0, 2, 0); - matrix.setNumber(0, 3, 0); - matrix.setNumber(0, 4, 1); - matrix.setNumber(0, 5, 0); - matrix.setNumber(0, 6, 1); - matrix.setNumber(0, 7, 1); - matrix.setNumber(0, 8, 1); - matrix.setNumber(0, 9, 0); - matrix.setNumber(0, 10, 1); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule3(matrix), 40); - // Vertical 10111010000. - matrix = new QRCodeByteMatrix(1, 11); - matrix.setNumber(0, 0, 1); - matrix.setNumber(0, 1, 0); - matrix.setNumber(0, 2, 1); - matrix.setNumber(0, 3, 1); - matrix.setNumber(0, 4, 1); - matrix.setNumber(0, 5, 0); - matrix.setNumber(0, 6, 1); - matrix.setNumber(0, 7, 0); - matrix.setNumber(0, 8, 0); - matrix.setNumber(0, 9, 0); - matrix.setNumber(0, 10, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule3(matrix), 40); - }); + it('testApplyMaskPenaltyRule3', () => { + // Horizontal 00001011101. + let matrix = new QRCodeByteMatrix(11, 1); + matrix.setNumber(0, 0, 0); + matrix.setNumber(1, 0, 0); + matrix.setNumber(2, 0, 0); + matrix.setNumber(3, 0, 0); + matrix.setNumber(4, 0, 1); + matrix.setNumber(5, 0, 0); + matrix.setNumber(6, 0, 1); + matrix.setNumber(7, 0, 1); + matrix.setNumber(8, 0, 1); + matrix.setNumber(9, 0, 0); + matrix.setNumber(10, 0, 1); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule3(matrix), 40); + // Horizontal 10111010000. + matrix = new QRCodeByteMatrix(11, 1); + matrix.setNumber(0, 0, 1); + matrix.setNumber(1, 0, 0); + matrix.setNumber(2, 0, 1); + matrix.setNumber(3, 0, 1); + matrix.setNumber(4, 0, 1); + matrix.setNumber(5, 0, 0); + matrix.setNumber(6, 0, 1); + matrix.setNumber(7, 0, 0); + matrix.setNumber(8, 0, 0); + matrix.setNumber(9, 0, 0); + matrix.setNumber(10, 0, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule3(matrix), 40); + // Vertical 00001011101. + matrix = new QRCodeByteMatrix(1, 11); + matrix.setNumber(0, 0, 0); + matrix.setNumber(0, 1, 0); + matrix.setNumber(0, 2, 0); + matrix.setNumber(0, 3, 0); + matrix.setNumber(0, 4, 1); + matrix.setNumber(0, 5, 0); + matrix.setNumber(0, 6, 1); + matrix.setNumber(0, 7, 1); + matrix.setNumber(0, 8, 1); + matrix.setNumber(0, 9, 0); + matrix.setNumber(0, 10, 1); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule3(matrix), 40); + // Vertical 10111010000. + matrix = new QRCodeByteMatrix(1, 11); + matrix.setNumber(0, 0, 1); + matrix.setNumber(0, 1, 0); + matrix.setNumber(0, 2, 1); + matrix.setNumber(0, 3, 1); + matrix.setNumber(0, 4, 1); + matrix.setNumber(0, 5, 0); + matrix.setNumber(0, 6, 1); + matrix.setNumber(0, 7, 0); + matrix.setNumber(0, 8, 0); + matrix.setNumber(0, 9, 0); + matrix.setNumber(0, 10, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule3(matrix), 40); + }); - it('testApplyMaskPenaltyRule4', () => { - // Dark cell ratio = 0% - let matrix = new QRCodeByteMatrix(1, 1); - matrix.setNumber(0, 0, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule4(matrix), 100); - // Dark cell ratio = 5% - matrix = new QRCodeByteMatrix(2, 1); - matrix.setNumber(0, 0, 0); - matrix.setNumber(0, 0, 1); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule4(matrix), 0); - // Dark cell ratio = 66.67% - matrix = new QRCodeByteMatrix(6, 1); - matrix.setNumber(0, 0, 0); - matrix.setNumber(1, 0, 1); - matrix.setNumber(2, 0, 1); - matrix.setNumber(3, 0, 1); - matrix.setNumber(4, 0, 1); - matrix.setNumber(5, 0, 0); - assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule4(matrix), 30); - }); + it('testApplyMaskPenaltyRule4', () => { + // Dark cell ratio = 0% + let matrix = new QRCodeByteMatrix(1, 1); + matrix.setNumber(0, 0, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule4(matrix), 100); + // Dark cell ratio = 5% + matrix = new QRCodeByteMatrix(2, 1); + matrix.setNumber(0, 0, 0); + matrix.setNumber(0, 0, 1); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule4(matrix), 0); + // Dark cell ratio = 66.67% + matrix = new QRCodeByteMatrix(6, 1); + matrix.setNumber(0, 0, 0); + matrix.setNumber(1, 0, 1); + matrix.setNumber(2, 0, 1); + matrix.setNumber(3, 0, 1); + matrix.setNumber(4, 0, 1); + matrix.setNumber(5, 0, 0); + assert.strictEqual(QRCodeMaskUtil.applyMaskPenaltyRule4(matrix), 30); + }); - function TestGetDataMaskBitInternal(maskPattern: number /*int*/, expected: Array): boolean { - for (let x: number /*int*/ = 0; x < 6; ++x) { - for (let y: number /*int*/ = 0; y < 6; ++y) { - if ((expected[y][x] === 1) !== QRCodeMaskUtil.getDataMaskBit(maskPattern, x, y)) { - return false; - } - } + function TestGetDataMaskBitInternal(maskPattern: number /* int */, expected: Array): boolean { + for (let x: number /* int */ = 0; x < 6; ++x) { + for (let y: number /* int */ = 0; y < 6; ++y) { + if ((expected[y][x] === 1) !== QRCodeMaskUtil.getDataMaskBit(maskPattern, x, y)) { + return false; } - return true; + } } + return true; + } - // See mask patterns on the page 43 of JISX0510:2004. - it('testGetDataMaskBit', () => { - const mask0 = [ - Int32Array.from([1, 0, 1, 0, 1, 0]), - Int32Array.from([0, 1, 0, 1, 0, 1]), - Int32Array.from([1, 0, 1, 0, 1, 0]), - Int32Array.from([0, 1, 0, 1, 0, 1]), - Int32Array.from([1, 0, 1, 0, 1, 0]), - Int32Array.from([0, 1, 0, 1, 0, 1]) - ]; - assert.strictEqual(TestGetDataMaskBitInternal(0, mask0), true); - const mask1 = [ - Int32Array.from([1, 1, 1, 1, 1, 1]), - Int32Array.from([0, 0, 0, 0, 0, 0]), - Int32Array.from([1, 1, 1, 1, 1, 1]), - Int32Array.from([0, 0, 0, 0, 0, 0]), - Int32Array.from([1, 1, 1, 1, 1, 1]), - Int32Array.from([0, 0, 0, 0, 0, 0]), - ]; - assert.strictEqual(TestGetDataMaskBitInternal(1, mask1), true); - const mask2 = [ - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([1, 0, 0, 1, 0, 0]), - ]; - assert.strictEqual(TestGetDataMaskBitInternal(2, mask2), true); - const mask3 = [ - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([0, 0, 1, 0, 0, 1]), - Int32Array.from([0, 1, 0, 0, 1, 0]), - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([0, 0, 1, 0, 0, 1]), - Int32Array.from([0, 1, 0, 0, 1, 0]), - ]; - assert.strictEqual(TestGetDataMaskBitInternal(3, mask3), true); - const mask4 = [ - Int32Array.from([1, 1, 1, 0, 0, 0]), - Int32Array.from([1, 1, 1, 0, 0, 0]), - Int32Array.from([0, 0, 0, 1, 1, 1]), - Int32Array.from([0, 0, 0, 1, 1, 1]), - Int32Array.from([1, 1, 1, 0, 0, 0]), - Int32Array.from([1, 1, 1, 0, 0, 0]), - ]; - assert.strictEqual(TestGetDataMaskBitInternal(4, mask4), true); - const mask5 = [ - Int32Array.from([1, 1, 1, 1, 1, 1]), - Int32Array.from([1, 0, 0, 0, 0, 0]), - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([1, 0, 1, 0, 1, 0]), - Int32Array.from([1, 0, 0, 1, 0, 0]), - Int32Array.from([1, 0, 0, 0, 0, 0]), - ]; - assert.strictEqual(TestGetDataMaskBitInternal(5, mask5), true); - const mask6 = [ - Int32Array.from([1, 1, 1, 1, 1, 1]), - Int32Array.from([1, 1, 1, 0, 0, 0]), - Int32Array.from([1, 1, 0, 1, 1, 0]), - Int32Array.from([1, 0, 1, 0, 1, 0]), - Int32Array.from([1, 0, 1, 1, 0, 1]), - Int32Array.from([1, 0, 0, 0, 1, 1]), - ]; - assert.strictEqual(TestGetDataMaskBitInternal(6, mask6), true); - const mask7 = [ - Int32Array.from([1, 0, 1, 0, 1, 0]), - Int32Array.from([0, 0, 0, 1, 1, 1]), - Int32Array.from([1, 0, 0, 0, 1, 1]), - Int32Array.from([0, 1, 0, 1, 0, 1]), - Int32Array.from([1, 1, 1, 0, 0, 0]), - Int32Array.from([0, 1, 1, 1, 0, 0]), - ]; - assert.strictEqual(TestGetDataMaskBitInternal(7, mask7), true); - }); + // See mask patterns on the page 43 of JISX0510:2004. + it('testGetDataMaskBit', () => { + const mask0 = [ + Int32Array.from([1, 0, 1, 0, 1, 0]), + Int32Array.from([0, 1, 0, 1, 0, 1]), + Int32Array.from([1, 0, 1, 0, 1, 0]), + Int32Array.from([0, 1, 0, 1, 0, 1]), + Int32Array.from([1, 0, 1, 0, 1, 0]), + Int32Array.from([0, 1, 0, 1, 0, 1]) + ]; + assert.strictEqual(TestGetDataMaskBitInternal(0, mask0), true); + const mask1 = [ + Int32Array.from([1, 1, 1, 1, 1, 1]), + Int32Array.from([0, 0, 0, 0, 0, 0]), + Int32Array.from([1, 1, 1, 1, 1, 1]), + Int32Array.from([0, 0, 0, 0, 0, 0]), + Int32Array.from([1, 1, 1, 1, 1, 1]), + Int32Array.from([0, 0, 0, 0, 0, 0]), + ]; + assert.strictEqual(TestGetDataMaskBitInternal(1, mask1), true); + const mask2 = [ + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([1, 0, 0, 1, 0, 0]), + ]; + assert.strictEqual(TestGetDataMaskBitInternal(2, mask2), true); + const mask3 = [ + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([0, 0, 1, 0, 0, 1]), + Int32Array.from([0, 1, 0, 0, 1, 0]), + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([0, 0, 1, 0, 0, 1]), + Int32Array.from([0, 1, 0, 0, 1, 0]), + ]; + assert.strictEqual(TestGetDataMaskBitInternal(3, mask3), true); + const mask4 = [ + Int32Array.from([1, 1, 1, 0, 0, 0]), + Int32Array.from([1, 1, 1, 0, 0, 0]), + Int32Array.from([0, 0, 0, 1, 1, 1]), + Int32Array.from([0, 0, 0, 1, 1, 1]), + Int32Array.from([1, 1, 1, 0, 0, 0]), + Int32Array.from([1, 1, 1, 0, 0, 0]), + ]; + assert.strictEqual(TestGetDataMaskBitInternal(4, mask4), true); + const mask5 = [ + Int32Array.from([1, 1, 1, 1, 1, 1]), + Int32Array.from([1, 0, 0, 0, 0, 0]), + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([1, 0, 1, 0, 1, 0]), + Int32Array.from([1, 0, 0, 1, 0, 0]), + Int32Array.from([1, 0, 0, 0, 0, 0]), + ]; + assert.strictEqual(TestGetDataMaskBitInternal(5, mask5), true); + const mask6 = [ + Int32Array.from([1, 1, 1, 1, 1, 1]), + Int32Array.from([1, 1, 1, 0, 0, 0]), + Int32Array.from([1, 1, 0, 1, 1, 0]), + Int32Array.from([1, 0, 1, 0, 1, 0]), + Int32Array.from([1, 0, 1, 1, 0, 1]), + Int32Array.from([1, 0, 0, 0, 1, 1]), + ]; + assert.strictEqual(TestGetDataMaskBitInternal(6, mask6), true); + const mask7 = [ + Int32Array.from([1, 0, 1, 0, 1, 0]), + Int32Array.from([0, 0, 0, 1, 1, 1]), + Int32Array.from([1, 0, 0, 0, 1, 1]), + Int32Array.from([0, 1, 0, 1, 0, 1]), + Int32Array.from([1, 1, 1, 0, 0, 0]), + Int32Array.from([0, 1, 1, 1, 0, 0]), + ]; + assert.strictEqual(TestGetDataMaskBitInternal(7, mask7), true); + }); }); diff --git a/src/test/core/qrcode/encoder/MatrixUtil.spec.ts b/src/test/core/qrcode/encoder/MatrixUtil.spec.ts index 613becd9..3ef8c851 100644 --- a/src/test/core/qrcode/encoder/MatrixUtil.spec.ts +++ b/src/test/core/qrcode/encoder/MatrixUtil.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.encoder;*/ +/* package com.google.zxing.qrcode.encoder; */ import * as assert from 'assert'; import { BitArray } from '@zxing/library'; @@ -29,274 +29,274 @@ import { QRCodeVersion } from '@zxing/library'; */ describe('QRCodeMatrixUtil', () => { - it('testToString', () => { - const array = new QRCodeByteMatrix(3, 3); - array.setNumber(0, 0, 0); - array.setNumber(1, 0, 1); - array.setNumber(2, 0, 0); - array.setNumber(0, 1, 1); - array.setNumber(1, 1, 0); - array.setNumber(2, 1, 1); - array.setNumber(0, 2, -1); - array.setNumber(1, 2, -1); - array.setNumber(2, 2, -1); - const expected: string = ' 0 1 0\n' + ' 1 0 1\n' + ' \n'; - assert.strictEqual(array.toString(), expected); - }); + it('testToString', () => { + const array = new QRCodeByteMatrix(3, 3); + array.setNumber(0, 0, 0); + array.setNumber(1, 0, 1); + array.setNumber(2, 0, 0); + array.setNumber(0, 1, 1); + array.setNumber(1, 1, 0); + array.setNumber(2, 1, 1); + array.setNumber(0, 2, -1); + array.setNumber(1, 2, -1); + array.setNumber(2, 2, -1); + const expected: string = ' 0 1 0\n' + ' 1 0 1\n' + ' \n'; + assert.strictEqual(array.toString(), expected); + }); - it('testClearMatrix', () => { - const matrix = new QRCodeByteMatrix(2, 2); - QRCodeMatrixUtil.clearMatrix(matrix); - // TYPESCRIPTPORT: we use UintArray se changed here from -1 to 255 - assert.strictEqual(matrix.get(0, 0), 255); - assert.strictEqual(matrix.get(1, 0), 255); - assert.strictEqual(matrix.get(0, 1), 255); - assert.strictEqual(matrix.get(1, 1), 255); - }); + it('testClearMatrix', () => { + const matrix = new QRCodeByteMatrix(2, 2); + QRCodeMatrixUtil.clearMatrix(matrix); + // TYPESCRIPTPORT: we use UintArray se changed here from -1 to 255 + assert.strictEqual(matrix.get(0, 0), 255); + assert.strictEqual(matrix.get(1, 0), 255); + assert.strictEqual(matrix.get(0, 1), 255); + assert.strictEqual(matrix.get(1, 1), 255); + }); - it('testEmbedBasicPatterns1', () => { - // QRCodeVersion 1. - const matrix = new QRCodeByteMatrix(21, 21); - QRCodeMatrixUtil.clearMatrix(matrix); - QRCodeMatrixUtil.embedBasicPatterns(QRCodeVersion.getVersionForNumber(1), matrix); - const expected: string = - ' 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n' + - ' 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 \n' + - ' 0 \n' + - ' 1 \n' + - ' 0 \n' + - ' 1 \n' + - ' 0 0 0 0 0 0 0 0 1 \n' + - ' 1 1 1 1 1 1 1 0 \n' + - ' 1 0 0 0 0 0 1 0 \n' + - ' 1 0 1 1 1 0 1 0 \n' + - ' 1 0 1 1 1 0 1 0 \n' + - ' 1 0 1 1 1 0 1 0 \n' + - ' 1 0 0 0 0 0 1 0 \n' + - ' 1 1 1 1 1 1 1 0 \n'; - assert.strictEqual(matrix.toString(), expected); - }); + it('testEmbedBasicPatterns1', () => { + // QRCodeVersion 1. + const matrix = new QRCodeByteMatrix(21, 21); + QRCodeMatrixUtil.clearMatrix(matrix); + QRCodeMatrixUtil.embedBasicPatterns(QRCodeVersion.getVersionForNumber(1), matrix); + const expected: string = + ' 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n' + + ' 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 \n' + + ' 0 \n' + + ' 1 \n' + + ' 0 \n' + + ' 1 \n' + + ' 0 0 0 0 0 0 0 0 1 \n' + + ' 1 1 1 1 1 1 1 0 \n' + + ' 1 0 0 0 0 0 1 0 \n' + + ' 1 0 1 1 1 0 1 0 \n' + + ' 1 0 1 1 1 0 1 0 \n' + + ' 1 0 1 1 1 0 1 0 \n' + + ' 1 0 0 0 0 0 1 0 \n' + + ' 1 1 1 1 1 1 1 0 \n'; + assert.strictEqual(matrix.toString(), expected); + }); - it('testEmbedBasicPatterns2', () => { - // QRCodeVersion 2. Position adjustment pattern should apppear at right - // bottom corner. - const matrix = new QRCodeByteMatrix(25, 25); - QRCodeMatrixUtil.clearMatrix(matrix); - QRCodeMatrixUtil.embedBasicPatterns(QRCodeVersion.getVersionForNumber(2), matrix); - const expected: string = - ' 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n' + - ' 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 \n' + - ' 0 \n' + - ' 1 \n' + - ' 0 \n' + - ' 1 \n' + - ' 0 \n' + - ' 1 \n' + - ' 0 \n' + - ' 1 1 1 1 1 1 \n' + - ' 0 0 0 0 0 0 0 0 1 1 0 0 0 1 \n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 \n' + - ' 1 0 0 0 0 0 1 0 1 0 0 0 1 \n' + - ' 1 0 1 1 1 0 1 0 1 1 1 1 1 \n' + - ' 1 0 1 1 1 0 1 0 \n' + - ' 1 0 1 1 1 0 1 0 \n' + - ' 1 0 0 0 0 0 1 0 \n' + - ' 1 1 1 1 1 1 1 0 \n'; - assert.strictEqual(matrix.toString(), expected); - }); + it('testEmbedBasicPatterns2', () => { + // QRCodeVersion 2. Position adjustment pattern should apppear at right + // bottom corner. + const matrix = new QRCodeByteMatrix(25, 25); + QRCodeMatrixUtil.clearMatrix(matrix); + QRCodeMatrixUtil.embedBasicPatterns(QRCodeVersion.getVersionForNumber(2), matrix); + const expected: string = + ' 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n' + + ' 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 \n' + + ' 0 \n' + + ' 1 \n' + + ' 0 \n' + + ' 1 \n' + + ' 0 \n' + + ' 1 \n' + + ' 0 \n' + + ' 1 1 1 1 1 1 \n' + + ' 0 0 0 0 0 0 0 0 1 1 0 0 0 1 \n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 \n' + + ' 1 0 0 0 0 0 1 0 1 0 0 0 1 \n' + + ' 1 0 1 1 1 0 1 0 1 1 1 1 1 \n' + + ' 1 0 1 1 1 0 1 0 \n' + + ' 1 0 1 1 1 0 1 0 \n' + + ' 1 0 0 0 0 0 1 0 \n' + + ' 1 1 1 1 1 1 1 0 \n'; + assert.strictEqual(matrix.toString(), expected); + }); - it('testEmbedTypeInfo', () => { - // Type info bits = 100000011001110. - const matrix = new QRCodeByteMatrix(21, 21); - QRCodeMatrixUtil.clearMatrix(matrix); - QRCodeMatrixUtil.embedTypeInfo(QRCodeDecoderErrorCorrectionLevel.M, 5, matrix); - const expected: string = - ' 0 \n' + - ' 1 \n' + - ' 1 \n' + - ' 1 \n' + - ' 0 \n' + - ' 0 \n' + - ' \n' + - ' 1 \n' + - ' 1 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' 0 \n' + - ' 0 \n' + - ' 0 \n' + - ' 0 \n' + - ' 0 \n' + - ' 0 \n' + - ' 1 \n'; - assert.strictEqual(matrix.toString(), expected); - }); + it('testEmbedTypeInfo', () => { + // Type info bits = 100000011001110. + const matrix = new QRCodeByteMatrix(21, 21); + QRCodeMatrixUtil.clearMatrix(matrix); + QRCodeMatrixUtil.embedTypeInfo(QRCodeDecoderErrorCorrectionLevel.M, 5, matrix); + const expected: string = + ' 0 \n' + + ' 1 \n' + + ' 1 \n' + + ' 1 \n' + + ' 0 \n' + + ' 0 \n' + + ' \n' + + ' 1 \n' + + ' 1 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' 0 \n' + + ' 0 \n' + + ' 0 \n' + + ' 0 \n' + + ' 0 \n' + + ' 0 \n' + + ' 1 \n'; + assert.strictEqual(matrix.toString(), expected); + }); - it('testEmbedVersionInfo', () => { - // QRCodeVersion info bits = 000111 110010 010100 - // Actually, version 7 QR Code has 45x45 matrix but we use 21x21 here - // since 45x45 matrix is too big to depict. - const matrix = new QRCodeByteMatrix(21, 21); - QRCodeMatrixUtil.clearMatrix(matrix); - QRCodeMatrixUtil.maybeEmbedVersionInfo(QRCodeVersion.getVersionForNumber(7), matrix); - const expected: string = - ' 0 0 1 \n' + - ' 0 1 0 \n' + - ' 0 1 0 \n' + - ' 0 1 1 \n' + - ' 1 1 1 \n' + - ' 0 0 0 \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' 0 0 0 0 1 0 \n' + - ' 0 1 1 1 1 0 \n' + - ' 1 0 0 1 1 0 \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n'; - assert.strictEqual(matrix.toString(), expected); - }); + it('testEmbedVersionInfo', () => { + // QRCodeVersion info bits = 000111 110010 010100 + // Actually, version 7 QR Code has 45x45 matrix but we use 21x21 here + // since 45x45 matrix is too big to depict. + const matrix = new QRCodeByteMatrix(21, 21); + QRCodeMatrixUtil.clearMatrix(matrix); + QRCodeMatrixUtil.maybeEmbedVersionInfo(QRCodeVersion.getVersionForNumber(7), matrix); + const expected: string = + ' 0 0 1 \n' + + ' 0 1 0 \n' + + ' 0 1 0 \n' + + ' 0 1 1 \n' + + ' 1 1 1 \n' + + ' 0 0 0 \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' 0 0 0 0 1 0 \n' + + ' 0 1 1 1 1 0 \n' + + ' 1 0 0 1 1 0 \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n'; + assert.strictEqual(matrix.toString(), expected); + }); - it('testEmbedDataBits', () => { - // Cells other than basic patterns should be filled with zero. - const matrix = new QRCodeByteMatrix(21, 21); - QRCodeMatrixUtil.clearMatrix(matrix); - QRCodeMatrixUtil.embedBasicPatterns(QRCodeVersion.getVersionForNumber(1), matrix); - const bits = new BitArray(); - QRCodeMatrixUtil.embedDataBits(bits, 255, matrix); - const expected: string = - ' 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + - ' 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n'; - assert.strictEqual(matrix.toString(), expected); - }); + it('testEmbedDataBits', () => { + // Cells other than basic patterns should be filled with zero. + const matrix = new QRCodeByteMatrix(21, 21); + QRCodeMatrixUtil.clearMatrix(matrix); + QRCodeMatrixUtil.embedBasicPatterns(QRCodeVersion.getVersionForNumber(1), matrix); + const bits = new BitArray(); + QRCodeMatrixUtil.embedDataBits(bits, 255, matrix); + const expected: string = + ' 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n' + + ' 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n'; + assert.strictEqual(matrix.toString(), expected); + }); - it('testBuildMatrix', () => { - // From http://www.swetake.com/qr/qr7.html - const bytes = Uint16Array.from([32, 65, 205, 69, 41, 220, 46, 128, 236, - 42, 159, 74, 221, 244, 169, 239, 150, 138, - 70, 237, 85, 224, 96, 74, 219, 61]); - const bits = new BitArray(); - for (let i = 0, length = bytes.length; i !== length; i++) { - const c = bytes[i]; - bits.appendBits(c, 8); - } - const matrix = new QRCodeByteMatrix(21, 21); - QRCodeMatrixUtil.buildMatrix(bits, - QRCodeDecoderErrorCorrectionLevel.H, - QRCodeVersion.getVersionForNumber(1), // QRCodeVersion 1 - 3, // Mask pattern 3 - matrix); - const expected: string = - ' 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n' + - ' 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 0 1\n' + - ' 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 0 0 1\n' + - ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0\n' + - ' 0 0 1 1 0 0 1 1 1 0 0 1 1 1 1 0 1 0 0 0 0\n' + - ' 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 1 0 1 1 1 0\n' + - ' 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 1 0 1 0\n' + - ' 1 0 1 0 1 1 0 1 1 1 0 0 1 1 1 0 0 1 0 1 0\n' + - ' 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 1 1 1\n' + - ' 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1\n' + - ' 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 1 0\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 0 0 0\n' + - ' 1 0 1 1 1 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1\n' + - ' 1 0 1 1 1 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 0\n' + - ' 1 0 1 1 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 0 0\n' + - ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0\n' + - ' 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 1 0 0 1 0\n'; - assert.strictEqual(matrix.toString(), expected); - }); + it('testBuildMatrix', () => { + // From http://www.swetake.com/qr/qr7.html + const bytes = Uint16Array.from([32, 65, 205, 69, 41, 220, 46, 128, 236, + 42, 159, 74, 221, 244, 169, 239, 150, 138, + 70, 237, 85, 224, 96, 74, 219, 61]); + const bits = new BitArray(); + for (let i = 0, length = bytes.length; i !== length; i++) { + const c = bytes[i]; + bits.appendBits(c, 8); + } + const matrix = new QRCodeByteMatrix(21, 21); + QRCodeMatrixUtil.buildMatrix(bits, + QRCodeDecoderErrorCorrectionLevel.H, + QRCodeVersion.getVersionForNumber(1), // QRCodeVersion 1 + 3, // Mask pattern 3 + matrix); + const expected: string = + ' 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n' + + ' 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 0 1\n' + + ' 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 0 0 1\n' + + ' 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0\n' + + ' 0 0 1 1 0 0 1 1 1 0 0 1 1 1 1 0 1 0 0 0 0\n' + + ' 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 1 0 1 1 1 0\n' + + ' 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 1 0 1 0\n' + + ' 1 0 1 0 1 1 0 1 1 1 0 0 1 1 1 0 0 1 0 1 0\n' + + ' 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 1 1 1\n' + + ' 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1\n' + + ' 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 1 0\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 0 0 0\n' + + ' 1 0 1 1 1 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1\n' + + ' 1 0 1 1 1 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 0\n' + + ' 1 0 1 1 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 0 0\n' + + ' 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0\n' + + ' 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 1 0 0 1 0\n'; + assert.strictEqual(matrix.toString(), expected); + }); - it('testFindMSBSet', () => { - assert.strictEqual(QRCodeMatrixUtil.findMSBSet(0), 0); - assert.strictEqual(QRCodeMatrixUtil.findMSBSet(1), 1); - assert.strictEqual(QRCodeMatrixUtil.findMSBSet(0x80), 8); - assert.strictEqual(QRCodeMatrixUtil.findMSBSet(0x80000000), 32); - }); + it('testFindMSBSet', () => { + assert.strictEqual(QRCodeMatrixUtil.findMSBSet(0), 0); + assert.strictEqual(QRCodeMatrixUtil.findMSBSet(1), 1); + assert.strictEqual(QRCodeMatrixUtil.findMSBSet(0x80), 8); + assert.strictEqual(QRCodeMatrixUtil.findMSBSet(0x80000000), 32); + }); - it('testCalculateBCHCode', () => { - // Encoding of type information. - // From Appendix C in JISX0510:2004 (p 65) - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(5, 0x537), 0xdc); - // From http://www.swetake.com/qr/qr6.html - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(0x13, 0x537), 0x1c2); - // From http://www.swetake.com/qr/qr11.html - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(0x1b, 0x537), 0x214); + it('testCalculateBCHCode', () => { + // Encoding of type information. + // From Appendix C in JISX0510:2004 (p 65) + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(5, 0x537), 0xdc); + // From http://www.swetake.com/qr/qr6.html + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(0x13, 0x537), 0x1c2); + // From http://www.swetake.com/qr/qr11.html + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(0x1b, 0x537), 0x214); - // Encoding of version information. - // From Appendix D in JISX0510:2004 (p 68) - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(7, 0x1f25), 0xc94); - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(8, 0x1f25), 0x5bc); - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(9, 0x1f25), 0xa99); - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(10, 0x1f25), 0x4d3); - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(20, 0x1f25), 0x9a6); - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(30, 0x1f25), 0xd75); - assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(40, 0x1f25), 0xc69); - }); + // Encoding of version information. + // From Appendix D in JISX0510:2004 (p 68) + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(7, 0x1f25), 0xc94); + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(8, 0x1f25), 0x5bc); + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(9, 0x1f25), 0xa99); + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(10, 0x1f25), 0x4d3); + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(20, 0x1f25), 0x9a6); + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(30, 0x1f25), 0xd75); + assert.strictEqual(QRCodeMatrixUtil.calculateBCHCode(40, 0x1f25), 0xc69); + }); - // We don't test a lot of cases in this function since we've already - // tested them in TEST(calculateBCHCode). - it('testMakeVersionInfoBits', () => { - // From Appendix D in JISX0510:2004 (p 68) - const bits = new BitArray(); - QRCodeMatrixUtil.makeVersionInfoBits(QRCodeVersion.getVersionForNumber(7), bits); - assert.strictEqual(bits.toString(), ' ...XXXXX ..X..X.X ..'); - }); + // We don't test a lot of cases in this function since we've already + // tested them in TEST(calculateBCHCode). + it('testMakeVersionInfoBits', () => { + // From Appendix D in JISX0510:2004 (p 68) + const bits = new BitArray(); + QRCodeMatrixUtil.makeVersionInfoBits(QRCodeVersion.getVersionForNumber(7), bits); + assert.strictEqual(bits.toString(), ' ...XXXXX ..X..X.X ..'); + }); - // We don't test a lot of cases in this function since we've already - // tested them in TEST(calculateBCHCode). - it('testMakeTypeInfoInfoBits', () => { - // From Appendix C in JISX0510:2004 (p 65) - const bits = new BitArray(); - QRCodeMatrixUtil.makeTypeInfoBits(QRCodeDecoderErrorCorrectionLevel.M, 5, bits); - assert.strictEqual(bits.toString(), ' X......X X..XXX.'); - }); + // We don't test a lot of cases in this function since we've already + // tested them in TEST(calculateBCHCode). + it('testMakeTypeInfoInfoBits', () => { + // From Appendix C in JISX0510:2004 (p 65) + const bits = new BitArray(); + QRCodeMatrixUtil.makeTypeInfoBits(QRCodeDecoderErrorCorrectionLevel.M, 5, bits); + assert.strictEqual(bits.toString(), ' X......X X..XXX.'); + }); }); diff --git a/src/test/core/qrcode/encoder/QRCode.spec.ts b/src/test/core/qrcode/encoder/QRCode.spec.ts index 06c10617..8470d91a 100644 --- a/src/test/core/qrcode/encoder/QRCode.spec.ts +++ b/src/test/core/qrcode/encoder/QRCode.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/*package com.google.zxing.qrcode.encoder;*/ +/* package com.google.zxing.qrcode.encoder; */ import * as assert from 'assert'; import { QRCodeDecoderErrorCorrectionLevel } from '@zxing/library'; @@ -29,97 +29,97 @@ import { QRCodeByteMatrix } from '@zxing/library'; */ describe('QRCodeEncoderQRCode', () => { - it('test', () => { - const qrCode = new QRCodeEncoderQRCode(); + it('test', () => { + const qrCode = new QRCodeEncoderQRCode(); - // First, test simple setters and getters. - // We use numbers of version 7-H. - qrCode.setMode(QRCodeMode.BYTE); - qrCode.setECLevel(QRCodeDecoderErrorCorrectionLevel.H); - qrCode.setVersion(QRCodeVersion.getVersionForNumber(7)); - qrCode.setMaskPattern(3); + // First, test simple setters and getters. + // We use numbers of version 7-H. + qrCode.setMode(QRCodeMode.BYTE); + qrCode.setECLevel(QRCodeDecoderErrorCorrectionLevel.H); + qrCode.setVersion(QRCodeVersion.getVersionForNumber(7)); + qrCode.setMaskPattern(3); - assert.strictEqual(QRCodeMode.BYTE.equals(qrCode.getMode()), true); - assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.H.equals(qrCode.getECLevel()), true); - assert.strictEqual(qrCode.getVersion().getVersionNumber(), 7); - assert.strictEqual(qrCode.getMaskPattern(), 3); + assert.strictEqual(QRCodeMode.BYTE.equals(qrCode.getMode()), true); + assert.strictEqual(QRCodeDecoderErrorCorrectionLevel.H.equals(qrCode.getECLevel()), true); + assert.strictEqual(qrCode.getVersion().getVersionNumber(), 7); + assert.strictEqual(qrCode.getMaskPattern(), 3); - // Prepare the matrix. - const matrix = new QRCodeByteMatrix(45, 45); - // Just set bogus zero/one values. - for (let y: number /*int*/ = 0; y < 45; ++y) { - for (let x: number /*int*/ = 0; x < 45; ++x) { - matrix.setNumber(x, y, (y + x) % 2); - } - } + // Prepare the matrix. + const matrix = new QRCodeByteMatrix(45, 45); + // Just set bogus zero/one values. + for (let y: number /* int */ = 0; y < 45; ++y) { + for (let x: number /* int */ = 0; x < 45; ++x) { + matrix.setNumber(x, y, (y + x) % 2); + } + } - // Set the matrix. - qrCode.setMatrix(matrix); - assert.strictEqual(matrix.equals(qrCode.getMatrix()), true); - }); + // Set the matrix. + qrCode.setMatrix(matrix); + assert.strictEqual(matrix.equals(qrCode.getMatrix()), true); + }); - it('testToString1', () => { - const qrCode = new QRCodeEncoderQRCode(); - const expected: string = - '<<\n' + - ' mode: null\n' + - ' ecLevel: null\n' + - ' version: null\n' + - ' maskPattern: -1\n' + - ' matrix: null\n' + - '>>\n'; - assert.strictEqual(qrCode.toString(), expected); - }); + it('testToString1', () => { + const qrCode = new QRCodeEncoderQRCode(); + const expected: string = + '<<\n' + + ' mode: null\n' + + ' ecLevel: null\n' + + ' version: null\n' + + ' maskPattern: -1\n' + + ' matrix: null\n' + + '>>\n'; + assert.strictEqual(qrCode.toString(), expected); + }); - it('testToString2', () => { - const qrCode = new QRCodeEncoderQRCode(); - qrCode.setMode(QRCodeMode.BYTE); - qrCode.setECLevel(QRCodeDecoderErrorCorrectionLevel.H); - qrCode.setVersion(QRCodeVersion.getVersionForNumber(1)); - qrCode.setMaskPattern(3); - const matrix = new QRCodeByteMatrix(21, 21); - for (let y: number /*int*/ = 0; y < 21; ++y) { - for (let x: number /*int*/ = 0; x < 21; ++x) { - matrix.setNumber(x, y, (y + x) % 2); - } - } - qrCode.setMatrix(matrix); - const expected: string = '<<\n' + - ' mode: BYTE\n' + - ' ecLevel: H\n' + - ' version: 1\n' + - ' maskPattern: 3\n' + - ' matrix:\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + - ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + - '>>\n'; - assert.strictEqual(qrCode.toString(), expected); - }); + it('testToString2', () => { + const qrCode = new QRCodeEncoderQRCode(); + qrCode.setMode(QRCodeMode.BYTE); + qrCode.setECLevel(QRCodeDecoderErrorCorrectionLevel.H); + qrCode.setVersion(QRCodeVersion.getVersionForNumber(1)); + qrCode.setMaskPattern(3); + const matrix = new QRCodeByteMatrix(21, 21); + for (let y: number /* int */ = 0; y < 21; ++y) { + for (let x: number /* int */ = 0; x < 21; ++x) { + matrix.setNumber(x, y, (y + x) % 2); + } + } + qrCode.setMatrix(matrix); + const expected: string = '<<\n' + + ' mode: BYTE\n' + + ' ecLevel: H\n' + + ' version: 1\n' + + ' maskPattern: 3\n' + + ' matrix:\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + ' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n' + + ' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' + + '>>\n'; + assert.strictEqual(qrCode.toString(), expected); + }); - it('testIsValidMaskPattern', () => { - assert.strictEqual(QRCodeEncoderQRCode.isValidMaskPattern(-1), false); - assert.strictEqual(QRCodeEncoderQRCode.isValidMaskPattern(0), true); - assert.strictEqual(QRCodeEncoderQRCode.isValidMaskPattern(7), true); - assert.strictEqual(QRCodeEncoderQRCode.isValidMaskPattern(8), false); - }); + it('testIsValidMaskPattern', () => { + assert.strictEqual(QRCodeEncoderQRCode.isValidMaskPattern(-1), false); + assert.strictEqual(QRCodeEncoderQRCode.isValidMaskPattern(0), true); + assert.strictEqual(QRCodeEncoderQRCode.isValidMaskPattern(7), true); + assert.strictEqual(QRCodeEncoderQRCode.isValidMaskPattern(8), false); + }); }); diff --git a/src/test/core/util/AssertUtils.ts b/src/test/core/util/AssertUtils.ts index a04df3ae..76c0679f 100644 --- a/src/test/core/util/AssertUtils.ts +++ b/src/test/core/util/AssertUtils.ts @@ -1,4 +1,4 @@ -import * as assert from 'assert'; +import { deepStrictEqual, strictEqual, notStrictEqual, throws, AssertionError } from 'assert'; export default class AssertUtils { @@ -19,11 +19,22 @@ export default class AssertUtils { } - -export const assertEquals = assert.strictEqual; -export const assertArrayEquals = (a: Array | Uint8Array | Int32Array, b: Array | Uint8Array | Int32Array) => assert.deepStrictEqual(a, b); -export const assertFalse = x => assert.strictEqual(!!x, false); -export const assertTrue = x => assert.strictEqual(!!x, true); -export const assertNull = x => assert.strictEqual(x, null); -export const assertNotNull = x => assert.notStrictEqual(x, null); -export const assertThrow = (func, err) => assert.throws(func, err); +export const assertEquals = (actual: any, expected: T, message?: string) => strictEqual(actual, expected, message); +export const assertArrayEquals = (a: Iterable, b: Iterable, message?: string) => deepStrictEqual(a, b, message); +export const assertFalse = x => strictEqual(!!x, false); +export const assertTrue = x => strictEqual(!!x, true); +export const assertNull = x => strictEqual(x, null); +export const assertNotNull = x => notStrictEqual(x, null); +export const assertThrow = (func, err) => throws(func, err); +export const assertLessThanEquals = (actual: number, expected: number, message: string) => { + if (actual > expected) throw new AssertionError({ actual, expected, message, operator: 'assertLessThanEquals' }); +}; +export const assertGreaterThanEquals = (actual: number, expected: number, message: string) => { + if (actual < expected) throw new AssertionError({ actual, expected, message, operator: 'assertGreaterThanEquals' }); +}; +export const assertLessThan = (actual: number, expected: number, message: string) => { + if (actual >= expected) throw new AssertionError({ actual, expected, message, operator: 'assertLessThan' }); +}; +export const assertGreaterThan = (actual: number, expected: number, message: string) => { + if (actual <= expected) throw new AssertionError({ actual, expected, message, operator: 'assertGreaterThan' }); +}; diff --git a/src/test/core/util/BitSet.ts b/src/test/core/util/BitSet.ts index 7e1c2e92..bf52d60a 100644 --- a/src/test/core/util/BitSet.ts +++ b/src/test/core/util/BitSet.ts @@ -12,8 +12,8 @@ export default BitSet; // /** // * Sets the bit at the specified index to true. // * Sets the bit at the specified index to the specified value. -// */ -// set(bitIndex: number/*int*/, value: boolean = true): this { +// */ +// set(bitIndex: number/*int */, value: boolean = true): this { // return super.set(bitIndex, value); // } diff --git a/src/test/core/util/Pattern.ts b/src/test/core/util/Pattern.ts index a2e66ac2..cafaa5a1 100644 --- a/src/test/core/util/Pattern.ts +++ b/src/test/core/util/Pattern.ts @@ -3,8 +3,8 @@ */ export class Pattern extends RegExp { - static compile(regexp: string): Pattern { - throw new Pattern(regexp); - } + static compile(regexp: string): Pattern { + throw new Pattern(regexp); + } } diff --git a/src/test/core/util/Random.ts b/src/test/core/util/Random.ts index 98ec322b..9ae93b1c 100644 --- a/src/test/core/util/Random.ts +++ b/src/test/core/util/Random.ts @@ -1,4 +1,4 @@ -import * as seedrandom from 'seedrandom'; +import seedrandom from 'seedrandom'; import { int } from '../../../customTypings'; diff --git a/src/test/core/util/SharpImage.ts b/src/test/core/util/SharpImage.ts index 91b29e7d..731763db 100644 --- a/src/test/core/util/SharpImage.ts +++ b/src/test/core/util/SharpImage.ts @@ -1,4 +1,4 @@ -import * as sharp from 'sharp'; +import sharp from 'sharp'; import { BitMatrix } from '@zxing/library'; @@ -13,13 +13,10 @@ export default class SharpImage { ) { } public static async loadWithRotations(path: string, rotations: number[]): Promise> { - const images = new Map(); for (const rotation of rotations) { - const image = await this.loadWithRotation(path, rotation); - images.set(rotation, image); } @@ -27,9 +24,7 @@ export default class SharpImage { } public static async loadWithRotation(path: string, rotation: number): Promise { - const wrapper = sharp(path).raw(); - const metadata = await wrapper.metadata(); if (metadata.channels !== 3 && metadata.space !== 'srgb') { @@ -44,14 +39,24 @@ export default class SharpImage { } public static load(path: string, rotation: number): SharpImage { + const wrapper = sharp(path).raw(); + return new SharpImage(wrapper, undefined, undefined, undefined); + } + + public static async loadAsync(path: string): Promise { const wrapper = sharp(path).raw(); - return new SharpImage(wrapper, undefined, undefined, undefined); + const { data, info } = await wrapper.toBuffer({ resolveWithObject: true }); + + const width = info.width; + const height = info.height; + const buffer = SharpImage.toGrayscaleBuffer(new Uint8ClampedArray(data.buffer), info.width, info.height, info.channels); + + return new SharpImage(wrapper, buffer, width, height); } public static async loadAsBitMatrix(path: string): Promise { - const wrapper = sharp(path).raw(); const metadata = await wrapper.metadata(); @@ -66,11 +71,20 @@ export default class SharpImage { const height = info.height; const grayscaleBuffer = SharpImage.toGrayscaleBuffer(new Uint8ClampedArray(data.buffer), width, height, channels); // const image = new SharpImage(wrapper, grayscaleBuffer, info.width, info.height) + + return SharpImage.bufferToBitMatrix(grayscaleBuffer, width, height); + } + + private static bufferToBitMatrix( + imageBuffer: Uint8ClampedArray, + width: number, + height: number + ): BitMatrix { const matrix = new BitMatrix(width, height); for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { - const pixel = grayscaleBuffer[y * width + x]; + const pixel = imageBuffer[y * width + x]; if (pixel <= 0x7F) { matrix.set(x, y); } @@ -81,7 +95,6 @@ export default class SharpImage { } private static toGrayscaleBuffer(imageBuffer: Uint8ClampedArray, width: number, height: number, channels: number): Uint8ClampedArray { - const grayscaleBuffer = new Uint8ClampedArray(width * height); for (let i = 0, j = 0, length = imageBuffer.length; i < length; i += channels, j++) { @@ -125,10 +138,6 @@ export default class SharpImage { return this.height; } - // public crop(x: number, y: number, width: number, height: number) { - // this.jimpImage.crop(x, y, width, height) - // } - public getRow(y: number, row: Uint8ClampedArray): void { for (let j = 0, i = y * this.width, end = (y + 1) * this.width; i !== end; i++) { row[j++] = this.buffer[i]; @@ -138,18 +147,4 @@ export default class SharpImage { public getMatrix(): Uint8ClampedArray { return this.buffer; } - - // private static getPixelIndex(width: number, height: number, x: number, y: number): number { - // // round input - // x = Math.round(x); - // y = Math.round(y); - - // let i = (width * y + x) << 2; - - // // if out of bounds index is -1 - // if (x < 0 || x > width) i = -1; - // if (y < 0 || y > height) i = -1; - - // return i; - // } } diff --git a/src/test/core/util/textEncodingFactory.ts b/src/test/core/util/textEncodingFactory.ts index 9d206834..42aedcc3 100644 --- a/src/test/core/util/textEncodingFactory.ts +++ b/src/test/core/util/textEncodingFactory.ts @@ -1,4 +1,4 @@ -import { TextEncoder, TextDecoder } from '@zxing/text-encoding'; +import { TextEncoder, TextDecoder } from '@zxing/text-encoding'; export function createCustomEncoder(e: string) { return new TextEncoder(e, { NONSTANDARD_allowLegacyEncoding: true }); diff --git a/src/test/extension/sources/MultiFormatLuminanceSource.spec.ts b/src/test/extension/sources/MultiFormatLuminanceSource.spec.ts new file mode 100644 index 00000000..90c9ea5d --- /dev/null +++ b/src/test/extension/sources/MultiFormatLuminanceSource.spec.ts @@ -0,0 +1,92 @@ +import { assertArrayEquals, assertEquals } from '../../core/util/AssertUtils'; +import { ColorFormat, MultiFormatLuminanceSource, LuminanceSource } from '@zxing/library'; + +describe('MultiFormatLuminanceSource', () => { + + const SOURCE = new MultiFormatLuminanceSource(Int32Array.from([ + 0x000000, 0x7F7F7F, 0xFFFFFF, + 0xFF0000, 0x00FF00, 0x0000FF, + 0x0000FF, 0x00FF00, 0xFF0000, + ]), 3, 3, ColorFormat.RGBHex); + + it('testCrop', () => { + assertEquals(SOURCE.isCropSupported(), true); + const cropped: LuminanceSource = SOURCE.crop(1, 1, 1, 1); + assertEquals(cropped.getHeight(), 1); + assertEquals(cropped.getWidth(), 1); + assertArrayEquals(cropped.getRow(0, null), new Uint8ClampedArray([127]), 'Failed to crop luminance data.'); + }); + + it('testMatrix', () => { + assertArrayEquals(SOURCE.getMatrix(), Uint8ClampedArray.from([0, 127, 255, 63, 127, 63, 63, 127, 63])); + + const croppedFullWidth = SOURCE.crop(0, 1, 3, 2); + assertArrayEquals(croppedFullWidth.getMatrix(), Uint8ClampedArray.from([63, 127, 63, 63, 127, 63]) ); + + const croppedCorner = SOURCE.crop(1, 1, 2, 2); + assertArrayEquals(croppedCorner.getMatrix(), Uint8ClampedArray.from([127, 63, 127, 63])); + }); + + it('testColorFormats', () => { + let buffer: Uint8ClampedArray; + buffer = new MultiFormatLuminanceSource(new Uint8ClampedArray([112]), 1, 1, ColorFormat.Luminance).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([112]), 'Should not convert if luminance array is given.'); + + buffer = new MultiFormatLuminanceSource(new Uint8ClampedArray([200, 50, 150]), 1, 1, ColorFormat.RGBMatrix).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([112]), 'Incorrect luminance conversion using format RGBMatrix.'); + + buffer = new MultiFormatLuminanceSource(new Uint8ClampedArray([200, 50, 150, 127]), 1, 1, ColorFormat.RGBAMatrix).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([112]), 'Incorrect luminance conversion using format RGBAMatrix.'); + + buffer = new MultiFormatLuminanceSource(new Uint8ClampedArray([200, 50, 150, 0]), 1, 1, ColorFormat.RGBAMatrix).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([255]), 'Incorrect transparency luminance conversion using format RGBMatrix.'); + + buffer = new MultiFormatLuminanceSource(new Int32Array([0xC83296]), 1, 1, ColorFormat.RGBHex).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([112]), 'Incorrect luminance conversion using format RGBHex.'); + + buffer = new MultiFormatLuminanceSource(new Int32Array([0x7FC83296]), 1, 1, ColorFormat.RGBAStartHex).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([112]), 'Incorrect luminance conversion using format RGBAStartHex.'); + + buffer = new MultiFormatLuminanceSource(new Int32Array([0x00C83296]), 1, 1, ColorFormat.RGBAStartHex).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([255]), 'Incorrect transparency luminance conversion using format RGBAStartHex.'); + + buffer = new MultiFormatLuminanceSource(new Int32Array([0xC832967F]), 1, 1, ColorFormat.RGBAEndHex).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([112]), 'Incorrect luminance conversion using format RGBAEndHex.'); + + buffer = new MultiFormatLuminanceSource(new Int32Array([0xC8329600]), 1, 1, ColorFormat.RGBAEndHex).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([255]), 'Incorrect transparency luminance conversion using format RGBAEndHex.'); + + buffer = new MultiFormatLuminanceSource(new Uint8ClampedArray([88, 60, 44]), 1, 1, ColorFormat.HSLMatrix).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([112]), 'Incorrect luminance conversion using format HSLMatrix.'); + + buffer = new MultiFormatLuminanceSource(new Uint8ClampedArray([88, 60, 44, 50]), 1, 1, ColorFormat.HSLAMatrix).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([112]), 'Incorrect luminance conversion using format HSLAMatrix.'); + + buffer = new MultiFormatLuminanceSource(new Uint8ClampedArray([88, 60, 44, 0]), 1, 1, ColorFormat.HSLAMatrix).getMatrix(); + assertArrayEquals(buffer, new Uint8ClampedArray([255]), 'Incorrect transparency luminance conversion using format HSLAMatrix.'); + }); + + it('testRotation', () => { + const enlargedSource = new MultiFormatLuminanceSource(new Uint8ClampedArray(16).map((_, i) => 256 / 16 * i), 4, 4, ColorFormat.Luminance); + let rotatedBuffer = enlargedSource.rotateCounterClockwise().getMatrix(); + assertArrayEquals(rotatedBuffer, Uint8ClampedArray.from([255, 255, 255, 255, 48, 112, 176, 240, 32, 96, 160, 224, 16, 80, 144, 208])); + + rotatedBuffer = enlargedSource.rotateCounterClockwise45().getMatrix(); + assertArrayEquals(rotatedBuffer, Uint8ClampedArray.from([ + 255, 255, 255, 255, 255, 255, + 255, 255, 48, 112, 255, 255, + 255, 16, 32, 96, 176, 255, + 0, 64, 80, 160, 240, 255, + 255, 128, 144, 224, 255, 255, + 255, 255, 192, 208, 255, 255, + ])); + }); + + it('testGetRow', () => { + assertArrayEquals(SOURCE.getRow(2, new Uint8ClampedArray(3)), Uint8ClampedArray.from([63, 127, 63])); + }); + + it('testToString', () => { + assertEquals(SOURCE.toString(), '#+ \n#+#\n#+#\n'); + }); +}); diff --git a/src/test/resources/blackbox/multi-qrcode-1/1.png b/src/test/resources/blackbox/multi-qrcode-1/1.png new file mode 100644 index 00000000..c82508b2 Binary files /dev/null and b/src/test/resources/blackbox/multi-qrcode-1/1.png differ diff --git a/tools/docs-deploy.js b/tools/docs-deploy.js new file mode 100644 index 00000000..08473719 --- /dev/null +++ b/tools/docs-deploy.js @@ -0,0 +1,56 @@ +const fs = require('fs').promises; +const path = require('path'); +const ghpages = require('gh-pages'); +const Git = require('gh-pages/lib/git'); +const argv = require('minimist')(process.argv.slice(2)); +const gitParse = require('git-url-parse'); + +const git = new Git(process.cwd(), 'git'); + +async function deploy(docsDir) { + try { + await fs.access(docsDir); + } catch (err) { + if (argv.v || argv.verbose) console.warn(err); + return; + } + + const actor = process.env.GITHUB_ACTOR || process.env.GIT_AUTHOR_NAME; + const token = process.env.GITHUB_TOKEN; + + if (!actor) throw new Error('You must specify an actor whom performs the commit using GITHUB_ACTOR env variable'); + if (!token) throw new Error('You must specify a token authenticating the commit using GITHUB_TOKEN env variable'); + + const metadata = require(path.resolve(process.cwd(), 'package.json')); + const origin = await git.getRemoteUrl('origin'); + const { resource, full_name } = gitParse(origin); + const url = `https://${actor}:${token}@${resource}/${full_name}.git`; + const message = `documentation v${metadata.version}`; + + return new Promise((resolve, reject) => { + ghpages.publish( + docsDir, + { + repo: url, + message: `chore(release): ${message} [skip ci]`, + }, + (err) => { + if (err) reject(err); + resolve({ name: full_name, message }); + }, + ); + }); +}; + +deploy(argv._.length ? path.resolve(argv._[0]) : path.resolve(process.cwd(), 'output', 'docs')) + .then((status) => { + if (status) console.log(`\n\x1b[36mDeploying "${status.message}" to GitHub Pages for repo ${status.name}\x1b[0m\n`); + else console.warn(`\n\x1b[33mNo documentation or insufficient rights, skipping deploy\x1b[0m\n`); + }) + .catch((err) => { + if (argv.v || argv.verbose) console.error(err); + console.error(`\n\x1b[31mFailed to publish documentation to GitHub Pages\x1b[0m\n`); + process.exit(1); + }); + + diff --git a/tsconfig.json b/tsconfig.json index c7235fad..dc32eaf3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,29 +1,27 @@ { "compilerOptions": { - "baseUrl": "./", - "module": "commonjs", - "target": "es5", - "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "alwaysStrict": true, + "baseUrl": "./src", + "downlevelIteration": true, + "esModuleInterop": true, "lib": [ - "es7", + "esnext", "dom" ], - "alwaysStrict": true, + "module": "esnext", + "moduleResolution": "node", "noImplicitAny": false, - "sourceMap": true, - "declaration": true, "preserveConstEnums": true, - "downlevelIteration": true, + "target": "esnext", + "types": [], "paths": { "@zxing/library": [ - "./dist" - ], - "@zxing/library/*": [ - "./dist/*" + "./index.ts" ] } }, "include": [ - "src/**/*.ts" + "src/**/*" ] } \ No newline at end of file diff --git a/tsconfig.lib-cjs.json b/tsconfig.lib-cjs.json deleted file mode 100644 index 26b017ea..00000000 --- a/tsconfig.lib-cjs.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "outDir": "dist/cjs" - }, - "exclude": [ - "src/test" - ] -} \ No newline at end of file diff --git a/tsconfig.lib-es2015.json b/tsconfig.lib-es2015.json deleted file mode 100644 index 47aa9778..00000000 --- a/tsconfig.lib-es2015.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "module": "es2015", - "target": "es2015", - "outDir": "dist/es2015" - }, - "exclude": [ - "src/test" - ] -} \ No newline at end of file diff --git a/tsconfig.lib-esm.json b/tsconfig.lib-esm.json deleted file mode 100644 index 98aebc8f..00000000 --- a/tsconfig.lib-esm.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "module": "es2015", - "target": "es5", - "outDir": "dist/esm" - }, - "exclude": [ - "src/test" - ] -} \ No newline at end of file diff --git a/tsconfig.lib.json b/tsconfig.lib.json new file mode 100644 index 00000000..927be532 --- /dev/null +++ b/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true + }, + "exclude": [ + "node_modules", + "src/test/**/*" + ] +} \ No newline at end of file diff --git a/tsconfig.lint.json b/tsconfig.lint.json new file mode 100644 index 00000000..9513e303 --- /dev/null +++ b/tsconfig.lint.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": {}, + "include": [ + "src/**/*", + ".mocharc.js", + "rollup.config.js", + "typedoc.js" + ] +} \ No newline at end of file diff --git a/tsconfig.test.json b/tsconfig.test.json index 2f3616e3..c1fc4492 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -1,20 +1,10 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "target": "es6", - "module": "commonjs", - "moduleResolution": "node", - "lib": [ - "es7", - "dom" - ], - "outDir": "output/tests" + "module": "commonjs" }, - "include": [ - "src/test/**/*.ts" - ], "exclude": [ "node_modules", - "src/core" + "src/core/**/*" ] } \ No newline at end of file diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 534acdce..00000000 --- a/tslint.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "extends": ["tslint-no-circular-imports"], - "rules": { - "class-name": true, - "comment-format": [ - true, - "check-space" - ], - "indent": [ - true, - "spaces", - 2 - ], - "no-duplicate-variable": true, - "no-eval": true, - "no-internal-module": true, - "no-trailing-whitespace": true, - "no-unsafe-finally": true, - "no-var-keyword": true, - "one-line": [ - true, - "check-open-brace", - "check-whitespace" - ], - "quotemark": [ - true, - "single" - ], - "semicolon": [ - true, - "always" - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "variable-name": [ - true, - "ban-keywords" - ], - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type" - ], - "no-bitwise": false /* we use a lot of these */, - "member-ordering": [ - false - ] /* to keep the same as with the java version */ - } -} \ No newline at end of file diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 00000000..6041c6cf --- /dev/null +++ b/typedoc.json @@ -0,0 +1,33 @@ +{ + "tsconfig": "tsconfig.lib.json", + "exclude": [ + "**/*(index|customTypings|.spec|.d).ts" + ], + "mode": "modules", + "includeVersion": true, + "out": "output/docs", + "theme": "pages-plugin", + "pages": { + "replaceGlobalsPage": true, + "groups": [ + { + "title": "Getting Started", + "pages": [ + { + "title": "Quick Start", + "source": "./documentation/getting-started/quick-start.md" + } + ] + }, + { + "title": "Examples", + "pages": [ + { + "title": "Multi Format Reader", + "source": "./documentation/examples/multi-format-reader.md" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 02955950..759309a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4,21 +4,21 @@ "@babel/code-frame@^7.0.0": version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz" integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== dependencies: "@babel/highlight" "^7.0.0" "@babel/code-frame@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz" integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: "@babel/highlight" "^7.10.4" "@babel/core@^7.7.5": version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz" integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== dependencies: "@babel/code-frame" "^7.10.4" @@ -40,7 +40,7 @@ "@babel/generator@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz#0d70be32bdaa03d7c51c8597dda76e0df1f15468" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz" integrity sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg== dependencies: "@babel/types" "^7.12.1" @@ -49,7 +49,7 @@ "@babel/helper-function-name@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz" integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: "@babel/helper-get-function-arity" "^7.10.4" @@ -58,28 +58,28 @@ "@babel/helper-get-function-arity@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz" integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== dependencies: "@babel/types" "^7.10.4" "@babel/helper-member-expression-to-functions@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz" integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== dependencies: "@babel/types" "^7.12.1" "@babel/helper-module-imports@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz#1644c01591a15a2f084dd6d092d9430eb1d1216c" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz" integrity sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-module-transforms@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz" integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== dependencies: "@babel/helper-module-imports" "^7.12.1" @@ -94,14 +94,14 @@ "@babel/helper-optimise-call-expression@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz" integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== dependencies: "@babel/types" "^7.10.4" "@babel/helper-replace-supers@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz#f15c9cc897439281891e11d5ce12562ac0cf3fa9" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz" integrity sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw== dependencies: "@babel/helper-member-expression-to-functions" "^7.12.1" @@ -111,26 +111,26 @@ "@babel/helper-simple-access@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz" integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-split-export-declaration@^7.11.0": version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz" integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== dependencies: "@babel/types" "^7.11.0" "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== "@babel/helpers@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.1.tgz#8a8261c1d438ec18cb890434df4ec768734c1e79" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.1.tgz" integrity sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g== dependencies: "@babel/template" "^7.10.4" @@ -139,7 +139,7 @@ "@babel/highlight@^7.0.0": version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz" integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== dependencies: chalk "^2.0.0" @@ -148,7 +148,7 @@ "@babel/highlight@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz" integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: "@babel/helper-validator-identifier" "^7.10.4" @@ -157,12 +157,12 @@ "@babel/parser@^7.10.4", "@babel/parser@^7.12.1", "@babel/parser@^7.12.3": version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz" integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw== "@babel/template@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz" integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== dependencies: "@babel/code-frame" "^7.10.4" @@ -171,7 +171,7 @@ "@babel/traverse@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.1.tgz#941395e0c5cc86d5d3e75caa095d3924526f0c1e" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.1.tgz" integrity sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw== dependencies: "@babel/code-frame" "^7.10.4" @@ -186,16 +186,32 @@ "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz#e109d9ab99a8de735be287ee3d6a9947a190c4ae" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz" integrity sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA== dependencies: "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.19" to-fast-properties "^2.0.0" +"@eslint/eslintrc@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz" + integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" @@ -206,161 +222,280 @@ "@istanbuljs/schema@^0.1.2": version "0.1.2" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@rollup/plugin-node-resolve@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz#80de384edfbd7bfc9101164910f86078151a3eca" - integrity sha512-RxtSL3XmdTAE2byxekYLnx+98kEUOrPHF/KRVjLH+DEIHy6kjIw7YINQzn+NXiH/NTrQLAwYs0GWB+csWygA9Q== +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@rollup/plugin-commonjs@^16.0.0": + version "16.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz" + integrity sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw== + dependencies: + "@rollup/pluginutils" "^3.1.0" + commondir "^1.0.1" + estree-walker "^2.0.1" + glob "^7.1.6" + is-reference "^1.2.1" + magic-string "^0.25.7" + resolve "^1.17.0" + +"@rollup/plugin-node-resolve@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-10.0.0.tgz" + integrity sha512-sNijGta8fqzwA1VwUEtTvWCx2E7qC70NMsDh4ZG13byAXYigBNZMxALhKUSycBks5gupJdq0lFrKumFrRZ8H3A== dependencies: - "@rollup/pluginutils" "^3.0.8" - "@types/resolve" "0.0.8" + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" builtin-modules "^3.1.0" + deepmerge "^4.2.2" is-module "^1.0.0" - resolve "^1.14.2" + resolve "^1.17.0" + +"@rollup/plugin-typescript@^6.1.0": + version "6.1.0" + resolved "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-6.1.0.tgz" + integrity sha512-hJxaiE6WyNOsK+fZpbFh9CUijZYqPQuAOWO5khaGTUkM8DYNNyA2TDlgamecE+qLOG1G1+CwbWMAx3rbqpp6xQ== + dependencies: + "@rollup/pluginutils" "^3.1.0" + resolve "^1.17.0" -"@rollup/pluginutils@^3.0.8": +"@rollup/pluginutils@^3.1.0": version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz" integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== dependencies: "@types/estree" "0.0.39" estree-walker "^1.0.1" picomatch "^2.2.2" -"@sinonjs/commons@^1", "@sinonjs/commons@^1.0.2", "@sinonjs/commons@^1.4.0": +"@sinonjs/commons@^1": version "1.4.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.4.0.tgz#7b3ec2d96af481d7a0321252e7b1c94724ec5a78" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.4.0.tgz" integrity sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw== dependencies: type-detect "4.0.8" -"@sinonjs/formatio@^3.1.0", "@sinonjs/formatio@^3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.1.tgz#52310f2f9bcbc67bdac18c94ad4901b95fde267e" - integrity sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ== +"@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz" + integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^6.0.0", "@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@sinonjs/formatio@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-5.0.1.tgz" + integrity sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ== dependencies: "@sinonjs/commons" "^1" - "@sinonjs/samsam" "^3.1.0" + "@sinonjs/samsam" "^5.0.2" -"@sinonjs/samsam@^3.1.0", "@sinonjs/samsam@^3.3.1": - version "3.3.2" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.2.tgz#63942e3d5eb0b79f6de3bef9abfad15fb4b6401b" - integrity sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA== +"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.2.0.tgz" + integrity sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw== dependencies: - "@sinonjs/commons" "^1.0.2" - array-from "^2.1.1" - lodash "^4.17.11" + "@sinonjs/commons" "^1.6.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" "@sinonjs/text-encoding@^0.7.1": version "0.7.1" - resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== -"@types/chai@^4.1.7": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.7.tgz#1b8e33b61a8c09cbe1f85133071baa0dbf9fa71a" - integrity sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA== +"@types/estree@*": + version "0.0.45" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz" + integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== "@types/estree@0.0.39": version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/json-schema@^7.0.3": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== + "@types/json5@^0.0.29": version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/mocha@^5.2.6": - version "5.2.7" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" - integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== +"@types/mocha@^8.0.4": + version "8.0.4" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.4.tgz" + integrity sha512-M4BwiTJjHmLq6kjON7ZoI2JMlBvpY3BYSdiP6s/qCT3jb1s9/DeJF0JELpAxiVSIxXDzfNKe+r7yedMIoLbknQ== "@types/node@*": version "12.6.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.8.tgz#e469b4bf9d1c9832aee4907ba8a051494357c12c" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.8.tgz" integrity sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg== -"@types/node@^10.12.29": - version "10.14.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.13.tgz#ac786d623860adf39a3f51d629480aacd6a6eec7" - integrity sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ== +"@types/node@^14.14.7": + version "14.14.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz" + integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg== -"@types/resolve@0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" - integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== +"@types/resolve@1.17.1": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz" + integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== dependencies: "@types/node" "*" -"@types/seedrandom@^2.4.27": +"@types/seedrandom@^2.4.28": version "2.4.28" - resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.28.tgz#9ce8fa048c1e8c85cb71d7fe4d704e000226036f" + resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.28.tgz" integrity sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA== -"@types/sharp@^0.22.2": - version "0.22.2" - resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.22.2.tgz#c9b613816ec000d94f153259b25ae41f874a75f5" - integrity sha512-oH49f42h3nf/qys0weYsaTGiMv67wPB769ynCoPfBAVwjjxFF3QtIPEe3MfhwyNjQAhQhTEfnmMKvVZfcFkhIw== +"@types/sharp@^0.26.1": + version "0.26.1" + resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.26.1.tgz" + integrity sha512-vOFcnP0+aQFDb+ToKVIj8ZV6xQ7pNYGGPeYweLHxyjoQUcIGj8iY9R3OVmJyRR5KUkb0Y4obBbMjoTrBXw6AQA== dependencies: "@types/node" "*" -"@zxing/text-encoding@~0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b" - integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA== +"@typescript-eslint/eslint-plugin@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.7.0.tgz" + integrity sha512-li9aiSVBBd7kU5VlQlT1AqP0uWGDK6JYKUQ9cVDnOg34VNnd9t4jr0Yqc/bKxJr/tDCPDaB4KzoSFN9fgVxe/Q== + dependencies: + "@typescript-eslint/experimental-utils" "4.7.0" + "@typescript-eslint/scope-manager" "4.7.0" + debug "^4.1.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.7.0.tgz" + integrity sha512-cymzovXAiD4EF+YoHAB5Oh02MpnXjvyaOb+v+BdpY7lsJXZQN34oIETeUwVT2XfV9rSNpXaIcknDLfupO/tUoA== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/scope-manager" "4.7.0" + "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/typescript-estree" "4.7.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.7.0.tgz" + integrity sha512-+meGV8bMP1sJHBI2AFq1GeTwofcGiur8LoIr6v+rEmD9knyCqDlrQcFHR0KDDfldHIFDU/enZ53fla6ReF4wRw== + dependencies: + "@typescript-eslint/scope-manager" "4.7.0" + "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/typescript-estree" "4.7.0" + debug "^4.1.1" -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +"@typescript-eslint/scope-manager@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.7.0.tgz" + integrity sha512-ILITvqwDJYbcDCROj6+Ob0oCKNg3SH46iWcNcTIT9B5aiVssoTYkhKjxOMNzR1F7WSJkik4zmuqve5MdnA0DyA== + dependencies: + "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/visitor-keys" "4.7.0" + +"@typescript-eslint/types@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.7.0.tgz" + integrity sha512-uLszFe0wExJc+I7q0Z/+BnP7wao/kzX0hB5vJn4LIgrfrMLgnB2UXoReV19lkJQS1a1mHWGGODSxnBx6JQC3Sg== -abbrev@1.0.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= +"@typescript-eslint/typescript-estree@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.7.0.tgz" + integrity sha512-5XZRQznD1MfUmxu1t8/j2Af4OxbA7EFU2rbo0No7meb46eHgGkSieFdfV6omiC/DGIBhH9H9gXn7okBbVOm8jw== + dependencies: + "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/visitor-keys" "4.7.0" + debug "^4.1.1" + globby "^11.0.1" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" -accepts@~1.3.4: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +"@typescript-eslint/visitor-keys@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.7.0.tgz" + integrity sha512-aDJDWuCRsf1lXOtignlfiPODkzSxxop7D0rZ91L6ZuMlcMCSh0YyK+gAfo5zN/ih6WxMwhoXgJWC3cWQdaKC+A== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + "@typescript-eslint/types" "4.7.0" + eslint-visitor-keys "^2.0.0" -acorn-jsx@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" - integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== -acorn@^4.0.4: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= +"@zxing/text-encoding@~0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz" + integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA== -acorn@^6.0.7: - version "6.2.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" - integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q== +acorn-jsx@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^6.10.2, ajv@^6.5.5: version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz" integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== dependencies: fast-deep-equal "^2.0.1" @@ -368,97 +503,73 @@ ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -amdefine@>=0.0.4, amdefine@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= - dependencies: - ansi-wrap "0.1.0" - -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= - dependencies: - ansi-wrap "0.1.0" +ansi-colors@4.1.1, ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-regex@^2.0.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-regex@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== ansi-regex@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" + normalize-path "^3.0.0" + picomatch "^2.0.4" append-transform@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz" integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== dependencies: default-require-extensions "^3.0.0" aproba@^1.0.3: version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== archy@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= are-we-there-yet@~1.1.2: version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz" integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" @@ -466,437 +577,159 @@ are-we-there-yet@~1.1.2: arg@^4.1.0: version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -arr-diff@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.0.1, arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + array-uniq "^1.0.1" -arr-union@^2.0.1: +array-union@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" - integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - -array-from@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195" - integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU= - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -arraybuffer.slice@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" - integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= asn1@~0.2.3: version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz" integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assert@^1.4.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - astral-regex@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== - -async@1.x: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= - -async@^2.1.4: +async@^2.6.1: version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== dependencies: lodash "^4.17.14" asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== aws-sign2@~0.7.0: version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz" integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= - balanced-match@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" - integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= - -base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== - -base64id@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" - integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY= - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== bcrypt-pbkdf@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" - integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= - dependencies: - callsite "1.0.0" - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +binary-extensions@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== -bl@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" - integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== +bl@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz" + integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -blob@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" - integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" -bluebird@^3.3.0, bluebird@^3.5.0, bluebird@^3.5.x: +bluebird@^3.5.0, bluebird@^3.5.x: version "3.5.5" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz" integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -body-parser@^1.16.1: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^0.1.2: - version "0.1.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6" - integrity sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY= - dependencies: - expand-range "^0.1.0" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browser-resolve@^1.11.0: - version "1.11.3" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" - integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: - resolve "1.1.7" + fill-range "^7.0.1" browser-stdout@1.3.1: version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= - -buffer-from@^1.0.0: +buffer-from@^1.0.0, buffer-from@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^5.0.6: - version "5.2.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - -builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= + base64-js "^1.3.1" + ieee754 "^1.1.13" builtin-modules@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz" integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw== -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - caching-transform@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz" integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== dependencies: hasha "^5.0.0" @@ -904,151 +737,89 @@ caching-transform@^4.0.0: package-hash "^4.0.0" write-file-atomic "^3.0.0" -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" - integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= - callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + caseless@~0.12.0: version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chai@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - pathval "^1.1.0" - type-detect "^4.0.5" - -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.2: +chalk@^2.0.0: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - -chokidar@^2.0.3: - version "2.1.6" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" - integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" +chokidar@3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" optionalDependencies: - fsevents "^1.2.7" + fsevents "~2.1.2" -chownr@^1.0.1, chownr@^1.1.1: +chownr@^1.1.1: version "1.1.2" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz" integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -circular-json@^0.5.5: - version "0.5.9" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" - integrity sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: - restore-cursor "^2.0.0" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" cliui@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz" integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: string-width "^4.2.0" strip-ansi "^6.0.0" wrap-ansi "^6.2.0" -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - codacy-coverage@^3.4.0: version "3.4.0" - resolved "https://registry.yarnpkg.com/codacy-coverage/-/codacy-coverage-3.4.0.tgz#196af70844c4e4179718f7a7f9d96b921b4b3a67" + resolved "https://registry.yarnpkg.com/codacy-coverage/-/codacy-coverage-3.4.0.tgz" integrity sha512-A0ats3/gZtOw76muu++HZ6QrInztWjjLefkLJmmBpjPfyn6nNwNLoApmGmj3F3dfgl2+o6u5GwPnUBkKdfKXTQ== dependencies: bluebird "^3.5.x" @@ -1063,928 +834,527 @@ codacy-coverage@^3.4.0: code-point-at@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== +color-string@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz" + integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" -color@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" - integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== +color@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz" + integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== dependencies: color-convert "^1.9.1" - color-string "^1.5.2" - -colors@^1.1.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" - integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== - -combine-lists@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6" - integrity sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y= - dependencies: - lodash "^4.5.0" - -combine-source-map@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" - integrity sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos= - dependencies: - convert-source-map "~1.1.0" - inline-source-map "~0.6.0" - lodash.memoize "~3.0.3" - source-map "~0.5.3" + color-string "^1.5.4" combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" commander@2.15.1: version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz" integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== -commander@^2.12.1, commander@^2.20.0, commander@~2.20.3: +commander@^2.18.0, commander@^2.20.0: version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commander@^2.x: version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= +compare-versions@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" + integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -connect@^3.6.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - -console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" - console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== - dependencies: - safe-buffer "~5.1.1" - convert-source-map@^1.7.0: version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" -convert-source-map@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" - integrity sha1-SCnId+n+SbMWHzvzZziI4gRpmGA= - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-js@^2.2.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" - integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== - core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.0: +cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" -crypto-browserify@^3.11.1: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - -custom-event@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" - integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= - dashdash@^1.12.0: version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz" integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" -date-format@^0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-0.0.0.tgz#09206863ab070eb459acea5542cbd856b11966b3" - integrity sha1-CSBoY6sHDrRZrOpVQsvYVrEZZrM= - -date-format@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-1.2.0.tgz#615e828e233dd1ab9bb9ae0950e0ceccfa6ecad8" - integrity sha1-YV6CjiM90aubua4JUODOzPpuytg= - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= - -dateformat@^1.0.6: - version "1.0.12" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" - integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk= - dependencies: - get-stdin "^4.0.1" - meow "^3.3.0" - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@3.1.0, debug@~3.1.0: +debug@3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" -debug@^0.7.2: - version "0.7.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" - integrity sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk= - -debug@^3.1.0, debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== +debug@4.2.0, debug@^4.1.0, debug@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== dependencies: - ms "^2.1.1" + ms "2.1.2" debug@^4.0.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== - dependencies: - ms "2.1.2" - -decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== decompress-response@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz" integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: - type-detect "^4.0.0" + mimic-response "^3.1.0" deep-extend@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + default-require-extensions@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz" integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== dependencies: strip-bom "^4.0.0" -defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= - dependencies: - clone "^1.0.2" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -detect-libc@^1.0.2, detect-libc@^1.0.3: +detect-libc@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -di@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" - integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= - -diff@3.5.0, diff@^3.2.0, diff@^3.5.0: +diff@3.5.0, diff@^3.1.0: version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== -diff@^4.0.1: +diff@4.0.2, diff@^4.0.1, diff@^4.0.2: version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" + path-type "^4.0.0" doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" -dom-serialize@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" - integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs= - dependencies: - custom-event "~1.0.0" - ent "~2.2.0" - extend "^3.0.0" - void-elements "^2.0.0" - -domain-browser@^1.1.7: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - ecc-jsbn@~0.1.1: version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -elliptic@^6.0.0: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" +email-addresses@^3.0.1: + version "3.1.0" + resolved "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz" + integrity sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg== emoji-regex@^7.0.1: version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: +end-of-stream@^1.1.0: version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz" integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" -engine.io-client@~3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" - integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw== - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.1.1" - has-cors "1.1.0" - indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~3.3.1" - xmlhttprequest-ssl "~1.5.4" - yeast "0.1.2" - -engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" - integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA== - dependencies: - after "0.8.2" - arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.5" - blob "0.0.5" - has-binary2 "~1.0.2" - -engine.io@~3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.1.tgz#b60281c35484a70ee0351ea0ebff83ec8c9522a2" - integrity sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w== +end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: - accepts "~1.3.4" - base64id "1.0.0" - cookie "0.3.1" - debug "~3.1.0" - engine.io-parser "~2.1.0" - ws "~3.3.1" - -ent@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= + once "^1.4.0" -error-ex@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== dependencies: - is-arrayish "^0.2.1" + ansi-colors "^4.1.1" es6-error@^4.0.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -es6-object-assign@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@1.8.x: - version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== +eslint-scope@^5.0.0, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - esrecurse "^4.1.0" + esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.3.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" - integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: - eslint-visitor-keys "^1.0.0" + eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^5.15.1: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== +eslint@^7.13.0: + version "7.13.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.13.0.tgz" + integrity sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" + "@eslint/eslintrc" "^0.2.1" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.0" + esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" + glob-parent "^5.0.0" + globals "^12.1.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" + levn "^0.4.1" + lodash "^4.17.19" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" table "^5.2.3" text-table "^0.2.0" + v8-compile-cache "^2.0.3" -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" - -esprima@2.7.x, esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + acorn "^7.4.0" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.3.0" esprima@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== dependencies: - estraverse "^4.0.0" + estraverse "^5.1.0" -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" + estraverse "^5.2.0" -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.1.1: version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + estree-walker@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== +estree-walker@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.1.tgz" + integrity sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg== + esutils@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz" integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -expand-braces@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea" - integrity sha1-SIsdHSRRyz06axks/AMPRMWFX+o= - dependencies: - array-slice "^0.2.3" - array-unique "^0.2.1" - braces "^0.1.2" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-range@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" - integrity sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ= - dependencies: - is-number "^0.1.1" - repeat-string "^0.2.2" - expand-template@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== -extend-shallow@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" - integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= - dependencies: - kind-of "^1.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@^3.0.0, extend@~3.0.2: +extend@~3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz" integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= fast-deep-equal@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.1.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz" integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= -fast-levenshtein@~2.0.4: +fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= +fastq@^1.6.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz" + integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== dependencies: - escape-string-regexp "^1.0.5" + reusify "^1.0.4" file-entry-cache@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz" integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== dependencies: flat-cache "^2.0.1" -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= +filename-reserved-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz" + integrity sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q= + +filenamify-url@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/filenamify-url/-/filenamify-url-1.0.0.tgz" + integrity sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A= + dependencies: + filenamify "^1.0.0" + humanize-url "^1.0.0" + +filenamify@^1.0.0: + version "1.2.1" + resolved "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz" + integrity sha1-qfL/0RxQO+0wABUCknI3jx8TZaU= + dependencies: + filename-reserved-regex "^1.0.0" + strip-outer "^1.0.0" + trim-repeated "^1.0.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" + to-regex-range "^5.0.1" -finalhandler@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^3.2.0: +find-cache-dir@^3.2.0, find-cache-dir@^3.3.1: version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz" integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== dependencies: commondir "^1.0.1" make-dir "^3.0.2" pkg-dir "^4.1.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -1992,31 +1362,26 @@ find-up@^4.0.0, find-up@^4.1.0: flat-cache@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz" integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== dependencies: flatted "^2.0.0" rimraf "2.6.3" write "1.0.3" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + flatted@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz" integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== -follow-redirects@^1.0.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" - integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - foreground-child@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz" integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== dependencies: cross-spawn "^7.0.0" @@ -2024,80 +1389,70 @@ foreground-child@^2.0.0: forever-agent@~0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz" integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" mime-types "^2.1.12" -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - fromentries@^1.2.0: version "1.2.1" - resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.1.tgz#64c31665630479bc993cd800d53387920dc61b4d" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.1.tgz" integrity sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw== -fs-access@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" - integrity sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o= - dependencies: - null-check "^1.0.0" - fs-constants@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-copy-file-sync@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz#11bf32c096c10d126e5f6b36d06eece776062918" - integrity sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ== +fs-extra@8.1.0, fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" - integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== +fs-extra@^9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== dependencies: - minipass "^2.2.1" + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^1.0.0" fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== - dependencies: - nan "^2.12.1" - node-pre-gyp "^0.12.0" - fsevents@~2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + functional-red-black-tree@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= gauge@~2.7.3: version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz" integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" @@ -2111,57 +1466,69 @@ gauge@~2.7.3: gensync@^1.0.0-beta.1: version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz" integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== get-caller-file@^2.0.1: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= - get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - getpass@^0.1.1: version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz" integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" +gh-pages@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/gh-pages/-/gh-pages-3.1.0.tgz" + integrity sha512-3b1rly9kuf3/dXsT8+ZxP0UhNLOo1CItj+3e31yUVcaph/yDsJ9RzD7JOw5o5zpBTJVQLlJAASNkUfepi9fe2w== + dependencies: + async "^2.6.1" + commander "^2.18.0" + email-addresses "^3.0.1" + filenamify-url "^1.0.0" + find-cache-dir "^3.3.1" + fs-extra "^8.1.0" + globby "^6.1.0" + +git-up@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.2.tgz#10c3d731051b366dc19d3df454bfca3f77913a7c" + integrity sha512-kbuvus1dWQB2sSW4cbfTeGpCMd8ge9jx9RKnhXhuJ7tnvT+NIrTVfYZxjtflZddQYcmdOTlkAcjmx7bor+15AQ== + dependencies: + is-ssh "^1.3.0" + parse-url "^5.0.0" + +git-url-parse@^11.4.0: + version "11.4.0" + resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.4.0.tgz#f2bb1f2b00f05552540e95a62e31399a639a6aa6" + integrity sha512-KlIa5jvMYLjXMQXkqpFzobsyD/V2K5DRHl5OAf+6oDFPlPLxrGDVQlIdI63c4/Kt6kai4kALENSALlzTGST3GQ== + dependencies: + git-up "^4.0.0" + github-from-package@0.0.0: version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz" integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" + is-glob "^4.0.1" glob@7.1.2: version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz" integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" @@ -2171,21 +1538,10 @@ glob@7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== +glob@7.1.6, glob@^7.0.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -2194,10 +1550,10 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.4, glob@^7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== +glob@^7.0.0, glob@^7.1.3: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -2206,132 +1562,101 @@ glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^11.1.0, globals@^11.7.0: +globals@^11.1.0: version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.2.0" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" - integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz" + integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" -graceful-fs@^4.1.15: +graceful-fs@^4.1.15, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== growl@1.10.5: version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -handlebars@^4.0.1: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== +handlebars@^4.7.6: + version "4.7.6" + resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz" + integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== dependencies: + minimist "^1.2.5" neo-async "^2.6.0" - optimist "^0.6.1" source-map "^0.6.1" + wordwrap "^1.0.0" optionalDependencies: uglify-js "^3.1.4" har-schema@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.0: version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz" integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== dependencies: ajv "^6.5.5" har-schema "^2.0.0" -has-binary2@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" - integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== - dependencies: - isarray "2.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-unicode@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz" integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" + function-bind "^1.1.1" hasha@^5.0.0: version "5.2.2" - resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz" integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== dependencies: is-stream "^2.0.0" @@ -2339,423 +1664,254 @@ hasha@^5.0.0: he@1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +highlight.js@^10.2.0: + version "10.3.2" + resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.3.2.tgz" + integrity sha512-3jRT7OUYsVsKvukNKZCtnvRcFyCJqSEIuIMsEybAXRiFSwpt65qjPd/Pr+UOdYt7WJlt+lj3+ypUsHiySBp/Jw== hoek@5.x.x: version "5.0.4" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-5.0.4.tgz#0f7fa270a1cafeb364a4b2ddfaa33f864e4157da" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-5.0.4.tgz" integrity sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w== hoek@6.x.x: version "6.1.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz" integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ== -hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== - html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-proxy@^1.13.0: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - http-signature@~1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz" integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== +humanize-url@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/humanize-url/-/humanize-url-1.0.1.tgz" + integrity sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8= dependencies: - safer-buffer ">= 2.1.2 < 3" - -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + normalize-url "^1.0.0" + strip-url-auth "^1.0.0" -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore@^4.0.6: version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + import-fresh@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz" integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" +import-fresh@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz" + integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" - indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -inline-source-map@~0.6.0: - version "0.6.2" - resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" - integrity sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU= - dependencies: - source-map "~0.5.3" - -inquirer@^6.2.2: - version "6.5.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42" - integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== interpret@^1.0.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - is-arrayish@^0.3.1: version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + binary-extensions "^2.0.0" -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== +is-core-module@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz" + integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== dependencies: - is-plain-object "^2.0.4" + has "^1.0.3" -is-extglob@^2.1.0, is-extglob@^2.1.1: +is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" is-module@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= -is-number@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806" - integrity sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY= +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-reference@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== dependencies: - isobject "^3.0.1" + "@types/estree" "*" -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= +is-ssh@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.2.tgz#a4b82ab63d73976fd8263cceee27f99a88bdae2b" + integrity sha512-elEw0/0c2UscLrNG+OAorbP539E3rhliKPg+hDMWN9VwrDXfYK+4PBEykDPfxlYYtQvl84TascnQyobfQLHEhQ== + dependencies: + protocols "^1.1.0" is-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - is-windows@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= -isarray@1.0.0, isarray@~1.0.0: +isarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isarray@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" - integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= - -isbinaryfile@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" - integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== - dependencies: - buffer-alloc "^1.2.0" - isemail@3.x.x: version "3.2.0" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz" integrity sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg== dependencies: punycode "2.x.x" isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - isstream@~0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== istanbul-lib-hook@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz" integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== dependencies: append-transform "^2.0.0" istanbul-lib-instrument@^4.0.0: version "4.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz" integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== dependencies: "@babel/core" "^7.7.5" @@ -2765,7 +1921,7 @@ istanbul-lib-instrument@^4.0.0: istanbul-lib-processinfo@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz" integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== dependencies: archy "^1.0.0" @@ -2778,7 +1934,7 @@ istanbul-lib-processinfo@^2.0.2: istanbul-lib-report@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== dependencies: istanbul-lib-coverage "^3.0.0" @@ -2787,7 +1943,7 @@ istanbul-lib-report@^3.0.0: istanbul-lib-source-maps@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz" integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== dependencies: debug "^4.1.1" @@ -2796,43 +1952,32 @@ istanbul-lib-source-maps@^4.0.0: istanbul-reports@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz" integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -istanbul@0.4.5, istanbul@^0.4.0: - version "0.4.5" - resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= - dependencies: - abbrev "1.0.x" - async "1.x" - escodegen "1.8.x" - esprima "2.7.x" - glob "^5.0.15" - handlebars "^4.0.1" - js-yaml "3.x" - mkdirp "0.5.x" - nopt "3.x" - once "1.x" - resolve "1.1.x" - supports-color "^3.1.0" - which "^1.1.1" - wordwrap "^1.0.0" - jacoco-parse@^2.x: version "2.0.1" - resolved "https://registry.yarnpkg.com/jacoco-parse/-/jacoco-parse-2.0.1.tgz#a1fab49df2c8a11fd9204b615677bc58ab784b65" + resolved "https://registry.yarnpkg.com/jacoco-parse/-/jacoco-parse-2.0.1.tgz" integrity sha512-YGhIb2iXuQ4/zNh2zgHd6Z6dqlYwLYH1wfsxtTNQ+jnHH9PhhuMwqOFihXymSI41trxok48LdKkSeDIWs28tYg== dependencies: mocha "^5.2.0" xml2js "^0.4.9" +jest-worker@^26.2.1: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + joi@^13.x: version "13.7.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-13.7.0.tgz#cfd85ebfe67e8a1900432400b4d03bbd93fb879f" + resolved "https://registry.yarnpkg.com/joi/-/joi-13.7.0.tgz" integrity sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q== dependencies: hoek "5.x.x" @@ -2841,20 +1986,12 @@ joi@^13.x: js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.x, js-yaml@^3.13.0: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^3.13.1: +js-yaml@3.14.0, js-yaml@^3.13.1: version "3.14.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz" integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== dependencies: argparse "^1.0.7" @@ -2862,51 +1999,67 @@ js-yaml@^3.13.1: jsbn@~0.1.0: version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@~5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json5@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz" integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" json5@^2.1.2: version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz" integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== dependencies: minimist "^1.2.5" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsprim@^1.2.2: version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz" integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" @@ -2916,467 +2069,187 @@ jsprim@^1.2.2: just-extend@^4.0.2: version "4.0.2" - resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz" integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw== -karma-chai@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/karma-chai/-/karma-chai-0.1.0.tgz#bee5ad40400517811ae34bb945f762909108b79a" - integrity sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o= - -karma-chrome-launcher@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf" - integrity sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w== - dependencies: - fs-access "^1.0.0" - which "^1.2.1" - -karma-coverage@^1.1.1, karma-coverage@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/karma-coverage/-/karma-coverage-1.1.2.tgz#cc09dceb589a83101aca5fe70c287645ef387689" - integrity sha512-eQawj4Cl3z/CjxslYy9ariU4uDh7cCNFZHNWXWRpl0pNeblY/4wHR7M7boTYXWrn9bY0z2pZmr11eKje/S/hIw== - dependencies: - dateformat "^1.0.6" - istanbul "^0.4.0" - lodash "^4.17.0" - minimatch "^3.0.0" - source-map "^0.5.1" - -karma-mocha@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-1.3.0.tgz#eeaac7ffc0e201eb63c467440d2b69c7cf3778bf" - integrity sha1-7qrH/8DiAetjxGdEDStpx883eL8= - dependencies: - minimist "1.2.0" - -karma-remap-coverage@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/karma-remap-coverage/-/karma-remap-coverage-0.1.5.tgz#d2e3bb2dd00adcd256603a702b08c371370fbc12" - integrity sha512-FM5h8eHcHbMMR+2INBUxD+4+wUbkCnobfn5uWprkLyj6Xcm2MRFQOuAJn9h2H13nNso6rk+QoNpHd5xCevlPOw== - dependencies: - remap-istanbul "^0.10" - -karma-sinon@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/karma-sinon/-/karma-sinon-1.0.5.tgz#4e3443f2830fdecff624d3747163f1217daa2a9a" - integrity sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo= - -karma-sourcemap-loader@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8" - integrity sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg= - dependencies: - graceful-fs "^4.1.2" - -karma-typescript-preprocessor@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/karma-typescript-preprocessor/-/karma-typescript-preprocessor-0.4.0.tgz#49adde8ae382b23dc7e30b06494509f79eea3e25" - integrity sha512-QMfsfQxt1OKZ3OXHIc8oHIvs+v9kX7WruvB4vvnojCyQ2Jtg9mamCxj1UroPxbvSqvhGNhzgWAgTjVitye4UYA== - dependencies: - typescript "^3.0.3" - -karma-typescript@^3.0.13: - version "3.0.13" - resolved "https://registry.yarnpkg.com/karma-typescript/-/karma-typescript-3.0.13.tgz#8948afbd103ac1987a5961a0f43a1ba2871067cd" - integrity sha1-iUivvRA6wZh6WWGg9DoboocQZ80= - dependencies: - acorn "^4.0.4" - assert "^1.4.1" - async "^2.1.4" - browser-resolve "^1.11.0" - browserify-zlib "^0.2.0" - buffer "^5.0.6" - combine-source-map "^0.8.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - convert-source-map "^1.5.0" - crypto-browserify "^3.11.1" - diff "^3.2.0" - domain-browser "^1.1.7" - events "^1.1.1" - glob "^7.1.1" - https-browserify "^1.0.0" - istanbul "0.4.5" - json-stringify-safe "^5.0.1" - karma-coverage "^1.1.1" - lodash "^4.17.4" - log4js "^1.1.1" - minimatch "^3.0.3" - os-browserify "^0.3.0" - pad "^2.0.0" - path-browserify "0.0.0" - process "^0.11.10" - punycode "^1.4.1" - querystring-es3 "^0.2.1" - readable-stream "^2.3.3" - remap-istanbul "^0.10.1" - source-map "0.6.1" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.3" - timers-browserify "^2.0.2" - tmp "0.0.29" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" - -karma@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/karma/-/karma-3.1.4.tgz#3890ca9722b10d1d14b726e1335931455788499e" - integrity sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw== - dependencies: - bluebird "^3.3.0" - body-parser "^1.16.1" - chokidar "^2.0.3" - colors "^1.1.0" - combine-lists "^1.0.0" - connect "^3.6.0" - core-js "^2.2.0" - di "^0.0.1" - dom-serialize "^2.2.0" - expand-braces "^0.1.1" - flatted "^2.0.0" - glob "^7.1.1" - graceful-fs "^4.1.2" - http-proxy "^1.13.0" - isbinaryfile "^3.0.0" - lodash "^4.17.5" - log4js "^3.0.0" - mime "^2.3.1" - minimatch "^3.0.2" - optimist "^0.6.1" - qjobs "^1.1.4" - range-parser "^1.2.0" - rimraf "^2.6.0" - safe-buffer "^5.0.1" - socket.io "2.1.1" - source-map "^0.6.1" - tmp "0.0.33" - useragent "2.3.0" - -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - lcov-parse@^1.x: version "1.0.0" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz" integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" + prelude-ls "^1.2.1" + type-check "~0.4.0" -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" + p-locate "^3.0.0" + path-exists "^3.0.0" locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash.flattendeep@^4.4.0: version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= -lodash.memoize@~3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" - integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= - -lodash@^4.17.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.5.0: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= -lodash@^4.17.19: +lodash@^4.1.2, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lodash@^4.17.11, lodash@^4.17.4: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== + log-driver@^1.x: version "1.2.7" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== -log4js@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-1.1.1.tgz#c21d29c7604089e4f255833e7f94b3461de1ff43" - integrity sha1-wh0px2BAieTyVYM+f5SzRh3h/0M= - dependencies: - debug "^2.2.0" - semver "^5.3.0" - streamroller "^0.4.0" - -log4js@^3.0.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-3.0.6.tgz#e6caced94967eeeb9ce399f9f8682a4b2b28c8ff" - integrity sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ== +log-symbols@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== dependencies: - circular-json "^0.5.5" - date-format "^1.2.0" - debug "^3.1.0" - rfdc "^1.1.2" - streamroller "0.7.0" + chalk "^4.0.0" -lolex@^4.0.1, lolex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.1.0.tgz#ecdd7b86539391d8237947a3419aa8ac975f0fe1" - integrity sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw== +loglevel@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz" + integrity sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ== -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" +lunr@^2.3.8, lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== -lru-cache@4.1.x: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== +magic-string@^0.25.7: + version "0.25.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" + sourcemap-codec "^1.4.4" make-dir@^3.0.0, make-dir@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" make-error@^1.1.1: version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= +marked@^1.1.1: + version "1.2.4" + resolved "https://registry.npmjs.org/marked/-/marked-1.2.4.tgz" + integrity sha512-6x5TFGCTKSQBLTZtOburGxCxFEBJEGYVLwCMTBCxzvyuisGcC20UNzDSJhCr/cJ/Kmh6ulfJm10g6WWEAJ3kvg== -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -meow@^3.3.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" + braces "^3.0.1" + picomatch "^2.0.5" mime-db@1.40.0: version "1.40.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz" integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== -mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.1.12, mime-types@~2.1.19: version "2.1.24" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz" integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== dependencies: mime-db "1.40.0" -mime@^2.3.1: - version "2.4.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" - integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-response@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@1.2.0, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@^1.2.5: +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -minipass@^2.2.1, minipass@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== - dependencies: - minipass "^2.2.1" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.1, mkdirp@^0.5.1: version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" -mkdirp@^0.5.3: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - mocha-lcov-reporter@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/mocha-lcov-reporter/-/mocha-lcov-reporter-1.3.0.tgz#469bdef4f8afc9a116056f079df6182d0afb0384" + resolved "https://registry.yarnpkg.com/mocha-lcov-reporter/-/mocha-lcov-reporter-1.3.0.tgz" integrity sha1-Rpve9PivyaEWBW8HnfYYLQr7A4Q= mocha@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz" integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== dependencies: browser-stdout "1.3.1" @@ -3391,176 +2264,125 @@ mocha@^5.2.0: mkdirp "0.5.1" supports-color "5.4.0" +mocha@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.2.1.tgz" + integrity sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.4.3" + debug "4.2.0" + diff "4.0.2" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.6" + growl "1.10.5" + he "1.2.0" + js-yaml "3.14.0" + log-symbols "4.0.0" + minimatch "3.0.4" + ms "2.1.2" + nanoid "3.1.12" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "7.2.0" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.0.2" + yargs "13.3.2" + yargs-parser "13.1.2" + yargs-unparser "2.0.0" + ms@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@2.1.2, ms@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= - -nan@^2.12.1, nan@^2.13.2: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" +nanoid@3.1.12: + version "3.1.12" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz" + integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A== napi-build-utils@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz" integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA== natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - neo-async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + version "2.6.2" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -nise@^1.4.10: - version "1.5.0" - resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.0.tgz#d03ea0e6c1b75c638015aa3585eddc132949a50d" - integrity sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww== +nise@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz" + integrity sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A== dependencies: - "@sinonjs/formatio" "^3.1.0" + "@sinonjs/commons" "^1.7.0" + "@sinonjs/fake-timers" "^6.0.0" "@sinonjs/text-encoding" "^0.7.1" just-extend "^4.0.2" - lolex "^4.1.0" path-to-regexp "^1.7.0" node-abi@^2.7.0: version "2.9.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.9.0.tgz#ae4075b298dab2d92dd1e22c48ccc7ffd7f06200" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.9.0.tgz" integrity sha512-jmEOvv0eanWjhX8dX1pmjb7oJl1U1oR4FOh0b2GnvALwSYoOdU7sj+kLDSAyjo4pfC9aj/IxkloxdLJQhSSQBA== dependencies: semver "^5.4.1" -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" +node-addon-api@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.2.tgz" + integrity sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg== node-preload@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz" integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== dependencies: process-on-spawn "^1.0.0" noop-logger@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz" integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= -nopt@3.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== +normalize-url@^1.0.0: + version "1.9.1" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz" + integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" + +normalize-url@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== -npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2: +npmlog@^4.0.1, npmlog@^4.1.2: version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" @@ -3568,19 +2390,14 @@ npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2: gauge "~2.7.3" set-blocking "~2.0.0" -null-check@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" - integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0= - number-is-nan@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= nyc@^15.1.0: version "15.1.0" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz" integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== dependencies: "@istanbuljs/load-nyc-config" "^1.0.0" @@ -3613,135 +2430,83 @@ nyc@^15.1.0: oauth-sign@~0.9.0: version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" - integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optionator@^0.8.1, optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -os-homedir@^1.0.0, os-homedir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" -p-limit@^2.2.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz" integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== dependencies: aggregate-error "^3.0.0" p-try@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== package-hash@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz" integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== dependencies: graceful-fs "^4.1.15" @@ -3749,362 +2514,201 @@ package-hash@^4.0.0: lodash.flattendeep "^4.4.0" release-zalgo "^1.0.0" -pad@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pad/-/pad-2.3.0.tgz#d604f0d5433c3e1500e207279cc5cd0234b1c2aa" - integrity sha512-lxrgnOG5AXmzMRT1O5urWtYFxHnFSE+QntgTHij1nvS4W+ubhQLmQRHmZXDeEvk9I00itAixLqU9Q6fE0gW3sw== - dependencies: - wcwidth "^1.0.1" - -pako@~1.0.5: - version "1.0.10" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" - integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== - parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0: - version "5.1.4" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" - integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" - integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= +parse-path@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.2.tgz#ef14f0d3d77bae8dd4bc66563a4c151aac9e65aa" + integrity sha512-HSqVz6iuXSiL8C1ku5Gl1Z5cwDd9Wo0q8CoffdAghP6bz8pJa1tcMC+m4N+z6VAS8QdksnIGq1TB6EgR4vPR6w== dependencies: - better-assert "~1.0.0" + is-ssh "^1.3.0" + protocols "^1.4.0" -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" - integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= +parse-url@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.2.tgz#856a3be1fcdf78dc93fc8b3791f169072d898b59" + integrity sha512-Czj+GIit4cdWtxo3ISZCvLiUjErSo0iI3wJ+q9Oi3QuMYTI6OZu+7cewMWZ+C1YAnKhYTk6/TLuhIgCypLthPA== dependencies: - better-assert "~1.0.0" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + is-ssh "^1.3.0" + normalize-url "^3.3.0" + parse-path "^4.0.0" + protocols "^1.4.0" -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@^1.7.0: version "1.7.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz" integrity sha1-Wf3g9DW62suhA6hOnTvGTpa5k30= dependencies: isarray "0.0.1" -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= - -pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== performance-now@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.2.2: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2: version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== pify@^2.0.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pinkie-promise@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^4.1.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" -plugin-error@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" - integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= - dependencies: - ansi-cyan "^0.1.1" - ansi-red "^0.1.1" - arr-diff "^1.0.1" - arr-union "^2.0.1" - extend-shallow "^1.1.2" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -prebuild-install@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.0.tgz#58b4d8344e03590990931ee088dd5401b03004c8" - integrity sha512-aaLVANlj4HgZweKttFNUVNRxDukytuIuxeK2boIMHjagNJCiVKWFsKF4tCE3ql3GbrD2tExPQ7/pwtEJcHNZeg== +prebuild-install@^5.3.5: + version "5.3.6" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.6.tgz" + integrity sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg== dependencies: detect-libc "^1.0.3" expand-template "^2.0.3" github-from-package "0.0.0" - minimist "^1.2.0" - mkdirp "^0.5.1" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" napi-build-utils "^1.0.1" node-abi "^2.7.0" noop-logger "^0.1.1" npmlog "^4.0.1" - os-homedir "^1.0.1" - pump "^2.0.1" + pump "^3.0.0" rc "^1.2.7" - simple-get "^2.7.0" - tar-fs "^1.13.0" + simple-get "^3.0.3" + tar-fs "^2.0.0" tunnel-agent "^0.6.0" which-pm-runs "^1.0.0" -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= +prepend-http@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process-on-spawn@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz" integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== dependencies: fromentries "^1.2.0" -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -progress@^2.0.0: +progress@^2.0.0, progress@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= +protocols@^1.1.0, protocols@^1.4.0: + version "1.4.8" + resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8" + integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg== psl@^1.1.24, psl@^1.1.28: version "1.2.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz" integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA== -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" - integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pump@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== punycode@^1.4.1: version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -qjobs@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" - integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - qs@~6.5.2: version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -querystring-es3@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz" + integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= + dependencies: + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: +randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - rc@^1.2.7: version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" @@ -4112,37 +2716,10 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -readable-stream@^1.1.7: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== +readable-stream@^2.0.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -4152,111 +2729,51 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.3.0, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@~2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" - integrity sha1-j5A0HmilPMySh4jaz80Rs265t44= +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~0.10.x" - util-deprecate "~1.0.1" + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" + picomatch "^2.2.1" rechoir@^0.6.2: version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz" integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== release-zalgo@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz" integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= dependencies: es6-error "^4.0.1" -remap-istanbul@^0.10, remap-istanbul@^0.10.1: - version "0.10.1" - resolved "https://registry.yarnpkg.com/remap-istanbul/-/remap-istanbul-0.10.1.tgz#3aa58dd5021d499f336d3ba5bf3bbb91c1b88e37" - integrity sha512-gsNQXs5kJLhErICSyYhzVZ++C8LBW8dgwr874Y2QvzAUS75zBlD/juZgXs39nbYJ09fZDlX2AVLVJAY2jbFJoQ== - dependencies: - amdefine "^1.0.0" - istanbul "0.4.5" - minimatch "^3.0.3" - plugin-error "^0.1.2" - source-map "^0.6.1" - through2 "2.0.1" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" - integrity sha1-x6jTI2BoNiBZp+RlH8aITosftK4= - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - request-promise-core@1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz" integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== dependencies: lodash "^4.17.11" request-promise@^4.x: version "4.2.4" - resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.4.tgz#1c5ed0d71441e38ad58c7ce4ea4ea5b06d54b310" + resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.4.tgz" integrity sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg== dependencies: bluebird "^3.5.0" @@ -4266,7 +2783,7 @@ request-promise@^4.x: request@^2.88.0: version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" @@ -4292,434 +2809,320 @@ request@^2.88.0: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-main-filename@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@1.1.7, resolve@1.1.x: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= +resolve@1.17.0, resolve@^1.3.2: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.10.0: +resolve@^1.1.6: version "1.11.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz" integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== dependencies: path-parse "^1.0.6" -resolve@^1.14.2, resolve@^1.3.2: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== +resolve@^1.17.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== dependencies: + is-core-module "^2.1.0" path-parse "^1.0.6" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -rfdc@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" - integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug== +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@2.6.3, rimraf@^2.6.0, rimraf@^2.6.1: +rimraf@2.6.3: version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" rimraf@^3.0.0: version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== +rollup-plugin-terser@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz" + integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rollup@^2.8.2: - version "2.32.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.32.0.tgz#ac58c8e85782bea8aa2d440fc05aba345013582a" - integrity sha512-0FIG1jY88uhCP2yP4CfvtKEqPDRmsUwfY1kEOOM+DH/KOGATgaIFd/is1+fQOxsvh62ELzcFfKonwKWnHhrqmw== + "@babel/code-frame" "^7.10.4" + jest-worker "^26.2.1" + serialize-javascript "^4.0.0" + terser "^5.0.0" + +rollup-plugin-typescript2@^0.29.0: + version "0.29.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.29.0.tgz" + integrity sha512-YytahBSZCIjn/elFugEGQR5qTsVhxhUwGZIsA9TmrSsC88qroGo65O5HZP/TTArH2dm0vUmYWhKchhwi2wL9bw== + dependencies: + "@rollup/pluginutils" "^3.1.0" + find-cache-dir "^3.3.1" + fs-extra "8.1.0" + resolve "1.17.0" + tslib "2.0.1" + +rollup@^2.33.2: + version "2.33.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.33.2.tgz" + integrity sha512-QPQ6/fWCrzHtSXkI269rhKaC7qXGghYBwXU04b1JsDZ6ibZa3DJ9D1SFAYRMgx1inDg0DaTbb3N4Z1NK/r3fhw== optionalDependencies: fsevents "~2.1.2" -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - -rxjs@^6.4.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" - integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== - dependencies: - tslib "^1.9.0" +run-parallel@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz" + integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@>=0.6.0, sax@^1.2.4: +sax@>=0.6.0: version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -seedrandom@^2.4.4: - version "2.4.4" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.4.tgz#b25ea98632c73e45f58b77cfaa931678df01f9ba" - integrity sha512-9A+PDmgm+2du77B5i0Ip2cxOqqHjgNxnBgglxLcX78A2D6c2rTo61z4jnVABpF4cKeDMDG+cmXXvdnqse2VqMA== +seedrandom@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz" + integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: +semver@^5.4.1: version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== semver@^6.0.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz" integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== semver@^6.3.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= +semver@^7.1.1, semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +serialize-javascript@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + randombytes "^2.1.0" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -sharp@^0.22.1: - version "0.22.1" - resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.22.1.tgz#a67c0e75567f03dd5a7861b901fec04072c5b0f4" - integrity sha512-lXzSk/FL5b/MpWrT1pQZneKe25stVjEbl6uhhJcTULm7PhmJgKKRbTDM/vtjyUuC/RLqL2PRyC4rpKwbv3soEw== +sharp@^0.26.2: + version "0.26.2" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.26.2.tgz" + integrity sha512-bGBPCxRAvdK9bX5HokqEYma4j/Q5+w8Nrmb2/sfgQCLEUx/HblcpmOfp59obL3+knIKnOhyKmDb4tEOhvFlp6Q== dependencies: - color "^3.1.1" + color "^3.1.2" detect-libc "^1.0.3" - fs-copy-file-sync "^1.1.1" - nan "^2.13.2" + node-addon-api "^3.0.2" npmlog "^4.1.2" - prebuild-install "^5.3.0" - semver "^6.0.0" - simple-get "^3.0.3" - tar "^4.4.8" + prebuild-install "^5.3.5" + semver "^7.3.2" + simple-get "^4.0.0" + tar-fs "^2.1.0" tunnel-agent "^0.6.0" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" - integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== +shelljs@^0.8.4: + version "0.8.4" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz" + integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" -shx@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.2.tgz#40501ce14eb5e0cbcac7ddbd4b325563aad8c123" - integrity sha512-aS0mWtW3T2sHAenrSrip2XGv39O9dXIFUqxAEWHEOS1ePtGIBavdPJY1kE2IHl14V/4iCbUiNDPGdyYTtmhSoA== +shx@0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.3.tgz" + integrity sha512-nZJ3HFWVoTSyyB+evEKjJ1STiixGztlqwKLTUNV5KqMWtGey9fTd4KU1gdZ1X9BV6215pswQ/Jew9NsuS/fNDA== dependencies: - es6-object-assign "^1.0.3" - minimist "^1.2.0" - shelljs "^0.8.1" + minimist "^1.2.3" + shelljs "^0.8.4" signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-concat@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz" integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= -simple-get@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== +simple-get@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.0.3.tgz" + integrity sha512-Wvre/Jq5vgoz31Z9stYWPLn0PqRqmBDpFSdypAnHu5AvRVCYPRYGnvryNLiXu8GOBNDH82J2FRHUGMjjHUpXFw== dependencies: decompress-response "^3.3.0" once "^1.3.1" simple-concat "^1.0.0" -simple-get@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.0.3.tgz#924528ac3f9d7718ce5e9ec1b1a69c0be4d62efa" - integrity sha512-Wvre/Jq5vgoz31Z9stYWPLn0PqRqmBDpFSdypAnHu5AvRVCYPRYGnvryNLiXu8GOBNDH82J2FRHUGMjjHUpXFw== +simple-get@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.0.tgz" + integrity sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ== dependencies: - decompress-response "^3.3.0" + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-get@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.0.tgz#73fa628278d21de83dadd5512d2cc1f4872bd675" + integrity sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ== + dependencies: + decompress-response "^6.0.0" once "^1.3.1" simple-concat "^1.0.0" simple-swizzle@^0.2.2: version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz" integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= dependencies: is-arrayish "^0.3.1" -sinon@^7.2.7: - version "7.3.2" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.3.2.tgz#82dba3a6d85f6d2181e1eca2c10d8657c2161f28" - integrity sha512-thErC1z64BeyGiPvF8aoSg0LEnptSaWE7YhdWWbWXgelOyThent7uKOnnEh9zBxDbKixtr5dEko+ws1sZMuFMA== - dependencies: - "@sinonjs/commons" "^1.4.0" - "@sinonjs/formatio" "^3.2.1" - "@sinonjs/samsam" "^3.3.1" - diff "^3.5.0" - lolex "^4.0.1" - nise "^1.4.10" - supports-color "^5.5.0" +sinon@^9.2.1: + version "9.2.1" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.2.1.tgz" + integrity sha512-naPfsamB5KEE1aiioaoqJ6MEhdUs/2vtI5w1hPAXX/UwvoPjXcwh1m5HiKx0HGgKR8lQSoFIgY5jM6KK8VrS9w== + dependencies: + "@sinonjs/commons" "^1.8.1" + "@sinonjs/fake-timers" "^6.0.1" + "@sinonjs/formatio" "^5.0.1" + "@sinonjs/samsam" "^5.2.0" + diff "^4.0.2" + nise "^4.0.4" + supports-color "^7.1.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== slice-ansi@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz" integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== dependencies: ansi-styles "^3.2.0" astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -socket.io-adapter@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" - integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs= - -socket.io-client@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f" - integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ== - dependencies: - backo2 "1.0.2" - base64-arraybuffer "0.1.5" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "~3.1.0" - engine.io-client "~3.2.0" - has-binary2 "~1.0.2" - has-cors "1.1.0" - indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - socket.io-parser "~3.2.0" - to-array "0.1.4" - -socket.io-parser@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" - integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA== +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz" + integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= dependencies: - component-emitter "1.2.1" - debug "~3.1.0" - isarray "2.0.1" + is-plain-obj "^1.0.0" -socket.io@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980" - integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA== - dependencies: - debug "~3.1.0" - engine.io "~3.2.0" - has-binary2 "~1.0.2" - socket.io-adapter "~1.1.0" - socket.io-client "2.1.1" - socket.io-parser "~3.2.0" - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@^0.5.17, source-map-support@~0.5.19: +source-map-support@^0.5.17, source-map-support@^0.5.6, source-map-support@~0.5.19: version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@~0.5.3: +source-map@^0.5.0: version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= - dependencies: - amdefine ">=0.0.4" +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.7.2: version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== +sourcemap-codec@^1.4.4: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + spawn-wrap@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz" integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== dependencies: foreground-child "^2.0.0" @@ -4729,47 +3132,14 @@ spawn-wrap@^2.0.0: signal-exit "^3.0.2" which "^2.0.1" -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz" integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== dependencies: asn1 "~0.2.3" @@ -4782,83 +3152,36 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - stealthy-require@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -streamroller@0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-0.7.0.tgz#a1d1b7cf83d39afb0d63049a5acbf93493bdf64b" - integrity sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ== - dependencies: - date-format "^1.2.0" - debug "^3.1.0" - mkdirp "^0.5.1" - readable-stream "^2.3.0" - -streamroller@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-0.4.1.tgz#d435bd5974373abd9bd9068359513085106cc05f" - integrity sha1-1DW9WXQ3Or2b2QaDWVEwhRBswF8= - dependencies: - date-format "^0.0.0" - debug "^0.7.2" - mkdirp "^0.5.1" - readable-stream "^1.1.7" +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= string-width@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.1.0: +"string-width@^1.0.2 || 2": version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" @@ -4867,120 +3190,111 @@ string-width@^3.0.0: string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string_decoder@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - safe-buffer "~5.1.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz" integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.1.0: +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" strip-ansi@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz" integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== dependencies: ansi-regex "^5.0.0" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-json-comments@~2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-outer@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz" + integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== + dependencies: + escape-string-regexp "^1.0.2" + +strip-url-auth@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/strip-url-auth/-/strip-url-auth-1.0.1.tgz" + integrity sha1-IrD6OkE4WzO+PzMVUbu4N/oM164= + supports-color@5.4.0: version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz" integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== dependencies: has-flag "^3.0.0" -supports-color@^3.1.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= +supports-color@7.2.0, supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: - has-flag "^1.0.0" + has-flag "^4.0.0" -supports-color@^5.3.0, supports-color@^5.5.0: +supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - table@^5.2.3: version "5.4.4" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.4.tgz#6e0f88fdae3692793d1077fd172a4667afe986a6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.4.tgz" integrity sha512-IIfEAUx5QlODLblLrGTTLJA7Tk0iLSGBvgY8essPRVNGHAzThujww1YqHLs6h3HfTg55h++RzLHH5Xw/rfv+mg== dependencies: ajv "^6.10.2" @@ -4988,46 +3302,31 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" -tar-fs@^1.13.0: - version "1.16.3" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" - integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== +tar-fs@^2.0.0, tar-fs@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== dependencies: - chownr "^1.0.1" - mkdirp "^0.5.1" - pump "^1.0.0" - tar-stream "^1.1.2" + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" -tar-stream@^1.1.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== +tar-stream@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.4.tgz" + integrity sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw== dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" + bl "^4.0.3" + end-of-stream "^1.4.1" fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - -tar@^4, tar@^4.4.8: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.5" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" + inherits "^2.0.3" + readable-stream "^3.1.1" -terser@^5.3.7: - version "5.3.7" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.7.tgz#798a4ae2e7ff67050c3e99fcc4e00725827d97e2" - integrity sha512-lJbKdfxWvjpV330U4PBZStCT9h3N9A4zZVA5Y4k9sCWXknrpdyxi1oMsRKLmQ/YDMDxSBKIh88v0SkdhdqX06w== +terser@^5.0.0, terser@^5.3.8: + version "5.3.8" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.8.tgz" + integrity sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ== dependencies: commander "^2.20.0" source-map "~0.7.2" @@ -5035,7 +3334,7 @@ terser@^5.3.7: test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz" integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: "@istanbuljs/schema" "^0.1.2" @@ -5044,103 +3343,31 @@ test-exclude@^6.0.0: text-table@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -through2@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.1.tgz#384e75314d49f32de12eebb8136b8eb6b5d59da9" - integrity sha1-OE51MU1J8y3hLuu4E2uOtrXVnak= - dependencies: - readable-stream "~2.0.0" - xtend "~4.0.0" - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -timers-browserify@^2.0.2: - version "2.0.10" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== - dependencies: - setimmediate "^1.0.4" - -tmp@0.0.29: - version "0.0.29" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" - integrity sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA= - dependencies: - os-tmpdir "~1.0.1" - -tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + is-number "^7.0.0" topo@3.x.x: version "3.0.3" - resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.3.tgz#d5a67fb2e69307ebeeb08402ec2a2a6f5f7ad95c" + resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.3.tgz" integrity sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ== dependencies: hoek "6.x.x" tough-cookie@^2.3.3: version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: psl "^1.1.28" @@ -5148,25 +3375,50 @@ tough-cookie@^2.3.3: tough-cookie@~2.4.3: version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz" integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" -trim-newlines@^1.0.0: +trim-repeated@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= + resolved "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz" + integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= + dependencies: + escape-string-regexp "^1.0.2" -ts-custom-error@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.1.1.tgz#d30c7415461dac93dc2cc9e9eb2dae92e6423901" - integrity sha512-f/syoy+pTE4z82qaiRuthEeZtCGNKzlfs0Zc8jpQFcz/CYMaFSwFSdfFt1sSFnPlDLOEm7RCROdIxZ44N8UlwA== +ts-custom-error@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.2.0.tgz" + integrity sha512-cBvC2QjtvJ9JfWLvstVnI45Y46Y5dMxIaG1TDMGAD/R87hpvqFL+7LhvUDhnRCfOnx/xitollFWWvUKKKhbN0A== + +ts-mocha@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-8.0.0.tgz" + integrity sha512-Kou1yxTlubLnD5C3unlCVO7nh0HERTezjoVhVw/M5S1SqoUec0WgllQvPk3vzPMc6by8m6xD1uR1yRf8lnVUbA== + dependencies: + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" ts-node@^9.0.0: version "9.0.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.0.0.tgz#e7699d2a110cc8c0d3b831715e417688683460b3" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.0.0.tgz" integrity sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg== dependencies: arg "^4.1.0" @@ -5175,9 +3427,9 @@ ts-node@^9.0.0: source-map-support "^0.5.17" yn "3.1.1" -tsconfig-paths@^3.9.0: +tsconfig-paths@^3.5.0, tsconfig-paths@^3.9.0: version "3.9.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz" integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== dependencies: "@types/json5" "^0.0.29" @@ -5185,294 +3437,221 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.13.0, tslib@^1.8.1: +tslib@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== + +tslib@^1.8.1: version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - -tslint-no-circular-imports@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/tslint-no-circular-imports/-/tslint-no-circular-imports-0.7.0.tgz#9df0a15654d66b172e0b7843eed073fa5ae99b5f" - integrity sha512-k3wxpeMC4ef40UbpfBVHEHIzKfNZq5/SCtAO1YjGsaNTklo+K53/TWLrym+poA65RJFDiYgYNWvkeIIkJNA0Vw== - -tslint@^6.1.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" - integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== - dependencies: - "@babel/code-frame" "^7.0.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^4.0.1" - glob "^7.1.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - mkdirp "^0.5.3" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.13.0" - tsutils "^2.29.0" +tslib@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" + integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== -tsutils@^2.29.0: - version "2.29.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== dependencies: tslib "^1.8.1" -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - tunnel-agent@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz" integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: - prelude-ls "~1.1.2" + prelude-ls "^1.2.1" -type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: +type-detect@4.0.8, type-detect@^4.0.8: version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.8.0: +type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.17: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - typedarray-to-buffer@^3.1.5: version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" -typescript@^3: - version "3.9.7" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" - integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== +typedoc-default-themes@^0.10.1: + version "0.10.2" + resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.10.2.tgz#743380a80afe62c5ef92ca1bd4abe2ac596be4d2" + integrity sha512-zo09yRj+xwLFE3hyhJeVHWRSPuKEIAsFK5r2u47KL/HBKqpwdUSanoaz5L34IKiSATFrjG5ywmIu98hPVMfxZg== + dependencies: + lunr "^2.3.8" -typescript@^3.0.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" - integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== +typedoc-default-themes@^0.11.4: + version "0.11.4" + resolved "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.11.4.tgz" + integrity sha512-Y4Lf+qIb9NTydrexlazAM46SSLrmrQRqWiD52593g53SsmUFioAsMWt8m834J6qsp+7wHRjxCXSZeiiW5cMUdw== -uglify-js@^3.1.4: - version "3.7.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a" - integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg== +typedoc-plugin-external-module-name@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/typedoc-plugin-external-module-name/-/typedoc-plugin-external-module-name-4.0.3.tgz" + integrity sha512-2PjEN9kdmkB7NxN3DEax6yDIPjq7HV8qELQhkSRJGxJs/8G/ZwPPvXT0z6hUqtWVr6MeCjpAoYJFzHo04C14Aw== dependencies: - commander "~2.20.3" - source-map "~0.6.1" - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + lodash "^4.1.2" + semver "^7.1.1" -union-value@^1.0.0: +typedoc-plugin-pages@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" + resolved "https://registry.yarnpkg.com/typedoc-plugin-pages/-/typedoc-plugin-pages-1.0.1.tgz#bddff942d91dce4b93b4783158cc40cb70107650" + integrity sha512-eOcjcvXZPxyvcpl6U5uP08SqjYz20F7DGZC4kOD1ES2p+2hde6rbF4MPuOjtzcGUOrQeev2HhiaIi+07SiGNsQ== + dependencies: + compare-versions "^3.6.0" + typedoc-default-themes "^0.10.1" + +typedoc@^0.19.2: + version "0.19.2" + resolved "https://registry.npmjs.org/typedoc/-/typedoc-0.19.2.tgz" + integrity sha512-oDEg1BLEzi1qvgdQXc658EYgJ5qJLVSeZ0hQ57Eq4JXy6Vj2VX4RVo18qYxRWz75ifAaYuYNBUCnbhjd37TfOg== + dependencies: + fs-extra "^9.0.1" + handlebars "^4.7.6" + highlight.js "^10.2.0" + lodash "^4.17.20" + lunr "^2.3.9" + marked "^1.1.1" + minimatch "^3.0.0" + progress "^2.0.3" + semver "^7.3.2" + shelljs "^0.8.4" + typedoc-default-themes "^0.11.4" -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= +typescript@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz" + integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== + +uglify-js@^3.1.4: + version "3.11.6" + resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.6.tgz" + integrity sha512-oASI1FOJ7BBFkSCNDZ446EgkSuHkOZBuqRFrwXIKWCoXw8ZXQETooTQjkAcBS03Acab7ubCKsXnwuV2svy061g== -unset-value@^1.0.0: +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" + resolved "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== -upath@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" - integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== uri-js@^4.2.2: version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz" integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -useragent@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" - integrity sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw== - dependencies: - lru-cache "4.1.x" - tmp "0.0.x" - -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.10.3: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== - dependencies: - inherits "2.0.3" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - uuid@^3.3.2: version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== uuid@^3.3.3: version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" +v8-compile-cache@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== verror@1.10.0: version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz" integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= - dependencies: - indexof "0.0.1" - -void-elements@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= - dependencies: - defaults "^1.0.3" - which-module@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which-pm-runs@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz" integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= -which@^1.1.1, which@^1.2.1, which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: +which@2.0.2, which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: +wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" -wordwrap@^1.0.0, wordwrap@~1.0.0: +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= +workerpool@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.2.tgz" + integrity sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q== + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" wrap-ansi@^6.2.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== dependencies: ansi-styles "^4.0.0" @@ -5481,12 +3660,12 @@ wrap-ansi@^6.2.0: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write-file-atomic@^3.0.0: version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== dependencies: imurmurhash "^0.1.4" @@ -5496,23 +3675,14 @@ write-file-atomic@^3.0.0: write@1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz" integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== dependencies: mkdirp "^0.5.1" -ws@~3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - xml2js@^0.4.9: version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz" integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== dependencies: sax ">=0.6.0" @@ -5520,45 +3690,59 @@ xml2js@^0.4.9: xmlbuilder@~9.0.1: version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= -xmlhttprequest-ssl@~1.5.4: - version "1.5.5" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" - integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= - -xtend@^4.0.0, xtend@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - y18n@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" - integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^3.0.0, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== +yargs-parser@13.1.2, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" yargs-parser@^18.1.2: version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + yargs@^15.0.2: version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" @@ -5573,17 +3757,17 @@ yargs@^15.0.2: y18n "^4.0.0" yargs-parser "^18.1.2" -yarn@^1.17.3: +yarn@^1.22.10: version "1.22.10" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz" integrity sha512-IanQGI9RRPAN87VGTF7zs2uxkSyQSrSPsju0COgbsKQOOXr5LtcVPeyXWgwVa0ywG3d8dg6kSYKGBuYK021qeA== -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= - yn@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz" + integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=