mirror of
https://github.com/gchq/CyberChef
synced 2026-02-20 11:24:17 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c97baa6fdf | ||
|
|
448cfc8012 | ||
|
|
9b2868a178 | ||
|
|
7ba58cd4ce | ||
|
|
bb41c36578 | ||
|
|
293f304841 | ||
|
|
324a23585e | ||
|
|
fe69ec5881 | ||
|
|
595c90a464 | ||
|
|
042afe4157 | ||
|
|
cc2c6d20fd | ||
|
|
abbb8496cc | ||
|
|
4ca5157508 | ||
|
|
eeb39a0b2b | ||
|
|
0cf7bcaddc | ||
|
|
4e8f0c34f3 | ||
|
|
de3a5ff634 | ||
|
|
693b7d86dd | ||
|
|
fa34e2fafc | ||
|
|
1542cadde8 | ||
|
|
64399ad60e | ||
|
|
96c93b95f2 | ||
|
|
9df82113c4 | ||
|
|
55ef47f645 | ||
|
|
5e53fe113d | ||
|
|
5c49f87727 | ||
|
|
e0c4957da4 | ||
|
|
9512444eee | ||
|
|
dd26c09003 | ||
|
|
a30f5f1b50 | ||
|
|
b885e8423d |
@@ -12,3 +12,7 @@ indent_size = 4
|
|||||||
[{package.json,.travis.yml,nightwatch.json}]
|
[{package.json,.travis.yml,nightwatch.json}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[.github/**.yml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|||||||
40
.github/workflows/codeql.yml
vendored
40
.github/workflows/codeql.yml
vendored
@@ -1,40 +0,0 @@
|
|||||||
name: "CodeQL Analysis"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ master ]
|
|
||||||
types: [synchronize, opened, reopened]
|
|
||||||
schedule:
|
|
||||||
- cron: '22 17 * * 5'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'javascript' ]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v2
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v2
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
83
.github/workflows/master.yml
vendored
83
.github/workflows/master.yml
vendored
@@ -4,55 +4,62 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
main:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pages: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '18.x'
|
node-version: 18
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
export DETECT_CHROMEDRIVER_VERSION=true
|
export DETECT_CHROMEDRIVER_VERSION=true
|
||||||
npm install
|
npm install
|
||||||
npm run setheapsize
|
npm run setheapsize
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: npx grunt lint
|
run: npx grunt lint
|
||||||
|
|
||||||
- name: Unit Tests
|
- name: Unit Tests
|
||||||
run: |
|
run: |
|
||||||
npm test
|
npm test
|
||||||
npm run testnodeconsumer
|
npm run testnodeconsumer
|
||||||
|
|
||||||
- name: Production Build
|
- name: Production Build
|
||||||
if: success()
|
if: success()
|
||||||
run: npx grunt prod --msg="Version 10 is here! Read about the new features <a href='https://github.com/gchq/CyberChef/wiki/Character-encoding,-EOL-separators,-and-editor-features'>here</a>"
|
run: npx grunt prod --msg=""
|
||||||
|
|
||||||
- name: Generate sitemap
|
- name: Generate sitemap
|
||||||
run: npx grunt exec:sitemap
|
run: npx grunt exec:sitemap
|
||||||
|
|
||||||
- name: UI Tests
|
- name: UI Tests
|
||||||
if: success()
|
if: success()
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install xvfb
|
sudo apt-get install xvfb
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|
||||||
- name: Prepare for GitHub Pages
|
- name: Prepare for GitHub Pages
|
||||||
if: success()
|
if: success()
|
||||||
run: npx grunt copy:ghPages
|
run: npx grunt copy:ghPages
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
if: success() && github.ref == 'refs/heads/master'
|
if: success() && github.ref == 'refs/heads/master'
|
||||||
uses: crazy-max/ghaction-github-pages@v3
|
uses: crazy-max/ghaction-github-pages@v3
|
||||||
with:
|
with:
|
||||||
target_branch: gh-pages
|
target_branch: gh-pages
|
||||||
build_dir: ./build/prod
|
build_dir: ./build/prod
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
76
.github/workflows/pull_requests.yml
vendored
76
.github/workflows/pull_requests.yml
vendored
@@ -1,5 +1,8 @@
|
|||||||
name: "Pull Requests"
|
name: "Pull Requests"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
pull_request:
|
pull_request:
|
||||||
@@ -9,47 +12,46 @@ jobs:
|
|||||||
main:
|
main:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '18.x'
|
node-version: 18
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
export DETECT_CHROMEDRIVER_VERSION=true
|
export DETECT_CHROMEDRIVER_VERSION=true
|
||||||
npm install
|
npm install
|
||||||
npm run setheapsize
|
npm run setheapsize
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: npx grunt lint
|
run: npx grunt lint
|
||||||
|
|
||||||
- name: Unit Tests
|
- name: Unit Tests
|
||||||
run: |
|
run: |
|
||||||
npm test
|
npm test
|
||||||
npm run testnodeconsumer
|
npm run testnodeconsumer
|
||||||
|
|
||||||
- name: Production Build
|
- name: Production Build
|
||||||
if: success()
|
if: success()
|
||||||
run: npx grunt prod
|
run: npx grunt prod
|
||||||
|
|
||||||
- name: Production Image Build
|
- name: Set up Docker Buildx
|
||||||
if: success()
|
uses: docker/setup-buildx-action@v3
|
||||||
id: build-image
|
|
||||||
uses: redhat-actions/buildah-build@v2
|
|
||||||
with:
|
|
||||||
# Not being uploaded to any registry, use a simple name to allow Buildah to build correctly.
|
|
||||||
image: cyberchef
|
|
||||||
containerfiles: ./Dockerfile
|
|
||||||
platforms: linux/amd64
|
|
||||||
oci: true
|
|
||||||
# Webpack seems to use a lot of open files, increase the max open file limit to accomodate.
|
|
||||||
extra-args: |
|
|
||||||
--ulimit nofile=10000
|
|
||||||
|
|
||||||
- name: UI Tests
|
- name: Set up QEMU
|
||||||
if: success()
|
uses: docker/setup-qemu-action@v3
|
||||||
run: |
|
|
||||||
sudo apt-get install xvfb
|
- name: Production Image Build
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
if: success()
|
||||||
|
id: build-image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
- name: UI Tests
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
sudo apt-get install xvfb
|
||||||
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|||||||
166
.github/workflows/releases.yml
vendored
166
.github/workflows/releases.yml
vendored
@@ -4,7 +4,10 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- "v*"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: ghcr.io
|
REGISTRY: ghcr.io
|
||||||
@@ -14,83 +17,110 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
main:
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '18.x'
|
node-version: 18
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
export DETECT_CHROMEDRIVER_VERSION=true
|
export DETECT_CHROMEDRIVER_VERSION=true
|
||||||
npm ci
|
npm ci
|
||||||
npm run setheapsize
|
npm run setheapsize
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: npx grunt lint
|
run: npx grunt lint
|
||||||
|
|
||||||
- name: Unit Tests
|
- name: Unit Tests
|
||||||
run: |
|
run: |
|
||||||
npm test
|
npm test
|
||||||
npm run testnodeconsumer
|
npm run testnodeconsumer
|
||||||
|
|
||||||
- name: Production Build
|
- name: Production Build
|
||||||
run: npx grunt prod
|
run: npx grunt prod
|
||||||
|
|
||||||
- name: UI Tests
|
- name: UI Tests
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install xvfb
|
sudo apt-get install xvfb
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|
||||||
- name: Image Metadata
|
- name: Set up Docker Buildx
|
||||||
id: image-metadata
|
uses: docker/setup-buildx-action@v3
|
||||||
uses: docker/metadata-action@v4
|
|
||||||
with:
|
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{major}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
|
|
||||||
- name: Production Image Build
|
- name: Set up QEMU
|
||||||
id: build-image
|
uses: docker/setup-qemu-action@v3
|
||||||
uses: redhat-actions/buildah-build@v2
|
|
||||||
with:
|
|
||||||
tags: ${{ steps.image-metadata.outputs.tags }}
|
|
||||||
labels: ${{ steps.image-metadata.outputs.labels }}
|
|
||||||
containerfiles: ./Dockerfile
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
oci: true
|
|
||||||
# enable build layer caching between platforms
|
|
||||||
layers: true
|
|
||||||
# Webpack seems to use a lot of open files, increase the max open file limit to accomodate.
|
|
||||||
extra-args: |
|
|
||||||
--ulimit nofile=10000
|
|
||||||
|
|
||||||
- name: Publish to GHCR
|
- name: Image Metadata
|
||||||
uses: redhat-actions/push-to-registry@v2
|
id: image-metadata
|
||||||
with:
|
uses: docker/metadata-action@v4
|
||||||
image: ${{ steps.build-image.outputs.image }}
|
with:
|
||||||
tags: ${{ steps.build-image.outputs.tags }}
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
registry: ${{ env.REGISTRY }}
|
tags: |
|
||||||
username: ${{ env.REGISTRY_USER }}
|
type=semver,pattern={{major}}
|
||||||
password: ${{ env.REGISTRY_PASSWORD }}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
|
||||||
- name: Upload Release Assets
|
- name: Log in to GHCR
|
||||||
id: upload-release-assets
|
uses: docker/login-action@v3
|
||||||
uses: svenstaro/upload-release-action@v2
|
with:
|
||||||
with:
|
registry: ${{ env.REGISTRY }}
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
username: ${{ env.REGISTRY_USER }}
|
||||||
file: build/prod/*.zip
|
password: ${{ env.REGISTRY_PASSWORD }}
|
||||||
tag: ${{ github.ref }}
|
|
||||||
overwrite: true
|
|
||||||
file_glob: true
|
|
||||||
body: "See the [CHANGELOG](https://github.com/gchq/CyberChef/blob/master/CHANGELOG.md) and [commit messages](https://github.com/gchq/CyberChef/commits/master) for details."
|
|
||||||
|
|
||||||
- name: Publish to NPM
|
- name: Publish to GHCR
|
||||||
uses: JS-DevTools/npm-publish@v1
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.NPM_TOKEN }}
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.image-metadata.outputs.tags }}
|
||||||
|
labels: ${{ steps.image-metadata.outputs.labels }}
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|
||||||
|
- name: Upload Release Assets
|
||||||
|
id: upload-release-assets
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: build/prod/*.zip
|
||||||
|
tag: ${{ github.ref }}
|
||||||
|
overwrite: true
|
||||||
|
file_glob: true
|
||||||
|
body: "See the [CHANGELOG](https://github.com/gchq/CyberChef/blob/master/CHANGELOG.md) and [commit messages](https://github.com/gchq/CyberChef/commits/master) for details."
|
||||||
|
|
||||||
|
npm-publish:
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: read
|
||||||
|
needs: main
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Set node version
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Create machine generated files
|
||||||
|
run: npm run node
|
||||||
|
|
||||||
|
- name: Reset node version ready for publish
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: ^24.5
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
|
- name: Publish to NPM
|
||||||
|
run: npm publish
|
||||||
|
|||||||
69
CHANGELOG.md
69
CHANGELOG.md
@@ -13,6 +13,35 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
### [10.22.0] - 2026-02-11
|
||||||
|
- Separate npm publish out into separate job and run with Node 24.5 [@GCHQDeveloper581] | [#2188]
|
||||||
|
- Fixed Percent delimiter for hex encoding [@beneri] [@C85297] | [#2137]
|
||||||
|
- Added the ability to paste one or more Images from the Clipboard [@t-martine] [@a3957273] [@C85297] | [#1876]
|
||||||
|
- Quoted Printable - consistent reference to 'email' [@wesinator] | [#2186]
|
||||||
|
- Fix freeze when output text decoding fails [@Raka-loah] | [#1573]
|
||||||
|
- Update Browserslist DB [@C85297] | [#2183]
|
||||||
|
- Add contents write permission to releases workflow [@C85297] | [#2182]
|
||||||
|
- Fix release workflow permissions [@C85297] | [#2181]
|
||||||
|
|
||||||
|
### [10.21.0] - 2026-02-05
|
||||||
|
- Fix import operations with special chars in them [@d98762625] [@jg42526] | [#1040]
|
||||||
|
- Remove custom CodeQL workflow [@C85297] | [#2176]
|
||||||
|
- Fix code scanning warnings in workflows [@GCHQDeveloper581] | [#2177]
|
||||||
|
- Use NPM trusted publishing [@C85297] [@GCHQDeveloper581] | [#2174]
|
||||||
|
- Fix: Correctly parse xxd odd byte hexdumps [@ThomasNotTom] [@GCHQDeveloper581] | [#2058]
|
||||||
|
- Update Sitemap URLs to Use Valid Paths in sitemap.mjs [@rbpi] [@C85297] | [#1861]
|
||||||
|
- Use recommended GitHub Actions to build image [@AlexGustafsson] [@C85297] | [#2055]
|
||||||
|
- Remove version 10 message from banner [@C85297] | [#2169]
|
||||||
|
- Bump form-data from 4.0.1 to 4.0.5 | [#2175]
|
||||||
|
- Bump node-forge from 1.3.1 to 1.3.3 | [#2173]
|
||||||
|
- Update crypto browserify [@C85297] | [#2172]
|
||||||
|
- Update kbpgp package (resolves #2135) [@GCHQDeveloper581] | [#2136]
|
||||||
|
- Fix the processing of ALPNs for JA4 to align with new specification update [@tuliperis] | [#2165]
|
||||||
|
- Add Bech32 and Bech32m encoding/decoding operations [@thomasxm] | [#2159]
|
||||||
|
- Exclude Delete character from hex dump output [@mikecat] [@C85297] | [#2086]
|
||||||
|
- Tiny typo fix in "To Base85" operation [@twostraws] | [#2118]
|
||||||
|
- Bump jsonpath-plus [@C85297] | [#2166]
|
||||||
|
|
||||||
### [10.20.0] - 2026-01-28
|
### [10.20.0] - 2026-01-28
|
||||||
- Fixed Optical Character Recognition and added tests [@n1474335] | [ab37c1e]
|
- Fixed Optical Character Recognition and added tests [@n1474335] | [ab37c1e]
|
||||||
- Fixed JA4 version fallback value [@n1474335] | [7a5225c]
|
- Fixed JA4 version fallback value [@n1474335] | [7a5225c]
|
||||||
@@ -509,6 +538,8 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
## [4.0.0] - 2016-11-28
|
## [4.0.0] - 2016-11-28
|
||||||
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
|
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
|
||||||
|
|
||||||
|
[10.22.0]: https://github.com/gchq/CyberChef/releases/tag/v10.22.0
|
||||||
|
[10.21.0]: https://github.com/gchq/CyberChef/releases/tag/v10.21.0
|
||||||
[10.20.0]: https://github.com/gchq/CyberChef/releases/tag/v10.20.0
|
[10.20.0]: https://github.com/gchq/CyberChef/releases/tag/v10.20.0
|
||||||
[10.19.0]: https://github.com/gchq/CyberChef/releases/tag/v10.19.0
|
[10.19.0]: https://github.com/gchq/CyberChef/releases/tag/v10.19.0
|
||||||
[10.18.0]: https://github.com/gchq/CyberChef/releases/tag/v10.18.0
|
[10.18.0]: https://github.com/gchq/CyberChef/releases/tag/v10.18.0
|
||||||
@@ -754,6 +785,18 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
[@remingtr]: https://github.com/remingtr
|
[@remingtr]: https://github.com/remingtr
|
||||||
[@0xff1ce]: https://github.com/0xff1ce
|
[@0xff1ce]: https://github.com/0xff1ce
|
||||||
[@starplanet]: https://github.com/starplanet
|
[@starplanet]: https://github.com/starplanet
|
||||||
|
[@C85297]: https://github.com/C85297
|
||||||
|
[@GCHQDeveloper581]: https://github.com/GCHQDeveloper581
|
||||||
|
[@ThomasNotTom]: https://github.com/ThomasNotTom
|
||||||
|
[@rbpi]: https://github.com/rbpi
|
||||||
|
[@AlexGustafsson]: https://github.com/AlexGustafsson
|
||||||
|
[@tuliperis]: https://github.com/tuliperis
|
||||||
|
[@thomasxm]: https://github.com/thomasxm
|
||||||
|
[@twostraws]: https://github.com/twostraws
|
||||||
|
[@beneri]: https://github.com/beneri
|
||||||
|
[@t-martine]: https://github.com/t-martine
|
||||||
|
[@wesinator]: https://github.com/wesinator
|
||||||
|
[@Raka-loah]: https://github.com/Raka-loah
|
||||||
|
|
||||||
|
|
||||||
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
||||||
@@ -942,3 +985,29 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
[#512]: https://github.com/gchq/CyberChef/issues/512
|
[#512]: https://github.com/gchq/CyberChef/issues/512
|
||||||
[#1732]: https://github.com/gchq/CyberChef/issues/1732
|
[#1732]: https://github.com/gchq/CyberChef/issues/1732
|
||||||
[#1789]: https://github.com/gchq/CyberChef/issues/1789
|
[#1789]: https://github.com/gchq/CyberChef/issues/1789
|
||||||
|
[#1040]: https://github.com/gchq/CyberChef/pull/1040
|
||||||
|
[#2176]: https://github.com/gchq/CyberChef/pull/2176
|
||||||
|
[#2177]: https://github.com/gchq/CyberChef/pull/2177
|
||||||
|
[#2174]: https://github.com/gchq/CyberChef/pull/2174
|
||||||
|
[#2058]: https://github.com/gchq/CyberChef/pull/2058
|
||||||
|
[#1861]: https://github.com/gchq/CyberChef/pull/1861
|
||||||
|
[#2055]: https://github.com/gchq/CyberChef/pull/2055
|
||||||
|
[#2169]: https://github.com/gchq/CyberChef/pull/2169
|
||||||
|
[#2175]: https://github.com/gchq/CyberChef/pull/2175
|
||||||
|
[#2173]: https://github.com/gchq/CyberChef/pull/2173
|
||||||
|
[#2172]: https://github.com/gchq/CyberChef/pull/2172
|
||||||
|
[#2136]: https://github.com/gchq/CyberChef/pull/2136
|
||||||
|
[#2165]: https://github.com/gchq/CyberChef/pull/2165
|
||||||
|
[#2159]: https://github.com/gchq/CyberChef/pull/2159
|
||||||
|
[#2086]: https://github.com/gchq/CyberChef/pull/2086
|
||||||
|
[#2118]: https://github.com/gchq/CyberChef/pull/2118
|
||||||
|
[#2166]: https://github.com/gchq/CyberChef/pull/2166
|
||||||
|
[#2188]: https://github.com/gchq/CyberChef/pull/2188
|
||||||
|
[#2137]: https://github.com/gchq/CyberChef/pull/2137
|
||||||
|
[#1876]: https://github.com/gchq/CyberChef/pull/1876
|
||||||
|
[#2186]: https://github.com/gchq/CyberChef/pull/2186
|
||||||
|
[#1573]: https://github.com/gchq/CyberChef/pull/1573
|
||||||
|
[#2183]: https://github.com/gchq/CyberChef/pull/2183
|
||||||
|
[#2182]: https://github.com/gchq/CyberChef/pull/2182
|
||||||
|
[#2181]: https://github.com/gchq/CyberChef/pull/2181
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,8 @@ RUN npm run build
|
|||||||
#########################################
|
#########################################
|
||||||
# Package static build files into nginx #
|
# Package static build files into nginx #
|
||||||
#########################################
|
#########################################
|
||||||
# We are using Github Actions: redhat-actions/buildah-build@v2 which needs manual selection of arch in base image
|
FROM nginx:stable-alpine AS cyberchef
|
||||||
# Remove TARGETARCH if docker buildx is supported in the CI release as --platform=$TARGETPLATFORM will be automatically set
|
|
||||||
ARG TARGETPLATFORM
|
LABEL maintainer="GCHQ <oss@gchq.gov.uk>"
|
||||||
FROM --platform=${TARGETPLATFORM} nginx:stable-alpine AS cyberchef
|
|
||||||
|
|
||||||
COPY --from=builder /app/build/prod /usr/share/nginx/html/
|
COPY --from=builder /app/build/prod /usr/share/nginx/html/
|
||||||
|
|||||||
12
Gruntfile.js
12
Gruntfile.js
@@ -432,18 +432,6 @@ module.exports = function (grunt) {
|
|||||||
},
|
},
|
||||||
stdout: false
|
stdout: false
|
||||||
},
|
},
|
||||||
fixJimpModule: {
|
|
||||||
command: function () {
|
|
||||||
switch (process.platform) {
|
|
||||||
case "darwin":
|
|
||||||
// Space added before comma to prevent multiple modifications
|
|
||||||
return `sed -i '' 's/"es\\/index.js",/"es\\/index.js" ,\\n "type": "module",/' ./node_modules/jimp/package.json`;
|
|
||||||
default:
|
|
||||||
return `sed -i 's/"es\\/index.js",/"es\\/index.js" ,\\n "type": "module",/' ./node_modules/jimp/package.json`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stdout: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
1081
package-lock.json
generated
1081
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "10.20.0",
|
"version": "10.22.1",
|
||||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||||
"author": "n1474335 <n1474335@gmail.com>",
|
"author": "n1474335 <n1474335@gmail.com>",
|
||||||
"homepage": "https://gchq.github.io/CyberChef",
|
"homepage": "https://gchq.github.io/CyberChef",
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
"chi-squared": "^1.1.0",
|
"chi-squared": "^1.1.0",
|
||||||
"codepage": "^1.15.0",
|
"codepage": "^1.15.0",
|
||||||
"crypto-api": "^0.8.5",
|
"crypto-api": "^0.8.5",
|
||||||
"crypto-browserify": "^3.12.0",
|
"crypto-browserify": "^3.12.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"ctph.js": "0.0.5",
|
"ctph.js": "0.0.5",
|
||||||
"d3": "7.9.0",
|
"d3": "7.9.0",
|
||||||
@@ -136,18 +136,18 @@
|
|||||||
"hash-wasm": "^4.12.0",
|
"hash-wasm": "^4.12.0",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"ieee754": "^1.2.1",
|
"ieee754": "^1.2.1",
|
||||||
"jimp": "^0.22.12",
|
"jimp": "^1.6.0",
|
||||||
"jq-web": "^0.5.1",
|
"jq-web": "^0.5.1",
|
||||||
"jquery": "3.7.1",
|
"jquery": "3.7.1",
|
||||||
"js-sha3": "^0.9.3",
|
"js-sha3": "^0.9.3",
|
||||||
"jsesc": "^3.0.2",
|
"jsesc": "^3.0.2",
|
||||||
"json5": "^2.2.3",
|
"json5": "^2.2.3",
|
||||||
"jsonata": "^2.0.3",
|
"jsonata": "^2.0.3",
|
||||||
"jsonpath-plus": "^9.0.0",
|
"jsonpath-plus": "^10.3.0",
|
||||||
"jsonwebtoken": "8.5.1",
|
"jsonwebtoken": "8.5.1",
|
||||||
"jsqr": "^1.4.0",
|
"jsqr": "^1.4.0",
|
||||||
"jsrsasign": "^11.1.0",
|
"jsrsasign": "^11.1.0",
|
||||||
"kbpgp": "2.1.15",
|
"kbpgp": "^2.1.17",
|
||||||
"libbzip2-wasm": "0.0.4",
|
"libbzip2-wasm": "0.0.4",
|
||||||
"libyara-wasm": "^1.2.1",
|
"libyara-wasm": "^1.2.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -200,9 +200,10 @@
|
|||||||
"testuidev": "npx nightwatch --env=dev",
|
"testuidev": "npx nightwatch --env=dev",
|
||||||
"lint": "npx grunt lint",
|
"lint": "npx grunt lint",
|
||||||
"lint:grammar": "cspell ./src",
|
"lint:grammar": "cspell ./src",
|
||||||
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup && npx grunt exec:fixJimpModule",
|
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup",
|
||||||
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
||||||
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs",
|
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs && npm version minor --git-tag-version=false && echo \"Updated to version v$(npm pkg get version | xargs), please create a pull request and once merged use 'npm run tag'\"",
|
||||||
|
"tag": "git tag -s \"v$(npm pkg get version | xargs)\" -m \"$(npm pkg get version | xargs)\" && echo \"Created v$(npm pkg get version | xargs), now check and push the tag\"",
|
||||||
"getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'",
|
"getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'",
|
||||||
"setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048"
|
"setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ class Recipe {
|
|||||||
}
|
}
|
||||||
this.lastRunOp = op;
|
this.lastRunOp = op;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
log.error(err);
|
||||||
// Return expected errors as output
|
// Return expected errors as output
|
||||||
if (err instanceof OperationError || err?.type === "OperationError") {
|
if (err instanceof OperationError || err?.type === "OperationError") {
|
||||||
// Cannot rely on `err instanceof OperationError` here as extending
|
// Cannot rely on `err instanceof OperationError` here as extending
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ class Utils {
|
|||||||
*/
|
*/
|
||||||
static printable(str, preserveWs=false, onlyAscii=false) {
|
static printable(str, preserveWs=false, onlyAscii=false) {
|
||||||
if (onlyAscii) {
|
if (onlyAscii) {
|
||||||
return str.replace(/[^\x20-\x7f]/g, ".");
|
return str.replace(/[^\x20-\x7e]/g, ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-misleading-character-class
|
// eslint-disable-next-line no-misleading-character-class
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
"From Base45",
|
"From Base45",
|
||||||
"To Base58",
|
"To Base58",
|
||||||
"From Base58",
|
"From Base58",
|
||||||
|
"To Bech32",
|
||||||
|
"From Bech32",
|
||||||
"To Base62",
|
"To Base62",
|
||||||
"From Base62",
|
"From Base62",
|
||||||
"To Base64",
|
"To Base64",
|
||||||
|
|||||||
@@ -7,138 +7,197 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint no-console: ["off"] */
|
/* eslint no-console: ["off"] */
|
||||||
|
/* eslint jsdoc/require-jsdoc: ["off"] */
|
||||||
|
|
||||||
import prompt from "prompt";
|
|
||||||
import colors from "colors";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import process from "process";
|
import process from "process";
|
||||||
|
import { execSync } from "child_process";
|
||||||
|
|
||||||
const dir = path.join(process.cwd() + "/src/core/config/");
|
const ignoredAuthors = ["github-advanced-security[bot]", "dependabot[bot]"];
|
||||||
if (!fs.existsSync(dir)) {
|
|
||||||
console.log("\nCWD: " + process.cwd());
|
|
||||||
console.log("Error: newMinorVersion.mjs should be run from the project root");
|
|
||||||
console.log("Example> node --experimental-modules src/core/config/scripts/newMinorVersion.mjs");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let changelogData = fs.readFileSync(path.join(process.cwd(), "CHANGELOG.md"), "utf8");
|
async function main() {
|
||||||
const lastVersion = changelogData.match(/## Details\s+### \[(\d+)\.(\d+)\.(\d+)\]/);
|
const dir = path.join(process.cwd() + "/src/core/config/");
|
||||||
const newVersion = [
|
if (!fs.existsSync(dir)) {
|
||||||
parseInt(lastVersion[1], 10),
|
console.log("\nCWD: " + process.cwd());
|
||||||
parseInt(lastVersion[2], 10) + 1,
|
console.log(
|
||||||
0
|
"Error: newMinorVersion.mjs should be run from the project root",
|
||||||
];
|
);
|
||||||
|
console.log(
|
||||||
|
"Example> node --experimental-modules src/core/config/scripts/newMinorVersion.mjs",
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
let knownContributors = changelogData.match(/^\[@([^\]]+)\]/gm);
|
let changelogData = fs.readFileSync(
|
||||||
knownContributors = knownContributors.map(c => c.slice(2, -1));
|
path.join(process.cwd(), "CHANGELOG.md"),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
const lastVersion = changelogData.match(
|
||||||
|
/## Details\s+### \[(\d+)\.(\d+)\.(\d+)\]/,
|
||||||
|
);
|
||||||
|
const newVersion = [
|
||||||
|
parseInt(lastVersion[1], 10),
|
||||||
|
parseInt(lastVersion[2], 10) + 1,
|
||||||
|
0,
|
||||||
|
];
|
||||||
|
|
||||||
const date = (new Date()).toISOString().split("T")[0];
|
let knownContributors = changelogData.match(/^\[@([^\]]+)\]/gm);
|
||||||
|
knownContributors = knownContributors.map((c) => c.slice(2, -1));
|
||||||
|
|
||||||
const schema = {
|
const date = new Date().toISOString().split("T")[0];
|
||||||
properties: {
|
|
||||||
message: {
|
const lastVersionSha = execSync(
|
||||||
description: "A short but descriptive summary of a feature in this version",
|
`git rev-list -n 1 v${lastVersion[1]}.${lastVersion[2]}.${lastVersion[3]}`,
|
||||||
example: "Added 'Op name' operation",
|
{
|
||||||
prompt: "Feature description",
|
encoding: "utf8",
|
||||||
type: "string",
|
|
||||||
required: true,
|
|
||||||
},
|
},
|
||||||
author: {
|
).trim();
|
||||||
description: "The author of the feature (only one supported, edit manually to add more)",
|
if (lastVersionSha.length !== 40) {
|
||||||
example: "n1474335",
|
throw new Error(
|
||||||
prompt: "Author",
|
`Unexpected output from git rev-list: ${lastVersionSha}`,
|
||||||
type: "string",
|
);
|
||||||
default: "n1474335"
|
}
|
||||||
},
|
|
||||||
id: {
|
const features = [];
|
||||||
description: "The PR number or full commit hash for this feature.",
|
|
||||||
example: "1200",
|
const commits = await (
|
||||||
prompt: "Pull request or commit ID",
|
await fetch(`https://api.github.com/repos/gchq/cyberchef/commits`)
|
||||||
type: "string"
|
).json();
|
||||||
},
|
let foundLast = false;
|
||||||
another: {
|
for (const commit of commits) {
|
||||||
description: "y/n",
|
if (commit.sha === lastVersionSha) {
|
||||||
example: "y",
|
foundLast = true;
|
||||||
prompt: "Add another feature?",
|
break;
|
||||||
type: "string",
|
} else {
|
||||||
pattern: /^[yn]$/,
|
const feature = {
|
||||||
|
message: "",
|
||||||
|
authors: [],
|
||||||
|
id: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const msgparts = commit.commit.message.split("\n\n");
|
||||||
|
feature.message = msgparts[0];
|
||||||
|
const prIdMatch = feature.message.match(/\(#(\d+)\)$/);
|
||||||
|
if (prIdMatch !== null) {
|
||||||
|
feature.message = feature.message
|
||||||
|
.replace(prIdMatch[0], "")
|
||||||
|
.trim();
|
||||||
|
feature.id = prIdMatch[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ignoredAuthors.includes(commit.author.login)) {
|
||||||
|
feature.authors.push(commit.author.login);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msgparts.length > 1) {
|
||||||
|
msgparts[1]
|
||||||
|
.split("\n")
|
||||||
|
.filter((line) => line.startsWith("Co-authored-by: "))
|
||||||
|
.forEach((line) => {
|
||||||
|
let coAuthor = line.slice("Co-authored-by: ".length);
|
||||||
|
if (coAuthor.indexOf(">") !== -1) {
|
||||||
|
const email = coAuthor.slice(
|
||||||
|
coAuthor.indexOf("<") + 1,
|
||||||
|
coAuthor.indexOf(">"),
|
||||||
|
);
|
||||||
|
if (email.endsWith("@users.noreply.github.com")) {
|
||||||
|
coAuthor = email.slice(
|
||||||
|
email.indexOf("+") + 1,
|
||||||
|
-"@users.noreply.github.com".length,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"Could not get ID of co-author: " +
|
||||||
|
coAuthor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"Could not get email of co-author: " + coAuthor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!ignoredAuthors.includes(coAuthor)) {
|
||||||
|
feature.authors.push(coAuthor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
features.push(feature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
if (!foundLast) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not find last version commit: ${lastVersionSha} - need to add paging functionality`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Build schema
|
let message = `### [${newVersion[0]}.${newVersion[1]}.${newVersion[2]}] - ${date}\n`;
|
||||||
for (const prop in schema.properties) {
|
|
||||||
const p = schema.properties[prop];
|
|
||||||
p.description = "\n" + colors.white(p.description) + colors.cyan("\nExample: " + p.example) + "\n" + colors.green(p.prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt.message = "";
|
const authors = [];
|
||||||
prompt.delimiter = ":".green;
|
const prIDs = [];
|
||||||
|
const commitIDs = [];
|
||||||
|
|
||||||
const features = [];
|
features.forEach((feature) => {
|
||||||
const authors = [];
|
const id =
|
||||||
const prIDs = [];
|
feature.id.length > 10 ? feature.id.slice(0, 7) : "#" + feature.id;
|
||||||
const commitIDs = [];
|
message += `- ${feature.message} ${feature.authors.map((a) => `[@${a}]`).join(" ")} | [${id}]\n`;
|
||||||
|
|
||||||
prompt.start();
|
feature.authors.forEach((author) => {
|
||||||
|
if (!knownContributors.includes(author)) {
|
||||||
|
knownContributors.push(author);
|
||||||
|
authors.push(`[@${author}]: https://github.com/${author}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const getFeature = function() {
|
if (feature.id.length > 10) {
|
||||||
prompt.get(schema, (err, result) => {
|
commitIDs.push(
|
||||||
if (err) {
|
`[${id}]: https://github.com/gchq/CyberChef/commit/${feature.id}`,
|
||||||
console.log("\nExiting script.");
|
);
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
features.push(result);
|
|
||||||
|
|
||||||
if (result.another === "y") {
|
|
||||||
getFeature();
|
|
||||||
} else {
|
} else {
|
||||||
let message = `### [${newVersion[0]}.${newVersion[1]}.${newVersion[2]}] - ${date}\n`;
|
prIDs.push(
|
||||||
|
`[#${feature.id}]: https://github.com/gchq/CyberChef/pull/${feature.id}`,
|
||||||
features.forEach(feature => {
|
);
|
||||||
const id = feature.id.length > 10 ? feature.id.slice(0, 7) : "#" + feature.id;
|
|
||||||
message += `- ${feature.message} [@${feature.author}] | [${id}]\n`;
|
|
||||||
|
|
||||||
if (!knownContributors.includes(feature.author)) {
|
|
||||||
authors.push(`[@${feature.author}]: https://github.com/${feature.author}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (feature.id.length > 10) {
|
|
||||||
commitIDs.push(`[${id}]: https://github.com/gchq/CyberChef/commit/${feature.id}`);
|
|
||||||
} else {
|
|
||||||
prIDs.push(`[#${feature.id}]: https://github.com/gchq/CyberChef/pull/${feature.id}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Message
|
|
||||||
changelogData = changelogData.replace(/## Details\n\n/, "## Details\n\n" + message + "\n");
|
|
||||||
|
|
||||||
// Tag
|
|
||||||
const newTag = `[${newVersion[0]}.${newVersion[1]}.${newVersion[2]}]: https://github.com/gchq/CyberChef/releases/tag/v${newVersion[0]}.${newVersion[1]}.${newVersion[2]}\n`;
|
|
||||||
changelogData = changelogData.replace(/\n\n(\[\d+\.\d+\.\d+\]: https)/, "\n\n" + newTag + "$1");
|
|
||||||
|
|
||||||
// Author
|
|
||||||
authors.forEach(author => {
|
|
||||||
changelogData = changelogData.replace(/(\n\[@[^\]]+\]: https:\/\/github\.com\/[^\n]+\n)\n/, "$1" + author + "\n\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Commit IDs
|
|
||||||
commitIDs.forEach(commitID => {
|
|
||||||
changelogData = changelogData.replace(/(\n\[[^\].]+\]: https:\/\/github.com\/gchq\/CyberChef\/commit\/[^\n]+\n)\n/, "$1" + commitID + "\n\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
// PR IDs
|
|
||||||
prIDs.forEach(prID => {
|
|
||||||
changelogData = changelogData.replace(/(\n\[#[^\]]+\]: https:\/\/github.com\/gchq\/CyberChef\/pull\/[^\n]+\n)\n*$/, "$1" + prID + "\n\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
|
||||||
|
|
||||||
console.log("Written CHANGELOG.md\nCommit changes and then run `npm version minor`.");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
getFeature();
|
// Message
|
||||||
|
changelogData = changelogData.replace(
|
||||||
|
/## Details\n\n/,
|
||||||
|
"## Details\n\n" + message + "\n",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Tag
|
||||||
|
const newTag = `[${newVersion[0]}.${newVersion[1]}.${newVersion[2]}]: https://github.com/gchq/CyberChef/releases/tag/v${newVersion[0]}.${newVersion[1]}.${newVersion[2]}\n`;
|
||||||
|
changelogData = changelogData.replace(
|
||||||
|
/\n\n(\[\d+\.\d+\.\d+\]: https)/,
|
||||||
|
"\n\n" + newTag + "$1",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Author
|
||||||
|
authors.forEach((author) => {
|
||||||
|
changelogData = changelogData.replace(
|
||||||
|
/(\n\[@[^\]]+\]: https:\/\/github\.com\/[^\n]+\n)\n/,
|
||||||
|
"$1" + author + "\n\n",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Commit IDs
|
||||||
|
commitIDs.forEach((commitID) => {
|
||||||
|
changelogData = changelogData.replace(
|
||||||
|
/(\n\[[^\].]+\]: https:\/\/github.com\/gchq\/CyberChef\/commit\/[^\n]+\n)\n/,
|
||||||
|
"$1" + commitID + "\n\n",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// PR IDs
|
||||||
|
prIDs.forEach((prID) => {
|
||||||
|
changelogData = changelogData.replace(
|
||||||
|
/(\n\[#[^\]]+\]: https:\/\/github.com\/gchq\/CyberChef\/(?:pull|issues)\/[^\n]+\n)\n*$/,
|
||||||
|
"$1" + prID + "\n\n",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
||||||
|
}
|
||||||
|
main().catch(console.error);
|
||||||
|
|||||||
371
src/core/lib/Bech32.mjs
Normal file
371
src/core/lib/Bech32.mjs
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
/**
|
||||||
|
* Pure JavaScript implementation of Bech32 and Bech32m encoding.
|
||||||
|
*
|
||||||
|
* Bech32 is defined in BIP-0173: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
|
||||||
|
* Bech32m is defined in BIP-0350: https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki
|
||||||
|
*
|
||||||
|
* @author Medjedtxm
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/** Bech32 character set (32 characters, excludes 1, b, i, o) */
|
||||||
|
const CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
||||||
|
|
||||||
|
/** Reverse lookup table for decoding */
|
||||||
|
const CHARSET_REV = {};
|
||||||
|
for (let i = 0; i < CHARSET.length; i++) {
|
||||||
|
CHARSET_REV[CHARSET[i]] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checksum constant for Bech32 (BIP-0173) */
|
||||||
|
const BECH32_CONST = 1;
|
||||||
|
|
||||||
|
/** Checksum constant for Bech32m (BIP-0350) */
|
||||||
|
const BECH32M_CONST = 0x2bc830a3;
|
||||||
|
|
||||||
|
/** Generator polynomial coefficients for checksum */
|
||||||
|
const GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the polymod checksum
|
||||||
|
* @param {number[]} values - Array of 5-bit values
|
||||||
|
* @returns {number} - Checksum value
|
||||||
|
*/
|
||||||
|
function polymod(values) {
|
||||||
|
let chk = 1;
|
||||||
|
for (const v of values) {
|
||||||
|
const top = chk >> 25;
|
||||||
|
chk = ((chk & 0x1ffffff) << 5) ^ v;
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
if ((top >> i) & 1) {
|
||||||
|
chk ^= GENERATOR[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand HRP for checksum computation
|
||||||
|
* @param {string} hrp - Human-readable part (lowercase)
|
||||||
|
* @returns {number[]} - Expanded values
|
||||||
|
*/
|
||||||
|
function hrpExpand(hrp) {
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < hrp.length; i++) {
|
||||||
|
result.push(hrp.charCodeAt(i) >> 5);
|
||||||
|
}
|
||||||
|
result.push(0);
|
||||||
|
for (let i = 0; i < hrp.length; i++) {
|
||||||
|
result.push(hrp.charCodeAt(i) & 31);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify checksum of a Bech32/Bech32m string
|
||||||
|
* @param {string} hrp - Human-readable part (lowercase)
|
||||||
|
* @param {number[]} data - Data including checksum (5-bit values)
|
||||||
|
* @param {string} encoding - "Bech32" or "Bech32m"
|
||||||
|
* @returns {boolean} - True if checksum is valid
|
||||||
|
*/
|
||||||
|
function verifyChecksum(hrp, data, encoding) {
|
||||||
|
const constant = encoding === "Bech32m" ? BECH32M_CONST : BECH32_CONST;
|
||||||
|
return polymod(hrpExpand(hrp).concat(data)) === constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create checksum for Bech32/Bech32m encoding
|
||||||
|
* @param {string} hrp - Human-readable part (lowercase)
|
||||||
|
* @param {number[]} data - Data values (5-bit)
|
||||||
|
* @param {string} encoding - "Bech32" or "Bech32m"
|
||||||
|
* @returns {number[]} - 6 checksum values
|
||||||
|
*/
|
||||||
|
function createChecksum(hrp, data, encoding) {
|
||||||
|
const constant = encoding === "Bech32m" ? BECH32M_CONST : BECH32_CONST;
|
||||||
|
const values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
|
||||||
|
const mod = polymod(values) ^ constant;
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
result.push((mod >> (5 * (5 - i))) & 31);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert 8-bit bytes to 5-bit words
|
||||||
|
* @param {number[]|Uint8Array} data - Input bytes
|
||||||
|
* @returns {number[]} - 5-bit words
|
||||||
|
*/
|
||||||
|
export function toWords(data) {
|
||||||
|
let value = 0;
|
||||||
|
let bits = 0;
|
||||||
|
const result = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
value = (value << 8) | data[i];
|
||||||
|
bits += 8;
|
||||||
|
|
||||||
|
while (bits >= 5) {
|
||||||
|
bits -= 5;
|
||||||
|
result.push((value >> bits) & 31);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad remaining bits
|
||||||
|
if (bits > 0) {
|
||||||
|
result.push((value << (5 - bits)) & 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert 5-bit words to 8-bit bytes
|
||||||
|
* @param {number[]} words - 5-bit words
|
||||||
|
* @returns {number[]} - Output bytes
|
||||||
|
*/
|
||||||
|
export function fromWords(words) {
|
||||||
|
let value = 0;
|
||||||
|
let bits = 0;
|
||||||
|
const result = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < words.length; i++) {
|
||||||
|
value = (value << 5) | words[i];
|
||||||
|
bits += 5;
|
||||||
|
|
||||||
|
while (bits >= 8) {
|
||||||
|
bits -= 8;
|
||||||
|
result.push((value >> bits) & 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for invalid padding per BIP-0173
|
||||||
|
// Condition 1: Cannot have 5+ bits remaining (would indicate incomplete byte)
|
||||||
|
if (bits >= 5) {
|
||||||
|
throw new OperationError("Invalid padding: too many bits remaining");
|
||||||
|
}
|
||||||
|
// Condition 2: Remaining padding bits must all be zero
|
||||||
|
if (bits > 0) {
|
||||||
|
const paddingValue = (value << (8 - bits)) & 255;
|
||||||
|
if (paddingValue !== 0) {
|
||||||
|
throw new OperationError("Invalid padding: non-zero bits in padding");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode data to Bech32/Bech32m string
|
||||||
|
*
|
||||||
|
* @param {string} hrp - Human-readable part
|
||||||
|
* @param {number[]|Uint8Array} data - Data bytes to encode
|
||||||
|
* @param {string} encoding - "Bech32" or "Bech32m"
|
||||||
|
* @param {boolean} segwit - If true, treat first byte as witness version (for Bitcoin SegWit)
|
||||||
|
* @returns {string} - Encoded Bech32/Bech32m string
|
||||||
|
*/
|
||||||
|
export function encode(hrp, data, encoding = "Bech32", segwit = false) {
|
||||||
|
// Validate HRP
|
||||||
|
if (!hrp || hrp.length === 0) {
|
||||||
|
throw new OperationError("Human-Readable Part (HRP) cannot be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check HRP characters (ASCII 33-126)
|
||||||
|
for (let i = 0; i < hrp.length; i++) {
|
||||||
|
const c = hrp.charCodeAt(i);
|
||||||
|
if (c < 33 || c > 126) {
|
||||||
|
throw new OperationError(`HRP contains invalid character at position ${i}. Only printable ASCII characters (33-126) are allowed.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert HRP to lowercase
|
||||||
|
const hrpLower = hrp.toLowerCase();
|
||||||
|
|
||||||
|
let words;
|
||||||
|
if (segwit && data.length >= 2) {
|
||||||
|
// SegWit encoding: first byte is witness version (0-16), rest is witness program
|
||||||
|
const witnessVersion = data[0];
|
||||||
|
if (witnessVersion > 16) {
|
||||||
|
throw new OperationError(`Invalid witness version: ${witnessVersion}. Must be 0-16.`);
|
||||||
|
}
|
||||||
|
const witnessProgram = Array.prototype.slice.call(data, 1);
|
||||||
|
|
||||||
|
// Validate witness program length per BIP-0141
|
||||||
|
if (witnessProgram.length < 2 || witnessProgram.length > 40) {
|
||||||
|
throw new OperationError(`Invalid witness program length: ${witnessProgram.length}. Must be 2-40 bytes.`);
|
||||||
|
}
|
||||||
|
if (witnessVersion === 0 && witnessProgram.length !== 20 && witnessProgram.length !== 32) {
|
||||||
|
throw new OperationError(`Invalid witness program length for v0: ${witnessProgram.length}. Must be 20 or 32 bytes.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Witness version is kept as single 5-bit value, program is converted
|
||||||
|
words = [witnessVersion].concat(toWords(witnessProgram));
|
||||||
|
} else {
|
||||||
|
// Generic encoding: convert all bytes to 5-bit words
|
||||||
|
words = toWords(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create checksum
|
||||||
|
const checksum = createChecksum(hrpLower, words, encoding);
|
||||||
|
|
||||||
|
// Build result string
|
||||||
|
let result = hrpLower + "1";
|
||||||
|
for (const w of words.concat(checksum)) {
|
||||||
|
result += CHARSET[w];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check maximum length (90 characters)
|
||||||
|
if (result.length > 90) {
|
||||||
|
throw new OperationError(`Encoded string exceeds maximum length of 90 characters (got ${result.length}). Consider using smaller input data.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a Bech32/Bech32m string
|
||||||
|
*
|
||||||
|
* @param {string} str - Bech32/Bech32m encoded string
|
||||||
|
* @param {string} encoding - "Bech32", "Bech32m", or "Auto-detect"
|
||||||
|
* @returns {{hrp: string, data: number[]}} - Decoded HRP and data bytes
|
||||||
|
*/
|
||||||
|
export function decode(str, encoding = "Auto-detect") {
|
||||||
|
// Check for empty input
|
||||||
|
if (!str || str.length === 0) {
|
||||||
|
throw new OperationError("Input cannot be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check maximum length
|
||||||
|
if (str.length > 90) {
|
||||||
|
throw new OperationError(`Invalid Bech32 string: exceeds maximum length of 90 characters (got ${str.length}).`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for mixed case
|
||||||
|
const hasUpper = /[A-Z]/.test(str);
|
||||||
|
const hasLower = /[a-z]/.test(str);
|
||||||
|
if (hasUpper && hasLower) {
|
||||||
|
throw new OperationError("Invalid Bech32 string: mixed case is not allowed. Use all uppercase or all lowercase.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to lowercase for processing
|
||||||
|
str = str.toLowerCase();
|
||||||
|
|
||||||
|
// Find separator (last occurrence of '1')
|
||||||
|
const sepIndex = str.lastIndexOf("1");
|
||||||
|
if (sepIndex === -1) {
|
||||||
|
throw new OperationError("Invalid Bech32 string: no separator '1' found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sepIndex === 0) {
|
||||||
|
throw new OperationError("Invalid Bech32 string: Human-Readable Part (HRP) cannot be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sepIndex + 7 > str.length) {
|
||||||
|
throw new OperationError("Invalid Bech32 string: data part is too short (minimum 6 characters for checksum).");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract HRP and data part
|
||||||
|
const hrp = str.substring(0, sepIndex);
|
||||||
|
const dataPart = str.substring(sepIndex + 1);
|
||||||
|
|
||||||
|
// Validate HRP characters
|
||||||
|
for (let i = 0; i < hrp.length; i++) {
|
||||||
|
const c = hrp.charCodeAt(i);
|
||||||
|
if (c < 33 || c > 126) {
|
||||||
|
throw new OperationError(`HRP contains invalid character at position ${i}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode data characters to 5-bit values
|
||||||
|
const data = [];
|
||||||
|
for (let i = 0; i < dataPart.length; i++) {
|
||||||
|
const c = dataPart[i];
|
||||||
|
if (CHARSET_REV[c] === undefined) {
|
||||||
|
throw new OperationError(`Invalid character '${c}' at position ${sepIndex + 1 + i}.`);
|
||||||
|
}
|
||||||
|
data.push(CHARSET_REV[c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify checksum
|
||||||
|
let usedEncoding;
|
||||||
|
if (encoding === "Bech32") {
|
||||||
|
if (!verifyChecksum(hrp, data, "Bech32")) {
|
||||||
|
throw new OperationError("Invalid Bech32 checksum.");
|
||||||
|
}
|
||||||
|
usedEncoding = "Bech32";
|
||||||
|
} else if (encoding === "Bech32m") {
|
||||||
|
if (!verifyChecksum(hrp, data, "Bech32m")) {
|
||||||
|
throw new OperationError("Invalid Bech32m checksum.");
|
||||||
|
}
|
||||||
|
usedEncoding = "Bech32m";
|
||||||
|
} else {
|
||||||
|
// Auto-detect: try Bech32 first, then Bech32m
|
||||||
|
if (verifyChecksum(hrp, data, "Bech32")) {
|
||||||
|
usedEncoding = "Bech32";
|
||||||
|
} else if (verifyChecksum(hrp, data, "Bech32m")) {
|
||||||
|
usedEncoding = "Bech32m";
|
||||||
|
} else {
|
||||||
|
throw new OperationError("Invalid Bech32/Bech32m string: checksum verification failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove checksum (last 6 values)
|
||||||
|
const words = data.slice(0, data.length - 6);
|
||||||
|
|
||||||
|
// Check if this is likely a SegWit address (Bitcoin, Litecoin, etc.)
|
||||||
|
// For SegWit, the first 5-bit word is the witness version (0-16)
|
||||||
|
// and should be extracted separately, not bit-converted with the rest
|
||||||
|
const segwitHrps = ["bc", "tb", "ltc", "tltc", "bcrt"];
|
||||||
|
const couldBeSegWit = segwitHrps.includes(hrp) && words.length > 0 && words[0] <= 16;
|
||||||
|
|
||||||
|
let bytes;
|
||||||
|
let witnessVersion = null;
|
||||||
|
|
||||||
|
if (couldBeSegWit) {
|
||||||
|
// Try SegWit decode first
|
||||||
|
try {
|
||||||
|
witnessVersion = words[0];
|
||||||
|
const programWords = words.slice(1);
|
||||||
|
const programBytes = fromWords(programWords);
|
||||||
|
|
||||||
|
// Validate SegWit witness program length (20 or 32 bytes for v0, 2-40 for others)
|
||||||
|
const validV0 = witnessVersion === 0 && (programBytes.length === 20 || programBytes.length === 32);
|
||||||
|
const validOther = witnessVersion !== 0 && programBytes.length >= 2 && programBytes.length <= 40;
|
||||||
|
|
||||||
|
if (validV0 || validOther) {
|
||||||
|
// Valid SegWit address
|
||||||
|
bytes = [witnessVersion, ...programBytes];
|
||||||
|
} else {
|
||||||
|
// Not valid SegWit, fall back to generic decode
|
||||||
|
witnessVersion = null;
|
||||||
|
bytes = fromWords(words);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// SegWit decode failed, try generic decode
|
||||||
|
witnessVersion = null;
|
||||||
|
try {
|
||||||
|
bytes = fromWords(words);
|
||||||
|
} catch (e2) {
|
||||||
|
throw new OperationError(`Failed to decode data: ${e2.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Generic Bech32: convert all words
|
||||||
|
try {
|
||||||
|
bytes = fromWords(words);
|
||||||
|
} catch (e) {
|
||||||
|
throw new OperationError(`Failed to decode data: ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hrp: hrp,
|
||||||
|
data: bytes,
|
||||||
|
encoding: usedEncoding,
|
||||||
|
witnessVersion: witnessVersion
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ export function toHex(data, delim=" ", padding=2, extraDelim="", lineSize=0) {
|
|||||||
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
|
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
|
||||||
|
|
||||||
let output = "";
|
let output = "";
|
||||||
const prepend = (delim === "0x" || delim === "\\x");
|
const prepend = (delim === "0x" || delim === "\\x" || delim === "%");
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const hex = data[i].toString(16).padStart(padding, "0");
|
const hex = data[i].toString(16).padStart(padding, "0");
|
||||||
|
|||||||
@@ -1,251 +0,0 @@
|
|||||||
/**
|
|
||||||
* Image manipulation resources
|
|
||||||
*
|
|
||||||
* @author j433866 [j433866@gmail.com]
|
|
||||||
* @copyright Crown Copyright 2019
|
|
||||||
* @license Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gaussian blurs an image.
|
|
||||||
*
|
|
||||||
* @param {jimp} input
|
|
||||||
* @param {number} radius
|
|
||||||
* @param {boolean} fast
|
|
||||||
* @returns {jimp}
|
|
||||||
*/
|
|
||||||
export function gaussianBlur (input, radius) {
|
|
||||||
try {
|
|
||||||
// From http://blog.ivank.net/fastest-gaussian-blur.html
|
|
||||||
const boxes = boxesForGauss(radius, 3);
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
input = boxBlur(input, (boxes[i] - 1) / 2);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
throw new OperationError(`Error blurring image. (${err})`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number} radius
|
|
||||||
* @param {number} numBoxes
|
|
||||||
* @returns {Array}
|
|
||||||
*/
|
|
||||||
function boxesForGauss(radius, numBoxes) {
|
|
||||||
const idealWidth = Math.sqrt((12 * radius * radius / numBoxes) + 1);
|
|
||||||
|
|
||||||
let wl = Math.floor(idealWidth);
|
|
||||||
|
|
||||||
if (wl % 2 === 0) {
|
|
||||||
wl--;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wu = wl + 2;
|
|
||||||
|
|
||||||
const mIdeal = (12 * radius * radius - numBoxes * wl * wl - 4 * numBoxes * wl - 3 * numBoxes) / (-4 * wl - 4);
|
|
||||||
const m = Math.round(mIdeal);
|
|
||||||
|
|
||||||
const sizes = [];
|
|
||||||
for (let i = 0; i < numBoxes; i++) {
|
|
||||||
sizes.push(i < m ? wl : wu);
|
|
||||||
}
|
|
||||||
return sizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies a box blur effect to the image
|
|
||||||
*
|
|
||||||
* @param {jimp} source
|
|
||||||
* @param {number} radius
|
|
||||||
* @returns {jimp}
|
|
||||||
*/
|
|
||||||
function boxBlur (source, radius) {
|
|
||||||
const width = source.bitmap.width;
|
|
||||||
const height = source.bitmap.height;
|
|
||||||
let output = source.clone();
|
|
||||||
output = boxBlurH(source, output, width, height, radius);
|
|
||||||
source = boxBlurV(output, source, width, height, radius);
|
|
||||||
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the horizontal blur
|
|
||||||
*
|
|
||||||
* @param {jimp} source
|
|
||||||
* @param {jimp} output
|
|
||||||
* @param {number} width
|
|
||||||
* @param {number} height
|
|
||||||
* @param {number} radius
|
|
||||||
* @returns {jimp}
|
|
||||||
*/
|
|
||||||
function boxBlurH (source, output, width, height, radius) {
|
|
||||||
const iarr = 1 / (radius + radius + 1);
|
|
||||||
for (let i = 0; i < height; i++) {
|
|
||||||
let ti = 0,
|
|
||||||
li = ti,
|
|
||||||
ri = ti + radius;
|
|
||||||
const idx = source.getPixelIndex(ti, i);
|
|
||||||
const firstValRed = source.bitmap.data[idx],
|
|
||||||
firstValGreen = source.bitmap.data[idx + 1],
|
|
||||||
firstValBlue = source.bitmap.data[idx + 2],
|
|
||||||
firstValAlpha = source.bitmap.data[idx + 3];
|
|
||||||
|
|
||||||
const lastIdx = source.getPixelIndex(width - 1, i),
|
|
||||||
lastValRed = source.bitmap.data[lastIdx],
|
|
||||||
lastValGreen = source.bitmap.data[lastIdx + 1],
|
|
||||||
lastValBlue = source.bitmap.data[lastIdx + 2],
|
|
||||||
lastValAlpha = source.bitmap.data[lastIdx + 3];
|
|
||||||
|
|
||||||
let red = (radius + 1) * firstValRed;
|
|
||||||
let green = (radius + 1) * firstValGreen;
|
|
||||||
let blue = (radius + 1) * firstValBlue;
|
|
||||||
let alpha = (radius + 1) * firstValAlpha;
|
|
||||||
|
|
||||||
for (let j = 0; j < radius; j++) {
|
|
||||||
const jIdx = source.getPixelIndex(ti + j, i);
|
|
||||||
red += source.bitmap.data[jIdx];
|
|
||||||
green += source.bitmap.data[jIdx + 1];
|
|
||||||
blue += source.bitmap.data[jIdx + 2];
|
|
||||||
alpha += source.bitmap.data[jIdx + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j <= radius; j++) {
|
|
||||||
const jIdx = source.getPixelIndex(ri++, i);
|
|
||||||
red += source.bitmap.data[jIdx] - firstValRed;
|
|
||||||
green += source.bitmap.data[jIdx + 1] - firstValGreen;
|
|
||||||
blue += source.bitmap.data[jIdx + 2] - firstValBlue;
|
|
||||||
alpha += source.bitmap.data[jIdx + 3] - firstValAlpha;
|
|
||||||
|
|
||||||
const tiIdx = source.getPixelIndex(ti++, i);
|
|
||||||
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = radius + 1; j < width - radius; j++) {
|
|
||||||
const riIdx = source.getPixelIndex(ri++, i);
|
|
||||||
const liIdx = source.getPixelIndex(li++, i);
|
|
||||||
red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx];
|
|
||||||
green += source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1];
|
|
||||||
blue += source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2];
|
|
||||||
alpha += source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3];
|
|
||||||
|
|
||||||
const tiIdx = source.getPixelIndex(ti++, i);
|
|
||||||
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = width - radius; j < width; j++) {
|
|
||||||
const liIdx = source.getPixelIndex(li++, i);
|
|
||||||
red += lastValRed - source.bitmap.data[liIdx];
|
|
||||||
green += lastValGreen - source.bitmap.data[liIdx + 1];
|
|
||||||
blue += lastValBlue - source.bitmap.data[liIdx + 2];
|
|
||||||
alpha += lastValAlpha - source.bitmap.data[liIdx + 3];
|
|
||||||
|
|
||||||
const tiIdx = source.getPixelIndex(ti++, i);
|
|
||||||
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the vertical blur
|
|
||||||
*
|
|
||||||
* @param {jimp} source
|
|
||||||
* @param {jimp} output
|
|
||||||
* @param {number} width
|
|
||||||
* @param {number} height
|
|
||||||
* @param {number} radius
|
|
||||||
* @returns {jimp}
|
|
||||||
*/
|
|
||||||
function boxBlurV (source, output, width, height, radius) {
|
|
||||||
const iarr = 1 / (radius + radius + 1);
|
|
||||||
for (let i = 0; i < width; i++) {
|
|
||||||
let ti = 0,
|
|
||||||
li = ti,
|
|
||||||
ri = ti + radius;
|
|
||||||
|
|
||||||
const idx = source.getPixelIndex(i, ti);
|
|
||||||
|
|
||||||
const firstValRed = source.bitmap.data[idx],
|
|
||||||
firstValGreen = source.bitmap.data[idx + 1],
|
|
||||||
firstValBlue = source.bitmap.data[idx + 2],
|
|
||||||
firstValAlpha = source.bitmap.data[idx + 3];
|
|
||||||
|
|
||||||
const lastIdx = source.getPixelIndex(i, height - 1),
|
|
||||||
lastValRed = source.bitmap.data[lastIdx],
|
|
||||||
lastValGreen = source.bitmap.data[lastIdx + 1],
|
|
||||||
lastValBlue = source.bitmap.data[lastIdx + 2],
|
|
||||||
lastValAlpha = source.bitmap.data[lastIdx + 3];
|
|
||||||
|
|
||||||
let red = (radius + 1) * firstValRed;
|
|
||||||
let green = (radius + 1) * firstValGreen;
|
|
||||||
let blue = (radius + 1) * firstValBlue;
|
|
||||||
let alpha = (radius + 1) * firstValAlpha;
|
|
||||||
|
|
||||||
for (let j = 0; j < radius; j++) {
|
|
||||||
const jIdx = source.getPixelIndex(i, ti + j);
|
|
||||||
red += source.bitmap.data[jIdx];
|
|
||||||
green += source.bitmap.data[jIdx + 1];
|
|
||||||
blue += source.bitmap.data[jIdx + 2];
|
|
||||||
alpha += source.bitmap.data[jIdx + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j <= radius; j++) {
|
|
||||||
const riIdx = source.getPixelIndex(i, ri++);
|
|
||||||
red += source.bitmap.data[riIdx] - firstValRed;
|
|
||||||
green += source.bitmap.data[riIdx + 1] - firstValGreen;
|
|
||||||
blue += source.bitmap.data[riIdx + 2] - firstValBlue;
|
|
||||||
alpha += source.bitmap.data[riIdx + 3] - firstValAlpha;
|
|
||||||
|
|
||||||
const tiIdx = source.getPixelIndex(i, ti++);
|
|
||||||
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = radius + 1; j < height - radius; j++) {
|
|
||||||
const riIdx = source.getPixelIndex(i, ri++);
|
|
||||||
const liIdx = source.getPixelIndex(i, li++);
|
|
||||||
red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx];
|
|
||||||
green += source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1];
|
|
||||||
blue += source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2];
|
|
||||||
alpha += source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3];
|
|
||||||
|
|
||||||
const tiIdx = source.getPixelIndex(i, ti++);
|
|
||||||
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = height - radius; j < height; j++) {
|
|
||||||
const liIdx = source.getPixelIndex(i, li++);
|
|
||||||
red += lastValRed - source.bitmap.data[liIdx];
|
|
||||||
green += lastValGreen - source.bitmap.data[liIdx + 1];
|
|
||||||
blue += lastValBlue - source.bitmap.data[liIdx + 2];
|
|
||||||
alpha += lastValAlpha - source.bitmap.data[liIdx + 3];
|
|
||||||
|
|
||||||
const tiIdx = source.getPixelIndex(i, ti++);
|
|
||||||
output.bitmap.data[tiIdx] = Math.round(red * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 1] = Math.round(green * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr);
|
|
||||||
output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
@@ -91,9 +91,7 @@ export function toJA4(bytes) {
|
|||||||
let alpn = "00";
|
let alpn = "00";
|
||||||
for (const ext of tlsr.handshake.value.extensions.value) {
|
for (const ext of tlsr.handshake.value.extensions.value) {
|
||||||
if (ext.type.value === "application_layer_protocol_negotiation") {
|
if (ext.type.value === "application_layer_protocol_negotiation") {
|
||||||
alpn = parseFirstALPNValue(ext.value.data);
|
alpn = alpnFingerprint(parseFirstALPNValue(ext.value.data));
|
||||||
alpn = alpn.charAt(0) + alpn.charAt(alpn.length - 1);
|
|
||||||
if (alpn.charCodeAt(0) > 127) alpn = "99";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,9 +210,7 @@ export function toJA4S(bytes) {
|
|||||||
let alpn = "00";
|
let alpn = "00";
|
||||||
for (const ext of tlsr.handshake.value.extensions.value) {
|
for (const ext of tlsr.handshake.value.extensions.value) {
|
||||||
if (ext.type.value === "application_layer_protocol_negotiation") {
|
if (ext.type.value === "application_layer_protocol_negotiation") {
|
||||||
alpn = parseFirstALPNValue(ext.value.data);
|
alpn = alpnFingerprint(parseFirstALPNValue(ext.value.data));
|
||||||
alpn = alpn.charAt(0) + alpn.charAt(alpn.length - 1);
|
|
||||||
if (alpn.charCodeAt(0) > 127) alpn = "99";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,3 +258,33 @@ function tlsVersionMapper(version) {
|
|||||||
default: return "00"; // Unknown
|
default: return "00"; // Unknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a byte is ASCII alphanumeric (0-9, A-Z, a-z).
|
||||||
|
* @param {number} byte
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isAlphanumeric(byte) {
|
||||||
|
return (byte >= 0x30 && byte <= 0x39) ||
|
||||||
|
(byte >= 0x41 && byte <= 0x5A) ||
|
||||||
|
(byte >= 0x61 && byte <= 0x7A);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the 2-character ALPN fingerprint from raw ALPN bytes.
|
||||||
|
* If both first and last bytes are ASCII alphanumeric, returns their characters.
|
||||||
|
* Otherwise, returns first hex digit of first byte + last hex digit of last byte.
|
||||||
|
* @param {Uint8Array|null} rawBytes
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function alpnFingerprint(rawBytes) {
|
||||||
|
if (!rawBytes || rawBytes.length === 0) return "00";
|
||||||
|
const firstByte = rawBytes[0];
|
||||||
|
const lastByte = rawBytes[rawBytes.length - 1];
|
||||||
|
if (isAlphanumeric(firstByte) && isAlphanumeric(lastByte)) {
|
||||||
|
return String.fromCharCode(firstByte) + String.fromCharCode(lastByte);
|
||||||
|
}
|
||||||
|
const firstHex = firstByte.toString(16).padStart(2, "0");
|
||||||
|
const lastHex = lastByte.toString(16).padStart(2, "0");
|
||||||
|
return firstHex[0] + lastHex[1];
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import jsQR from "jsqr";
|
import jsQR from "jsqr";
|
||||||
import qr from "qr-image";
|
import qr from "qr-image";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a QR code image from an image
|
* Parses a QR code image from an image
|
||||||
@@ -29,18 +29,31 @@ export async function parseQrCode(input, normalise) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (normalise) {
|
if (normalise) {
|
||||||
image.rgba(false);
|
|
||||||
image.background(0xFFFFFFFF);
|
|
||||||
image.normalize();
|
|
||||||
image.greyscale();
|
image.greyscale();
|
||||||
image = await image.getBufferAsync(Jimp.MIME_JPEG);
|
image.normalize();
|
||||||
image = await Jimp.read(image);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error normalising image. (${err})`);
|
throw new OperationError(`Error normalising image. (${err})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const qrData = jsQR(image.bitmap.data, image.getWidth(), image.getHeight());
|
// Remove transparency which jsQR cannot handle
|
||||||
|
image.scan((x, y, idx) => {
|
||||||
|
// If pixel is fully transparent, make it opaque white
|
||||||
|
if (image.bitmap.data[idx + 3] === 0x00) {
|
||||||
|
image.bitmap.data[idx + 0] = 0xff;
|
||||||
|
image.bitmap.data[idx + 1] = 0xff;
|
||||||
|
image.bitmap.data[idx + 2] = 0xff;
|
||||||
|
}
|
||||||
|
// Otherwise, make it fully opaque at its existing colour
|
||||||
|
image.bitmap.data[idx + 3] = 0xff;
|
||||||
|
});
|
||||||
|
image = await Jimp.read(await image.getBuffer(JimpMime.jpeg));
|
||||||
|
|
||||||
|
const qrData = jsQR(
|
||||||
|
new Uint8ClampedArray(image.bitmap.data),
|
||||||
|
image.width,
|
||||||
|
image.height,
|
||||||
|
);
|
||||||
if (qrData) {
|
if (qrData) {
|
||||||
return qrData.data;
|
return qrData.data;
|
||||||
} else {
|
} else {
|
||||||
@@ -58,7 +71,13 @@ export async function parseQrCode(input, normalise) {
|
|||||||
* @param {string} errorCorrection
|
* @param {string} errorCorrection
|
||||||
* @returns {ArrayBuffer}
|
* @returns {ArrayBuffer}
|
||||||
*/
|
*/
|
||||||
export function generateQrCode(input, format, moduleSize, margin, errorCorrection) {
|
export function generateQrCode(
|
||||||
|
input,
|
||||||
|
format,
|
||||||
|
moduleSize,
|
||||||
|
margin,
|
||||||
|
errorCorrection,
|
||||||
|
) {
|
||||||
const formats = ["SVG", "EPS", "PDF", "PNG"];
|
const formats = ["SVG", "EPS", "PDF", "PNG"];
|
||||||
if (!formats.includes(format.toUpperCase())) {
|
if (!formats.includes(format.toUpperCase())) {
|
||||||
throw new OperationError("Unsupported QR code format.");
|
throw new OperationError("Unsupported QR code format.");
|
||||||
@@ -70,7 +89,8 @@ export function generateQrCode(input, format, moduleSize, margin, errorCorrectio
|
|||||||
type: format,
|
type: format,
|
||||||
size: moduleSize,
|
size: moduleSize,
|
||||||
margin: margin,
|
margin: margin,
|
||||||
"ec_level": errorCorrection.charAt(0).toUpperCase()
|
// eslint-disable-next-line camelcase
|
||||||
|
ec_level: errorCorrection.charAt(0).toUpperCase(),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error generating QR code. (${err})`);
|
throw new OperationError(`Error generating QR code. (${err})`);
|
||||||
|
|||||||
@@ -863,15 +863,15 @@ export function parseHighestSupportedVersion(bytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the application_layer_protocol_negotiation extension and returns the first value.
|
* Parses the application_layer_protocol_negotiation extension and returns the first value as raw bytes.
|
||||||
* @param {Uint8Array} bytes
|
* @param {Uint8Array} bytes
|
||||||
* @returns {number}
|
* @returns {Uint8Array|null}
|
||||||
*/
|
*/
|
||||||
export function parseFirstALPNValue(bytes) {
|
export function parseFirstALPNValue(bytes) {
|
||||||
const s = new Stream(bytes);
|
const s = new Stream(bytes);
|
||||||
const alpnExtLen = s.readInt(2);
|
const alpnExtLen = s.readInt(2);
|
||||||
if (alpnExtLen < 3) return "00";
|
if (alpnExtLen < 2) return null;
|
||||||
const strLen = s.readInt(1);
|
const strLen = s.readInt(1);
|
||||||
if (strLen < 2) return "00";
|
if (strLen < 1) return null;
|
||||||
return s.readString(strLen);
|
return s.getBytes(strLen);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,19 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import {
|
||||||
|
Jimp,
|
||||||
|
JimpMime,
|
||||||
|
ResizeStrategy,
|
||||||
|
measureText,
|
||||||
|
measureTextHeight,
|
||||||
|
loadFont,
|
||||||
|
} from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add Text To Image operation
|
* Add Text To Image operation
|
||||||
*/
|
*/
|
||||||
class AddTextToImage extends Operation {
|
class AddTextToImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AddTextToImage constructor
|
* AddTextToImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +30,8 @@ class AddTextToImage extends Operation {
|
|||||||
|
|
||||||
this.name = "Add Text To Image";
|
this.name = "Add Text To Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Adds text onto an image.<br><br>Text can be horizontally or vertically aligned, or the position can be manually specified.<br>Variants of the Roboto font face are available in any size or colour.";
|
this.description =
|
||||||
|
"Adds text onto an image.<br><br>Text can be horizontally or vertically aligned, or the position can be manually specified.<br>Variants of the Roboto font face are available in any size or colour.";
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -33,72 +40,67 @@ class AddTextToImage extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Text",
|
name: "Text",
|
||||||
type: "string",
|
type: "string",
|
||||||
value: ""
|
value: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Horizontal align",
|
name: "Horizontal align",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["None", "Left", "Center", "Right"]
|
value: ["None", "Left", "Center", "Right"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Vertical align",
|
name: "Vertical align",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["None", "Top", "Middle", "Bottom"]
|
value: ["None", "Top", "Middle", "Bottom"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "X position",
|
name: "X position",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0
|
value: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Y position",
|
name: "Y position",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0
|
value: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Size",
|
name: "Size",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 32,
|
value: 32,
|
||||||
min: 8
|
min: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Font face",
|
name: "Font face",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: [
|
value: ["Roboto", "Roboto Black", "Roboto Mono", "Roboto Slab"],
|
||||||
"Roboto",
|
|
||||||
"Roboto Black",
|
|
||||||
"Roboto Mono",
|
|
||||||
"Roboto Slab"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Red",
|
name: "Red",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 255,
|
value: 255,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 255
|
max: 255,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Green",
|
name: "Green",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 255,
|
value: 255,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 255
|
max: 255,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Blue",
|
name: "Blue",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 255,
|
value: 255,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 255
|
max: 255,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Alpha",
|
name: "Alpha",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 255,
|
value: 255,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 255
|
max: 255,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,35 +139,49 @@ class AddTextToImage extends Operation {
|
|||||||
|
|
||||||
const fontsMap = {};
|
const fontsMap = {};
|
||||||
const fonts = [
|
const fonts = [
|
||||||
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.fnt"),
|
import(
|
||||||
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.fnt"),
|
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.fnt"
|
||||||
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.fnt"),
|
),
|
||||||
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.fnt")
|
import(
|
||||||
|
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.fnt"
|
||||||
|
),
|
||||||
|
import(
|
||||||
|
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.fnt"
|
||||||
|
),
|
||||||
|
import(
|
||||||
|
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.fnt"
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all(fonts)
|
await Promise.all(fonts).then((fonts) => {
|
||||||
.then(fonts => {
|
fontsMap.Roboto = fonts[0];
|
||||||
fontsMap.Roboto = fonts[0];
|
fontsMap["Roboto Black"] = fonts[1];
|
||||||
fontsMap["Roboto Black"] = fonts[1];
|
fontsMap["Roboto Mono"] = fonts[2];
|
||||||
fontsMap["Roboto Mono"] = fonts[2];
|
fontsMap["Roboto Slab"] = fonts[3];
|
||||||
fontsMap["Roboto Slab"] = fonts[3];
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Make Webpack load the png font images
|
// Make Webpack load the png font images
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.png"),
|
import(
|
||||||
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.png"),
|
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/Roboto72White.png"
|
||||||
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.png"),
|
),
|
||||||
import(/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.png")
|
import(
|
||||||
|
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoSlab72White.png"
|
||||||
|
),
|
||||||
|
import(
|
||||||
|
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoMono72White.png"
|
||||||
|
),
|
||||||
|
import(
|
||||||
|
/* webpackMode: "eager" */ "../../web/static/fonts/bmfonts/RobotoBlack72White.png"
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const font = fontsMap[fontFace];
|
const font = fontsMap[fontFace];
|
||||||
|
|
||||||
// LoadFont needs an absolute url, so append the font name to self.docURL
|
// LoadFont needs an absolute url, so append the font name to self.docURL
|
||||||
const jimpFont = await Jimp.loadFont(self.docURL + "/" + font.default);
|
const jimpFont = await loadFont(self.docURL + "/" + font.default);
|
||||||
|
|
||||||
jimpFont.pages.forEach(function(page) {
|
jimpFont.pages.forEach(function (page) {
|
||||||
if (page.bitmap) {
|
if (page.bitmap) {
|
||||||
// Adjust the RGB values of the image pages to change the font colour.
|
// Adjust the RGB values of the image pages to change the font colour.
|
||||||
const pageWidth = page.bitmap.width;
|
const pageWidth = page.bitmap.width;
|
||||||
@@ -175,32 +191,52 @@ class AddTextToImage extends Operation {
|
|||||||
const idx = (iy * pageWidth + ix) << 2;
|
const idx = (iy * pageWidth + ix) << 2;
|
||||||
|
|
||||||
const newRed = page.bitmap.data[idx] - (255 - red);
|
const newRed = page.bitmap.data[idx] - (255 - red);
|
||||||
const newGreen = page.bitmap.data[idx + 1] - (255 - green);
|
const newGreen =
|
||||||
const newBlue = page.bitmap.data[idx + 2] - (255 - blue);
|
page.bitmap.data[idx + 1] - (255 - green);
|
||||||
const newAlpha = page.bitmap.data[idx + 3] - (255 - alpha);
|
const newBlue =
|
||||||
|
page.bitmap.data[idx + 2] - (255 - blue);
|
||||||
|
const newAlpha =
|
||||||
|
page.bitmap.data[idx + 3] - (255 - alpha);
|
||||||
|
|
||||||
// Make sure the bitmap values don't go below 0 as that makes jimp very unhappy
|
// Make sure the bitmap values don't go below 0 as that makes jimp very unhappy
|
||||||
page.bitmap.data[idx] = (newRed > 0) ? newRed : 0;
|
page.bitmap.data[idx] = newRed > 0 ? newRed : 0;
|
||||||
page.bitmap.data[idx + 1] = (newGreen > 0) ? newGreen : 0;
|
page.bitmap.data[idx + 1] =
|
||||||
page.bitmap.data[idx + 2] = (newBlue > 0) ? newBlue : 0;
|
newGreen > 0 ? newGreen : 0;
|
||||||
page.bitmap.data[idx + 3] = (newAlpha > 0) ? newAlpha : 0;
|
page.bitmap.data[idx + 2] =
|
||||||
|
newBlue > 0 ? newBlue : 0;
|
||||||
|
page.bitmap.data[idx + 3] =
|
||||||
|
newAlpha > 0 ? newAlpha : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a temporary image to hold the rendered text
|
// Create a temporary image to hold the rendered text
|
||||||
const textImage = new Jimp(Jimp.measureText(jimpFont, text), Jimp.measureTextHeight(jimpFont, text));
|
const textImage = new Jimp({
|
||||||
textImage.print(jimpFont, 0, 0, text);
|
width: measureText(jimpFont, text),
|
||||||
|
height: measureTextHeight(jimpFont, text),
|
||||||
|
});
|
||||||
|
textImage.print({
|
||||||
|
font: jimpFont,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
text,
|
||||||
|
});
|
||||||
|
|
||||||
// Scale the rendered text image to the correct size
|
// Scale the rendered text image to the correct size
|
||||||
const scaleFactor = size / 72;
|
const scaleFactor = size / 72;
|
||||||
if (size !== 1) {
|
if (size !== 1) {
|
||||||
// Use bicubic for decreasing size
|
// Use bicubic for decreasing size
|
||||||
if (size > 1) {
|
if (size > 1) {
|
||||||
textImage.scale(scaleFactor, Jimp.RESIZE_BICUBIC);
|
textImage.scale({
|
||||||
|
f: scaleFactor,
|
||||||
|
mode: ResizeStrategy.BICUBIC,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
textImage.scale(scaleFactor, Jimp.RESIZE_BILINEAR);
|
textImage.scale({
|
||||||
|
f: scaleFactor,
|
||||||
|
mode: ResizeStrategy.BILINEAR,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,10 +246,10 @@ class AddTextToImage extends Operation {
|
|||||||
xPos = 0;
|
xPos = 0;
|
||||||
break;
|
break;
|
||||||
case "Center":
|
case "Center":
|
||||||
xPos = (image.getWidth() / 2) - (textImage.getWidth() / 2);
|
xPos = image.width / 2 - textImage.width / 2;
|
||||||
break;
|
break;
|
||||||
case "Right":
|
case "Right":
|
||||||
xPos = image.getWidth() - textImage.getWidth();
|
xPos = image.width - textImage.width;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,21 +258,25 @@ class AddTextToImage extends Operation {
|
|||||||
yPos = 0;
|
yPos = 0;
|
||||||
break;
|
break;
|
||||||
case "Middle":
|
case "Middle":
|
||||||
yPos = (image.getHeight() / 2) - (textImage.getHeight() / 2);
|
yPos = image.height / 2 - textImage.height / 2;
|
||||||
break;
|
break;
|
||||||
case "Bottom":
|
case "Bottom":
|
||||||
yPos = image.getHeight() - textImage.getHeight();
|
yPos = image.height - textImage.height;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blit the rendered text image onto the original source image
|
// Blit the rendered text image onto the original source image
|
||||||
image.blit(textImage, xPos, yPos);
|
image.blit({
|
||||||
|
src: textImage,
|
||||||
|
x: xPos,
|
||||||
|
y: yPos,
|
||||||
|
});
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -261,7 +301,6 @@ class AddTextToImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddTextToImage;
|
export default AddTextToImage;
|
||||||
|
|||||||
@@ -9,14 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { gaussianBlur } from "../lib/ImageManipulation.mjs";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
import Jimp from "jimp/es/index.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blur Image operation
|
* Blur Image operation
|
||||||
*/
|
*/
|
||||||
class BlurImage extends Operation {
|
class BlurImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BlurImage constructor
|
* BlurImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -25,7 +23,8 @@ class BlurImage extends Operation {
|
|||||||
|
|
||||||
this.name = "Blur Image";
|
this.name = "Blur Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Applies a blur effect to the image.<br><br>Gaussian blur is much slower than fast blur, but produces better results.";
|
this.description =
|
||||||
|
"Applies a blur effect to the image.<br><br>Gaussian blur is much slower than fast blur, but produces better results.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Gaussian_blur";
|
this.infoURL = "https://wikipedia.org/wiki/Gaussian_blur";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -35,13 +34,13 @@ class BlurImage extends Operation {
|
|||||||
name: "Amount",
|
name: "Amount",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 5,
|
value: 5,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Type",
|
name: "Type",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["Fast", "Gaussian"]
|
value: ["Fast", "Gaussian"],
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,15 +72,15 @@ class BlurImage extends Operation {
|
|||||||
case "Gaussian":
|
case "Gaussian":
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Gaussian blurring image...");
|
self.sendStatusMessage("Gaussian blurring image...");
|
||||||
image = gaussianBlur(image, blurAmount);
|
image.gaussian(blurAmount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -106,7 +105,6 @@ class BlurImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlurImage;
|
export default BlurImage;
|
||||||
|
|||||||
@@ -9,13 +9,18 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import {
|
||||||
|
Jimp,
|
||||||
|
JimpMime,
|
||||||
|
ResizeStrategy,
|
||||||
|
HorizontalAlign,
|
||||||
|
VerticalAlign,
|
||||||
|
} from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contain Image operation
|
* Contain Image operation
|
||||||
*/
|
*/
|
||||||
class ContainImage extends Operation {
|
class ContainImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ContainImage constructor
|
* ContainImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +29,8 @@ class ContainImage extends Operation {
|
|||||||
|
|
||||||
this.name = "Contain Image";
|
this.name = "Contain Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Scales an image to the specified width and height, maintaining the aspect ratio. The image may be letterboxed.";
|
this.description =
|
||||||
|
"Scales an image to the specified width and height, maintaining the aspect ratio. The image may be letterboxed.";
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -34,33 +40,25 @@ class ContainImage extends Operation {
|
|||||||
name: "Width",
|
name: "Width",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 100,
|
value: 100,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Height",
|
name: "Height",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 100,
|
value: 100,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Horizontal align",
|
name: "Horizontal align",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: [
|
value: ["Left", "Center", "Right"],
|
||||||
"Left",
|
defaultIndex: 1,
|
||||||
"Center",
|
|
||||||
"Right"
|
|
||||||
],
|
|
||||||
defaultIndex: 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Vertical align",
|
name: "Vertical align",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: [
|
value: ["Top", "Middle", "Bottom"],
|
||||||
"Top",
|
defaultIndex: 1,
|
||||||
"Middle",
|
|
||||||
"Bottom"
|
|
||||||
],
|
|
||||||
defaultIndex: 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Resizing algorithm",
|
name: "Resizing algorithm",
|
||||||
@@ -70,15 +68,15 @@ class ContainImage extends Operation {
|
|||||||
"Bilinear",
|
"Bilinear",
|
||||||
"Bicubic",
|
"Bicubic",
|
||||||
"Hermite",
|
"Hermite",
|
||||||
"Bezier"
|
"Bezier",
|
||||||
],
|
],
|
||||||
defaultIndex: 1
|
defaultIndex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Opaque background",
|
name: "Opaque background",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true
|
value: true,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,20 +89,20 @@ class ContainImage extends Operation {
|
|||||||
const [width, height, hAlign, vAlign, alg, opaqueBg] = args;
|
const [width, height, hAlign, vAlign, alg, opaqueBg] = args;
|
||||||
|
|
||||||
const resizeMap = {
|
const resizeMap = {
|
||||||
"Nearest Neighbour": Jimp.RESIZE_NEAREST_NEIGHBOR,
|
"Nearest Neighbour": ResizeStrategy.NEAREST_NEIGHBOR,
|
||||||
"Bilinear": Jimp.RESIZE_BILINEAR,
|
Bilinear: ResizeStrategy.BILINEAR,
|
||||||
"Bicubic": Jimp.RESIZE_BICUBIC,
|
Bicubic: ResizeStrategy.BICUBIC,
|
||||||
"Hermite": Jimp.RESIZE_HERMITE,
|
Hermite: ResizeStrategy.HERMITE,
|
||||||
"Bezier": Jimp.RESIZE_BEZIER
|
Bezier: ResizeStrategy.BEZIER,
|
||||||
};
|
};
|
||||||
|
|
||||||
const alignMap = {
|
const alignMap = {
|
||||||
"Left": Jimp.HORIZONTAL_ALIGN_LEFT,
|
Left: HorizontalAlign.LEFT,
|
||||||
"Center": Jimp.HORIZONTAL_ALIGN_CENTER,
|
Center: HorizontalAlign.CENTER,
|
||||||
"Right": Jimp.HORIZONTAL_ALIGN_RIGHT,
|
Right: HorizontalAlign.RIGHT,
|
||||||
"Top": Jimp.VERTICAL_ALIGN_TOP,
|
Top: VerticalAlign.TOP,
|
||||||
"Middle": Jimp.VERTICAL_ALIGN_MIDDLE,
|
Middle: VerticalAlign.MIDDLE,
|
||||||
"Bottom": Jimp.VERTICAL_ALIGN_BOTTOM
|
Bottom: VerticalAlign.BOTTOM,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isImage(input)) {
|
if (!isImage(input)) {
|
||||||
@@ -117,22 +115,35 @@ class ContainImage extends Operation {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error loading image. (${err})`);
|
throw new OperationError(`Error loading image. (${err})`);
|
||||||
}
|
}
|
||||||
|
const originalMime = image.mime;
|
||||||
try {
|
try {
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Containing image...");
|
self.sendStatusMessage("Containing image...");
|
||||||
image.contain(width, height, alignMap[hAlign] | alignMap[vAlign], resizeMap[alg]);
|
image.contain({
|
||||||
|
w: width,
|
||||||
|
h: height,
|
||||||
|
align: alignMap[hAlign] | alignMap[vAlign],
|
||||||
|
mode: resizeMap[alg],
|
||||||
|
});
|
||||||
|
|
||||||
if (opaqueBg) {
|
if (opaqueBg) {
|
||||||
const newImage = await Jimp.read(width, height, 0x000000FF);
|
const newImage = new Jimp({
|
||||||
newImage.blit(image, 0, 0);
|
width,
|
||||||
image = newImage;
|
height,
|
||||||
|
color: 0x000000ff,
|
||||||
|
});
|
||||||
|
image = newImage.blit({
|
||||||
|
src: image,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (originalMime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(originalMime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -156,7 +167,6 @@ class ContainImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ContainImage;
|
export default ContainImage;
|
||||||
|
|||||||
@@ -8,13 +8,12 @@ import Operation from "../Operation.mjs";
|
|||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime, PNGFilterType } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert Image Format operation
|
* Convert Image Format operation
|
||||||
*/
|
*/
|
||||||
class ConvertImageFormat extends Operation {
|
class ConvertImageFormat extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConvertImageFormat constructor
|
* ConvertImageFormat constructor
|
||||||
*/
|
*/
|
||||||
@@ -23,7 +22,8 @@ class ConvertImageFormat extends Operation {
|
|||||||
|
|
||||||
this.name = "Convert Image Format";
|
this.name = "Convert Image Format";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Converts an image between different formats. Supported formats:<br><ul><li>Joint Photographic Experts Group (JPEG)</li><li>Portable Network Graphics (PNG)</li><li>Bitmap (BMP)</li><li>Tagged Image File Format (TIFF)</li></ul><br>Note: GIF files are supported for input, but cannot be outputted.";
|
this.description =
|
||||||
|
"Converts an image between different formats. Supported formats:<br><ul><li>Joint Photographic Experts Group (JPEG)</li><li>Portable Network Graphics (PNG)</li><li>Bitmap (BMP)</li><li>Tagged Image File Format (TIFF)</li></ul><br>Note: GIF files are supported for input, but cannot be outputted.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Image_file_formats";
|
this.infoURL = "https://wikipedia.org/wiki/Image_file_formats";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -32,39 +32,27 @@ class ConvertImageFormat extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Output Format",
|
name: "Output Format",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: [
|
value: ["JPEG", "PNG", "BMP", "TIFF"],
|
||||||
"JPEG",
|
|
||||||
"PNG",
|
|
||||||
"BMP",
|
|
||||||
"TIFF"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "JPEG Quality",
|
name: "JPEG Quality",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 80,
|
value: 80,
|
||||||
min: 1,
|
min: 1,
|
||||||
max: 100
|
max: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PNG Filter Type",
|
name: "PNG Filter Type",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: [
|
value: ["Auto", "None", "Sub", "Up", "Average", "Paeth"],
|
||||||
"Auto",
|
|
||||||
"None",
|
|
||||||
"Sub",
|
|
||||||
"Up",
|
|
||||||
"Average",
|
|
||||||
"Paeth"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PNG Deflate Level",
|
name: "PNG Deflate Level",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 9,
|
value: 9,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 9
|
max: 9,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,19 +64,19 @@ class ConvertImageFormat extends Operation {
|
|||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
const [format, jpegQuality, pngFilterType, pngDeflateLevel] = args;
|
const [format, jpegQuality, pngFilterType, pngDeflateLevel] = args;
|
||||||
const formatMap = {
|
const formatMap = {
|
||||||
"JPEG": Jimp.MIME_JPEG,
|
JPEG: JimpMime.jpeg,
|
||||||
"PNG": Jimp.MIME_PNG,
|
PNG: JimpMime.png,
|
||||||
"BMP": Jimp.MIME_BMP,
|
BMP: JimpMime.bmp,
|
||||||
"TIFF": Jimp.MIME_TIFF
|
TIFF: JimpMime.tiff,
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngFilterMap = {
|
const pngFilterMap = {
|
||||||
"Auto": Jimp.PNG_FILTER_AUTO,
|
Auto: PNGFilterType.AUTO,
|
||||||
"None": Jimp.PNG_FILTER_NONE,
|
None: PNGFilterType.NONE,
|
||||||
"Sub": Jimp.PNG_FILTER_SUB,
|
Sub: PNGFilterType.SUB,
|
||||||
"Up": Jimp.PNG_FILTER_UP,
|
Up: PNGFilterType.UP,
|
||||||
"Average": Jimp.PNG_FILTER_AVERAGE,
|
Average: PNGFilterType.AVERAGE,
|
||||||
"Paeth": Jimp.PNG_FILTER_PATH
|
Paeth: PNGFilterType.PATH,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mime = formatMap[format];
|
const mime = formatMap[format];
|
||||||
@@ -103,18 +91,25 @@ class ConvertImageFormat extends Operation {
|
|||||||
throw new OperationError(`Error opening image file. (${err})`);
|
throw new OperationError(`Error opening image file. (${err})`);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
switch (format) {
|
let buffer;
|
||||||
case "JPEG":
|
switch (mime) {
|
||||||
image.quality(jpegQuality);
|
case JimpMime.jpeg:
|
||||||
|
buffer = await image.getBuffer(mime, {
|
||||||
|
quality: jpegQuality,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "PNG":
|
case JimpMime.png:
|
||||||
image.filterType(pngFilterMap[pngFilterType]);
|
buffer = await image.getBuffer(mime, {
|
||||||
image.deflateLevel(pngDeflateLevel);
|
filterType: pngFilterMap[pngFilterType],
|
||||||
|
deflateLevel: pngDeflateLevel,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buffer = await image.getBuffer(mime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageBuffer = await image.getBufferAsync(mime);
|
return buffer.buffer;
|
||||||
return imageBuffer.buffer;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error converting image format. (${err})`);
|
throw new OperationError(`Error converting image format. (${err})`);
|
||||||
}
|
}
|
||||||
@@ -137,7 +132,6 @@ class ConvertImageFormat extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ConvertImageFormat;
|
export default ConvertImageFormat;
|
||||||
|
|||||||
@@ -9,13 +9,18 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import jimp from "jimp/es/index.js";
|
import {
|
||||||
|
Jimp,
|
||||||
|
JimpMime,
|
||||||
|
ResizeStrategy,
|
||||||
|
HorizontalAlign,
|
||||||
|
VerticalAlign,
|
||||||
|
} from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cover Image operation
|
* Cover Image operation
|
||||||
*/
|
*/
|
||||||
class CoverImage extends Operation {
|
class CoverImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CoverImage constructor
|
* CoverImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +29,8 @@ class CoverImage extends Operation {
|
|||||||
|
|
||||||
this.name = "Cover Image";
|
this.name = "Cover Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Scales the image to the given width and height, keeping the aspect ratio. The image may be clipped.";
|
this.description =
|
||||||
|
"Scales the image to the given width and height, keeping the aspect ratio. The image may be clipped.";
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -34,33 +40,25 @@ class CoverImage extends Operation {
|
|||||||
name: "Width",
|
name: "Width",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 100,
|
value: 100,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Height",
|
name: "Height",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 100,
|
value: 100,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Horizontal align",
|
name: "Horizontal align",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: [
|
value: ["Left", "Center", "Right"],
|
||||||
"Left",
|
defaultIndex: 1,
|
||||||
"Center",
|
|
||||||
"Right"
|
|
||||||
],
|
|
||||||
defaultIndex: 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Vertical align",
|
name: "Vertical align",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: [
|
value: ["Top", "Middle", "Bottom"],
|
||||||
"Top",
|
defaultIndex: 1,
|
||||||
"Middle",
|
|
||||||
"Bottom"
|
|
||||||
],
|
|
||||||
defaultIndex: 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Resizing algorithm",
|
name: "Resizing algorithm",
|
||||||
@@ -70,10 +68,10 @@ class CoverImage extends Operation {
|
|||||||
"Bilinear",
|
"Bilinear",
|
||||||
"Bicubic",
|
"Bicubic",
|
||||||
"Hermite",
|
"Hermite",
|
||||||
"Bezier"
|
"Bezier",
|
||||||
],
|
],
|
||||||
defaultIndex: 1
|
defaultIndex: 1,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,20 +84,20 @@ class CoverImage extends Operation {
|
|||||||
const [width, height, hAlign, vAlign, alg] = args;
|
const [width, height, hAlign, vAlign, alg] = args;
|
||||||
|
|
||||||
const resizeMap = {
|
const resizeMap = {
|
||||||
"Nearest Neighbour": jimp.RESIZE_NEAREST_NEIGHBOR,
|
"Nearest Neighbour": ResizeStrategy.NEAREST_NEIGHBOR,
|
||||||
"Bilinear": jimp.RESIZE_BILINEAR,
|
Bilinear: ResizeStrategy.BILINEAR,
|
||||||
"Bicubic": jimp.RESIZE_BICUBIC,
|
Bicubic: ResizeStrategy.BICUBIC,
|
||||||
"Hermite": jimp.RESIZE_HERMITE,
|
Hermite: ResizeStrategy.HERMITE,
|
||||||
"Bezier": jimp.RESIZE_BEZIER
|
Bezier: ResizeStrategy.BEZIER,
|
||||||
};
|
};
|
||||||
|
|
||||||
const alignMap = {
|
const alignMap = {
|
||||||
"Left": jimp.HORIZONTAL_ALIGN_LEFT,
|
Left: HorizontalAlign.LEFT,
|
||||||
"Center": jimp.HORIZONTAL_ALIGN_CENTER,
|
Center: HorizontalAlign.CENTER,
|
||||||
"Right": jimp.HORIZONTAL_ALIGN_RIGHT,
|
Right: HorizontalAlign.RIGHT,
|
||||||
"Top": jimp.VERTICAL_ALIGN_TOP,
|
Top: VerticalAlign.TOP,
|
||||||
"Middle": jimp.VERTICAL_ALIGN_MIDDLE,
|
Middle: VerticalAlign.MIDDLE,
|
||||||
"Bottom": jimp.VERTICAL_ALIGN_BOTTOM
|
Bottom: VerticalAlign.BOTTOM,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isImage(input)) {
|
if (!isImage(input)) {
|
||||||
@@ -108,19 +106,24 @@ class CoverImage extends Operation {
|
|||||||
|
|
||||||
let image;
|
let image;
|
||||||
try {
|
try {
|
||||||
image = await jimp.read(input);
|
image = await Jimp.read(input);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error loading image. (${err})`);
|
throw new OperationError(`Error loading image. (${err})`);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Covering image...");
|
self.sendStatusMessage("Covering image...");
|
||||||
image.cover(width, height, alignMap[hAlign] | alignMap[vAlign], resizeMap[alg]);
|
image.cover({
|
||||||
|
w: width,
|
||||||
|
h: height,
|
||||||
|
align: alignMap[hAlign] | alignMap[vAlign],
|
||||||
|
mode: resizeMap[alg],
|
||||||
|
});
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -144,7 +147,6 @@ class CoverImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CoverImage;
|
export default CoverImage;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crop Image operation
|
* Crop Image operation
|
||||||
*/
|
*/
|
||||||
class CropImage extends Operation {
|
class CropImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CropImage constructor
|
* CropImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +23,8 @@ class CropImage extends Operation {
|
|||||||
|
|
||||||
this.name = "Crop Image";
|
this.name = "Crop Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Crops an image to the specified region, or automatically crops edges.<br><br><b><u>Autocrop</u></b><br>Automatically crops same-colour borders from the image.<br><br><u>Autocrop tolerance</u><br>A percentage value for the tolerance of colour difference between pixels.<br><br><u>Only autocrop frames</u><br>Only crop real frames (all sides must have the same border)<br><br><u>Symmetric autocrop</u><br>Force autocrop to be symmetric (top/bottom and left/right are cropped by the same amount)<br><br><u>Autocrop keep border</u><br>The number of pixels of border to leave around the image.";
|
this.description =
|
||||||
|
"Crops an image to the specified region, or automatically crops edges.<br><br><b><u>Autocrop</u></b><br>Automatically crops same-colour borders from the image.<br><br><u>Autocrop tolerance</u><br>A percentage value for the tolerance of colour difference between pixels.<br><br><u>Only autocrop frames</u><br>Only crop real frames (all sides must have the same border)<br><br><u>Symmetric autocrop</u><br>Force autocrop to be symmetric (top/bottom and left/right are cropped by the same amount)<br><br><u>Autocrop keep border</u><br>The number of pixels of border to leave around the image.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Cropping_(image)";
|
this.infoURL = "https://wikipedia.org/wiki/Cropping_(image)";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -34,30 +34,30 @@ class CropImage extends Operation {
|
|||||||
name: "X Position",
|
name: "X Position",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0,
|
||||||
min: 0
|
min: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Y Position",
|
name: "Y Position",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0,
|
||||||
min: 0
|
min: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Width",
|
name: "Width",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 10,
|
value: 10,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Height",
|
name: "Height",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 10,
|
value: 10,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Autocrop",
|
name: "Autocrop",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: false
|
value: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Autocrop tolerance (%)",
|
name: "Autocrop tolerance (%)",
|
||||||
@@ -65,24 +65,24 @@ class CropImage extends Operation {
|
|||||||
value: 0.02,
|
value: 0.02,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 100,
|
max: 100,
|
||||||
step: 0.01
|
step: 0.01,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Only autocrop frames",
|
name: "Only autocrop frames",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true
|
value: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Symmetric autocrop",
|
name: "Symmetric autocrop",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: false
|
value: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Autocrop keep border (px)",
|
name: "Autocrop keep border (px)",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0,
|
||||||
min: 0
|
min: 0,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,17 @@ class CropImage extends Operation {
|
|||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
const [xPos, yPos, width, height, autocrop, autoTolerance, autoFrames, autoSymmetric, autoBorder] = args;
|
const [
|
||||||
|
xPos,
|
||||||
|
yPos,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
autocrop,
|
||||||
|
autoTolerance,
|
||||||
|
autoFrames,
|
||||||
|
autoSymmetric,
|
||||||
|
autoBorder,
|
||||||
|
] = args;
|
||||||
if (!isImage(input)) {
|
if (!isImage(input)) {
|
||||||
throw new OperationError("Invalid file type.");
|
throw new OperationError("Invalid file type.");
|
||||||
}
|
}
|
||||||
@@ -108,20 +118,25 @@ class CropImage extends Operation {
|
|||||||
self.sendStatusMessage("Cropping image...");
|
self.sendStatusMessage("Cropping image...");
|
||||||
if (autocrop) {
|
if (autocrop) {
|
||||||
image.autocrop({
|
image.autocrop({
|
||||||
tolerance: (autoTolerance / 100),
|
tolerance: autoTolerance / 100,
|
||||||
cropOnlyFrames: autoFrames,
|
cropOnlyFrames: autoFrames,
|
||||||
cropSymmetric: autoSymmetric,
|
cropSymmetric: autoSymmetric,
|
||||||
leaveBorder: autoBorder
|
leaveBorder: autoBorder,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
image.crop(xPos, yPos, width, height);
|
image.crop({
|
||||||
|
x: xPos,
|
||||||
|
y: yPos,
|
||||||
|
w: width,
|
||||||
|
h: height,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -145,7 +160,6 @@ class CropImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CropImage;
|
export default CropImage;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image Dither operation
|
* Image Dither operation
|
||||||
*/
|
*/
|
||||||
class DitherImage extends Operation {
|
class DitherImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DitherImage constructor
|
* DitherImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -51,17 +50,19 @@ class DitherImage extends Operation {
|
|||||||
try {
|
try {
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Applying dither to image...");
|
self.sendStatusMessage("Applying dither to image...");
|
||||||
image.dither565();
|
image.dither();
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error applying dither to image. (${err})`);
|
throw new OperationError(
|
||||||
|
`Error applying dither to image. (${err})`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +82,6 @@ class DitherImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DitherImage;
|
export default DitherImage;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import { fromBinary } from "../lib/Binary.mjs";
|
import { fromBinary } from "../lib/Binary.mjs";
|
||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract LSB operation
|
* Extract LSB operation
|
||||||
*/
|
*/
|
||||||
class ExtractLSB extends Operation {
|
class ExtractLSB extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ExtractLSB constructor
|
* ExtractLSB constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,8 +23,10 @@ class ExtractLSB extends Operation {
|
|||||||
|
|
||||||
this.name = "Extract LSB";
|
this.name = "Extract LSB";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Extracts the Least Significant Bit data from each pixel in an image. This is a common way to hide data in Steganography.";
|
this.description =
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Bit_numbering#Least_significant_bit_in_digital_steganography";
|
"Extracts the Least Significant Bit data from each pixel in an image. This is a common way to hide data in Steganography.";
|
||||||
|
this.infoURL =
|
||||||
|
"https://wikipedia.org/wiki/Bit_numbering#Least_significant_bit_in_digital_steganography";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "byteArray";
|
this.outputType = "byteArray";
|
||||||
this.args = [
|
this.args = [
|
||||||
@@ -57,8 +58,8 @@ class ExtractLSB extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Bit",
|
name: "Bit",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0
|
value: 0,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,21 +69,27 @@ class ExtractLSB extends Operation {
|
|||||||
* @returns {byteArray}
|
* @returns {byteArray}
|
||||||
*/
|
*/
|
||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
if (!isImage(input)) throw new OperationError("Please enter a valid image file.");
|
if (!isImage(input))
|
||||||
|
throw new OperationError("Please enter a valid image file.");
|
||||||
|
|
||||||
const bit = 7 - args.pop(),
|
const bit = 7 - args.pop(),
|
||||||
pixelOrder = args.pop(),
|
pixelOrder = args.pop(),
|
||||||
colours = args.filter(option => option !== "").map(option => COLOUR_OPTIONS.indexOf(option)),
|
colours = args
|
||||||
|
.filter((option) => option !== "")
|
||||||
|
.map((option) => COLOUR_OPTIONS.indexOf(option)),
|
||||||
parsedImage = await Jimp.read(input),
|
parsedImage = await Jimp.read(input),
|
||||||
width = parsedImage.bitmap.width,
|
width = parsedImage.bitmap.width,
|
||||||
height = parsedImage.bitmap.height,
|
height = parsedImage.bitmap.height,
|
||||||
rgba = parsedImage.bitmap.data;
|
rgba = parsedImage.bitmap.data;
|
||||||
|
|
||||||
if (bit < 0 || bit > 7) {
|
if (bit < 0 || bit > 7) {
|
||||||
throw new OperationError("Error: Bit argument must be between 0 and 7");
|
throw new OperationError(
|
||||||
|
"Error: Bit argument must be between 0 and 7",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let i, combinedBinary = "";
|
let i,
|
||||||
|
combinedBinary = "";
|
||||||
|
|
||||||
if (pixelOrder === "Row") {
|
if (pixelOrder === "Row") {
|
||||||
for (i = 0; i < rgba.length; i += 4) {
|
for (i = 0; i < rgba.length; i += 4) {
|
||||||
@@ -106,7 +113,6 @@ class ExtractLSB extends Operation {
|
|||||||
|
|
||||||
return fromBinary(combinedBinary);
|
return fromBinary(combinedBinary);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const COLOUR_OPTIONS = ["R", "G", "B", "A"];
|
const COLOUR_OPTIONS = ["R", "G", "B", "A"];
|
||||||
|
|||||||
@@ -7,15 +7,14 @@
|
|||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp } from "jimp";
|
||||||
|
|
||||||
import {RGBA_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
import { RGBA_DELIM_OPTIONS } from "../lib/Delim.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract RGBA operation
|
* Extract RGBA operation
|
||||||
*/
|
*/
|
||||||
class ExtractRGBA extends Operation {
|
class ExtractRGBA extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ExtractRGBA constructor
|
* ExtractRGBA constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +23,8 @@ class ExtractRGBA extends Operation {
|
|||||||
|
|
||||||
this.name = "Extract RGBA";
|
this.name = "Extract RGBA";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Extracts each pixel's RGBA value in an image. These are sometimes used in Steganography to hide text or data.";
|
this.description =
|
||||||
|
"Extracts each pixel's RGBA value in an image. These are sometimes used in Steganography to hide text or data.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/RGBA_color_space";
|
this.infoURL = "https://wikipedia.org/wiki/RGBA_color_space";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
@@ -32,13 +32,13 @@ class ExtractRGBA extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Delimiter",
|
name: "Delimiter",
|
||||||
type: "editableOption",
|
type: "editableOption",
|
||||||
value: RGBA_DELIM_OPTIONS
|
value: RGBA_DELIM_OPTIONS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Include Alpha",
|
name: "Include Alpha",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true
|
value: true,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,18 +48,20 @@ class ExtractRGBA extends Operation {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
if (!isImage(input)) throw new OperationError("Please enter a valid image file.");
|
if (!isImage(input))
|
||||||
|
throw new OperationError("Please enter a valid image file.");
|
||||||
|
|
||||||
const delimiter = args[0],
|
const delimiter = args[0],
|
||||||
includeAlpha = args[1],
|
includeAlpha = args[1],
|
||||||
parsedImage = await Jimp.read(input);
|
parsedImage = await Jimp.read(input);
|
||||||
|
|
||||||
let bitmap = parsedImage.bitmap.data;
|
let bitmap = parsedImage.bitmap.data;
|
||||||
bitmap = includeAlpha ? bitmap : bitmap.filter((val, idx) => idx % 4 !== 3);
|
bitmap = includeAlpha ?
|
||||||
|
bitmap :
|
||||||
|
bitmap.filter((val, idx) => idx % 4 !== 3);
|
||||||
|
|
||||||
return bitmap.join(delimiter);
|
return bitmap.join(delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ExtractRGBA;
|
export default ExtractRGBA;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flip Image operation
|
* Flip Image operation
|
||||||
*/
|
*/
|
||||||
class FlipImage extends Operation {
|
class FlipImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlipImage constructor
|
* FlipImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -33,8 +32,8 @@ class FlipImage extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Axis",
|
name: "Axis",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["Horizontal", "Vertical"]
|
value: ["Horizontal", "Vertical"],
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,18 +59,24 @@ class FlipImage extends Operation {
|
|||||||
self.sendStatusMessage("Flipping image...");
|
self.sendStatusMessage("Flipping image...");
|
||||||
switch (flipAxis) {
|
switch (flipAxis) {
|
||||||
case "Horizontal":
|
case "Horizontal":
|
||||||
image.flip(true, false);
|
image.flip({
|
||||||
|
horizontal: true,
|
||||||
|
vertical: false,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "Vertical":
|
case "Vertical":
|
||||||
image.flip(false, true);
|
image.flip({
|
||||||
|
horizontal: false,
|
||||||
|
vertical: true,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -95,7 +100,6 @@ class FlipImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FlipImage;
|
export default FlipImage;
|
||||||
|
|||||||
149
src/core/operations/FromBech32.mjs
Normal file
149
src/core/operations/FromBech32.mjs
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* @author Medjedtxm
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import { decode } from "../lib/Bech32.mjs";
|
||||||
|
import { toHex } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From Bech32 operation
|
||||||
|
*/
|
||||||
|
class FromBech32 extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FromBech32 constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "From Bech32";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Bech32 is an encoding scheme primarily used for Bitcoin SegWit addresses (BIP-0173). It uses a 32-character alphabet that excludes easily confused characters (1, b, i, o) and includes a checksum for error detection.<br><br>Bech32m (BIP-0350) is an updated version used for Bitcoin Taproot addresses.<br><br>Auto-detect will attempt Bech32 first, then Bech32m if the checksum fails.<br><br>Output format options allow you to see the Human-Readable Part (HRP) along with the decoded data.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Bech32";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Encoding",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Auto-detect", "Bech32", "Bech32m"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output Format",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Raw", "Hex", "Bitcoin scriptPubKey", "HRP: Hex", "JSON"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
this.checks = [
|
||||||
|
{
|
||||||
|
// Bitcoin mainnet SegWit/Taproot addresses
|
||||||
|
pattern: "^bc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87}$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Auto-detect", "Hex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Bitcoin testnet addresses
|
||||||
|
pattern: "^tb1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87}$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Auto-detect", "Hex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// AGE public keys
|
||||||
|
pattern: "^age1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87}$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Auto-detect", "HRP: Hex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// AGE secret keys
|
||||||
|
pattern: "^AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{6,87}$",
|
||||||
|
flags: "",
|
||||||
|
args: ["Auto-detect", "HRP: Hex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Litecoin mainnet addresses
|
||||||
|
pattern: "^ltc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87}$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Auto-detect", "Hex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Generic bech32 pattern
|
||||||
|
pattern: "^[a-z]{1,83}1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,}$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Auto-detect", "Hex"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const encoding = args[0];
|
||||||
|
const outputFormat = args[1];
|
||||||
|
|
||||||
|
input = input.trim();
|
||||||
|
|
||||||
|
if (input.length === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const decoded = decode(input, encoding);
|
||||||
|
|
||||||
|
// Format output based on selected option
|
||||||
|
switch (outputFormat) {
|
||||||
|
case "Raw":
|
||||||
|
return decoded.data.map(b => String.fromCharCode(b)).join("");
|
||||||
|
|
||||||
|
case "Hex":
|
||||||
|
return toHex(decoded.data, "");
|
||||||
|
|
||||||
|
case "Bitcoin scriptPubKey": {
|
||||||
|
// Convert to Bitcoin scriptPubKey format as shown in BIP-0173/BIP-0350
|
||||||
|
// Format: [OP_version][length][witness_program]
|
||||||
|
// OP_0 = 0x00, OP_1-OP_16 = 0x51-0x60
|
||||||
|
if (decoded.witnessVersion === null || decoded.data.length < 2) {
|
||||||
|
// Not a SegWit address, fall back to hex
|
||||||
|
return toHex(decoded.data, "");
|
||||||
|
}
|
||||||
|
const witnessVersion = decoded.data[0];
|
||||||
|
const witnessProgram = decoded.data.slice(1);
|
||||||
|
|
||||||
|
// Convert witness version to OP code
|
||||||
|
let opCode;
|
||||||
|
if (witnessVersion === 0) {
|
||||||
|
opCode = 0x00; // OP_0
|
||||||
|
} else if (witnessVersion >= 1 && witnessVersion <= 16) {
|
||||||
|
opCode = 0x50 + witnessVersion; // OP_1 = 0x51, ..., OP_16 = 0x60
|
||||||
|
} else {
|
||||||
|
// Invalid witness version, fall back to hex
|
||||||
|
return toHex(decoded.data, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build scriptPubKey: [OP_version][length][program]
|
||||||
|
const scriptPubKey = [opCode, witnessProgram.length, ...witnessProgram];
|
||||||
|
return toHex(scriptPubKey, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
case "HRP: Hex":
|
||||||
|
return `${decoded.hrp}: ${toHex(decoded.data, "")}`;
|
||||||
|
|
||||||
|
case "JSON":
|
||||||
|
return JSON.stringify({
|
||||||
|
hrp: decoded.hrp,
|
||||||
|
encoding: decoded.encoding,
|
||||||
|
data: toHex(decoded.data, "")
|
||||||
|
}, null, 2);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return toHex(decoded.data, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FromBech32;
|
||||||
@@ -43,7 +43,7 @@ class FromHexdump extends Operation {
|
|||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const output = [],
|
const output = [],
|
||||||
regex = /^\s*(?:[\dA-F]{4,16}h?:?)?[ \t]+((?:[\dA-F]{2} ){1,8}(?:[ \t]|[\dA-F]{2}-)(?:[\dA-F]{2} ){1,8}|(?:[\dA-F]{4} )*[\dA-F]{4}|(?:[\dA-F]{2} )*[\dA-F]{2})/igm;
|
regex = /^\s*(?:[\dA-F]{4,16}h?:?)?[ \t]+((?:[\dA-F]{2} ){1,8}(?:[ \t]|[\dA-F]{2}-)(?:[\dA-F]{2} ){1,8}|(?:[\dA-F]{4} )+(?:[\dA-F]{2})?|(?:[\dA-F]{2} )*[\dA-F]{2})/igm;
|
||||||
let block, line;
|
let block, line;
|
||||||
|
|
||||||
while ((block = regex.exec(input))) {
|
while ((block = regex.exec(input))) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class FromQuotedPrintable extends Operation {
|
|||||||
|
|
||||||
this.name = "From Quoted Printable";
|
this.name = "From Quoted Printable";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Converts QP-encoded text back to standard text.<br><br>e.g. The quoted-printable encoded string <code>hello=20world</code> becomes <code>hello world</code>";
|
this.description = "Converts QP-encoded text back to standard text. This format is a content transfer encoding common in email messages.<br><br>e.g. The quoted-printable encoded string <code>hello=20world</code> becomes <code>hello world</code>";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Quoted-printable";
|
this.infoURL = "https://wikipedia.org/wiki/Quoted-printable";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "byteArray";
|
this.outputType = "byteArray";
|
||||||
|
|||||||
@@ -7,16 +7,15 @@
|
|||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import {isImage} from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import {toBase64} from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import {isWorkerEnvironment} from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime, ResizeStrategy, rgbaToInt } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate Image operation
|
* Generate Image operation
|
||||||
*/
|
*/
|
||||||
class GenerateImage extends Operation {
|
class GenerateImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GenerateImage constructor
|
* GenerateImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -25,27 +24,28 @@ class GenerateImage extends Operation {
|
|||||||
|
|
||||||
this.name = "Generate Image";
|
this.name = "Generate Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Generates an image using the input as pixel values.";
|
this.description =
|
||||||
|
"Generates an image using the input as pixel values.";
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
this.presentType = "html";
|
this.presentType = "html";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
"name": "Mode",
|
name: "Mode",
|
||||||
"type": "option",
|
type: "option",
|
||||||
"value": ["Greyscale", "RG", "RGB", "RGBA", "Bits"]
|
value: ["Greyscale", "RG", "RGB", "RGBA", "Bits"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Pixel Scale Factor",
|
name: "Pixel Scale Factor",
|
||||||
"type": "number",
|
type: "number",
|
||||||
"value": 8,
|
value: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Pixels per row",
|
name: "Pixels per row",
|
||||||
"type": "number",
|
type: "number",
|
||||||
"value": 64,
|
value: 64,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,21 +67,23 @@ class GenerateImage extends Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bytePerPixelMap = {
|
const bytePerPixelMap = {
|
||||||
"Greyscale": 1,
|
Greyscale: 1,
|
||||||
"RG": 2,
|
RG: 2,
|
||||||
"RGB": 3,
|
RGB: 3,
|
||||||
"RGBA": 4,
|
RGBA: 4,
|
||||||
"Bits": 1/8,
|
Bits: 1 / 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
const bytesPerPixel = bytePerPixelMap[mode];
|
const bytesPerPixel = bytePerPixelMap[mode];
|
||||||
|
|
||||||
if (bytesPerPixel > 0 && input.length % bytesPerPixel !== 0) {
|
if (bytesPerPixel > 0 && input.length % bytesPerPixel !== 0) {
|
||||||
throw new OperationError(`Number of bytes is not a divisor of ${bytesPerPixel}`);
|
throw new OperationError(
|
||||||
|
`Number of bytes is not a divisor of ${bytesPerPixel}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const height = Math.ceil(input.length / bytesPerPixel / width);
|
const height = Math.ceil(input.length / bytesPerPixel / width);
|
||||||
const image = await new Jimp(width, height, (err, image) => {});
|
const image = new Jimp({ width, height });
|
||||||
|
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Generating image from data...");
|
self.sendStatusMessage("Generating image from data...");
|
||||||
@@ -94,8 +96,8 @@ class GenerateImage extends Operation {
|
|||||||
const x = index % width;
|
const x = index % width;
|
||||||
const y = Math.floor(index / width);
|
const y = Math.floor(index / width);
|
||||||
|
|
||||||
const value = curByte[k] === "0" ? 0xFF : 0x00;
|
const value = curByte[k] === "0" ? 0xff : 0x00;
|
||||||
const pixel = Jimp.rgbaToInt(value, value, value, 0xFF);
|
const pixel = rgbaToInt(value, value, value, 0xff);
|
||||||
image.setPixelColor(pixel, x, y);
|
image.setPixelColor(pixel, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +111,7 @@ class GenerateImage extends Operation {
|
|||||||
let red = 0x00;
|
let red = 0x00;
|
||||||
let green = 0x00;
|
let green = 0x00;
|
||||||
let blue = 0x00;
|
let blue = 0x00;
|
||||||
let alpha = 0xFF;
|
let alpha = 0xff;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "Greyscale":
|
case "Greyscale":
|
||||||
@@ -139,10 +141,12 @@ class GenerateImage extends Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const pixel = Jimp.rgbaToInt(red, green, blue, alpha);
|
const pixel = rgbaToInt(red, green, blue, alpha);
|
||||||
image.setPixelColor(pixel, x, y);
|
image.setPixelColor(pixel, x, y);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error while generating image from pixel values. (${err})`);
|
throw new OperationError(
|
||||||
|
`Error while generating image from pixel values. (${err})`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,11 +155,15 @@ class GenerateImage extends Operation {
|
|||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Scaling image...");
|
self.sendStatusMessage("Scaling image...");
|
||||||
|
|
||||||
image.scaleToFit(width*scale, height*scale, Jimp.RESIZE_NEAREST_NEIGHBOR);
|
image.scaleToFit({
|
||||||
|
w: width * scale,
|
||||||
|
h: height * scale,
|
||||||
|
mode: ResizeStrategy.NEAREST_NEIGHBOR,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
const imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error generating image. (${err})`);
|
throw new OperationError(`Error generating image. (${err})`);
|
||||||
@@ -178,7 +186,6 @@ class GenerateImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GenerateImage;
|
export default GenerateImage;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image Brightness / Contrast operation
|
* Image Brightness / Contrast operation
|
||||||
*/
|
*/
|
||||||
class ImageBrightnessContrast extends Operation {
|
class ImageBrightnessContrast extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageBrightnessContrast constructor
|
* ImageBrightnessContrast constructor
|
||||||
*/
|
*/
|
||||||
@@ -35,15 +34,15 @@ class ImageBrightnessContrast extends Operation {
|
|||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0,
|
||||||
min: -100,
|
min: -100,
|
||||||
max: 100
|
max: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Contrast",
|
name: "Contrast",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0,
|
||||||
min: -100,
|
min: -100,
|
||||||
max: 100
|
max: 100,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,14 +76,16 @@ class ImageBrightnessContrast extends Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error adjusting image brightness or contrast. (${err})`);
|
throw new OperationError(
|
||||||
|
`Error adjusting image brightness or contrast. (${err})`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +105,6 @@ class ImageBrightnessContrast extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ImageBrightnessContrast;
|
export default ImageBrightnessContrast;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image Filter operation
|
* Image Filter operation
|
||||||
*/
|
*/
|
||||||
class ImageFilter extends Operation {
|
class ImageFilter extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageFilter constructor
|
* ImageFilter constructor
|
||||||
*/
|
*/
|
||||||
@@ -33,11 +32,8 @@ class ImageFilter extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Filter type",
|
name: "Filter type",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: [
|
value: ["Greyscale", "Sepia"],
|
||||||
"Greyscale",
|
},
|
||||||
"Sepia"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +56,11 @@ class ImageFilter extends Operation {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Applying " + filterType.toLowerCase() + " filter to image...");
|
self.sendStatusMessage(
|
||||||
|
"Applying " +
|
||||||
|
filterType.toLowerCase() +
|
||||||
|
" filter to image...",
|
||||||
|
);
|
||||||
if (filterType === "Greyscale") {
|
if (filterType === "Greyscale") {
|
||||||
image.greyscale();
|
image.greyscale();
|
||||||
} else {
|
} else {
|
||||||
@@ -68,14 +68,16 @@ class ImageFilter extends Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error applying filter to image. (${err})`);
|
throw new OperationError(
|
||||||
|
`Error applying filter to image. (${err})`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +97,6 @@ class ImageFilter extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ImageFilter;
|
export default ImageFilter;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image Hue/Saturation/Lightness operation
|
* Image Hue/Saturation/Lightness operation
|
||||||
*/
|
*/
|
||||||
class ImageHueSaturationLightness extends Operation {
|
class ImageHueSaturationLightness extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageHueSaturationLightness constructor
|
* ImageHueSaturationLightness constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +23,8 @@ class ImageHueSaturationLightness extends Operation {
|
|||||||
|
|
||||||
this.name = "Image Hue/Saturation/Lightness";
|
this.name = "Image Hue/Saturation/Lightness";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Adjusts the hue / saturation / lightness (HSL) values of an image.";
|
this.description =
|
||||||
|
"Adjusts the hue / saturation / lightness (HSL) values of an image.";
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -35,22 +35,22 @@ class ImageHueSaturationLightness extends Operation {
|
|||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0,
|
||||||
min: -360,
|
min: -360,
|
||||||
max: 360
|
max: 360,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Saturation",
|
name: "Saturation",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0,
|
||||||
min: -100,
|
min: -100,
|
||||||
max: 100
|
max: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Lightness",
|
name: "Lightness",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0,
|
value: 0,
|
||||||
min: -100,
|
min: -100,
|
||||||
max: 100
|
max: 100,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,43 +76,45 @@ class ImageHueSaturationLightness extends Operation {
|
|||||||
if (hue !== 0) {
|
if (hue !== 0) {
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Changing image hue...");
|
self.sendStatusMessage("Changing image hue...");
|
||||||
image.colour([
|
image.color([
|
||||||
{
|
{
|
||||||
apply: "hue",
|
apply: "hue",
|
||||||
params: [hue]
|
params: [hue],
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if (saturation !== 0) {
|
if (saturation !== 0) {
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Changing image saturation...");
|
self.sendStatusMessage("Changing image saturation...");
|
||||||
image.colour([
|
image.color([
|
||||||
{
|
{
|
||||||
apply: "saturate",
|
apply: "saturate",
|
||||||
params: [saturation]
|
params: [saturation],
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if (lightness !== 0) {
|
if (lightness !== 0) {
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Changing image lightness...");
|
self.sendStatusMessage("Changing image lightness...");
|
||||||
image.colour([
|
image.color([
|
||||||
{
|
{
|
||||||
apply: "lighten",
|
apply: "lighten",
|
||||||
params: [lightness]
|
params: [lightness],
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Error adjusting image hue / saturation / lightness. (${err})`);
|
throw new OperationError(
|
||||||
|
`Error adjusting image hue / saturation / lightness. (${err})`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image Opacity operation
|
* Image Opacity operation
|
||||||
*/
|
*/
|
||||||
class ImageOpacity extends Operation {
|
class ImageOpacity extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageOpacity constructor
|
* ImageOpacity constructor
|
||||||
*/
|
*/
|
||||||
@@ -35,8 +34,8 @@ class ImageOpacity extends Operation {
|
|||||||
type: "number",
|
type: "number",
|
||||||
value: 100,
|
value: 100,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 100
|
max: 100,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,10 +62,10 @@ class ImageOpacity extends Operation {
|
|||||||
image.opacity(opacity / 100);
|
image.opacity(opacity / 100);
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -90,7 +89,6 @@ class ImageOpacity extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ImageOpacity;
|
export default ImageOpacity;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invert Image operation
|
* Invert Image operation
|
||||||
*/
|
*/
|
||||||
class InvertImage extends Operation {
|
class InvertImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InvertImage constructor
|
* InvertImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -54,10 +53,10 @@ class InvertImage extends Operation {
|
|||||||
image.invert();
|
image.invert();
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -81,7 +80,6 @@ class InvertImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default InvertImage;
|
export default InvertImage;
|
||||||
|
|||||||
@@ -8,13 +8,12 @@ import Operation from "../Operation.mjs";
|
|||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalise Image operation
|
* Normalise Image operation
|
||||||
*/
|
*/
|
||||||
class NormaliseImage extends Operation {
|
class NormaliseImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NormaliseImage constructor
|
* NormaliseImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -27,7 +26,7 @@ class NormaliseImage extends Operation {
|
|||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
this.presentType= "html";
|
this.presentType = "html";
|
||||||
this.args = [];
|
this.args = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,10 +51,10 @@ class NormaliseImage extends Operation {
|
|||||||
image.normalize();
|
image.normalize();
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -79,7 +78,6 @@ class NormaliseImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NormaliseImage;
|
export default NormaliseImage;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { parseQrCode } from "../lib/QRCode.mjs";
|
|||||||
* Parse QR Code operation
|
* Parse QR Code operation
|
||||||
*/
|
*/
|
||||||
class ParseQRCode extends Operation {
|
class ParseQRCode extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ParseQRCode constructor
|
* ParseQRCode constructor
|
||||||
*/
|
*/
|
||||||
@@ -22,24 +21,26 @@ class ParseQRCode extends Operation {
|
|||||||
|
|
||||||
this.name = "Parse QR Code";
|
this.name = "Parse QR Code";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Reads an image file and attempts to detect and read a Quick Response (QR) code from the image.<br><br><u>Normalise Image</u><br>Attempts to normalise the image before parsing it to improve detection of a QR code.";
|
this.description =
|
||||||
|
"Reads an image file and attempts to detect and read a Quick Response (QR) code from the image.<br><br><u>Normalise Image</u><br>Attempts to normalise the image before parsing it to improve detection of a QR code.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/QR_code";
|
this.infoURL = "https://wikipedia.org/wiki/QR_code";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
"name": "Normalise image",
|
name: "Normalise image",
|
||||||
"type": "boolean",
|
type: "boolean",
|
||||||
"value": false
|
value: false,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
this.checks = [
|
this.checks = [
|
||||||
{
|
{
|
||||||
"pattern": "^(?:\\xff\\xd8\\xff|\\x89\\x50\\x4e\\x47|\\x47\\x49\\x46|.{8}\\x57\\x45\\x42\\x50|\\x42\\x4d)",
|
pattern:
|
||||||
"flags": "",
|
"^(?:\\xff\\xd8\\xff|\\x89\\x50\\x4e\\x47|\\x47\\x49\\x46|.{8}\\x57\\x45\\x42\\x50|\\x42\\x4d)",
|
||||||
"args": [false],
|
flags: "",
|
||||||
"useful": true
|
args: [false],
|
||||||
}
|
useful: true,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,9 +55,8 @@ class ParseQRCode extends Operation {
|
|||||||
if (!isImage(input)) {
|
if (!isImage(input)) {
|
||||||
throw new OperationError("Invalid file type.");
|
throw new OperationError("Invalid file type.");
|
||||||
}
|
}
|
||||||
return await parseQrCode(input, normalise);
|
return parseQrCode(input, normalise);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ParseQRCode;
|
export default ParseQRCode;
|
||||||
|
|||||||
@@ -10,13 +10,12 @@ import Utils from "../Utils.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { runHash } from "../lib/Hash.mjs";
|
import { runHash } from "../lib/Hash.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Randomize Colour Palette operation
|
* Randomize Colour Palette operation
|
||||||
*/
|
*/
|
||||||
class RandomizeColourPalette extends Operation {
|
class RandomizeColourPalette extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RandomizeColourPalette constructor
|
* RandomizeColourPalette constructor
|
||||||
*/
|
*/
|
||||||
@@ -25,7 +24,8 @@ class RandomizeColourPalette extends Operation {
|
|||||||
|
|
||||||
this.name = "Randomize Colour Palette";
|
this.name = "Randomize Colour Palette";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Randomizes each colour in an image's colour palette. This can often reveal text or symbols that were previously a very similar colour to their surroundings, a technique sometimes used in Steganography.";
|
this.description =
|
||||||
|
"Randomizes each colour in an image's colour palette. This can often reveal text or symbols that were previously a very similar colour to their surroundings, a technique sometimes used in Steganography.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Indexed_color";
|
this.infoURL = "https://wikipedia.org/wiki/Indexed_color";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -34,8 +34,8 @@ class RandomizeColourPalette extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Seed",
|
name: "Seed",
|
||||||
type: "string",
|
type: "string",
|
||||||
value: ""
|
value: "",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,23 +45,24 @@ class RandomizeColourPalette extends Operation {
|
|||||||
* @returns {ArrayBuffer}
|
* @returns {ArrayBuffer}
|
||||||
*/
|
*/
|
||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
if (!isImage(input)) throw new OperationError("Please enter a valid image file.");
|
if (!isImage(input))
|
||||||
|
throw new OperationError("Please enter a valid image file.");
|
||||||
|
|
||||||
const seed = args[0] || (Math.random().toString().substr(2)),
|
const seed = args[0] || Math.random().toString().substr(2),
|
||||||
parsedImage = await Jimp.read(input),
|
parsedImage = await Jimp.read(input),
|
||||||
width = parsedImage.bitmap.width,
|
width = parsedImage.bitmap.width,
|
||||||
height = parsedImage.bitmap.height;
|
height = parsedImage.bitmap.height;
|
||||||
|
|
||||||
let rgbString, rgbHash, rgbHex;
|
let rgbString, rgbHash, rgbHex;
|
||||||
|
|
||||||
parsedImage.scan(0, 0, width, height, function(x, y, idx) {
|
parsedImage.scan(0, 0, width, height, function (x, y, idx) {
|
||||||
rgbString = this.bitmap.data.slice(idx, idx+3).join(".");
|
rgbString = this.bitmap.data.slice(idx, idx + 3).join(".");
|
||||||
rgbHash = runHash("md5", Utils.strToArrayBuffer(seed + rgbString));
|
rgbHash = runHash("md5", Utils.strToArrayBuffer(seed + rgbString));
|
||||||
rgbHex = rgbHash.substr(0, 6) + "ff";
|
rgbHex = rgbHash.substr(0, 6) + "ff";
|
||||||
parsedImage.setPixelColor(parseInt(rgbHex, 16), x, y);
|
parsedImage.setPixelColor(parseInt(rgbHex, 16), x, y);
|
||||||
});
|
});
|
||||||
|
|
||||||
const imageBuffer = await parsedImage.getBufferAsync(Jimp.AUTO);
|
const imageBuffer = await parsedImage.getBuffer(parsedImage.mime);
|
||||||
|
|
||||||
return new Uint8Array(imageBuffer).buffer;
|
return new Uint8Array(imageBuffer).buffer;
|
||||||
}
|
}
|
||||||
@@ -77,7 +78,6 @@ class RandomizeColourPalette extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(data)}">`;
|
return `<img src="data:${type};base64,${toBase64(data)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RandomizeColourPalette;
|
export default RandomizeColourPalette;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime, ResizeStrategy } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resize Image operation
|
* Resize Image operation
|
||||||
*/
|
*/
|
||||||
class ResizeImage extends Operation {
|
class ResizeImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResizeImage constructor
|
* ResizeImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +23,8 @@ class ResizeImage extends Operation {
|
|||||||
|
|
||||||
this.name = "Resize Image";
|
this.name = "Resize Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Resizes an image to the specified width and height values.";
|
this.description =
|
||||||
|
"Resizes an image to the specified width and height values.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Image_scaling";
|
this.infoURL = "https://wikipedia.org/wiki/Image_scaling";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -34,23 +34,23 @@ class ResizeImage extends Operation {
|
|||||||
name: "Width",
|
name: "Width",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 100,
|
value: 100,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Height",
|
name: "Height",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 100,
|
value: 100,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Unit type",
|
name: "Unit type",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: ["Pixels", "Percent"]
|
value: ["Pixels", "Percent"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Maintain aspect ratio",
|
name: "Maintain aspect ratio",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: false
|
value: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Resizing algorithm",
|
name: "Resizing algorithm",
|
||||||
@@ -60,10 +60,10 @@ class ResizeImage extends Operation {
|
|||||||
"Bilinear",
|
"Bilinear",
|
||||||
"Bicubic",
|
"Bicubic",
|
||||||
"Hermite",
|
"Hermite",
|
||||||
"Bezier"
|
"Bezier",
|
||||||
],
|
],
|
||||||
defaultIndex: 1
|
defaultIndex: 1,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,11 +80,11 @@ class ResizeImage extends Operation {
|
|||||||
resizeAlg = args[4];
|
resizeAlg = args[4];
|
||||||
|
|
||||||
const resizeMap = {
|
const resizeMap = {
|
||||||
"Nearest Neighbour": Jimp.RESIZE_NEAREST_NEIGHBOR,
|
"Nearest Neighbour": ResizeStrategy.NEAREST_NEIGHBOR,
|
||||||
"Bilinear": Jimp.RESIZE_BILINEAR,
|
Bilinear: ResizeStrategy.BILINEAR,
|
||||||
"Bicubic": Jimp.RESIZE_BICUBIC,
|
Bicubic: ResizeStrategy.BICUBIC,
|
||||||
"Hermite": Jimp.RESIZE_HERMITE,
|
Hermite: ResizeStrategy.HERMITE,
|
||||||
"Bezier": Jimp.RESIZE_BEZIER
|
Bezier: ResizeStrategy.BEZIER,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isImage(input)) {
|
if (!isImage(input)) {
|
||||||
@@ -99,23 +99,31 @@ class ResizeImage extends Operation {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (unit === "Percent") {
|
if (unit === "Percent") {
|
||||||
width = image.getWidth() * (width / 100);
|
width = image.width * (width / 100);
|
||||||
height = image.getHeight() * (height / 100);
|
height = image.height * (height / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Resizing image...");
|
self.sendStatusMessage("Resizing image...");
|
||||||
if (aspect) {
|
if (aspect) {
|
||||||
image.scaleToFit(width, height, resizeMap[resizeAlg]);
|
image.scaleToFit({
|
||||||
|
w: width,
|
||||||
|
h: height,
|
||||||
|
mode: resizeMap[resizeAlg],
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
image.resize(width, height, resizeMap[resizeAlg]);
|
image.resize({
|
||||||
|
w: width,
|
||||||
|
h: height,
|
||||||
|
mode: resizeMap[resizeAlg],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -139,7 +147,6 @@ class ResizeImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ResizeImage;
|
export default ResizeImage;
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate Image operation
|
* Rotate Image operation
|
||||||
*/
|
*/
|
||||||
class RotateImage extends Operation {
|
class RotateImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RotateImage constructor
|
* RotateImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +23,8 @@ class RotateImage extends Operation {
|
|||||||
|
|
||||||
this.name = "Rotate Image";
|
this.name = "Rotate Image";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Rotates an image by the specified number of degrees.";
|
this.description =
|
||||||
|
"Rotates an image by the specified number of degrees.";
|
||||||
this.infoURL = "";
|
this.infoURL = "";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -33,8 +33,8 @@ class RotateImage extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Rotation amount (degrees)",
|
name: "Rotation amount (degrees)",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 90
|
value: 90,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,10 +62,10 @@ class RotateImage extends Operation {
|
|||||||
image.rotate(degrees);
|
image.rotate(degrees);
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -89,7 +89,6 @@ class RotateImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RotateImage;
|
export default RotateImage;
|
||||||
|
|||||||
@@ -8,15 +8,13 @@ import Operation from "../Operation.mjs";
|
|||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { gaussianBlur } from "../lib/ImageManipulation.mjs";
|
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sharpen Image operation
|
* Sharpen Image operation
|
||||||
*/
|
*/
|
||||||
class SharpenImage extends Operation {
|
class SharpenImage extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SharpenImage constructor
|
* SharpenImage constructor
|
||||||
*/
|
*/
|
||||||
@@ -35,22 +33,22 @@ class SharpenImage extends Operation {
|
|||||||
name: "Radius",
|
name: "Radius",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 2,
|
value: 2,
|
||||||
min: 1
|
min: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Amount",
|
name: "Amount",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 1,
|
value: 1,
|
||||||
min: 0,
|
min: 0,
|
||||||
step: 0.1
|
step: 0.1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Threshold",
|
name: "Threshold",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 10,
|
value: 10,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 100
|
max: 100,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,67 +77,102 @@ class SharpenImage extends Operation {
|
|||||||
const blurMask = image.clone();
|
const blurMask = image.clone();
|
||||||
|
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Sharpening image... (Blurring cloned image)");
|
self.sendStatusMessage(
|
||||||
const blurImage = gaussianBlur(image.clone(), radius);
|
"Sharpening image... (Blurring cloned image)",
|
||||||
|
);
|
||||||
|
const blurImage = image.clone().gaussian(radius);
|
||||||
|
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Sharpening image... (Creating unsharp mask)");
|
self.sendStatusMessage(
|
||||||
blurMask.scan(0, 0, blurMask.bitmap.width, blurMask.bitmap.height, function(x, y, idx) {
|
"Sharpening image... (Creating unsharp mask)",
|
||||||
const blurRed = blurImage.bitmap.data[idx];
|
);
|
||||||
const blurGreen = blurImage.bitmap.data[idx + 1];
|
blurMask.scan(
|
||||||
const blurBlue = blurImage.bitmap.data[idx + 2];
|
0,
|
||||||
|
0,
|
||||||
|
blurMask.bitmap.width,
|
||||||
|
blurMask.bitmap.height,
|
||||||
|
function (x, y, idx) {
|
||||||
|
const blurRed = blurImage.bitmap.data[idx];
|
||||||
|
const blurGreen = blurImage.bitmap.data[idx + 1];
|
||||||
|
const blurBlue = blurImage.bitmap.data[idx + 2];
|
||||||
|
|
||||||
const normalRed = this.bitmap.data[idx];
|
const normalRed = this.bitmap.data[idx];
|
||||||
const normalGreen = this.bitmap.data[idx + 1];
|
const normalGreen = this.bitmap.data[idx + 1];
|
||||||
const normalBlue = this.bitmap.data[idx + 2];
|
const normalBlue = this.bitmap.data[idx + 2];
|
||||||
|
|
||||||
// Subtract blurred pixel value from normal image
|
// Subtract blurred pixel value from normal image
|
||||||
this.bitmap.data[idx] = (normalRed > blurRed) ? normalRed - blurRed : 0;
|
this.bitmap.data[idx] =
|
||||||
this.bitmap.data[idx + 1] = (normalGreen > blurGreen) ? normalGreen - blurGreen : 0;
|
normalRed > blurRed ? normalRed - blurRed : 0;
|
||||||
this.bitmap.data[idx + 2] = (normalBlue > blurBlue) ? normalBlue - blurBlue : 0;
|
this.bitmap.data[idx + 1] =
|
||||||
});
|
normalGreen > blurGreen ? normalGreen - blurGreen : 0;
|
||||||
|
this.bitmap.data[idx + 2] =
|
||||||
|
normalBlue > blurBlue ? normalBlue - blurBlue : 0;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Sharpening image... (Merging with unsharp mask)");
|
self.sendStatusMessage(
|
||||||
image.scan(0, 0, image.bitmap.width, image.bitmap.height, function(x, y, idx) {
|
"Sharpening image... (Merging with unsharp mask)",
|
||||||
let maskRed = blurMask.bitmap.data[idx];
|
);
|
||||||
let maskGreen = blurMask.bitmap.data[idx + 1];
|
image.scan(
|
||||||
let maskBlue = blurMask.bitmap.data[idx + 2];
|
0,
|
||||||
|
0,
|
||||||
|
image.bitmap.width,
|
||||||
|
image.bitmap.height,
|
||||||
|
function (x, y, idx) {
|
||||||
|
let maskRed = blurMask.bitmap.data[idx];
|
||||||
|
let maskGreen = blurMask.bitmap.data[idx + 1];
|
||||||
|
let maskBlue = blurMask.bitmap.data[idx + 2];
|
||||||
|
|
||||||
const normalRed = this.bitmap.data[idx];
|
const normalRed = this.bitmap.data[idx];
|
||||||
const normalGreen = this.bitmap.data[idx + 1];
|
const normalGreen = this.bitmap.data[idx + 1];
|
||||||
const normalBlue = this.bitmap.data[idx + 2];
|
const normalBlue = this.bitmap.data[idx + 2];
|
||||||
|
|
||||||
// Calculate luminance
|
// Calculate luminance
|
||||||
const maskLuminance = (0.2126 * maskRed + 0.7152 * maskGreen + 0.0722 * maskBlue);
|
const maskLuminance =
|
||||||
const normalLuminance = (0.2126 * normalRed + 0.7152 * normalGreen + 0.0722 * normalBlue);
|
0.2126 * maskRed +
|
||||||
|
0.7152 * maskGreen +
|
||||||
|
0.0722 * maskBlue;
|
||||||
|
const normalLuminance =
|
||||||
|
0.2126 * normalRed +
|
||||||
|
0.7152 * normalGreen +
|
||||||
|
0.0722 * normalBlue;
|
||||||
|
|
||||||
let luminanceDiff;
|
let luminanceDiff;
|
||||||
if (maskLuminance > normalLuminance) {
|
if (maskLuminance > normalLuminance) {
|
||||||
luminanceDiff = maskLuminance - normalLuminance;
|
luminanceDiff = maskLuminance - normalLuminance;
|
||||||
} else {
|
} else {
|
||||||
luminanceDiff = normalLuminance - maskLuminance;
|
luminanceDiff = normalLuminance - maskLuminance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale mask colours by amount
|
// Scale mask colours by amount
|
||||||
maskRed = maskRed * amount;
|
maskRed = maskRed * amount;
|
||||||
maskGreen = maskGreen * amount;
|
maskGreen = maskGreen * amount;
|
||||||
maskBlue = maskBlue * amount;
|
maskBlue = maskBlue * amount;
|
||||||
|
|
||||||
// Only change pixel value if the difference is higher than threshold
|
// Only change pixel value if the difference is higher than threshold
|
||||||
if ((luminanceDiff / 255) * 100 >= threshold) {
|
if ((luminanceDiff / 255) * 100 >= threshold) {
|
||||||
this.bitmap.data[idx] = (normalRed + maskRed) <= 255 ? normalRed + maskRed : 255;
|
this.bitmap.data[idx] =
|
||||||
this.bitmap.data[idx + 1] = (normalGreen + maskGreen) <= 255 ? normalGreen + maskGreen : 255;
|
normalRed + maskRed <= 255 ?
|
||||||
this.bitmap.data[idx + 2] = (normalBlue + maskBlue) <= 255 ? normalBlue + maskBlue : 255;
|
normalRed + maskRed :
|
||||||
}
|
255;
|
||||||
});
|
this.bitmap.data[idx + 1] =
|
||||||
|
normalGreen + maskGreen <= 255 ?
|
||||||
|
normalGreen + maskGreen :
|
||||||
|
255;
|
||||||
|
this.bitmap.data[idx + 2] =
|
||||||
|
normalBlue + maskBlue <= 255 ?
|
||||||
|
normalBlue + maskBlue :
|
||||||
|
255;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let imageBuffer;
|
let imageBuffer;
|
||||||
if (image.getMIME() === "image/gif") {
|
if (image.mime === "image/gif") {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
|
imageBuffer = await image.getBuffer(JimpMime.png);
|
||||||
} else {
|
} else {
|
||||||
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
|
imageBuffer = await image.getBuffer(image.mime);
|
||||||
}
|
}
|
||||||
return imageBuffer.buffer;
|
return imageBuffer.buffer;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -163,7 +196,6 @@ class SharpenImage extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
return `<img src="data:${type};base64,${toBase64(dataArray)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SharpenImage;
|
export default SharpenImage;
|
||||||
|
|||||||
@@ -7,14 +7,13 @@
|
|||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import {isImage} from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp, JimpMime } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split Colour Channels operation
|
* Split Colour Channels operation
|
||||||
*/
|
*/
|
||||||
class SplitColourChannels extends Operation {
|
class SplitColourChannels extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SplitColourChannels constructor
|
* SplitColourChannels constructor
|
||||||
*/
|
*/
|
||||||
@@ -23,7 +22,8 @@ class SplitColourChannels extends Operation {
|
|||||||
|
|
||||||
this.name = "Split Colour Channels";
|
this.name = "Split Colour Channels";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Splits the given image into its red, green and blue colour channels.";
|
this.description =
|
||||||
|
"Splits the given image into its red, green and blue colour channels.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Channel_(digital_image)";
|
this.infoURL = "https://wikipedia.org/wiki/Channel_(digital_image)";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "List<File>";
|
this.outputType = "List<File>";
|
||||||
@@ -48,26 +48,44 @@ class SplitColourChannels extends Operation {
|
|||||||
const split = parsedImage
|
const split = parsedImage
|
||||||
.clone()
|
.clone()
|
||||||
.color([
|
.color([
|
||||||
{apply: "blue", params: [-255]},
|
{ apply: "blue", params: [-255] },
|
||||||
{apply: "green", params: [-255]}
|
{ apply: "green", params: [-255] },
|
||||||
])
|
])
|
||||||
.getBufferAsync(Jimp.MIME_PNG);
|
.getBuffer(JimpMime.png);
|
||||||
resolve(new File([new Uint8Array((await split).values())], "red.png", {type: "image/png"}));
|
resolve(
|
||||||
|
new File(
|
||||||
|
[new Uint8Array((await split).values())],
|
||||||
|
"red.png",
|
||||||
|
{ type: "image/png" },
|
||||||
|
),
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new OperationError(`Could not split red channel: ${err}`));
|
reject(
|
||||||
|
new OperationError(`Could not split red channel: ${err}`),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const green = new Promise(async (resolve, reject) => {
|
const green = new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const split = parsedImage.clone()
|
const split = parsedImage
|
||||||
|
.clone()
|
||||||
.color([
|
.color([
|
||||||
{apply: "red", params: [-255]},
|
{ apply: "red", params: [-255] },
|
||||||
{apply: "blue", params: [-255]},
|
{ apply: "blue", params: [-255] },
|
||||||
]).getBufferAsync(Jimp.MIME_PNG);
|
])
|
||||||
resolve(new File([new Uint8Array((await split).values())], "green.png", {type: "image/png"}));
|
.getBuffer(JimpMime.png);
|
||||||
|
resolve(
|
||||||
|
new File(
|
||||||
|
[new Uint8Array((await split).values())],
|
||||||
|
"green.png",
|
||||||
|
{ type: "image/png" },
|
||||||
|
),
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new OperationError(`Could not split green channel: ${err}`));
|
reject(
|
||||||
|
new OperationError(`Could not split green channel: ${err}`),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -75,12 +93,21 @@ class SplitColourChannels extends Operation {
|
|||||||
try {
|
try {
|
||||||
const split = parsedImage
|
const split = parsedImage
|
||||||
.color([
|
.color([
|
||||||
{apply: "red", params: [-255]},
|
{ apply: "red", params: [-255] },
|
||||||
{apply: "green", params: [-255]},
|
{ apply: "green", params: [-255] },
|
||||||
]).getBufferAsync(Jimp.MIME_PNG);
|
])
|
||||||
resolve(new File([new Uint8Array((await split).values())], "blue.png", {type: "image/png"}));
|
.getBuffer(JimpMime.png);
|
||||||
|
resolve(
|
||||||
|
new File(
|
||||||
|
[new Uint8Array((await split).values())],
|
||||||
|
"blue.png",
|
||||||
|
{ type: "image/png" },
|
||||||
|
),
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new OperationError(`Could not split blue channel: ${err}`));
|
reject(
|
||||||
|
new OperationError(`Could not split blue channel: ${err}`),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -96,7 +123,6 @@ class SplitColourChannels extends Operation {
|
|||||||
async present(files) {
|
async present(files) {
|
||||||
return await Utils.displayFilesAsHTML(files);
|
return await Utils.displayFilesAsHTML(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SplitColourChannels;
|
export default SplitColourChannels;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class ToBase85 extends Operation {
|
|||||||
value: ALPHABET_OPTIONS
|
value: ALPHABET_OPTIONS
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Include delimeter",
|
name: "Include delimiter",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: false
|
value: false
|
||||||
}
|
}
|
||||||
|
|||||||
92
src/core/operations/ToBech32.mjs
Normal file
92
src/core/operations/ToBech32.mjs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* @author Medjedtxm
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import { encode } from "../lib/Bech32.mjs";
|
||||||
|
import { fromHex } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To Bech32 operation
|
||||||
|
*/
|
||||||
|
class ToBech32 extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ToBech32 constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "To Bech32";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Bech32 is an encoding scheme primarily used for Bitcoin SegWit addresses (BIP-0173). It uses a 32-character alphabet that excludes easily confused characters (1, b, i, o) and includes a checksum for error detection.<br><br>Bech32m (BIP-0350) is an updated version that fixes a weakness in the original Bech32 checksum and is used for Bitcoin Taproot addresses.<br><br>The Human-Readable Part (HRP) identifies the network or purpose (e.g., 'bc' for Bitcoin mainnet, 'tb' for testnet, 'age' for AGE encryption keys).<br><br>Maximum output length is 90 characters as per specification.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Bech32";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Human-Readable Part (HRP)",
|
||||||
|
"type": "string",
|
||||||
|
"value": "bc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Encoding",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Bech32", "Bech32m"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input Format",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Raw bytes", "Hex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mode",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Generic", "Bitcoin SegWit"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Witness Version",
|
||||||
|
"type": "number",
|
||||||
|
"value": 0,
|
||||||
|
"hint": "SegWit witness version (0-16). Only used in Bitcoin SegWit mode."
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const hrp = args[0];
|
||||||
|
const encoding = args[1];
|
||||||
|
const inputFormat = args[2];
|
||||||
|
const mode = args[3];
|
||||||
|
const witnessVersion = args[4];
|
||||||
|
|
||||||
|
let inputArray;
|
||||||
|
if (inputFormat === "Hex") {
|
||||||
|
// Convert hex string to bytes
|
||||||
|
const hexStr = new TextDecoder().decode(new Uint8Array(input)).replace(/\s/g, "");
|
||||||
|
inputArray = fromHex(hexStr);
|
||||||
|
} else {
|
||||||
|
inputArray = new Uint8Array(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === "Bitcoin SegWit") {
|
||||||
|
// Prepend witness version to the input data
|
||||||
|
const withVersion = new Uint8Array(inputArray.length + 1);
|
||||||
|
withVersion[0] = witnessVersion;
|
||||||
|
withVersion.set(inputArray, 1);
|
||||||
|
return encode(hrp, withVersion, encoding, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return encode(hrp, inputArray, encoding, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ToBech32;
|
||||||
@@ -23,7 +23,7 @@ class ToQuotedPrintable extends Operation {
|
|||||||
|
|
||||||
this.name = "To Quoted Printable";
|
this.name = "To Quoted Printable";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Quoted-Printable, or QP encoding, is an encoding using printable ASCII characters (alphanumeric and the equals sign '=') to transmit 8-bit data over a 7-bit data path or, generally, over a medium which is not 8-bit clean. It is defined as a MIME content transfer encoding for use in e-mail.<br><br>QP works by using the equals sign '=' as an escape character. It also limits line length to 76, as some software has limits on line length.";
|
this.description = "Quoted-Printable, or QP encoding, is an encoding using printable ASCII characters (alphanumeric and the equals sign '=') to transmit 8-bit data over a 7-bit data path or, generally, over a medium which is not 8-bit clean. It is defined as a MIME content transfer encoding for use in email.<br><br>QP works by using the equals sign '=' as an escape character. It also limits line length to 76, as some software has limits on line length.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Quoted-printable";
|
this.infoURL = "https://wikipedia.org/wiki/Quoted-printable";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import { isImage } from "../lib/FileType.mjs";
|
import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import Jimp from "jimp/es/index.js";
|
import { Jimp } from "jimp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View Bit Plane operation
|
* View Bit Plane operation
|
||||||
*/
|
*/
|
||||||
class ViewBitPlane extends Operation {
|
class ViewBitPlane extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ViewBitPlane constructor
|
* ViewBitPlane constructor
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +23,8 @@ class ViewBitPlane extends Operation {
|
|||||||
|
|
||||||
this.name = "View Bit Plane";
|
this.name = "View Bit Plane";
|
||||||
this.module = "Image";
|
this.module = "Image";
|
||||||
this.description = "Extracts and displays a bit plane of any given image. These show only a single bit from each pixel, and can be used to hide messages in Steganography.";
|
this.description =
|
||||||
|
"Extracts and displays a bit plane of any given image. These show only a single bit from each pixel, and can be used to hide messages in Steganography.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Bit_plane";
|
this.infoURL = "https://wikipedia.org/wiki/Bit_plane";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "ArrayBuffer";
|
||||||
@@ -33,13 +33,13 @@ class ViewBitPlane extends Operation {
|
|||||||
{
|
{
|
||||||
name: "Colour",
|
name: "Colour",
|
||||||
type: "option",
|
type: "option",
|
||||||
value: COLOUR_OPTIONS
|
value: COLOUR_OPTIONS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Bit",
|
name: "Bit",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: 0
|
value: 0,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,36 +49,38 @@ class ViewBitPlane extends Operation {
|
|||||||
* @returns {ArrayBuffer}
|
* @returns {ArrayBuffer}
|
||||||
*/
|
*/
|
||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
if (!isImage(input)) throw new OperationError("Please enter a valid image file.");
|
if (!isImage(input))
|
||||||
|
throw new OperationError("Please enter a valid image file.");
|
||||||
|
|
||||||
const [colour, bit] = args,
|
const [colour, bit] = args,
|
||||||
parsedImage = await Jimp.read(input),
|
parsedImage = await Jimp.read(input),
|
||||||
width = parsedImage.bitmap.width,
|
width = parsedImage.bitmap.width,
|
||||||
height = parsedImage.bitmap.height,
|
height = parsedImage.bitmap.height,
|
||||||
colourIndex = COLOUR_OPTIONS.indexOf(colour),
|
colourIndex = COLOUR_OPTIONS.indexOf(colour),
|
||||||
bitIndex = 7-bit;
|
bitIndex = 7 - bit;
|
||||||
|
|
||||||
if (bit < 0 || bit > 7) {
|
if (bit < 0 || bit > 7) {
|
||||||
throw new OperationError("Error: Bit argument must be between 0 and 7");
|
throw new OperationError(
|
||||||
|
"Error: Bit argument must be between 0 and 7",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pixel, bin, newPixelValue;
|
let pixel, bin, newPixelValue;
|
||||||
|
|
||||||
parsedImage.scan(0, 0, width, height, function(x, y, idx) {
|
parsedImage.scan(0, 0, width, height, function (x, y, idx) {
|
||||||
pixel = this.bitmap.data[idx + colourIndex];
|
pixel = this.bitmap.data[idx + colourIndex];
|
||||||
bin = Utils.bin(pixel);
|
bin = Utils.bin(pixel);
|
||||||
newPixelValue = 255;
|
newPixelValue = 255;
|
||||||
|
|
||||||
if (bin.charAt(bitIndex) === "1") newPixelValue = 0;
|
if (bin.charAt(bitIndex) === "1") newPixelValue = 0;
|
||||||
|
|
||||||
for (let i=0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
this.bitmap.data[idx + i] = newPixelValue;
|
this.bitmap.data[idx + i] = newPixelValue;
|
||||||
}
|
}
|
||||||
this.bitmap.data[idx + 3] = 255;
|
this.bitmap.data[idx + 3] = 255;
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const imageBuffer = await parsedImage.getBufferAsync(Jimp.AUTO);
|
const imageBuffer = await parsedImage.getBuffer(parsedImage.mime);
|
||||||
|
|
||||||
return new Uint8Array(imageBuffer).buffer;
|
return new Uint8Array(imageBuffer).buffer;
|
||||||
}
|
}
|
||||||
@@ -94,14 +96,8 @@ class ViewBitPlane extends Operation {
|
|||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(data)}">`;
|
return `<img src="data:${type};base64,${toBase64(data)}">`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const COLOUR_OPTIONS = [
|
const COLOUR_OPTIONS = ["Red", "Green", "Blue", "Alpha"];
|
||||||
"Red",
|
|
||||||
"Green",
|
|
||||||
"Blue",
|
|
||||||
"Alpha"
|
|
||||||
];
|
|
||||||
|
|
||||||
export default ViewBitPlane;
|
export default ViewBitPlane;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export function removeSubheadingsFromArray(array) {
|
|||||||
* @param str
|
* @param str
|
||||||
*/
|
*/
|
||||||
export function sanitise(str) {
|
export function sanitise(str) {
|
||||||
return str.replace(/ /g, "").toLowerCase();
|
return str.replace(/[/\s.-]/g, "").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -650,7 +650,7 @@ class App {
|
|||||||
|
|
||||||
// const compareURL = `https://github.com/gchq/CyberChef/compare/v${prev.join(".")}...v${PKG_VERSION}`;
|
// const compareURL = `https://github.com/gchq/CyberChef/compare/v${prev.join(".")}...v${PKG_VERSION}`;
|
||||||
|
|
||||||
let compileInfo = `<a href='https://github.com/gchq/CyberChef/blob/master/CHANGELOG.md'>Last build: ${timeSinceCompile.substr(0, 1).toUpperCase() + timeSinceCompile.substr(1)} ago</a>`;
|
let compileInfo = `<a href='https://github.com/gchq/CyberChef/blob/master/CHANGELOG.md'>Last build: ${timeSinceCompile.substring(0, 1).toUpperCase() + timeSinceCompile.substring(1)} ago</a>`;
|
||||||
|
|
||||||
if (window.compileMessage !== "") {
|
if (window.compileMessage !== "") {
|
||||||
compileInfo += " - " + window.compileMessage;
|
compileInfo += " - " + window.compileMessage;
|
||||||
|
|||||||
@@ -1,485 +1,491 @@
|
|||||||
info face="Roboto" size=72 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,1,1,1 spacing=-2,-2
|
<?xml version="1.0"?>
|
||||||
common lineHeight=85 base=67 scaleW=512 scaleH=512 pages=1 packed=0
|
<font>
|
||||||
page id=0 file="Roboto72White.png"
|
<info face="Roboto" size="72" bold="0" italic="0" charset="" unicode="0" stretchH="100" smooth="1" aa="1" padding="1,1,1,1" spacing="-2,-2" outline="0" />
|
||||||
chars count=98
|
<common lineHeight="85" base="67" scaleW="512" scaleH="512" pages="1" packed="0" alphaChnl="0" redChnl="0" greenChnl="0" blueChnl="0" />
|
||||||
char id=0 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=66 xadvance=0 page=0 chnl=0
|
<pages>
|
||||||
char id=10 x=0 y=0 width=70 height=99 xoffset=2 yoffset=-11 xadvance=74 page=0 chnl=0
|
<page id="0" file="Roboto72White.png" /> </pages>
|
||||||
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=66 xadvance=18 page=0 chnl=0
|
<chars count="98">
|
||||||
char id=33 x=493 y=99 width=10 height=55 xoffset=5 yoffset=14 xadvance=19 page=0 chnl=0
|
<char id="0" x="0" y="0" width="0" height="0" xoffset="-1" yoffset="66" xadvance="0" page="0" chnl="0" />
|
||||||
char id=34 x=446 y=319 width=16 height=19 xoffset=4 yoffset=12 xadvance=23 page=0 chnl=0
|
<char id="10" x="0" y="0" width="70" height="99" xoffset="2" yoffset="-11" xadvance="74" page="0" chnl="0" />
|
||||||
char id=35 x=204 y=265 width=41 height=54 xoffset=3 yoffset=14 xadvance=44 page=0 chnl=0
|
<char id="32" x="0" y="0" width="0" height="0" xoffset="-1" yoffset="66" xadvance="18" page="0" chnl="0" />
|
||||||
char id=36 x=269 y=0 width=35 height=69 xoffset=3 yoffset=6 xadvance=40 page=0 chnl=0
|
<char id="33" x="493" y="99" width="10" height="55" xoffset="5" yoffset="14" xadvance="19" page="0" chnl="0" />
|
||||||
char id=37 x=31 y=155 width=48 height=56 xoffset=3 yoffset=13 xadvance=53 page=0 chnl=0
|
<char id="34" x="446" y="319" width="16" height="19" xoffset="4" yoffset="12" xadvance="23" page="0" chnl="0" />
|
||||||
char id=38 x=79 y=155 width=43 height=56 xoffset=3 yoffset=13 xadvance=45 page=0 chnl=0
|
<char id="35" x="204" y="265" width="41" height="54" xoffset="3" yoffset="14" xadvance="44" page="0" chnl="0" />
|
||||||
char id=39 x=503 y=99 width=7 height=19 xoffset=3 yoffset=12 xadvance=13 page=0 chnl=0
|
<char id="36" x="269" y="0" width="35" height="69" xoffset="3" yoffset="6" xadvance="40" page="0" chnl="0" />
|
||||||
char id=40 x=70 y=0 width=21 height=78 xoffset=4 yoffset=7 xadvance=25 page=0 chnl=0
|
<char id="37" x="31" y="155" width="48" height="56" xoffset="3" yoffset="13" xadvance="53" page="0" chnl="0" />
|
||||||
char id=41 x=91 y=0 width=22 height=78 xoffset=-1 yoffset=7 xadvance=25 page=0 chnl=0
|
<char id="38" x="79" y="155" width="43" height="56" xoffset="3" yoffset="13" xadvance="45" page="0" chnl="0" />
|
||||||
char id=42 x=342 y=319 width=32 height=32 xoffset=-1 yoffset=14 xadvance=31 page=0 chnl=0
|
<char id="39" x="503" y="99" width="7" height="19" xoffset="3" yoffset="12" xadvance="13" page="0" chnl="0" />
|
||||||
char id=43 x=242 y=319 width=37 height=40 xoffset=2 yoffset=23 xadvance=41 page=0 chnl=0
|
<char id="40" x="70" y="0" width="21" height="78" xoffset="4" yoffset="7" xadvance="25" page="0" chnl="0" />
|
||||||
char id=44 x=433 y=319 width=13 height=21 xoffset=-1 yoffset=58 xadvance=14 page=0 chnl=0
|
<char id="41" x="91" y="0" width="22" height="78" xoffset="-1" yoffset="7" xadvance="25" page="0" chnl="0" />
|
||||||
char id=45 x=27 y=360 width=19 height=8 xoffset=0 yoffset=41 xadvance=19 page=0 chnl=0
|
<char id="42" x="342" y="319" width="32" height="32" xoffset="-1" yoffset="14" xadvance="31" page="0" chnl="0" />
|
||||||
char id=46 x=17 y=360 width=10 height=11 xoffset=4 yoffset=58 xadvance=19 page=0 chnl=0
|
<char id="43" x="242" y="319" width="37" height="40" xoffset="2" yoffset="23" xadvance="41" page="0" chnl="0" />
|
||||||
char id=47 x=355 y=0 width=30 height=58 xoffset=-1 yoffset=14 xadvance=30 page=0 chnl=0
|
<char id="44" x="433" y="319" width="13" height="21" xoffset="-1" yoffset="58" xadvance="14" page="0" chnl="0" />
|
||||||
char id=48 x=449 y=99 width=34 height=56 xoffset=3 yoffset=13 xadvance=40 page=0 chnl=0
|
<char id="45" x="27" y="360" width="19" height="8" xoffset="0" yoffset="41" xadvance="19" page="0" chnl="0" />
|
||||||
char id=49 x=474 y=211 width=22 height=54 xoffset=5 yoffset=14 xadvance=40 page=0 chnl=0
|
<char id="46" x="17" y="360" width="10" height="11" xoffset="4" yoffset="58" xadvance="19" page="0" chnl="0" />
|
||||||
char id=50 x=195 y=155 width=37 height=55 xoffset=2 yoffset=13 xadvance=41 page=0 chnl=0
|
<char id="47" x="355" y="0" width="30" height="58" xoffset="-1" yoffset="14" xadvance="30" page="0" chnl="0" />
|
||||||
char id=51 x=379 y=99 width=35 height=56 xoffset=2 yoffset=13 xadvance=40 page=0 chnl=0
|
<char id="48" x="449" y="99" width="34" height="56" xoffset="3" yoffset="13" xadvance="40" page="0" chnl="0" />
|
||||||
char id=52 x=128 y=265 width=39 height=54 xoffset=1 yoffset=14 xadvance=41 page=0 chnl=0
|
<char id="49" x="474" y="211" width="22" height="54" xoffset="5" yoffset="14" xadvance="40" page="0" chnl="0" />
|
||||||
char id=53 x=232 y=155 width=35 height=55 xoffset=4 yoffset=14 xadvance=40 page=0 chnl=0
|
<char id="50" x="195" y="155" width="37" height="55" xoffset="2" yoffset="13" xadvance="41" page="0" chnl="0" />
|
||||||
char id=54 x=267 y=155 width=35 height=55 xoffset=4 yoffset=14 xadvance=41 page=0 chnl=0
|
<char id="51" x="379" y="99" width="35" height="56" xoffset="2" yoffset="13" xadvance="40" page="0" chnl="0" />
|
||||||
char id=55 x=167 y=265 width=37 height=54 xoffset=2 yoffset=14 xadvance=41 page=0 chnl=0
|
<char id="52" x="128" y="265" width="39" height="54" xoffset="1" yoffset="14" xadvance="41" page="0" chnl="0" />
|
||||||
char id=56 x=414 y=99 width=35 height=56 xoffset=3 yoffset=13 xadvance=40 page=0 chnl=0
|
<char id="53" x="232" y="155" width="35" height="55" xoffset="4" yoffset="14" xadvance="40" page="0" chnl="0" />
|
||||||
char id=57 x=302 y=155 width=34 height=55 xoffset=3 yoffset=13 xadvance=41 page=0 chnl=0
|
<char id="54" x="267" y="155" width="35" height="55" xoffset="4" yoffset="14" xadvance="41" page="0" chnl="0" />
|
||||||
char id=58 x=495 y=265 width=10 height=41 xoffset=4 yoffset=28 xadvance=18 page=0 chnl=0
|
<char id="55" x="167" y="265" width="37" height="54" xoffset="2" yoffset="14" xadvance="41" page="0" chnl="0" />
|
||||||
char id=59 x=496 y=211 width=13 height=52 xoffset=0 yoffset=28 xadvance=15 page=0 chnl=0
|
<char id="56" x="414" y="99" width="35" height="56" xoffset="3" yoffset="13" xadvance="40" page="0" chnl="0" />
|
||||||
char id=60 x=279 y=319 width=31 height=35 xoffset=2 yoffset=27 xadvance=37 page=0 chnl=0
|
<char id="57" x="302" y="155" width="34" height="55" xoffset="3" yoffset="13" xadvance="41" page="0" chnl="0" />
|
||||||
char id=61 x=402 y=319 width=31 height=23 xoffset=4 yoffset=31 xadvance=39 page=0 chnl=0
|
<char id="58" x="495" y="265" width="10" height="41" xoffset="4" yoffset="28" xadvance="18" page="0" chnl="0" />
|
||||||
char id=62 x=310 y=319 width=32 height=35 xoffset=4 yoffset=27 xadvance=38 page=0 chnl=0
|
<char id="59" x="496" y="211" width="13" height="52" xoffset="0" yoffset="28" xadvance="15" page="0" chnl="0" />
|
||||||
char id=63 x=0 y=155 width=31 height=56 xoffset=2 yoffset=13 xadvance=34 page=0 chnl=0
|
<char id="60" x="279" y="319" width="31" height="35" xoffset="2" yoffset="27" xadvance="37" page="0" chnl="0" />
|
||||||
char id=64 x=210 y=0 width=59 height=69 xoffset=3 yoffset=15 xadvance=65 page=0 chnl=0
|
<char id="61" x="402" y="319" width="31" height="23" xoffset="4" yoffset="31" xadvance="39" page="0" chnl="0" />
|
||||||
char id=65 x=336 y=155 width=49 height=54 xoffset=-1 yoffset=14 xadvance=47 page=0 chnl=0
|
<char id="62" x="310" y="319" width="32" height="35" xoffset="4" yoffset="27" xadvance="38" page="0" chnl="0" />
|
||||||
char id=66 x=385 y=155 width=37 height=54 xoffset=5 yoffset=14 xadvance=45 page=0 chnl=0
|
<char id="63" x="0" y="155" width="31" height="56" xoffset="2" yoffset="13" xadvance="34" page="0" chnl="0" />
|
||||||
char id=67 x=0 y=99 width=42 height=56 xoffset=3 yoffset=13 xadvance=46 page=0 chnl=0
|
<char id="64" x="210" y="0" width="59" height="69" xoffset="3" yoffset="15" xadvance="65" page="0" chnl="0" />
|
||||||
char id=68 x=422 y=155 width=39 height=54 xoffset=5 yoffset=14 xadvance=47 page=0 chnl=0
|
<char id="65" x="336" y="155" width="49" height="54" xoffset="-1" yoffset="14" xadvance="47" page="0" chnl="0" />
|
||||||
char id=69 x=461 y=155 width=35 height=54 xoffset=5 yoffset=14 xadvance=41 page=0 chnl=0
|
<char id="66" x="385" y="155" width="37" height="54" xoffset="5" yoffset="14" xadvance="45" page="0" chnl="0" />
|
||||||
char id=70 x=0 y=211 width=34 height=54 xoffset=5 yoffset=14 xadvance=40 page=0 chnl=0
|
<char id="67" x="0" y="99" width="42" height="56" xoffset="3" yoffset="13" xadvance="46" page="0" chnl="0" />
|
||||||
char id=71 x=42 y=99 width=42 height=56 xoffset=3 yoffset=13 xadvance=49 page=0 chnl=0
|
<char id="68" x="422" y="155" width="39" height="54" xoffset="5" yoffset="14" xadvance="47" page="0" chnl="0" />
|
||||||
char id=72 x=34 y=211 width=41 height=54 xoffset=5 yoffset=14 xadvance=51 page=0 chnl=0
|
<char id="69" x="461" y="155" width="35" height="54" xoffset="5" yoffset="14" xadvance="41" page="0" chnl="0" />
|
||||||
char id=73 x=496 y=155 width=9 height=54 xoffset=5 yoffset=14 xadvance=19 page=0 chnl=0
|
<char id="70" x="0" y="211" width="34" height="54" xoffset="5" yoffset="14" xadvance="40" page="0" chnl="0" />
|
||||||
char id=74 x=122 y=155 width=34 height=55 xoffset=1 yoffset=14 xadvance=40 page=0 chnl=0
|
<char id="71" x="42" y="99" width="42" height="56" xoffset="3" yoffset="13" xadvance="49" page="0" chnl="0" />
|
||||||
char id=75 x=75 y=211 width=41 height=54 xoffset=5 yoffset=14 xadvance=45 page=0 chnl=0
|
<char id="72" x="34" y="211" width="41" height="54" xoffset="5" yoffset="14" xadvance="51" page="0" chnl="0" />
|
||||||
char id=76 x=116 y=211 width=33 height=54 xoffset=5 yoffset=14 xadvance=39 page=0 chnl=0
|
<char id="73" x="496" y="155" width="9" height="54" xoffset="5" yoffset="14" xadvance="19" page="0" chnl="0" />
|
||||||
char id=77 x=149 y=211 width=53 height=54 xoffset=5 yoffset=14 xadvance=63 page=0 chnl=0
|
<char id="74" x="122" y="155" width="34" height="55" xoffset="1" yoffset="14" xadvance="40" page="0" chnl="0" />
|
||||||
char id=78 x=202 y=211 width=41 height=54 xoffset=5 yoffset=14 xadvance=51 page=0 chnl=0
|
<char id="75" x="75" y="211" width="41" height="54" xoffset="5" yoffset="14" xadvance="45" page="0" chnl="0" />
|
||||||
char id=79 x=84 y=99 width=43 height=56 xoffset=3 yoffset=13 xadvance=49 page=0 chnl=0
|
<char id="76" x="116" y="211" width="33" height="54" xoffset="5" yoffset="14" xadvance="39" page="0" chnl="0" />
|
||||||
char id=80 x=243 y=211 width=39 height=54 xoffset=5 yoffset=14 xadvance=45 page=0 chnl=0
|
<char id="77" x="149" y="211" width="53" height="54" xoffset="5" yoffset="14" xadvance="63" page="0" chnl="0" />
|
||||||
char id=81 x=304 y=0 width=44 height=64 xoffset=3 yoffset=13 xadvance=49 page=0 chnl=0
|
<char id="78" x="202" y="211" width="41" height="54" xoffset="5" yoffset="14" xadvance="51" page="0" chnl="0" />
|
||||||
char id=82 x=282 y=211 width=40 height=54 xoffset=5 yoffset=14 xadvance=45 page=0 chnl=0
|
<char id="79" x="84" y="99" width="43" height="56" xoffset="3" yoffset="13" xadvance="49" page="0" chnl="0" />
|
||||||
char id=83 x=127 y=99 width=39 height=56 xoffset=2 yoffset=13 xadvance=43 page=0 chnl=0
|
<char id="80" x="243" y="211" width="39" height="54" xoffset="5" yoffset="14" xadvance="45" page="0" chnl="0" />
|
||||||
char id=84 x=322 y=211 width=42 height=54 xoffset=1 yoffset=14 xadvance=44 page=0 chnl=0
|
<char id="81" x="304" y="0" width="44" height="64" xoffset="3" yoffset="13" xadvance="49" page="0" chnl="0" />
|
||||||
char id=85 x=156 y=155 width=39 height=55 xoffset=4 yoffset=14 xadvance=47 page=0 chnl=0
|
<char id="82" x="282" y="211" width="40" height="54" xoffset="5" yoffset="14" xadvance="45" page="0" chnl="0" />
|
||||||
char id=86 x=364 y=211 width=47 height=54 xoffset=-1 yoffset=14 xadvance=46 page=0 chnl=0
|
<char id="83" x="127" y="99" width="39" height="56" xoffset="2" yoffset="13" xadvance="43" page="0" chnl="0" />
|
||||||
char id=87 x=411 y=211 width=63 height=54 xoffset=1 yoffset=14 xadvance=64 page=0 chnl=0
|
<char id="84" x="322" y="211" width="42" height="54" xoffset="1" yoffset="14" xadvance="44" page="0" chnl="0" />
|
||||||
char id=88 x=0 y=265 width=44 height=54 xoffset=1 yoffset=14 xadvance=45 page=0 chnl=0
|
<char id="85" x="156" y="155" width="39" height="55" xoffset="4" yoffset="14" xadvance="47" page="0" chnl="0" />
|
||||||
char id=89 x=44 y=265 width=45 height=54 xoffset=-1 yoffset=14 xadvance=43 page=0 chnl=0
|
<char id="86" x="364" y="211" width="47" height="54" xoffset="-1" yoffset="14" xadvance="46" page="0" chnl="0" />
|
||||||
char id=90 x=89 y=265 width=39 height=54 xoffset=2 yoffset=14 xadvance=43 page=0 chnl=0
|
<char id="87" x="411" y="211" width="63" height="54" xoffset="1" yoffset="14" xadvance="64" page="0" chnl="0" />
|
||||||
char id=91 x=161 y=0 width=16 height=72 xoffset=4 yoffset=7 xadvance=19 page=0 chnl=0
|
<char id="88" x="0" y="265" width="44" height="54" xoffset="1" yoffset="14" xadvance="45" page="0" chnl="0" />
|
||||||
char id=92 x=385 y=0 width=30 height=58 xoffset=0 yoffset=14 xadvance=30 page=0 chnl=0
|
<char id="89" x="44" y="265" width="45" height="54" xoffset="-1" yoffset="14" xadvance="43" page="0" chnl="0" />
|
||||||
char id=93 x=177 y=0 width=16 height=72 xoffset=0 yoffset=7 xadvance=20 page=0 chnl=0
|
<char id="90" x="89" y="265" width="39" height="54" xoffset="2" yoffset="14" xadvance="43" page="0" chnl="0" />
|
||||||
char id=94 x=374 y=319 width=28 height=28 xoffset=1 yoffset=14 xadvance=30 page=0 chnl=0
|
<char id="91" x="161" y="0" width="16" height="72" xoffset="4" yoffset="7" xadvance="19" page="0" chnl="0" />
|
||||||
char id=95 x=46 y=360 width=34 height=8 xoffset=0 yoffset=65 xadvance=34 page=0 chnl=0
|
<char id="92" x="385" y="0" width="30" height="58" xoffset="0" yoffset="14" xadvance="30" page="0" chnl="0" />
|
||||||
char id=96 x=0 y=360 width=17 height=13 xoffset=1 yoffset=11 xadvance=22 page=0 chnl=0
|
<char id="93" x="177" y="0" width="16" height="72" xoffset="0" yoffset="7" xadvance="20" page="0" chnl="0" />
|
||||||
char id=97 x=268 y=265 width=34 height=42 xoffset=3 yoffset=27 xadvance=39 page=0 chnl=0
|
<char id="94" x="374" y="319" width="28" height="28" xoffset="1" yoffset="14" xadvance="30" page="0" chnl="0" />
|
||||||
char id=98 x=415 y=0 width=34 height=57 xoffset=4 yoffset=12 xadvance=40 page=0 chnl=0
|
<char id="95" x="46" y="360" width="34" height="8" xoffset="0" yoffset="65" xadvance="34" page="0" chnl="0" />
|
||||||
char id=99 x=302 y=265 width=34 height=42 xoffset=2 yoffset=27 xadvance=38 page=0 chnl=0
|
<char id="96" x="0" y="360" width="17" height="13" xoffset="1" yoffset="11" xadvance="22" page="0" chnl="0" />
|
||||||
char id=100 x=449 y=0 width=34 height=57 xoffset=2 yoffset=12 xadvance=40 page=0 chnl=0
|
<char id="97" x="268" y="265" width="34" height="42" xoffset="3" yoffset="27" xadvance="39" page="0" chnl="0" />
|
||||||
char id=101 x=336 y=265 width=34 height=42 xoffset=2 yoffset=27 xadvance=38 page=0 chnl=0
|
<char id="98" x="415" y="0" width="34" height="57" xoffset="4" yoffset="12" xadvance="40" page="0" chnl="0" />
|
||||||
char id=102 x=483 y=0 width=25 height=57 xoffset=1 yoffset=11 xadvance=26 page=0 chnl=0
|
<char id="99" x="302" y="265" width="34" height="42" xoffset="2" yoffset="27" xadvance="38" page="0" chnl="0" />
|
||||||
char id=103 x=166 y=99 width=34 height=56 xoffset=2 yoffset=27 xadvance=40 page=0 chnl=0
|
<char id="100" x="449" y="0" width="34" height="57" xoffset="2" yoffset="12" xadvance="40" page="0" chnl="0" />
|
||||||
char id=104 x=200 y=99 width=32 height=56 xoffset=4 yoffset=12 xadvance=40 page=0 chnl=0
|
<char id="101" x="336" y="265" width="34" height="42" xoffset="2" yoffset="27" xadvance="38" page="0" chnl="0" />
|
||||||
char id=105 x=483 y=99 width=10 height=55 xoffset=4 yoffset=13 xadvance=18 page=0 chnl=0
|
<char id="102" x="483" y="0" width="25" height="57" xoffset="1" yoffset="11" xadvance="26" page="0" chnl="0" />
|
||||||
char id=106 x=193 y=0 width=17 height=71 xoffset=-4 yoffset=13 xadvance=17 page=0 chnl=0
|
<char id="103" x="166" y="99" width="34" height="56" xoffset="2" yoffset="27" xadvance="40" page="0" chnl="0" />
|
||||||
char id=107 x=232 y=99 width=34 height=56 xoffset=4 yoffset=12 xadvance=37 page=0 chnl=0
|
<char id="104" x="200" y="99" width="32" height="56" xoffset="4" yoffset="12" xadvance="40" page="0" chnl="0" />
|
||||||
char id=108 x=266 y=99 width=9 height=56 xoffset=4 yoffset=12 xadvance=17 page=0 chnl=0
|
<char id="105" x="483" y="99" width="10" height="55" xoffset="4" yoffset="13" xadvance="18" page="0" chnl="0" />
|
||||||
char id=109 x=439 y=265 width=56 height=41 xoffset=4 yoffset=27 xadvance=64 page=0 chnl=0
|
<char id="106" x="193" y="0" width="17" height="71" xoffset="-4" yoffset="13" xadvance="17" page="0" chnl="0" />
|
||||||
char id=110 x=0 y=319 width=32 height=41 xoffset=4 yoffset=27 xadvance=40 page=0 chnl=0
|
<char id="107" x="232" y="99" width="34" height="56" xoffset="4" yoffset="12" xadvance="37" page="0" chnl="0" />
|
||||||
char id=111 x=370 y=265 width=37 height=42 xoffset=2 yoffset=27 xadvance=41 page=0 chnl=0
|
<char id="108" x="266" y="99" width="9" height="56" xoffset="4" yoffset="12" xadvance="17" page="0" chnl="0" />
|
||||||
char id=112 x=275 y=99 width=34 height=56 xoffset=4 yoffset=27 xadvance=40 page=0 chnl=0
|
<char id="109" x="439" y="265" width="56" height="41" xoffset="4" yoffset="27" xadvance="64" page="0" chnl="0" />
|
||||||
char id=113 x=309 y=99 width=34 height=56 xoffset=2 yoffset=27 xadvance=41 page=0 chnl=0
|
<char id="110" x="0" y="319" width="32" height="41" xoffset="4" yoffset="27" xadvance="40" page="0" chnl="0" />
|
||||||
char id=114 x=32 y=319 width=21 height=41 xoffset=4 yoffset=27 xadvance=25 page=0 chnl=0
|
<char id="111" x="370" y="265" width="37" height="42" xoffset="2" yoffset="27" xadvance="41" page="0" chnl="0" />
|
||||||
char id=115 x=407 y=265 width=32 height=42 xoffset=2 yoffset=27 xadvance=37 page=0 chnl=0
|
<char id="112" x="275" y="99" width="34" height="56" xoffset="4" yoffset="27" xadvance="40" page="0" chnl="0" />
|
||||||
char id=116 x=245 y=265 width=23 height=51 xoffset=0 yoffset=18 xadvance=25 page=0 chnl=0
|
<char id="113" x="309" y="99" width="34" height="56" xoffset="2" yoffset="27" xadvance="41" page="0" chnl="0" />
|
||||||
char id=117 x=53 y=319 width=32 height=41 xoffset=4 yoffset=28 xadvance=40 page=0 chnl=0
|
<char id="114" x="32" y="319" width="21" height="41" xoffset="4" yoffset="27" xadvance="25" page="0" chnl="0" />
|
||||||
char id=118 x=85 y=319 width=35 height=40 xoffset=0 yoffset=28 xadvance=35 page=0 chnl=0
|
<char id="115" x="407" y="265" width="32" height="42" xoffset="2" yoffset="27" xadvance="37" page="0" chnl="0" />
|
||||||
char id=119 x=120 y=319 width=54 height=40 xoffset=0 yoffset=28 xadvance=54 page=0 chnl=0
|
<char id="116" x="245" y="265" width="23" height="51" xoffset="0" yoffset="18" xadvance="25" page="0" chnl="0" />
|
||||||
char id=120 x=174 y=319 width=36 height=40 xoffset=0 yoffset=28 xadvance=36 page=0 chnl=0
|
<char id="117" x="53" y="319" width="32" height="41" xoffset="4" yoffset="28" xadvance="40" page="0" chnl="0" />
|
||||||
char id=121 x=343 y=99 width=36 height=56 xoffset=-1 yoffset=28 xadvance=34 page=0 chnl=0
|
<char id="118" x="85" y="319" width="35" height="40" xoffset="0" yoffset="28" xadvance="35" page="0" chnl="0" />
|
||||||
char id=122 x=210 y=319 width=32 height=40 xoffset=2 yoffset=28 xadvance=35 page=0 chnl=0
|
<char id="119" x="120" y="319" width="54" height="40" xoffset="0" yoffset="28" xadvance="54" page="0" chnl="0" />
|
||||||
char id=123 x=113 y=0 width=24 height=73 xoffset=1 yoffset=9 xadvance=25 page=0 chnl=0
|
<char id="120" x="174" y="319" width="36" height="40" xoffset="0" yoffset="28" xadvance="36" page="0" chnl="0" />
|
||||||
char id=124 x=348 y=0 width=7 height=63 xoffset=5 yoffset=14 xadvance=17 page=0 chnl=0
|
<char id="121" x="343" y="99" width="36" height="56" xoffset="-1" yoffset="28" xadvance="34" page="0" chnl="0" />
|
||||||
char id=125 x=137 y=0 width=24 height=73 xoffset=-1 yoffset=9 xadvance=24 page=0 chnl=0
|
<char id="122" x="210" y="319" width="32" height="40" xoffset="2" yoffset="28" xadvance="35" page="0" chnl="0" />
|
||||||
char id=126 x=462 y=319 width=42 height=16 xoffset=4 yoffset=38 xadvance=50 page=0 chnl=0
|
<char id="123" x="113" y="0" width="24" height="73" xoffset="1" yoffset="9" xadvance="25" page="0" chnl="0" />
|
||||||
char id=127 x=0 y=0 width=70 height=99 xoffset=2 yoffset=-11 xadvance=74 page=0 chnl=0
|
<char id="124" x="348" y="0" width="7" height="63" xoffset="5" yoffset="14" xadvance="17" page="0" chnl="0" />
|
||||||
kernings count=382
|
<char id="125" x="137" y="0" width="24" height="73" xoffset="-1" yoffset="9" xadvance="24" page="0" chnl="0" />
|
||||||
kerning first=70 second=74 amount=-9
|
<char id="126" x="462" y="319" width="42" height="16" xoffset="4" yoffset="38" xadvance="50" page="0" chnl="0" />
|
||||||
kerning first=34 second=97 amount=-2
|
<char id="127" x="0" y="0" width="70" height="99" xoffset="2" yoffset="-11" xadvance="74" page="0" chnl="0" />
|
||||||
kerning first=34 second=101 amount=-2
|
</chars>
|
||||||
kerning first=34 second=113 amount=-2
|
<kernings count="382">
|
||||||
kerning first=34 second=99 amount=-2
|
<kerning first="70" second="74" amount="-9" />
|
||||||
kerning first=70 second=99 amount=-1
|
<kerning first="34" second="97" amount="-2" />
|
||||||
kerning first=88 second=113 amount=-1
|
<kerning first="34" second="101" amount="-2" />
|
||||||
kerning first=84 second=46 amount=-8
|
<kerning first="34" second="113" amount="-2" />
|
||||||
kerning first=84 second=119 amount=-2
|
<kerning first="34" second="99" amount="-2" />
|
||||||
kerning first=87 second=97 amount=-1
|
<kerning first="70" second="99" amount="-1" />
|
||||||
kerning first=90 second=117 amount=-1
|
<kerning first="88" second="113" amount="-1" />
|
||||||
kerning first=39 second=97 amount=-2
|
<kerning first="84" second="46" amount="-8" />
|
||||||
kerning first=69 second=111 amount=-1
|
<kerning first="84" second="119" amount="-2" />
|
||||||
kerning first=87 second=41 amount=1
|
<kerning first="87" second="97" amount="-1" />
|
||||||
kerning first=76 second=86 amount=-6
|
<kerning first="90" second="117" amount="-1" />
|
||||||
kerning first=121 second=34 amount=1
|
<kerning first="39" second="97" amount="-2" />
|
||||||
kerning first=40 second=86 amount=1
|
<kerning first="69" second="111" amount="-1" />
|
||||||
kerning first=85 second=65 amount=-1
|
<kerning first="87" second="41" amount="1" />
|
||||||
kerning first=89 second=89 amount=1
|
<kerning first="76" second="86" amount="-6" />
|
||||||
kerning first=72 second=65 amount=1
|
<kerning first="121" second="34" amount="1" />
|
||||||
kerning first=104 second=39 amount=-4
|
<kerning first="40" second="86" amount="1" />
|
||||||
kerning first=114 second=102 amount=1
|
<kerning first="85" second="65" amount="-1" />
|
||||||
kerning first=89 second=42 amount=-2
|
<kerning first="89" second="89" amount="1" />
|
||||||
kerning first=114 second=34 amount=1
|
<kerning first="72" second="65" amount="1" />
|
||||||
kerning first=84 second=115 amount=-4
|
<kerning first="104" second="39" amount="-4" />
|
||||||
kerning first=84 second=71 amount=-1
|
<kerning first="114" second="102" amount="1" />
|
||||||
kerning first=89 second=101 amount=-2
|
<kerning first="89" second="42" amount="-2" />
|
||||||
kerning first=89 second=45 amount=-2
|
<kerning first="114" second="34" amount="1" />
|
||||||
kerning first=122 second=99 amount=-1
|
<kerning first="84" second="115" amount="-4" />
|
||||||
kerning first=78 second=88 amount=1
|
<kerning first="84" second="71" amount="-1" />
|
||||||
kerning first=68 second=89 amount=-2
|
<kerning first="89" second="101" amount="-2" />
|
||||||
kerning first=122 second=103 amount=-1
|
<kerning first="89" second="45" amount="-2" />
|
||||||
kerning first=78 second=84 amount=-1
|
<kerning first="122" second="99" amount="-1" />
|
||||||
kerning first=86 second=103 amount=-2
|
<kerning first="78" second="88" amount="1" />
|
||||||
kerning first=89 second=67 amount=-1
|
<kerning first="68" second="89" amount="-2" />
|
||||||
kerning first=89 second=79 amount=-1
|
<kerning first="122" second="103" amount="-1" />
|
||||||
kerning first=75 second=111 amount=-1
|
<kerning first="78" second="84" amount="-1" />
|
||||||
kerning first=111 second=120 amount=-1
|
<kerning first="86" second="103" amount="-2" />
|
||||||
kerning first=87 second=44 amount=-4
|
<kerning first="89" second="67" amount="-1" />
|
||||||
kerning first=91 second=74 amount=-1
|
<kerning first="89" second="79" amount="-1" />
|
||||||
kerning first=120 second=111 amount=-1
|
<kerning first="75" second="111" amount="-1" />
|
||||||
kerning first=84 second=111 amount=-3
|
<kerning first="111" second="120" amount="-1" />
|
||||||
kerning first=102 second=113 amount=-1
|
<kerning first="87" second="44" amount="-4" />
|
||||||
kerning first=80 second=88 amount=-1
|
<kerning first="91" second="74" amount="-1" />
|
||||||
kerning first=66 second=84 amount=-1
|
<kerning first="120" second="111" amount="-1" />
|
||||||
kerning first=65 second=87 amount=-2
|
<kerning first="84" second="111" amount="-3" />
|
||||||
kerning first=86 second=100 amount=-2
|
<kerning first="102" second="113" amount="-1" />
|
||||||
kerning first=122 second=100 amount=-1
|
<kerning first="80" second="88" amount="-1" />
|
||||||
kerning first=75 second=118 amount=-1
|
<kerning first="66" second="84" amount="-1" />
|
||||||
kerning first=70 second=118 amount=-1
|
<kerning first="65" second="87" amount="-2" />
|
||||||
kerning first=73 second=88 amount=1
|
<kerning first="86" second="100" amount="-2" />
|
||||||
kerning first=70 second=121 amount=-1
|
<kerning first="122" second="100" amount="-1" />
|
||||||
kerning first=65 second=34 amount=-4
|
<kerning first="75" second="118" amount="-1" />
|
||||||
kerning first=39 second=101 amount=-2
|
<kerning first="70" second="118" amount="-1" />
|
||||||
kerning first=75 second=101 amount=-1
|
<kerning first="73" second="88" amount="1" />
|
||||||
kerning first=84 second=99 amount=-3
|
<kerning first="70" second="121" amount="-1" />
|
||||||
kerning first=84 second=65 amount=-3
|
<kerning first="65" second="34" amount="-4" />
|
||||||
kerning first=112 second=39 amount=-1
|
<kerning first="39" second="101" amount="-2" />
|
||||||
kerning first=76 second=39 amount=-12
|
<kerning first="75" second="101" amount="-1" />
|
||||||
kerning first=78 second=65 amount=1
|
<kerning first="84" second="99" amount="-3" />
|
||||||
kerning first=88 second=45 amount=-2
|
<kerning first="84" second="65" amount="-3" />
|
||||||
kerning first=65 second=121 amount=-2
|
<kerning first="112" second="39" amount="-1" />
|
||||||
kerning first=34 second=111 amount=-2
|
<kerning first="76" second="39" amount="-12" />
|
||||||
kerning first=89 second=85 amount=-3
|
<kerning first="78" second="65" amount="1" />
|
||||||
kerning first=114 second=99 amount=-1
|
<kerning first="88" second="45" amount="-2" />
|
||||||
kerning first=86 second=125 amount=1
|
<kerning first="65" second="121" amount="-2" />
|
||||||
kerning first=70 second=111 amount=-1
|
<kerning first="34" second="111" amount="-2" />
|
||||||
kerning first=89 second=120 amount=-1
|
<kerning first="89" second="85" amount="-3" />
|
||||||
kerning first=90 second=119 amount=-1
|
<kerning first="114" second="99" amount="-1" />
|
||||||
kerning first=120 second=99 amount=-1
|
<kerning first="86" second="125" amount="1" />
|
||||||
kerning first=89 second=117 amount=-1
|
<kerning first="70" second="111" amount="-1" />
|
||||||
kerning first=82 second=89 amount=-2
|
<kerning first="89" second="120" amount="-1" />
|
||||||
kerning first=75 second=117 amount=-1
|
<kerning first="90" second="119" amount="-1" />
|
||||||
kerning first=34 second=34 amount=-4
|
<kerning first="120" second="99" amount="-1" />
|
||||||
kerning first=89 second=110 amount=-1
|
<kerning first="89" second="117" amount="-1" />
|
||||||
kerning first=88 second=101 amount=-1
|
<kerning first="82" second="89" amount="-2" />
|
||||||
kerning first=107 second=103 amount=-1
|
<kerning first="75" second="117" amount="-1" />
|
||||||
kerning first=34 second=115 amount=-3
|
<kerning first="34" second="34" amount="-4" />
|
||||||
kerning first=98 second=39 amount=-1
|
<kerning first="89" second="110" amount="-1" />
|
||||||
kerning first=70 second=65 amount=-6
|
<kerning first="88" second="101" amount="-1" />
|
||||||
kerning first=70 second=46 amount=-8
|
<kerning first="107" second="103" amount="-1" />
|
||||||
kerning first=98 second=34 amount=-1
|
<kerning first="34" second="115" amount="-3" />
|
||||||
kerning first=70 second=84 amount=1
|
<kerning first="98" second="39" amount="-1" />
|
||||||
kerning first=114 second=100 amount=-1
|
<kerning first="70" second="65" amount="-6" />
|
||||||
kerning first=88 second=79 amount=-1
|
<kerning first="70" second="46" amount="-8" />
|
||||||
kerning first=39 second=113 amount=-2
|
<kerning first="98" second="34" amount="-1" />
|
||||||
kerning first=114 second=103 amount=-1
|
<kerning first="70" second="84" amount="1" />
|
||||||
kerning first=77 second=65 amount=1
|
<kerning first="114" second="100" amount="-1" />
|
||||||
kerning first=120 second=103 amount=-1
|
<kerning first="88" second="79" amount="-1" />
|
||||||
kerning first=114 second=121 amount=1
|
<kerning first="39" second="113" amount="-2" />
|
||||||
kerning first=89 second=100 amount=-2
|
<kerning first="114" second="103" amount="-1" />
|
||||||
kerning first=80 second=65 amount=-5
|
<kerning first="77" second="65" amount="1" />
|
||||||
kerning first=121 second=111 amount=-1
|
<kerning first="120" second="103" amount="-1" />
|
||||||
kerning first=84 second=74 amount=-8
|
<kerning first="114" second="121" amount="1" />
|
||||||
kerning first=122 second=111 amount=-1
|
<kerning first="89" second="100" amount="-2" />
|
||||||
kerning first=114 second=118 amount=1
|
<kerning first="80" second="65" amount="-5" />
|
||||||
kerning first=102 second=41 amount=1
|
<kerning first="121" second="111" amount="-1" />
|
||||||
kerning first=122 second=113 amount=-1
|
<kerning first="84" second="74" amount="-8" />
|
||||||
kerning first=89 second=122 amount=-1
|
<kerning first="122" second="111" amount="-1" />
|
||||||
kerning first=89 second=38 amount=-1
|
<kerning first="114" second="118" amount="1" />
|
||||||
kerning first=81 second=89 amount=-1
|
<kerning first="102" second="41" amount="1" />
|
||||||
kerning first=114 second=111 amount=-1
|
<kerning first="122" second="113" amount="-1" />
|
||||||
kerning first=46 second=34 amount=-6
|
<kerning first="89" second="122" amount="-1" />
|
||||||
kerning first=84 second=112 amount=-4
|
<kerning first="89" second="38" amount="-1" />
|
||||||
kerning first=112 second=34 amount=-1
|
<kerning first="81" second="89" amount="-1" />
|
||||||
kerning first=76 second=34 amount=-12
|
<kerning first="114" second="111" amount="-1" />
|
||||||
kerning first=102 second=125 amount=1
|
<kerning first="46" second="34" amount="-6" />
|
||||||
kerning first=39 second=115 amount=-3
|
<kerning first="84" second="112" amount="-4" />
|
||||||
kerning first=76 second=118 amount=-5
|
<kerning first="112" second="34" amount="-1" />
|
||||||
kerning first=86 second=99 amount=-2
|
<kerning first="76" second="34" amount="-12" />
|
||||||
kerning first=84 second=84 amount=1
|
<kerning first="102" second="125" amount="1" />
|
||||||
kerning first=86 second=65 amount=-3
|
<kerning first="39" second="115" amount="-3" />
|
||||||
kerning first=87 second=101 amount=-1
|
<kerning first="76" second="118" amount="-5" />
|
||||||
kerning first=67 second=125 amount=-1
|
<kerning first="86" second="99" amount="-2" />
|
||||||
kerning first=120 second=113 amount=-1
|
<kerning first="84" second="84" amount="1" />
|
||||||
kerning first=118 second=46 amount=-4
|
<kerning first="86" second="65" amount="-3" />
|
||||||
kerning first=88 second=103 amount=-1
|
<kerning first="87" second="101" amount="-1" />
|
||||||
kerning first=111 second=122 amount=-1
|
<kerning first="67" second="125" amount="-1" />
|
||||||
kerning first=77 second=84 amount=-1
|
<kerning first="120" second="113" amount="-1" />
|
||||||
kerning first=114 second=46 amount=-4
|
<kerning first="118" second="46" amount="-4" />
|
||||||
kerning first=34 second=39 amount=-4
|
<kerning first="88" second="103" amount="-1" />
|
||||||
kerning first=114 second=44 amount=-4
|
<kerning first="111" second="122" amount="-1" />
|
||||||
kerning first=69 second=84 amount=1
|
<kerning first="77" second="84" amount="-1" />
|
||||||
kerning first=89 second=46 amount=-7
|
<kerning first="114" second="46" amount="-4" />
|
||||||
kerning first=97 second=39 amount=-2
|
<kerning first="34" second="39" amount="-4" />
|
||||||
kerning first=34 second=100 amount=-2
|
<kerning first="114" second="44" amount="-4" />
|
||||||
kerning first=70 second=100 amount=-1
|
<kerning first="69" second="84" amount="1" />
|
||||||
kerning first=84 second=120 amount=-3
|
<kerning first="89" second="46" amount="-7" />
|
||||||
kerning first=90 second=118 amount=-1
|
<kerning first="97" second="39" amount="-2" />
|
||||||
kerning first=70 second=114 amount=-1
|
<kerning first="34" second="100" amount="-2" />
|
||||||
kerning first=34 second=112 amount=-1
|
<kerning first="70" second="100" amount="-1" />
|
||||||
kerning first=109 second=34 amount=-4
|
<kerning first="84" second="120" amount="-3" />
|
||||||
kerning first=86 second=113 amount=-2
|
<kerning first="90" second="118" amount="-1" />
|
||||||
kerning first=88 second=71 amount=-1
|
<kerning first="70" second="114" amount="-1" />
|
||||||
kerning first=66 second=89 amount=-2
|
<kerning first="34" second="112" amount="-1" />
|
||||||
kerning first=102 second=103 amount=-1
|
<kerning first="109" second="34" amount="-4" />
|
||||||
kerning first=88 second=67 amount=-1
|
<kerning first="86" second="113" amount="-2" />
|
||||||
kerning first=39 second=110 amount=-1
|
<kerning first="88" second="71" amount="-1" />
|
||||||
kerning first=75 second=110 amount=-1
|
<kerning first="66" second="89" amount="-2" />
|
||||||
kerning first=88 second=117 amount=-1
|
<kerning first="102" second="103" amount="-1" />
|
||||||
kerning first=89 second=118 amount=-1
|
<kerning first="88" second="67" amount="-1" />
|
||||||
kerning first=97 second=118 amount=-1
|
<kerning first="39" second="110" amount="-1" />
|
||||||
kerning first=87 second=65 amount=-2
|
<kerning first="75" second="110" amount="-1" />
|
||||||
kerning first=73 second=89 amount=-1
|
<kerning first="88" second="117" amount="-1" />
|
||||||
kerning first=89 second=74 amount=-3
|
<kerning first="89" second="118" amount="-1" />
|
||||||
kerning first=102 second=101 amount=-1
|
<kerning first="97" second="118" amount="-1" />
|
||||||
kerning first=86 second=111 amount=-2
|
<kerning first="87" second="65" amount="-2" />
|
||||||
kerning first=65 second=119 amount=-1
|
<kerning first="73" second="89" amount="-1" />
|
||||||
kerning first=84 second=100 amount=-3
|
<kerning first="89" second="74" amount="-3" />
|
||||||
kerning first=104 second=34 amount=-4
|
<kerning first="102" second="101" amount="-1" />
|
||||||
kerning first=86 second=41 amount=1
|
<kerning first="86" second="111" amount="-2" />
|
||||||
kerning first=111 second=34 amount=-5
|
<kerning first="65" second="119" amount="-1" />
|
||||||
kerning first=40 second=89 amount=1
|
<kerning first="84" second="100" amount="-3" />
|
||||||
kerning first=121 second=39 amount=1
|
<kerning first="104" second="34" amount="-4" />
|
||||||
kerning first=68 second=90 amount=-1
|
<kerning first="86" second="41" amount="1" />
|
||||||
kerning first=114 second=113 amount=-1
|
<kerning first="111" second="34" amount="-5" />
|
||||||
kerning first=68 second=88 amount=-1
|
<kerning first="40" second="89" amount="1" />
|
||||||
kerning first=98 second=120 amount=-1
|
<kerning first="121" second="39" amount="1" />
|
||||||
kerning first=110 second=34 amount=-4
|
<kerning first="68" second="90" amount="-1" />
|
||||||
kerning first=119 second=44 amount=-4
|
<kerning first="114" second="113" amount="-1" />
|
||||||
kerning first=119 second=46 amount=-4
|
<kerning first="68" second="88" amount="-1" />
|
||||||
kerning first=118 second=44 amount=-4
|
<kerning first="98" second="120" amount="-1" />
|
||||||
kerning first=84 second=114 amount=-3
|
<kerning first="110" second="34" amount="-4" />
|
||||||
kerning first=86 second=97 amount=-2
|
<kerning first="119" second="44" amount="-4" />
|
||||||
kerning first=68 second=86 amount=-1
|
<kerning first="119" second="46" amount="-4" />
|
||||||
kerning first=86 second=93 amount=1
|
<kerning first="118" second="44" amount="-4" />
|
||||||
kerning first=97 second=34 amount=-2
|
<kerning first="84" second="114" amount="-3" />
|
||||||
kerning first=34 second=65 amount=-4
|
<kerning first="86" second="97" amount="-2" />
|
||||||
kerning first=84 second=118 amount=-3
|
<kerning first="68" second="86" amount="-1" />
|
||||||
kerning first=76 second=84 amount=-10
|
<kerning first="86" second="93" amount="1" />
|
||||||
kerning first=107 second=99 amount=-1
|
<kerning first="97" second="34" amount="-2" />
|
||||||
kerning first=121 second=46 amount=-4
|
<kerning first="34" second="65" amount="-4" />
|
||||||
kerning first=123 second=85 amount=-1
|
<kerning first="84" second="118" amount="-3" />
|
||||||
kerning first=65 second=63 amount=-2
|
<kerning first="76" second="84" amount="-10" />
|
||||||
kerning first=89 second=44 amount=-7
|
<kerning first="107" second="99" amount="-1" />
|
||||||
kerning first=80 second=118 amount=1
|
<kerning first="121" second="46" amount="-4" />
|
||||||
kerning first=112 second=122 amount=-1
|
<kerning first="123" second="85" amount="-1" />
|
||||||
kerning first=79 second=65 amount=-1
|
<kerning first="65" second="63" amount="-2" />
|
||||||
kerning first=80 second=121 amount=1
|
<kerning first="89" second="44" amount="-7" />
|
||||||
kerning first=118 second=34 amount=1
|
<kerning first="80" second="118" amount="1" />
|
||||||
kerning first=87 second=45 amount=-2
|
<kerning first="112" second="122" amount="-1" />
|
||||||
kerning first=69 second=100 amount=-1
|
<kerning first="79" second="65" amount="-1" />
|
||||||
kerning first=87 second=103 amount=-1
|
<kerning first="80" second="121" amount="1" />
|
||||||
kerning first=112 second=120 amount=-1
|
<kerning first="118" second="34" amount="1" />
|
||||||
kerning first=68 second=44 amount=-4
|
<kerning first="87" second="45" amount="-2" />
|
||||||
kerning first=86 second=45 amount=-1
|
<kerning first="69" second="100" amount="-1" />
|
||||||
kerning first=39 second=34 amount=-4
|
<kerning first="87" second="103" amount="-1" />
|
||||||
kerning first=68 second=46 amount=-4
|
<kerning first="112" second="120" amount="-1" />
|
||||||
kerning first=65 second=89 amount=-3
|
<kerning first="68" second="44" amount="-4" />
|
||||||
kerning first=69 second=118 amount=-1
|
<kerning first="86" second="45" amount="-1" />
|
||||||
kerning first=88 second=99 amount=-1
|
<kerning first="39" second="34" amount="-4" />
|
||||||
kerning first=87 second=46 amount=-4
|
<kerning first="68" second="46" amount="-4" />
|
||||||
kerning first=47 second=47 amount=-8
|
<kerning first="65" second="89" amount="-3" />
|
||||||
kerning first=73 second=65 amount=1
|
<kerning first="69" second="118" amount="-1" />
|
||||||
kerning first=123 second=74 amount=-1
|
<kerning first="88" second="99" amount="-1" />
|
||||||
kerning first=69 second=102 amount=-1
|
<kerning first="87" second="46" amount="-4" />
|
||||||
kerning first=87 second=111 amount=-1
|
<kerning first="47" second="47" amount="-8" />
|
||||||
kerning first=39 second=112 amount=-1
|
<kerning first="73" second="65" amount="1" />
|
||||||
kerning first=89 second=116 amount=-1
|
<kerning first="123" second="74" amount="-1" />
|
||||||
kerning first=70 second=113 amount=-1
|
<kerning first="69" second="102" amount="-1" />
|
||||||
kerning first=77 second=88 amount=1
|
<kerning first="87" second="111" amount="-1" />
|
||||||
kerning first=84 second=32 amount=-1
|
<kerning first="39" second="112" amount="-1" />
|
||||||
kerning first=90 second=103 amount=-1
|
<kerning first="89" second="116" amount="-1" />
|
||||||
kerning first=65 second=86 amount=-3
|
<kerning first="70" second="113" amount="-1" />
|
||||||
kerning first=75 second=112 amount=-1
|
<kerning first="77" second="88" amount="1" />
|
||||||
kerning first=39 second=109 amount=-1
|
<kerning first="84" second="32" amount="-1" />
|
||||||
kerning first=75 second=81 amount=-1
|
<kerning first="90" second="103" amount="-1" />
|
||||||
kerning first=89 second=115 amount=-2
|
<kerning first="65" second="86" amount="-3" />
|
||||||
kerning first=84 second=83 amount=-1
|
<kerning first="75" second="112" amount="-1" />
|
||||||
kerning first=89 second=87 amount=1
|
<kerning first="39" second="109" amount="-1" />
|
||||||
kerning first=114 second=101 amount=-1
|
<kerning first="75" second="81" amount="-1" />
|
||||||
kerning first=116 second=111 amount=-1
|
<kerning first="89" second="115" amount="-2" />
|
||||||
kerning first=90 second=100 amount=-1
|
<kerning first="84" second="83" amount="-1" />
|
||||||
kerning first=84 second=122 amount=-2
|
<kerning first="89" second="87" amount="1" />
|
||||||
kerning first=68 second=84 amount=-1
|
<kerning first="114" second="101" amount="-1" />
|
||||||
kerning first=32 second=84 amount=-1
|
<kerning first="116" second="111" amount="-1" />
|
||||||
kerning first=84 second=117 amount=-3
|
<kerning first="90" second="100" amount="-1" />
|
||||||
kerning first=74 second=65 amount=-1
|
<kerning first="84" second="122" amount="-2" />
|
||||||
kerning first=107 second=101 amount=-1
|
<kerning first="68" second="84" amount="-1" />
|
||||||
kerning first=75 second=109 amount=-1
|
<kerning first="32" second="84" amount="-1" />
|
||||||
kerning first=80 second=46 amount=-11
|
<kerning first="84" second="117" amount="-3" />
|
||||||
kerning first=89 second=93 amount=1
|
<kerning first="74" second="65" amount="-1" />
|
||||||
kerning first=89 second=65 amount=-3
|
<kerning first="107" second="101" amount="-1" />
|
||||||
kerning first=87 second=117 amount=-1
|
<kerning first="75" second="109" amount="-1" />
|
||||||
kerning first=89 second=81 amount=-1
|
<kerning first="80" second="46" amount="-11" />
|
||||||
kerning first=39 second=103 amount=-2
|
<kerning first="89" second="93" amount="1" />
|
||||||
kerning first=86 second=101 amount=-2
|
<kerning first="89" second="65" amount="-3" />
|
||||||
kerning first=86 second=117 amount=-1
|
<kerning first="87" second="117" amount="-1" />
|
||||||
kerning first=84 second=113 amount=-3
|
<kerning first="89" second="81" amount="-1" />
|
||||||
kerning first=34 second=110 amount=-1
|
<kerning first="39" second="103" amount="-2" />
|
||||||
kerning first=89 second=84 amount=1
|
<kerning first="86" second="101" amount="-2" />
|
||||||
kerning first=84 second=110 amount=-4
|
<kerning first="86" second="117" amount="-1" />
|
||||||
kerning first=39 second=99 amount=-2
|
<kerning first="84" second="113" amount="-3" />
|
||||||
kerning first=88 second=121 amount=-1
|
<kerning first="34" second="110" amount="-1" />
|
||||||
kerning first=65 second=39 amount=-4
|
<kerning first="89" second="84" amount="1" />
|
||||||
kerning first=110 second=39 amount=-4
|
<kerning first="84" second="110" amount="-4" />
|
||||||
kerning first=75 second=67 amount=-1
|
<kerning first="39" second="99" amount="-2" />
|
||||||
kerning first=88 second=118 amount=-1
|
<kerning first="88" second="121" amount="-1" />
|
||||||
kerning first=86 second=114 amount=-1
|
<kerning first="65" second="39" amount="-4" />
|
||||||
kerning first=80 second=74 amount=-7
|
<kerning first="110" second="39" amount="-4" />
|
||||||
kerning first=84 second=97 amount=-4
|
<kerning first="75" second="67" amount="-1" />
|
||||||
kerning first=82 second=84 amount=-3
|
<kerning first="88" second="118" amount="-1" />
|
||||||
kerning first=91 second=85 amount=-1
|
<kerning first="86" second="114" amount="-1" />
|
||||||
kerning first=102 second=99 amount=-1
|
<kerning first="80" second="74" amount="-7" />
|
||||||
kerning first=66 second=86 amount=-1
|
<kerning first="84" second="97" amount="-4" />
|
||||||
kerning first=120 second=101 amount=-1
|
<kerning first="82" second="84" amount="-3" />
|
||||||
kerning first=102 second=93 amount=1
|
<kerning first="91" second="85" amount="-1" />
|
||||||
kerning first=75 second=100 amount=-1
|
<kerning first="102" second="99" amount="-1" />
|
||||||
kerning first=84 second=79 amount=-1
|
<kerning first="66" second="86" amount="-1" />
|
||||||
kerning first=111 second=121 amount=-1
|
<kerning first="120" second="101" amount="-1" />
|
||||||
kerning first=75 second=121 amount=-1
|
<kerning first="102" second="93" amount="1" />
|
||||||
kerning first=81 second=87 amount=-1
|
<kerning first="75" second="100" amount="-1" />
|
||||||
kerning first=107 second=113 amount=-1
|
<kerning first="84" second="79" amount="-1" />
|
||||||
kerning first=120 second=100 amount=-1
|
<kerning first="111" second="121" amount="-1" />
|
||||||
kerning first=90 second=79 amount=-1
|
<kerning first="75" second="121" amount="-1" />
|
||||||
kerning first=89 second=114 amount=-1
|
<kerning first="81" second="87" amount="-1" />
|
||||||
kerning first=122 second=101 amount=-1
|
<kerning first="107" second="113" amount="-1" />
|
||||||
kerning first=111 second=118 amount=-1
|
<kerning first="120" second="100" amount="-1" />
|
||||||
kerning first=82 second=86 amount=-1
|
<kerning first="90" second="79" amount="-1" />
|
||||||
kerning first=67 second=84 amount=-1
|
<kerning first="89" second="114" amount="-1" />
|
||||||
kerning first=70 second=101 amount=-1
|
<kerning first="122" second="101" amount="-1" />
|
||||||
kerning first=89 second=83 amount=-1
|
<kerning first="111" second="118" amount="-1" />
|
||||||
kerning first=114 second=97 amount=-1
|
<kerning first="82" second="86" amount="-1" />
|
||||||
kerning first=70 second=97 amount=-1
|
<kerning first="67" second="84" amount="-1" />
|
||||||
kerning first=89 second=102 amount=-1
|
<kerning first="70" second="101" amount="-1" />
|
||||||
kerning first=78 second=89 amount=-1
|
<kerning first="89" second="83" amount="-1" />
|
||||||
kerning first=70 second=44 amount=-8
|
<kerning first="114" second="97" amount="-1" />
|
||||||
kerning first=44 second=39 amount=-6
|
<kerning first="70" second="97" amount="-1" />
|
||||||
kerning first=84 second=45 amount=-8
|
<kerning first="89" second="102" amount="-1" />
|
||||||
kerning first=89 second=121 amount=-1
|
<kerning first="78" second="89" amount="-1" />
|
||||||
kerning first=84 second=86 amount=1
|
<kerning first="70" second="44" amount="-8" />
|
||||||
kerning first=87 second=99 amount=-1
|
<kerning first="44" second="39" amount="-6" />
|
||||||
kerning first=98 second=122 amount=-1
|
<kerning first="84" second="45" amount="-8" />
|
||||||
kerning first=89 second=112 amount=-1
|
<kerning first="89" second="121" amount="-1" />
|
||||||
kerning first=89 second=103 amount=-2
|
<kerning first="84" second="86" amount="1" />
|
||||||
kerning first=88 second=81 amount=-1
|
<kerning first="87" second="99" amount="-1" />
|
||||||
kerning first=102 second=34 amount=1
|
<kerning first="98" second="122" amount="-1" />
|
||||||
kerning first=109 second=39 amount=-4
|
<kerning first="89" second="112" amount="-1" />
|
||||||
kerning first=81 second=84 amount=-2
|
<kerning first="89" second="103" amount="-2" />
|
||||||
kerning first=121 second=97 amount=-1
|
<kerning first="88" second="81" amount="-1" />
|
||||||
kerning first=89 second=99 amount=-2
|
<kerning first="102" second="34" amount="1" />
|
||||||
kerning first=89 second=125 amount=1
|
<kerning first="109" second="39" amount="-4" />
|
||||||
kerning first=81 second=86 amount=-1
|
<kerning first="81" second="84" amount="-2" />
|
||||||
kerning first=114 second=116 amount=2
|
<kerning first="121" second="97" amount="-1" />
|
||||||
kerning first=114 second=119 amount=1
|
<kerning first="89" second="99" amount="-2" />
|
||||||
kerning first=84 second=44 amount=-8
|
<kerning first="89" second="125" amount="1" />
|
||||||
kerning first=102 second=39 amount=1
|
<kerning first="81" second="86" amount="-1" />
|
||||||
kerning first=44 second=34 amount=-6
|
<kerning first="114" second="116" amount="2" />
|
||||||
kerning first=34 second=109 amount=-1
|
<kerning first="114" second="119" amount="1" />
|
||||||
kerning first=75 second=119 amount=-2
|
<kerning first="84" second="44" amount="-8" />
|
||||||
kerning first=76 second=65 amount=1
|
<kerning first="102" second="39" amount="1" />
|
||||||
kerning first=84 second=81 amount=-1
|
<kerning first="44" second="34" amount="-6" />
|
||||||
kerning first=76 second=121 amount=-5
|
<kerning first="34" second="109" amount="-1" />
|
||||||
kerning first=69 second=101 amount=-1
|
<kerning first="75" second="119" amount="-2" />
|
||||||
kerning first=89 second=111 amount=-2
|
<kerning first="76" second="65" amount="1" />
|
||||||
kerning first=80 second=90 amount=-1
|
<kerning first="84" second="81" amount="-1" />
|
||||||
kerning first=89 second=97 amount=-3
|
<kerning first="76" second="121" amount="-5" />
|
||||||
kerning first=89 second=109 amount=-1
|
<kerning first="69" second="101" amount="-1" />
|
||||||
kerning first=90 second=99 amount=-1
|
<kerning first="89" second="111" amount="-2" />
|
||||||
kerning first=89 second=86 amount=1
|
<kerning first="80" second="90" amount="-1" />
|
||||||
kerning first=79 second=88 amount=-1
|
<kerning first="89" second="97" amount="-3" />
|
||||||
kerning first=70 second=103 amount=-1
|
<kerning first="89" second="109" amount="-1" />
|
||||||
kerning first=34 second=103 amount=-2
|
<kerning first="90" second="99" amount="-1" />
|
||||||
kerning first=84 second=67 amount=-1
|
<kerning first="89" second="86" amount="1" />
|
||||||
kerning first=76 second=79 amount=-2
|
<kerning first="79" second="88" amount="-1" />
|
||||||
kerning first=89 second=41 amount=1
|
<kerning first="70" second="103" amount="-1" />
|
||||||
kerning first=65 second=118 amount=-2
|
<kerning first="34" second="103" amount="-2" />
|
||||||
kerning first=75 second=71 amount=-1
|
<kerning first="84" second="67" amount="-1" />
|
||||||
kerning first=76 second=87 amount=-5
|
<kerning first="76" second="79" amount="-2" />
|
||||||
kerning first=77 second=89 amount=-1
|
<kerning first="89" second="41" amount="1" />
|
||||||
kerning first=90 second=113 amount=-1
|
<kerning first="65" second="118" amount="-2" />
|
||||||
kerning first=79 second=89 amount=-2
|
<kerning first="75" second="71" amount="-1" />
|
||||||
kerning first=118 second=111 amount=-1
|
<kerning first="76" second="87" amount="-5" />
|
||||||
kerning first=118 second=97 amount=-1
|
<kerning first="77" second="89" amount="-1" />
|
||||||
kerning first=88 second=100 amount=-1
|
<kerning first="90" second="113" amount="-1" />
|
||||||
kerning first=90 second=121 amount=-1
|
<kerning first="79" second="89" amount="-2" />
|
||||||
kerning first=89 second=113 amount=-2
|
<kerning first="118" second="111" amount="-1" />
|
||||||
kerning first=84 second=87 amount=1
|
<kerning first="118" second="97" amount="-1" />
|
||||||
kerning first=39 second=111 amount=-2
|
<kerning first="88" second="100" amount="-1" />
|
||||||
kerning first=80 second=44 amount=-11
|
<kerning first="90" second="121" amount="-1" />
|
||||||
kerning first=39 second=100 amount=-2
|
<kerning first="89" second="113" amount="-2" />
|
||||||
kerning first=75 second=113 amount=-1
|
<kerning first="84" second="87" amount="1" />
|
||||||
kerning first=88 second=111 amount=-1
|
<kerning first="39" second="111" amount="-2" />
|
||||||
kerning first=84 second=89 amount=1
|
<kerning first="80" second="44" amount="-11" />
|
||||||
kerning first=84 second=103 amount=-3
|
<kerning first="39" second="100" amount="-2" />
|
||||||
kerning first=70 second=117 amount=-1
|
<kerning first="75" second="113" amount="-1" />
|
||||||
kerning first=67 second=41 amount=-1
|
<kerning first="88" second="111" amount="-1" />
|
||||||
kerning first=89 second=71 amount=-1
|
<kerning first="84" second="89" amount="1" />
|
||||||
kerning first=121 second=44 amount=-4
|
<kerning first="84" second="103" amount="-3" />
|
||||||
kerning first=97 second=121 amount=-1
|
<kerning first="70" second="117" amount="-1" />
|
||||||
kerning first=87 second=113 amount=-1
|
<kerning first="67" second="41" amount="-1" />
|
||||||
kerning first=73 second=84 amount=-1
|
<kerning first="89" second="71" amount="-1" />
|
||||||
kerning first=84 second=101 amount=-3
|
<kerning first="121" second="44" amount="-4" />
|
||||||
kerning first=75 second=99 amount=-1
|
<kerning first="97" second="121" amount="-1" />
|
||||||
kerning first=65 second=85 amount=-1
|
<kerning first="87" second="113" amount="-1" />
|
||||||
kerning first=76 second=67 amount=-2
|
<kerning first="73" second="84" amount="-1" />
|
||||||
kerning first=76 second=81 amount=-2
|
<kerning first="84" second="101" amount="-3" />
|
||||||
kerning first=75 second=79 amount=-1
|
<kerning first="75" second="99" amount="-1" />
|
||||||
kerning first=39 second=65 amount=-4
|
<kerning first="65" second="85" amount="-1" />
|
||||||
kerning first=76 second=117 amount=-2
|
<kerning first="76" second="67" amount="-2" />
|
||||||
kerning first=65 second=84 amount=-5
|
<kerning first="76" second="81" amount="-2" />
|
||||||
kerning first=90 second=101 amount=-1
|
<kerning first="75" second="79" amount="-1" />
|
||||||
kerning first=84 second=121 amount=-3
|
<kerning first="39" second="65" amount="-4" />
|
||||||
kerning first=69 second=99 amount=-1
|
<kerning first="76" second="117" amount="-2" />
|
||||||
kerning first=114 second=39 amount=1
|
<kerning first="65" second="84" amount="-5" />
|
||||||
kerning first=84 second=109 amount=-4
|
<kerning first="90" second="101" amount="-1" />
|
||||||
kerning first=76 second=119 amount=-3
|
<kerning first="84" second="121" amount="-3" />
|
||||||
kerning first=76 second=85 amount=-2
|
<kerning first="69" second="99" amount="-1" />
|
||||||
kerning first=65 second=116 amount=-1
|
<kerning first="114" second="39" amount="1" />
|
||||||
kerning first=76 second=71 amount=-2
|
<kerning first="84" second="109" amount="-4" />
|
||||||
kerning first=79 second=90 amount=-1
|
<kerning first="76" second="119" amount="-3" />
|
||||||
kerning first=107 second=100 amount=-1
|
<kerning first="76" second="85" amount="-2" />
|
||||||
kerning first=90 second=111 amount=-1
|
<kerning first="65" second="116" amount="-1" />
|
||||||
kerning first=79 second=44 amount=-4
|
<kerning first="76" second="71" amount="-2" />
|
||||||
kerning first=75 second=45 amount=-2
|
<kerning first="79" second="90" amount="-1" />
|
||||||
kerning first=40 second=87 amount=1
|
<kerning first="107" second="100" amount="-1" />
|
||||||
kerning first=79 second=86 amount=-1
|
<kerning first="90" second="111" amount="-1" />
|
||||||
kerning first=102 second=100 amount=-1
|
<kerning first="79" second="44" amount="-4" />
|
||||||
kerning first=72 second=89 amount=-1
|
<kerning first="75" second="45" amount="-2" />
|
||||||
kerning first=72 second=88 amount=1
|
<kerning first="40" second="87" amount="1" />
|
||||||
kerning first=79 second=46 amount=-4
|
<kerning first="79" second="86" amount="-1" />
|
||||||
kerning first=76 second=89 amount=-8
|
<kerning first="102" second="100" amount="-1" />
|
||||||
kerning first=68 second=65 amount=-1
|
<kerning first="72" second="89" amount="-1" />
|
||||||
kerning first=79 second=84 amount=-1
|
<kerning first="72" second="88" amount="1" />
|
||||||
kerning first=87 second=100 amount=-1
|
<kerning first="79" second="46" amount="-4" />
|
||||||
kerning first=75 second=103 amount=-1
|
<kerning first="76" second="89" amount="-8" />
|
||||||
kerning first=90 second=67 amount=-1
|
<kerning first="68" second="65" amount="-1" />
|
||||||
kerning first=69 second=103 amount=-1
|
<kerning first="79" second="84" amount="-1" />
|
||||||
kerning first=90 second=71 amount=-1
|
<kerning first="87" second="100" amount="-1" />
|
||||||
kerning first=86 second=44 amount=-8
|
<kerning first="75" second="103" amount="-1" />
|
||||||
kerning first=69 second=121 amount=-1
|
<kerning first="90" second="67" amount="-1" />
|
||||||
kerning first=87 second=114 amount=-1
|
<kerning first="69" second="103" amount="-1" />
|
||||||
kerning first=118 second=39 amount=1
|
<kerning first="90" second="71" amount="-1" />
|
||||||
kerning first=46 second=39 amount=-6
|
<kerning first="86" second="44" amount="-8" />
|
||||||
kerning first=72 second=84 amount=-1
|
<kerning first="69" second="121" amount="-1" />
|
||||||
kerning first=86 second=46 amount=-8
|
<kerning first="87" second="114" amount="-1" />
|
||||||
kerning first=69 second=113 amount=-1
|
<kerning first="118" second="39" amount="1" />
|
||||||
kerning first=69 second=119 amount=-1
|
<kerning first="46" second="39" amount="-6" />
|
||||||
kerning first=39 second=39 amount=-4
|
<kerning first="72" second="84" amount="-1" />
|
||||||
kerning first=69 second=117 amount=-1
|
<kerning first="86" second="46" amount="-8" />
|
||||||
kerning first=111 second=39 amount=-5
|
<kerning first="69" second="113" amount="-1" />
|
||||||
kerning first=90 second=81 amount=-1
|
<kerning first="69" second="119" amount="-1" />
|
||||||
|
<kerning first="39" second="39" amount="-4" />
|
||||||
|
<kerning first="69" second="117" amount="-1" />
|
||||||
|
<kerning first="111" second="39" amount="-5" />
|
||||||
|
<kerning first="90" second="81" amount="-1" />
|
||||||
|
</kernings>
|
||||||
|
</font>
|
||||||
|
|||||||
@@ -1,488 +1,494 @@
|
|||||||
info face="Roboto Black" size=72 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,1,1,1 spacing=-2,-2
|
<?xml version="1.0"?>
|
||||||
common lineHeight=85 base=67 scaleW=512 scaleH=512 pages=1 packed=0
|
<font>
|
||||||
page id=0 file="RobotoBlack72White.png"
|
<info face="Roboto Black" size="72" bold="0" italic="0" charset="" unicode="0" stretchH="100" smooth="1" aa="1" padding="1,1,1,1" spacing="-2,-2" outline="0" />
|
||||||
chars count=98
|
<common lineHeight="85" base="67" scaleW="512" scaleH="512" pages="1" packed="0" alphaChnl="0" redChnl="0" greenChnl="0" blueChnl="0" />
|
||||||
char id=0 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=66 xadvance=0 page=0 chnl=0
|
<pages>
|
||||||
char id=10 x=0 y=0 width=70 height=99 xoffset=2 yoffset=-11 xadvance=74 page=0 chnl=0
|
<page id="0" file="RobotoBlack72White.png" /> </pages>
|
||||||
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=66 xadvance=18 page=0 chnl=0
|
<chars count="98">
|
||||||
char id=33 x=460 y=156 width=15 height=55 xoffset=3 yoffset=14 xadvance=20 page=0 chnl=0
|
<char id="0" x="0" y="0" width="0" height="0" xoffset="-1" yoffset="66" xadvance="0" page="0" chnl="0" />
|
||||||
char id=34 x=207 y=362 width=22 height=22 xoffset=0 yoffset=12 xadvance=23 page=0 chnl=0
|
<char id="10" x="0" y="0" width="70" height="99" xoffset="2" yoffset="-11" xadvance="74" page="0" chnl="0" />
|
||||||
char id=35 x=404 y=266 width=41 height=54 xoffset=0 yoffset=14 xadvance=42 page=0 chnl=0
|
<char id="32" x="0" y="0" width="0" height="0" xoffset="-1" yoffset="66" xadvance="18" page="0" chnl="0" />
|
||||||
char id=36 x=220 y=0 width=38 height=69 xoffset=2 yoffset=7 xadvance=42 page=0 chnl=0
|
<char id="33" x="460" y="156" width="15" height="55" xoffset="3" yoffset="14" xadvance="20" page="0" chnl="0" />
|
||||||
char id=37 x=167 y=156 width=49 height=56 xoffset=2 yoffset=13 xadvance=53 page=0 chnl=0
|
<char id="34" x="207" y="362" width="22" height="22" xoffset="0" yoffset="12" xadvance="23" page="0" chnl="0" />
|
||||||
char id=38 x=216 y=156 width=48 height=56 xoffset=1 yoffset=13 xadvance=48 page=0 chnl=0
|
<char id="35" x="404" y="266" width="41" height="54" xoffset="0" yoffset="14" xadvance="42" page="0" chnl="0" />
|
||||||
char id=39 x=499 y=320 width=10 height=22 xoffset=1 yoffset=12 xadvance=11 page=0 chnl=0
|
<char id="36" x="220" y="0" width="38" height="69" xoffset="2" yoffset="7" xadvance="42" page="0" chnl="0" />
|
||||||
char id=40 x=70 y=0 width=22 height=75 xoffset=3 yoffset=9 xadvance=25 page=0 chnl=0
|
<char id="37" x="167" y="156" width="49" height="56" xoffset="2" yoffset="13" xadvance="53" page="0" chnl="0" />
|
||||||
char id=41 x=92 y=0 width=23 height=75 xoffset=0 yoffset=9 xadvance=25 page=0 chnl=0
|
<char id="38" x="216" y="156" width="48" height="56" xoffset="1" yoffset="13" xadvance="48" page="0" chnl="0" />
|
||||||
char id=42 x=103 y=362 width=36 height=34 xoffset=-1 yoffset=14 xadvance=33 page=0 chnl=0
|
<char id="39" x="499" y="320" width="10" height="22" xoffset="1" yoffset="12" xadvance="11" page="0" chnl="0" />
|
||||||
char id=43 x=0 y=362 width=37 height=40 xoffset=1 yoffset=23 xadvance=39 page=0 chnl=0
|
<char id="40" x="70" y="0" width="22" height="75" xoffset="3" yoffset="9" xadvance="25" page="0" chnl="0" />
|
||||||
char id=44 x=483 y=320 width=16 height=25 xoffset=0 yoffset=57 xadvance=20 page=0 chnl=0
|
<char id="41" x="92" y="0" width="23" height="75" xoffset="0" yoffset="9" xadvance="25" page="0" chnl="0" />
|
||||||
char id=45 x=308 y=362 width=23 height=12 xoffset=4 yoffset=38 xadvance=32 page=0 chnl=0
|
<char id="42" x="103" y="362" width="36" height="34" xoffset="-1" yoffset="14" xadvance="33" page="0" chnl="0" />
|
||||||
char id=46 x=270 y=362 width=15 height=15 xoffset=3 yoffset=54 xadvance=22 page=0 chnl=0
|
<char id="43" x="0" y="362" width="37" height="40" xoffset="1" yoffset="23" xadvance="39" page="0" chnl="0" />
|
||||||
char id=47 x=374 y=0 width=29 height=58 xoffset=-3 yoffset=14 xadvance=25 page=0 chnl=0
|
<char id="44" x="483" y="320" width="16" height="25" xoffset="0" yoffset="57" xadvance="20" page="0" chnl="0" />
|
||||||
char id=48 x=77 y=156 width=38 height=56 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=0
|
<char id="45" x="308" y="362" width="23" height="12" xoffset="4" yoffset="38" xadvance="32" page="0" chnl="0" />
|
||||||
char id=49 x=299 y=266 width=26 height=54 xoffset=4 yoffset=14 xadvance=41 page=0 chnl=0
|
<char id="46" x="270" y="362" width="15" height="15" xoffset="3" yoffset="54" xadvance="22" page="0" chnl="0" />
|
||||||
char id=50 x=383 y=156 width=39 height=55 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=0
|
<char id="47" x="374" y="0" width="29" height="58" xoffset="-3" yoffset="14" xadvance="25" page="0" chnl="0" />
|
||||||
char id=51 x=434 y=99 width=39 height=56 xoffset=1 yoffset=13 xadvance=42 page=0 chnl=0
|
<char id="48" x="77" y="156" width="38" height="56" xoffset="2" yoffset="13" xadvance="42" page="0" chnl="0" />
|
||||||
char id=52 x=325 y=266 width=40 height=54 xoffset=1 yoffset=14 xadvance=42 page=0 chnl=0
|
<char id="49" x="299" y="266" width="26" height="54" xoffset="4" yoffset="14" xadvance="41" page="0" chnl="0" />
|
||||||
char id=53 x=422 y=156 width=38 height=55 xoffset=2 yoffset=14 xadvance=42 page=0 chnl=0
|
<char id="50" x="383" y="156" width="39" height="55" xoffset="1" yoffset="13" xadvance="42" page="0" chnl="0" />
|
||||||
char id=54 x=0 y=156 width=39 height=56 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=0
|
<char id="51" x="434" y="99" width="39" height="56" xoffset="1" yoffset="13" xadvance="42" page="0" chnl="0" />
|
||||||
char id=55 x=365 y=266 width=39 height=54 xoffset=1 yoffset=14 xadvance=42 page=0 chnl=0
|
<char id="52" x="325" y="266" width="40" height="54" xoffset="1" yoffset="14" xadvance="42" page="0" chnl="0" />
|
||||||
char id=56 x=473 y=99 width=38 height=56 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=0
|
<char id="53" x="422" y="156" width="38" height="55" xoffset="2" yoffset="14" xadvance="42" page="0" chnl="0" />
|
||||||
char id=57 x=39 y=156 width=38 height=56 xoffset=2 yoffset=13 xadvance=42 page=0 chnl=0
|
<char id="54" x="0" y="156" width="39" height="56" xoffset="2" yoffset="13" xadvance="42" page="0" chnl="0" />
|
||||||
char id=58 x=471 y=266 width=15 height=43 xoffset=3 yoffset=26 xadvance=21 page=0 chnl=0
|
<char id="55" x="365" y="266" width="39" height="54" xoffset="1" yoffset="14" xadvance="42" page="0" chnl="0" />
|
||||||
char id=59 x=150 y=156 width=17 height=56 xoffset=1 yoffset=26 xadvance=21 page=0 chnl=0
|
<char id="56" x="473" y="99" width="38" height="56" xoffset="2" yoffset="13" xadvance="42" page="0" chnl="0" />
|
||||||
char id=60 x=37 y=362 width=33 height=38 xoffset=1 yoffset=26 xadvance=37 page=0 chnl=0
|
<char id="57" x="39" y="156" width="38" height="56" xoffset="2" yoffset="13" xadvance="42" page="0" chnl="0" />
|
||||||
char id=61 x=172 y=362 width=35 height=27 xoffset=3 yoffset=31 xadvance=42 page=0 chnl=0
|
<char id="58" x="471" y="266" width="15" height="43" xoffset="3" yoffset="26" xadvance="21" page="0" chnl="0" />
|
||||||
char id=62 x=70 y=362 width=33 height=38 xoffset=3 yoffset=26 xadvance=37 page=0 chnl=0
|
<char id="59" x="150" y="156" width="17" height="56" xoffset="1" yoffset="26" xadvance="21" page="0" chnl="0" />
|
||||||
char id=63 x=115 y=156 width=35 height=56 xoffset=0 yoffset=13 xadvance=36 page=0 chnl=0
|
<char id="60" x="37" y="362" width="33" height="38" xoffset="1" yoffset="26" xadvance="37" page="0" chnl="0" />
|
||||||
char id=64 x=258 y=0 width=61 height=68 xoffset=1 yoffset=16 xadvance=64 page=0 chnl=0
|
<char id="61" x="172" y="362" width="35" height="27" xoffset="3" yoffset="31" xadvance="42" page="0" chnl="0" />
|
||||||
char id=65 x=0 y=212 width=53 height=54 xoffset=-2 yoffset=14 xadvance=49 page=0 chnl=0
|
<char id="62" x="70" y="362" width="33" height="38" xoffset="3" yoffset="26" xadvance="37" page="0" chnl="0" />
|
||||||
char id=66 x=53 y=212 width=42 height=54 xoffset=3 yoffset=14 xadvance=47 page=0 chnl=0
|
<char id="63" x="115" y="156" width="35" height="56" xoffset="0" yoffset="13" xadvance="36" page="0" chnl="0" />
|
||||||
char id=67 x=37 y=99 width=46 height=56 xoffset=1 yoffset=13 xadvance=47 page=0 chnl=0
|
<char id="64" x="258" y="0" width="61" height="68" xoffset="1" yoffset="16" xadvance="64" page="0" chnl="0" />
|
||||||
char id=68 x=95 y=212 width=42 height=54 xoffset=3 yoffset=14 xadvance=47 page=0 chnl=0
|
<char id="65" x="0" y="212" width="53" height="54" xoffset="-2" yoffset="14" xadvance="49" page="0" chnl="0" />
|
||||||
char id=69 x=137 y=212 width=38 height=54 xoffset=3 yoffset=14 xadvance=41 page=0 chnl=0
|
<char id="66" x="53" y="212" width="42" height="54" xoffset="3" yoffset="14" xadvance="47" page="0" chnl="0" />
|
||||||
char id=70 x=475 y=156 width=36 height=54 xoffset=3 yoffset=14 xadvance=39 page=0 chnl=0
|
<char id="67" x="37" y="99" width="46" height="56" xoffset="1" yoffset="13" xadvance="47" page="0" chnl="0" />
|
||||||
char id=71 x=83 y=99 width=45 height=56 xoffset=2 yoffset=13 xadvance=49 page=0 chnl=0
|
<char id="68" x="95" y="212" width="42" height="54" xoffset="3" yoffset="14" xadvance="47" page="0" chnl="0" />
|
||||||
char id=72 x=175 y=212 width=45 height=54 xoffset=3 yoffset=14 xadvance=51 page=0 chnl=0
|
<char id="69" x="137" y="212" width="38" height="54" xoffset="3" yoffset="14" xadvance="41" page="0" chnl="0" />
|
||||||
char id=73 x=220 y=212 width=14 height=54 xoffset=4 yoffset=14 xadvance=22 page=0 chnl=0
|
<char id="70" x="475" y="156" width="36" height="54" xoffset="3" yoffset="14" xadvance="39" page="0" chnl="0" />
|
||||||
char id=74 x=264 y=156 width=37 height=55 xoffset=0 yoffset=14 xadvance=40 page=0 chnl=0
|
<char id="71" x="83" y="99" width="45" height="56" xoffset="2" yoffset="13" xadvance="49" page="0" chnl="0" />
|
||||||
char id=75 x=234 y=212 width=45 height=54 xoffset=3 yoffset=14 xadvance=46 page=0 chnl=0
|
<char id="72" x="175" y="212" width="45" height="54" xoffset="3" yoffset="14" xadvance="51" page="0" chnl="0" />
|
||||||
char id=76 x=279 y=212 width=36 height=54 xoffset=3 yoffset=14 xadvance=39 page=0 chnl=0
|
<char id="73" x="220" y="212" width="14" height="54" xoffset="4" yoffset="14" xadvance="22" page="0" chnl="0" />
|
||||||
char id=77 x=315 y=212 width=58 height=54 xoffset=3 yoffset=14 xadvance=63 page=0 chnl=0
|
<char id="74" x="264" y="156" width="37" height="55" xoffset="0" yoffset="14" xadvance="40" page="0" chnl="0" />
|
||||||
char id=78 x=373 y=212 width=45 height=54 xoffset=3 yoffset=14 xadvance=51 page=0 chnl=0
|
<char id="75" x="234" y="212" width="45" height="54" xoffset="3" yoffset="14" xadvance="46" page="0" chnl="0" />
|
||||||
char id=79 x=128 y=99 width=47 height=56 xoffset=1 yoffset=13 xadvance=50 page=0 chnl=0
|
<char id="76" x="279" y="212" width="36" height="54" xoffset="3" yoffset="14" xadvance="39" page="0" chnl="0" />
|
||||||
char id=80 x=418 y=212 width=43 height=54 xoffset=3 yoffset=14 xadvance=48 page=0 chnl=0
|
<char id="77" x="315" y="212" width="58" height="54" xoffset="3" yoffset="14" xadvance="63" page="0" chnl="0" />
|
||||||
char id=81 x=319 y=0 width=47 height=65 xoffset=2 yoffset=13 xadvance=50 page=0 chnl=0
|
<char id="78" x="373" y="212" width="45" height="54" xoffset="3" yoffset="14" xadvance="51" page="0" chnl="0" />
|
||||||
char id=82 x=461 y=212 width=43 height=54 xoffset=3 yoffset=14 xadvance=46 page=0 chnl=0
|
<char id="79" x="128" y="99" width="47" height="56" xoffset="1" yoffset="13" xadvance="50" page="0" chnl="0" />
|
||||||
char id=83 x=175 y=99 width=42 height=56 xoffset=1 yoffset=13 xadvance=44 page=0 chnl=0
|
<char id="80" x="418" y="212" width="43" height="54" xoffset="3" yoffset="14" xadvance="48" page="0" chnl="0" />
|
||||||
char id=84 x=0 y=266 width=45 height=54 xoffset=0 yoffset=14 xadvance=45 page=0 chnl=0
|
<char id="81" x="319" y="0" width="47" height="65" xoffset="2" yoffset="13" xadvance="50" page="0" chnl="0" />
|
||||||
char id=85 x=301 y=156 width=42 height=55 xoffset=3 yoffset=14 xadvance=48 page=0 chnl=0
|
<char id="82" x="461" y="212" width="43" height="54" xoffset="3" yoffset="14" xadvance="46" page="0" chnl="0" />
|
||||||
char id=86 x=45 y=266 width=51 height=54 xoffset=-2 yoffset=14 xadvance=48 page=0 chnl=0
|
<char id="83" x="175" y="99" width="42" height="56" xoffset="1" yoffset="13" xadvance="44" page="0" chnl="0" />
|
||||||
char id=87 x=96 y=266 width=64 height=54 xoffset=-1 yoffset=14 xadvance=63 page=0 chnl=0
|
<char id="84" x="0" y="266" width="45" height="54" xoffset="0" yoffset="14" xadvance="45" page="0" chnl="0" />
|
||||||
char id=88 x=160 y=266 width=48 height=54 xoffset=-1 yoffset=14 xadvance=46 page=0 chnl=0
|
<char id="85" x="301" y="156" width="42" height="55" xoffset="3" yoffset="14" xadvance="48" page="0" chnl="0" />
|
||||||
char id=89 x=208 y=266 width=49 height=54 xoffset=-2 yoffset=14 xadvance=45 page=0 chnl=0
|
<char id="86" x="45" y="266" width="51" height="54" xoffset="-2" yoffset="14" xadvance="48" page="0" chnl="0" />
|
||||||
char id=90 x=257 y=266 width=42 height=54 xoffset=1 yoffset=14 xadvance=44 page=0 chnl=0
|
<char id="87" x="96" y="266" width="64" height="54" xoffset="-1" yoffset="14" xadvance="63" page="0" chnl="0" />
|
||||||
char id=91 x=115 y=0 width=18 height=75 xoffset=3 yoffset=5 xadvance=21 page=0 chnl=0
|
<char id="88" x="160" y="266" width="48" height="54" xoffset="-1" yoffset="14" xadvance="46" page="0" chnl="0" />
|
||||||
char id=92 x=403 y=0 width=37 height=58 xoffset=-2 yoffset=14 xadvance=31 page=0 chnl=0
|
<char id="89" x="208" y="266" width="49" height="54" xoffset="-2" yoffset="14" xadvance="45" page="0" chnl="0" />
|
||||||
char id=93 x=133 y=0 width=18 height=75 xoffset=0 yoffset=5 xadvance=21 page=0 chnl=0
|
<char id="90" x="257" y="266" width="42" height="54" xoffset="1" yoffset="14" xadvance="44" page="0" chnl="0" />
|
||||||
char id=94 x=139 y=362 width=33 height=28 xoffset=0 yoffset=14 xadvance=32 page=0 chnl=0
|
<char id="91" x="115" y="0" width="18" height="75" xoffset="3" yoffset="5" xadvance="21" page="0" chnl="0" />
|
||||||
char id=95 x=331 y=362 width=34 height=12 xoffset=-1 yoffset=65 xadvance=33 page=0 chnl=0
|
<char id="92" x="403" y="0" width="37" height="58" xoffset="-2" yoffset="14" xadvance="31" page="0" chnl="0" />
|
||||||
char id=96 x=285 y=362 width=23 height=13 xoffset=0 yoffset=12 xadvance=24 page=0 chnl=0
|
<char id="93" x="133" y="0" width="18" height="75" xoffset="0" yoffset="5" xadvance="21" page="0" chnl="0" />
|
||||||
char id=97 x=0 y=320 width=37 height=42 xoffset=1 yoffset=27 xadvance=38 page=0 chnl=0
|
<char id="94" x="139" y="362" width="33" height="28" xoffset="0" yoffset="14" xadvance="32" page="0" chnl="0" />
|
||||||
char id=98 x=440 y=0 width=37 height=57 xoffset=2 yoffset=12 xadvance=40 page=0 chnl=0
|
<char id="95" x="331" y="362" width="34" height="12" xoffset="-1" yoffset="65" xadvance="33" page="0" chnl="0" />
|
||||||
char id=99 x=37 y=320 width=36 height=42 xoffset=1 yoffset=27 xadvance=38 page=0 chnl=0
|
<char id="96" x="285" y="362" width="23" height="13" xoffset="0" yoffset="12" xadvance="24" page="0" chnl="0" />
|
||||||
char id=100 x=0 y=99 width=37 height=57 xoffset=1 yoffset=12 xadvance=40 page=0 chnl=0
|
<char id="97" x="0" y="320" width="37" height="42" xoffset="1" yoffset="27" xadvance="38" page="0" chnl="0" />
|
||||||
char id=101 x=73 y=320 width=38 height=42 xoffset=1 yoffset=27 xadvance=39 page=0 chnl=0
|
<char id="98" x="440" y="0" width="37" height="57" xoffset="2" yoffset="12" xadvance="40" page="0" chnl="0" />
|
||||||
char id=102 x=477 y=0 width=28 height=57 xoffset=0 yoffset=11 xadvance=27 page=0 chnl=0
|
<char id="99" x="37" y="320" width="36" height="42" xoffset="1" yoffset="27" xadvance="38" page="0" chnl="0" />
|
||||||
char id=103 x=217 y=99 width=38 height=56 xoffset=1 yoffset=27 xadvance=41 page=0 chnl=0
|
<char id="100" x="0" y="99" width="37" height="57" xoffset="1" yoffset="12" xadvance="40" page="0" chnl="0" />
|
||||||
char id=104 x=255 y=99 width=36 height=56 xoffset=2 yoffset=12 xadvance=40 page=0 chnl=0
|
<char id="101" x="73" y="320" width="38" height="42" xoffset="1" yoffset="27" xadvance="39" page="0" chnl="0" />
|
||||||
char id=105 x=291 y=99 width=15 height=56 xoffset=2 yoffset=12 xadvance=19 page=0 chnl=0
|
<char id="102" x="477" y="0" width="28" height="57" xoffset="0" yoffset="11" xadvance="27" page="0" chnl="0" />
|
||||||
char id=106 x=197 y=0 width=23 height=71 xoffset=-5 yoffset=12 xadvance=20 page=0 chnl=0
|
<char id="103" x="217" y="99" width="38" height="56" xoffset="1" yoffset="27" xadvance="41" page="0" chnl="0" />
|
||||||
char id=107 x=306 y=99 width=40 height=56 xoffset=2 yoffset=12 xadvance=39 page=0 chnl=0
|
<char id="104" x="255" y="99" width="36" height="56" xoffset="2" yoffset="12" xadvance="40" page="0" chnl="0" />
|
||||||
char id=108 x=346 y=99 width=14 height=56 xoffset=3 yoffset=12 xadvance=20 page=0 chnl=0
|
<char id="105" x="291" y="99" width="15" height="56" xoffset="2" yoffset="12" xadvance="19" page="0" chnl="0" />
|
||||||
char id=109 x=186 y=320 width=58 height=41 xoffset=2 yoffset=27 xadvance=63 page=0 chnl=0
|
<char id="106" x="197" y="0" width="23" height="71" xoffset="-5" yoffset="12" xadvance="20" page="0" chnl="0" />
|
||||||
char id=110 x=244 y=320 width=36 height=41 xoffset=2 yoffset=27 xadvance=40 page=0 chnl=0
|
<char id="107" x="306" y="99" width="40" height="56" xoffset="2" yoffset="12" xadvance="39" page="0" chnl="0" />
|
||||||
char id=111 x=111 y=320 width=39 height=42 xoffset=1 yoffset=27 xadvance=41 page=0 chnl=0
|
<char id="108" x="346" y="99" width="14" height="56" xoffset="3" yoffset="12" xadvance="20" page="0" chnl="0" />
|
||||||
char id=112 x=360 y=99 width=37 height=56 xoffset=2 yoffset=27 xadvance=40 page=0 chnl=0
|
<char id="109" x="186" y="320" width="58" height="41" xoffset="2" yoffset="27" xadvance="63" page="0" chnl="0" />
|
||||||
char id=113 x=397 y=99 width=37 height=56 xoffset=1 yoffset=27 xadvance=40 page=0 chnl=0
|
<char id="110" x="244" y="320" width="36" height="41" xoffset="2" yoffset="27" xadvance="40" page="0" chnl="0" />
|
||||||
char id=114 x=486 y=266 width=25 height=41 xoffset=2 yoffset=27 xadvance=27 page=0 chnl=0
|
<char id="111" x="111" y="320" width="39" height="42" xoffset="1" yoffset="27" xadvance="41" page="0" chnl="0" />
|
||||||
char id=115 x=150 y=320 width=36 height=42 xoffset=0 yoffset=27 xadvance=37 page=0 chnl=0
|
<char id="112" x="360" y="99" width="37" height="56" xoffset="2" yoffset="27" xadvance="40" page="0" chnl="0" />
|
||||||
char id=116 x=445 y=266 width=26 height=51 xoffset=0 yoffset=18 xadvance=25 page=0 chnl=0
|
<char id="113" x="397" y="99" width="37" height="56" xoffset="1" yoffset="27" xadvance="40" page="0" chnl="0" />
|
||||||
char id=117 x=280 y=320 width=36 height=41 xoffset=2 yoffset=28 xadvance=40 page=0 chnl=0
|
<char id="114" x="486" y="266" width="25" height="41" xoffset="2" yoffset="27" xadvance="27" page="0" chnl="0" />
|
||||||
char id=118 x=316 y=320 width=39 height=40 xoffset=-1 yoffset=28 xadvance=37 page=0 chnl=0
|
<char id="115" x="150" y="320" width="36" height="42" xoffset="0" yoffset="27" xadvance="37" page="0" chnl="0" />
|
||||||
char id=119 x=355 y=320 width=54 height=40 xoffset=-1 yoffset=28 xadvance=52 page=0 chnl=0
|
<char id="116" x="445" y="266" width="26" height="51" xoffset="0" yoffset="18" xadvance="25" page="0" chnl="0" />
|
||||||
char id=120 x=409 y=320 width=40 height=40 xoffset=-1 yoffset=28 xadvance=37 page=0 chnl=0
|
<char id="117" x="280" y="320" width="36" height="41" xoffset="2" yoffset="28" xadvance="40" page="0" chnl="0" />
|
||||||
char id=121 x=343 y=156 width=40 height=55 xoffset=-1 yoffset=28 xadvance=37 page=0 chnl=0
|
<char id="118" x="316" y="320" width="39" height="40" xoffset="-1" yoffset="28" xadvance="37" page="0" chnl="0" />
|
||||||
char id=122 x=449 y=320 width=34 height=40 xoffset=1 yoffset=28 xadvance=36 page=0 chnl=0
|
<char id="119" x="355" y="320" width="54" height="40" xoffset="-1" yoffset="28" xadvance="52" page="0" chnl="0" />
|
||||||
char id=123 x=151 y=0 width=23 height=72 xoffset=0 yoffset=9 xadvance=23 page=0 chnl=0
|
<char id="120" x="409" y="320" width="40" height="40" xoffset="-1" yoffset="28" xadvance="37" page="0" chnl="0" />
|
||||||
char id=124 x=366 y=0 width=8 height=63 xoffset=5 yoffset=14 xadvance=18 page=0 chnl=0
|
<char id="121" x="343" y="156" width="40" height="55" xoffset="-1" yoffset="28" xadvance="37" page="0" chnl="0" />
|
||||||
char id=125 x=174 y=0 width=23 height=72 xoffset=0 yoffset=9 xadvance=23 page=0 chnl=0
|
<char id="122" x="449" y="320" width="34" height="40" xoffset="1" yoffset="28" xadvance="36" page="0" chnl="0" />
|
||||||
char id=126 x=229 y=362 width=41 height=19 xoffset=2 yoffset=36 xadvance=45 page=0 chnl=0
|
<char id="123" x="151" y="0" width="23" height="72" xoffset="0" yoffset="9" xadvance="23" page="0" chnl="0" />
|
||||||
char id=127 x=0 y=0 width=70 height=99 xoffset=2 yoffset=-11 xadvance=74 page=0 chnl=0
|
<char id="124" x="366" y="0" width="8" height="63" xoffset="5" yoffset="14" xadvance="18" page="0" chnl="0" />
|
||||||
kernings count=385
|
<char id="125" x="174" y="0" width="23" height="72" xoffset="0" yoffset="9" xadvance="23" page="0" chnl="0" />
|
||||||
kerning first=84 second=74 amount=-8
|
<char id="126" x="229" y="362" width="41" height="19" xoffset="2" yoffset="36" xadvance="45" page="0" chnl="0" />
|
||||||
kerning first=86 second=100 amount=-2
|
<char id="127" x="0" y="0" width="70" height="99" xoffset="2" yoffset="-11" xadvance="74" page="0" chnl="0" />
|
||||||
kerning first=114 second=113 amount=-1
|
</chars>
|
||||||
kerning first=70 second=121 amount=-1
|
<kernings count="385">
|
||||||
kerning first=34 second=99 amount=-2
|
<kerning first="84" second="74" amount="-8" />
|
||||||
kerning first=70 second=99 amount=-1
|
<kerning first="86" second="100" amount="-2" />
|
||||||
kerning first=69 second=99 amount=-1
|
<kerning first="114" second="113" amount="-1" />
|
||||||
kerning first=88 second=113 amount=-1
|
<kerning first="70" second="121" amount="-1" />
|
||||||
kerning first=84 second=46 amount=-9
|
<kerning first="34" second="99" amount="-2" />
|
||||||
kerning first=87 second=97 amount=-1
|
<kerning first="70" second="99" amount="-1" />
|
||||||
kerning first=90 second=117 amount=-1
|
<kerning first="69" second="99" amount="-1" />
|
||||||
kerning first=39 second=97 amount=-2
|
<kerning first="88" second="113" amount="-1" />
|
||||||
kerning first=69 second=111 amount=-1
|
<kerning first="84" second="46" amount="-9" />
|
||||||
kerning first=87 second=41 amount=1
|
<kerning first="87" second="97" amount="-1" />
|
||||||
kerning first=121 second=34 amount=1
|
<kerning first="90" second="117" amount="-1" />
|
||||||
kerning first=40 second=86 amount=1
|
<kerning first="39" second="97" amount="-2" />
|
||||||
kerning first=85 second=65 amount=-1
|
<kerning first="69" second="111" amount="-1" />
|
||||||
kerning first=72 second=65 amount=1
|
<kerning first="87" second="41" amount="1" />
|
||||||
kerning first=114 second=102 amount=1
|
<kerning first="121" second="34" amount="1" />
|
||||||
kerning first=89 second=42 amount=-2
|
<kerning first="40" second="86" amount="1" />
|
||||||
kerning first=114 second=34 amount=1
|
<kerning first="85" second="65" amount="-1" />
|
||||||
kerning first=75 second=67 amount=-1
|
<kerning first="72" second="65" amount="1" />
|
||||||
kerning first=89 second=85 amount=-3
|
<kerning first="114" second="102" amount="1" />
|
||||||
kerning first=77 second=88 amount=1
|
<kerning first="89" second="42" amount="-2" />
|
||||||
kerning first=84 second=115 amount=-3
|
<kerning first="114" second="34" amount="1" />
|
||||||
kerning first=84 second=71 amount=-1
|
<kerning first="75" second="67" amount="-1" />
|
||||||
kerning first=89 second=101 amount=-2
|
<kerning first="89" second="85" amount="-3" />
|
||||||
kerning first=89 second=45 amount=-5
|
<kerning first="77" second="88" amount="1" />
|
||||||
kerning first=78 second=88 amount=1
|
<kerning first="84" second="115" amount="-3" />
|
||||||
kerning first=68 second=89 amount=-2
|
<kerning first="84" second="71" amount="-1" />
|
||||||
kerning first=122 second=103 amount=-1
|
<kerning first="89" second="101" amount="-2" />
|
||||||
kerning first=78 second=84 amount=-1
|
<kerning first="89" second="45" amount="-5" />
|
||||||
kerning first=86 second=103 amount=-2
|
<kerning first="78" second="88" amount="1" />
|
||||||
kerning first=89 second=79 amount=-1
|
<kerning first="68" second="89" amount="-2" />
|
||||||
kerning first=75 second=111 amount=-1
|
<kerning first="122" second="103" amount="-1" />
|
||||||
kerning first=111 second=120 amount=-1
|
<kerning first="78" second="84" amount="-1" />
|
||||||
kerning first=87 second=44 amount=-5
|
<kerning first="86" second="103" amount="-2" />
|
||||||
kerning first=67 second=84 amount=-1
|
<kerning first="89" second="79" amount="-1" />
|
||||||
kerning first=84 second=111 amount=-7
|
<kerning first="75" second="111" amount="-1" />
|
||||||
kerning first=84 second=83 amount=-1
|
<kerning first="111" second="120" amount="-1" />
|
||||||
kerning first=102 second=113 amount=-1
|
<kerning first="87" second="44" amount="-5" />
|
||||||
kerning first=39 second=101 amount=-2
|
<kerning first="67" second="84" amount="-1" />
|
||||||
kerning first=80 second=88 amount=-2
|
<kerning first="84" second="111" amount="-7" />
|
||||||
kerning first=66 second=84 amount=-1
|
<kerning first="84" second="83" amount="-1" />
|
||||||
kerning first=65 second=87 amount=-1
|
<kerning first="102" second="113" amount="-1" />
|
||||||
kerning first=122 second=100 amount=-1
|
<kerning first="39" second="101" amount="-2" />
|
||||||
kerning first=75 second=118 amount=-1
|
<kerning first="80" second="88" amount="-2" />
|
||||||
kerning first=73 second=65 amount=1
|
<kerning first="66" second="84" amount="-1" />
|
||||||
kerning first=70 second=118 amount=-1
|
<kerning first="65" second="87" amount="-1" />
|
||||||
kerning first=73 second=88 amount=1
|
<kerning first="122" second="100" amount="-1" />
|
||||||
kerning first=82 second=89 amount=-2
|
<kerning first="75" second="118" amount="-1" />
|
||||||
kerning first=65 second=34 amount=-4
|
<kerning first="73" second="65" amount="1" />
|
||||||
kerning first=120 second=99 amount=-1
|
<kerning first="70" second="118" amount="-1" />
|
||||||
kerning first=84 second=99 amount=-3
|
<kerning first="73" second="88" amount="1" />
|
||||||
kerning first=84 second=65 amount=-4
|
<kerning first="82" second="89" amount="-2" />
|
||||||
kerning first=112 second=39 amount=-1
|
<kerning first="65" second="34" amount="-4" />
|
||||||
kerning first=76 second=39 amount=-10
|
<kerning first="120" second="99" amount="-1" />
|
||||||
kerning first=78 second=65 amount=1
|
<kerning first="84" second="99" amount="-3" />
|
||||||
kerning first=88 second=45 amount=-5
|
<kerning first="84" second="65" amount="-4" />
|
||||||
kerning first=34 second=111 amount=-3
|
<kerning first="112" second="39" amount="-1" />
|
||||||
kerning first=114 second=99 amount=-1
|
<kerning first="76" second="39" amount="-10" />
|
||||||
kerning first=86 second=125 amount=1
|
<kerning first="78" second="65" amount="1" />
|
||||||
kerning first=70 second=111 amount=-1
|
<kerning first="88" second="45" amount="-5" />
|
||||||
kerning first=89 second=120 amount=-1
|
<kerning first="34" second="111" amount="-3" />
|
||||||
kerning first=90 second=119 amount=-1
|
<kerning first="114" second="99" amount="-1" />
|
||||||
kerning first=89 second=89 amount=1
|
<kerning first="86" second="125" amount="1" />
|
||||||
kerning first=89 second=117 amount=-1
|
<kerning first="70" second="111" amount="-1" />
|
||||||
kerning first=75 second=117 amount=-1
|
<kerning first="89" second="120" amount="-1" />
|
||||||
kerning first=76 second=65 amount=1
|
<kerning first="90" second="119" amount="-1" />
|
||||||
kerning first=34 second=34 amount=-1
|
<kerning first="89" second="89" amount="1" />
|
||||||
kerning first=89 second=110 amount=-1
|
<kerning first="89" second="117" amount="-1" />
|
||||||
kerning first=88 second=101 amount=-1
|
<kerning first="75" second="117" amount="-1" />
|
||||||
kerning first=107 second=103 amount=-1
|
<kerning first="76" second="65" amount="1" />
|
||||||
kerning first=34 second=115 amount=-3
|
<kerning first="34" second="34" amount="-1" />
|
||||||
kerning first=80 second=44 amount=-14
|
<kerning first="89" second="110" amount="-1" />
|
||||||
kerning first=98 second=39 amount=-1
|
<kerning first="88" second="101" amount="-1" />
|
||||||
kerning first=70 second=65 amount=-7
|
<kerning first="107" second="103" amount="-1" />
|
||||||
kerning first=89 second=116 amount=-1
|
<kerning first="34" second="115" amount="-3" />
|
||||||
kerning first=70 second=46 amount=-10
|
<kerning first="80" second="44" amount="-14" />
|
||||||
kerning first=98 second=34 amount=-1
|
<kerning first="98" second="39" amount="-1" />
|
||||||
kerning first=70 second=84 amount=1
|
<kerning first="70" second="65" amount="-7" />
|
||||||
kerning first=114 second=100 amount=-1
|
<kerning first="89" second="116" amount="-1" />
|
||||||
kerning first=88 second=79 amount=-1
|
<kerning first="70" second="46" amount="-10" />
|
||||||
kerning first=39 second=113 amount=-2
|
<kerning first="98" second="34" amount="-1" />
|
||||||
kerning first=65 second=118 amount=-2
|
<kerning first="70" second="84" amount="1" />
|
||||||
kerning first=114 second=103 amount=-1
|
<kerning first="114" second="100" amount="-1" />
|
||||||
kerning first=77 second=65 amount=1
|
<kerning first="88" second="79" amount="-1" />
|
||||||
kerning first=120 second=103 amount=-1
|
<kerning first="39" second="113" amount="-2" />
|
||||||
kerning first=65 second=110 amount=-2
|
<kerning first="65" second="118" amount="-2" />
|
||||||
kerning first=114 second=121 amount=1
|
<kerning first="114" second="103" amount="-1" />
|
||||||
kerning first=89 second=100 amount=-2
|
<kerning first="77" second="65" amount="1" />
|
||||||
kerning first=80 second=65 amount=-6
|
<kerning first="120" second="103" amount="-1" />
|
||||||
kerning first=121 second=111 amount=-1
|
<kerning first="65" second="110" amount="-2" />
|
||||||
kerning first=34 second=101 amount=-2
|
<kerning first="114" second="121" amount="1" />
|
||||||
kerning first=122 second=111 amount=-1
|
<kerning first="89" second="100" amount="-2" />
|
||||||
kerning first=114 second=118 amount=1
|
<kerning first="80" second="65" amount="-6" />
|
||||||
kerning first=102 second=41 amount=1
|
<kerning first="121" second="111" amount="-1" />
|
||||||
kerning first=122 second=113 amount=-1
|
<kerning first="34" second="101" amount="-2" />
|
||||||
kerning first=89 second=122 amount=-1
|
<kerning first="122" second="111" amount="-1" />
|
||||||
kerning first=68 second=88 amount=-1
|
<kerning first="114" second="118" amount="1" />
|
||||||
kerning first=81 second=89 amount=-1
|
<kerning first="102" second="41" amount="1" />
|
||||||
kerning first=114 second=111 amount=-1
|
<kerning first="122" second="113" amount="-1" />
|
||||||
kerning first=46 second=34 amount=-10
|
<kerning first="89" second="122" amount="-1" />
|
||||||
kerning first=84 second=112 amount=-3
|
<kerning first="68" second="88" amount="-1" />
|
||||||
kerning first=76 second=34 amount=-10
|
<kerning first="81" second="89" amount="-1" />
|
||||||
kerning first=39 second=115 amount=-3
|
<kerning first="114" second="111" amount="-1" />
|
||||||
kerning first=76 second=118 amount=-4
|
<kerning first="46" second="34" amount="-10" />
|
||||||
kerning first=86 second=99 amount=-2
|
<kerning first="84" second="112" amount="-3" />
|
||||||
kerning first=84 second=84 amount=1
|
<kerning first="76" second="34" amount="-10" />
|
||||||
kerning first=120 second=111 amount=-1
|
<kerning first="39" second="115" amount="-3" />
|
||||||
kerning first=65 second=79 amount=-1
|
<kerning first="76" second="118" amount="-4" />
|
||||||
kerning first=87 second=101 amount=-1
|
<kerning first="86" second="99" amount="-2" />
|
||||||
kerning first=67 second=125 amount=-1
|
<kerning first="84" second="84" amount="1" />
|
||||||
kerning first=120 second=113 amount=-1
|
<kerning first="120" second="111" amount="-1" />
|
||||||
kerning first=118 second=46 amount=-6
|
<kerning first="65" second="79" amount="-1" />
|
||||||
kerning first=88 second=103 amount=-1
|
<kerning first="87" second="101" amount="-1" />
|
||||||
kerning first=111 second=122 amount=-1
|
<kerning first="67" second="125" amount="-1" />
|
||||||
kerning first=77 second=84 amount=-1
|
<kerning first="120" second="113" amount="-1" />
|
||||||
kerning first=114 second=46 amount=-6
|
<kerning first="118" second="46" amount="-6" />
|
||||||
kerning first=34 second=39 amount=-1
|
<kerning first="88" second="103" amount="-1" />
|
||||||
kerning first=65 second=121 amount=-2
|
<kerning first="111" second="122" amount="-1" />
|
||||||
kerning first=114 second=44 amount=-6
|
<kerning first="77" second="84" amount="-1" />
|
||||||
kerning first=69 second=84 amount=1
|
<kerning first="114" second="46" amount="-6" />
|
||||||
kerning first=89 second=46 amount=-8
|
<kerning first="34" second="39" amount="-1" />
|
||||||
kerning first=97 second=39 amount=-1
|
<kerning first="65" second="121" amount="-2" />
|
||||||
kerning first=34 second=100 amount=-2
|
<kerning first="114" second="44" amount="-6" />
|
||||||
kerning first=70 second=100 amount=-1
|
<kerning first="69" second="84" amount="1" />
|
||||||
kerning first=84 second=120 amount=-3
|
<kerning first="89" second="46" amount="-8" />
|
||||||
kerning first=90 second=118 amount=-1
|
<kerning first="97" second="39" amount="-1" />
|
||||||
kerning first=70 second=114 amount=-1
|
<kerning first="34" second="100" amount="-2" />
|
||||||
kerning first=34 second=112 amount=-1
|
<kerning first="70" second="100" amount="-1" />
|
||||||
kerning first=89 second=86 amount=1
|
<kerning first="84" second="120" amount="-3" />
|
||||||
kerning first=86 second=113 amount=-2
|
<kerning first="90" second="118" amount="-1" />
|
||||||
kerning first=88 second=71 amount=-1
|
<kerning first="70" second="114" amount="-1" />
|
||||||
kerning first=122 second=99 amount=-1
|
<kerning first="34" second="112" amount="-1" />
|
||||||
kerning first=66 second=89 amount=-2
|
<kerning first="89" second="86" amount="1" />
|
||||||
kerning first=102 second=103 amount=-1
|
<kerning first="86" second="113" amount="-2" />
|
||||||
kerning first=88 second=67 amount=-1
|
<kerning first="88" second="71" amount="-1" />
|
||||||
kerning first=39 second=110 amount=-1
|
<kerning first="122" second="99" amount="-1" />
|
||||||
kerning first=88 second=117 amount=-1
|
<kerning first="66" second="89" amount="-2" />
|
||||||
kerning first=89 second=118 amount=-1
|
<kerning first="102" second="103" amount="-1" />
|
||||||
kerning first=97 second=118 amount=-1
|
<kerning first="88" second="67" amount="-1" />
|
||||||
kerning first=87 second=65 amount=-2
|
<kerning first="39" second="110" amount="-1" />
|
||||||
kerning first=89 second=67 amount=-1
|
<kerning first="88" second="117" amount="-1" />
|
||||||
kerning first=89 second=74 amount=-3
|
<kerning first="89" second="118" amount="-1" />
|
||||||
kerning first=102 second=101 amount=-1
|
<kerning first="97" second="118" amount="-1" />
|
||||||
kerning first=86 second=111 amount=-2
|
<kerning first="87" second="65" amount="-2" />
|
||||||
kerning first=65 second=119 amount=-1
|
<kerning first="89" second="67" amount="-1" />
|
||||||
kerning first=84 second=100 amount=-3
|
<kerning first="89" second="74" amount="-3" />
|
||||||
kerning first=120 second=100 amount=-1
|
<kerning first="102" second="101" amount="-1" />
|
||||||
kerning first=104 second=34 amount=-3
|
<kerning first="86" second="111" amount="-2" />
|
||||||
kerning first=86 second=41 amount=1
|
<kerning first="65" second="119" amount="-1" />
|
||||||
kerning first=111 second=34 amount=-3
|
<kerning first="84" second="100" amount="-3" />
|
||||||
kerning first=40 second=89 amount=1
|
<kerning first="120" second="100" amount="-1" />
|
||||||
kerning first=121 second=39 amount=1
|
<kerning first="104" second="34" amount="-3" />
|
||||||
kerning first=70 second=74 amount=-7
|
<kerning first="86" second="41" amount="1" />
|
||||||
kerning first=68 second=90 amount=-1
|
<kerning first="111" second="34" amount="-3" />
|
||||||
kerning first=98 second=120 amount=-1
|
<kerning first="40" second="89" amount="1" />
|
||||||
kerning first=110 second=34 amount=-3
|
<kerning first="121" second="39" amount="1" />
|
||||||
kerning first=119 second=46 amount=-4
|
<kerning first="70" second="74" amount="-7" />
|
||||||
kerning first=69 second=102 amount=-1
|
<kerning first="68" second="90" amount="-1" />
|
||||||
kerning first=118 second=44 amount=-6
|
<kerning first="98" second="120" amount="-1" />
|
||||||
kerning first=84 second=114 amount=-2
|
<kerning first="110" second="34" amount="-3" />
|
||||||
kerning first=86 second=97 amount=-2
|
<kerning first="119" second="46" amount="-4" />
|
||||||
kerning first=40 second=87 amount=1
|
<kerning first="69" second="102" amount="-1" />
|
||||||
kerning first=65 second=109 amount=-2
|
<kerning first="118" second="44" amount="-6" />
|
||||||
kerning first=68 second=86 amount=-1
|
<kerning first="84" second="114" amount="-2" />
|
||||||
kerning first=86 second=93 amount=1
|
<kerning first="86" second="97" amount="-2" />
|
||||||
kerning first=65 second=67 amount=-1
|
<kerning first="40" second="87" amount="1" />
|
||||||
kerning first=97 second=34 amount=-1
|
<kerning first="65" second="109" amount="-2" />
|
||||||
kerning first=34 second=65 amount=-4
|
<kerning first="68" second="86" amount="-1" />
|
||||||
kerning first=84 second=118 amount=-3
|
<kerning first="86" second="93" amount="1" />
|
||||||
kerning first=112 second=34 amount=-1
|
<kerning first="65" second="67" amount="-1" />
|
||||||
kerning first=76 second=84 amount=-7
|
<kerning first="97" second="34" amount="-1" />
|
||||||
kerning first=107 second=99 amount=-1
|
<kerning first="34" second="65" amount="-4" />
|
||||||
kerning first=123 second=85 amount=-1
|
<kerning first="84" second="118" amount="-3" />
|
||||||
kerning first=102 second=125 amount=1
|
<kerning first="112" second="34" amount="-1" />
|
||||||
kerning first=65 second=63 amount=-3
|
<kerning first="76" second="84" amount="-7" />
|
||||||
kerning first=89 second=44 amount=-8
|
<kerning first="107" second="99" amount="-1" />
|
||||||
kerning first=80 second=118 amount=1
|
<kerning first="123" second="85" amount="-1" />
|
||||||
kerning first=112 second=122 amount=-1
|
<kerning first="102" second="125" amount="1" />
|
||||||
kerning first=79 second=65 amount=-1
|
<kerning first="65" second="63" amount="-3" />
|
||||||
kerning first=80 second=121 amount=1
|
<kerning first="89" second="44" amount="-8" />
|
||||||
kerning first=118 second=34 amount=1
|
<kerning first="80" second="118" amount="1" />
|
||||||
kerning first=87 second=45 amount=-2
|
<kerning first="112" second="122" amount="-1" />
|
||||||
kerning first=69 second=100 amount=-1
|
<kerning first="79" second="65" amount="-1" />
|
||||||
kerning first=87 second=103 amount=-1
|
<kerning first="80" second="121" amount="1" />
|
||||||
kerning first=112 second=120 amount=-1
|
<kerning first="118" second="34" amount="1" />
|
||||||
kerning first=86 second=65 amount=-3
|
<kerning first="87" second="45" amount="-2" />
|
||||||
kerning first=65 second=81 amount=-1
|
<kerning first="69" second="100" amount="-1" />
|
||||||
kerning first=68 second=44 amount=-4
|
<kerning first="87" second="103" amount="-1" />
|
||||||
kerning first=86 second=45 amount=-6
|
<kerning first="112" second="120" amount="-1" />
|
||||||
kerning first=39 second=34 amount=-1
|
<kerning first="86" second="65" amount="-3" />
|
||||||
kerning first=72 second=88 amount=1
|
<kerning first="65" second="81" amount="-1" />
|
||||||
kerning first=68 second=46 amount=-4
|
<kerning first="68" second="44" amount="-4" />
|
||||||
kerning first=65 second=89 amount=-5
|
<kerning first="86" second="45" amount="-6" />
|
||||||
kerning first=69 second=118 amount=-1
|
<kerning first="39" second="34" amount="-1" />
|
||||||
kerning first=89 second=38 amount=-1
|
<kerning first="72" second="88" amount="1" />
|
||||||
kerning first=88 second=99 amount=-1
|
<kerning first="68" second="46" amount="-4" />
|
||||||
kerning first=65 second=71 amount=-1
|
<kerning first="65" second="89" amount="-5" />
|
||||||
kerning first=91 second=74 amount=-1
|
<kerning first="69" second="118" amount="-1" />
|
||||||
kerning first=75 second=101 amount=-1
|
<kerning first="89" second="38" amount="-1" />
|
||||||
kerning first=39 second=112 amount=-1
|
<kerning first="88" second="99" amount="-1" />
|
||||||
kerning first=70 second=113 amount=-1
|
<kerning first="65" second="71" amount="-1" />
|
||||||
kerning first=119 second=44 amount=-4
|
<kerning first="91" second="74" amount="-1" />
|
||||||
kerning first=72 second=89 amount=-1
|
<kerning first="75" second="101" amount="-1" />
|
||||||
kerning first=90 second=103 amount=-1
|
<kerning first="39" second="112" amount="-1" />
|
||||||
kerning first=65 second=86 amount=-3
|
<kerning first="70" second="113" amount="-1" />
|
||||||
kerning first=84 second=119 amount=-2
|
<kerning first="119" second="44" amount="-4" />
|
||||||
kerning first=34 second=110 amount=-1
|
<kerning first="72" second="89" amount="-1" />
|
||||||
kerning first=39 second=109 amount=-1
|
<kerning first="90" second="103" amount="-1" />
|
||||||
kerning first=75 second=81 amount=-1
|
<kerning first="65" second="86" amount="-3" />
|
||||||
kerning first=89 second=115 amount=-2
|
<kerning first="84" second="119" amount="-2" />
|
||||||
kerning first=89 second=87 amount=1
|
<kerning first="34" second="110" amount="-1" />
|
||||||
kerning first=114 second=101 amount=-1
|
<kerning first="39" second="109" amount="-1" />
|
||||||
kerning first=116 second=111 amount=-1
|
<kerning first="75" second="81" amount="-1" />
|
||||||
kerning first=90 second=100 amount=-1
|
<kerning first="89" second="115" amount="-2" />
|
||||||
kerning first=79 second=89 amount=-2
|
<kerning first="89" second="87" amount="1" />
|
||||||
kerning first=84 second=122 amount=-2
|
<kerning first="114" second="101" amount="-1" />
|
||||||
kerning first=68 second=84 amount=-3
|
<kerning first="116" second="111" amount="-1" />
|
||||||
kerning first=76 second=86 amount=-7
|
<kerning first="90" second="100" amount="-1" />
|
||||||
kerning first=74 second=65 amount=-1
|
<kerning first="79" second="89" amount="-2" />
|
||||||
kerning first=107 second=101 amount=-1
|
<kerning first="84" second="122" amount="-2" />
|
||||||
kerning first=80 second=46 amount=-14
|
<kerning first="68" second="84" amount="-3" />
|
||||||
kerning first=89 second=93 amount=1
|
<kerning first="76" second="86" amount="-7" />
|
||||||
kerning first=89 second=65 amount=-5
|
<kerning first="74" second="65" amount="-1" />
|
||||||
kerning first=87 second=117 amount=-1
|
<kerning first="107" second="101" amount="-1" />
|
||||||
kerning first=89 second=81 amount=-1
|
<kerning first="80" second="46" amount="-14" />
|
||||||
kerning first=39 second=103 amount=-2
|
<kerning first="89" second="93" amount="1" />
|
||||||
kerning first=86 second=101 amount=-2
|
<kerning first="89" second="65" amount="-5" />
|
||||||
kerning first=86 second=117 amount=-1
|
<kerning first="87" second="117" amount="-1" />
|
||||||
kerning first=84 second=113 amount=-3
|
<kerning first="89" second="81" amount="-1" />
|
||||||
kerning first=87 second=46 amount=-5
|
<kerning first="39" second="103" amount="-2" />
|
||||||
kerning first=47 second=47 amount=-9
|
<kerning first="86" second="101" amount="-2" />
|
||||||
kerning first=75 second=103 amount=-1
|
<kerning first="86" second="117" amount="-1" />
|
||||||
kerning first=89 second=84 amount=1
|
<kerning first="84" second="113" amount="-3" />
|
||||||
kerning first=84 second=110 amount=-3
|
<kerning first="87" second="46" amount="-5" />
|
||||||
kerning first=39 second=99 amount=-2
|
<kerning first="47" second="47" amount="-9" />
|
||||||
kerning first=88 second=121 amount=-1
|
<kerning first="75" second="103" amount="-1" />
|
||||||
kerning first=65 second=39 amount=-4
|
<kerning first="89" second="84" amount="1" />
|
||||||
kerning first=110 second=39 amount=-3
|
<kerning first="84" second="110" amount="-3" />
|
||||||
kerning first=88 second=118 amount=-1
|
<kerning first="39" second="99" amount="-2" />
|
||||||
kerning first=86 second=114 amount=-1
|
<kerning first="88" second="121" amount="-1" />
|
||||||
kerning first=80 second=74 amount=-6
|
<kerning first="65" second="39" amount="-4" />
|
||||||
kerning first=84 second=97 amount=-6
|
<kerning first="110" second="39" amount="-3" />
|
||||||
kerning first=82 second=84 amount=-2
|
<kerning first="88" second="118" amount="-1" />
|
||||||
kerning first=91 second=85 amount=-1
|
<kerning first="86" second="114" amount="-1" />
|
||||||
kerning first=102 second=99 amount=-1
|
<kerning first="80" second="74" amount="-6" />
|
||||||
kerning first=66 second=86 amount=-1
|
<kerning first="84" second="97" amount="-6" />
|
||||||
kerning first=120 second=101 amount=-1
|
<kerning first="82" second="84" amount="-2" />
|
||||||
kerning first=102 second=93 amount=1
|
<kerning first="91" second="85" amount="-1" />
|
||||||
kerning first=75 second=100 amount=-1
|
<kerning first="102" second="99" amount="-1" />
|
||||||
kerning first=84 second=79 amount=-1
|
<kerning first="66" second="86" amount="-1" />
|
||||||
kerning first=44 second=39 amount=-10
|
<kerning first="120" second="101" amount="-1" />
|
||||||
kerning first=111 second=121 amount=-1
|
<kerning first="102" second="93" amount="1" />
|
||||||
kerning first=75 second=121 amount=-1
|
<kerning first="75" second="100" amount="-1" />
|
||||||
kerning first=81 second=87 amount=-1
|
<kerning first="84" second="79" amount="-1" />
|
||||||
kerning first=107 second=113 amount=-1
|
<kerning first="44" second="39" amount="-10" />
|
||||||
kerning first=90 second=79 amount=-1
|
<kerning first="111" second="121" amount="-1" />
|
||||||
kerning first=89 second=114 amount=-1
|
<kerning first="75" second="121" amount="-1" />
|
||||||
kerning first=122 second=101 amount=-1
|
<kerning first="81" second="87" amount="-1" />
|
||||||
kerning first=111 second=118 amount=-1
|
<kerning first="107" second="113" amount="-1" />
|
||||||
kerning first=82 second=86 amount=-1
|
<kerning first="90" second="79" amount="-1" />
|
||||||
kerning first=70 second=101 amount=-1
|
<kerning first="89" second="114" amount="-1" />
|
||||||
kerning first=114 second=97 amount=-1
|
<kerning first="122" second="101" amount="-1" />
|
||||||
kerning first=70 second=97 amount=-1
|
<kerning first="111" second="118" amount="-1" />
|
||||||
kerning first=34 second=97 amount=-2
|
<kerning first="82" second="86" amount="-1" />
|
||||||
kerning first=89 second=102 amount=-1
|
<kerning first="70" second="101" amount="-1" />
|
||||||
kerning first=78 second=89 amount=-1
|
<kerning first="114" second="97" amount="-1" />
|
||||||
kerning first=70 second=44 amount=-10
|
<kerning first="70" second="97" amount="-1" />
|
||||||
kerning first=104 second=39 amount=-3
|
<kerning first="34" second="97" amount="-2" />
|
||||||
kerning first=84 second=45 amount=-10
|
<kerning first="89" second="102" amount="-1" />
|
||||||
kerning first=89 second=121 amount=-1
|
<kerning first="78" second="89" amount="-1" />
|
||||||
kerning first=109 second=34 amount=-3
|
<kerning first="70" second="44" amount="-10" />
|
||||||
kerning first=84 second=86 amount=1
|
<kerning first="104" second="39" amount="-3" />
|
||||||
kerning first=87 second=99 amount=-1
|
<kerning first="84" second="45" amount="-10" />
|
||||||
kerning first=32 second=84 amount=-2
|
<kerning first="89" second="121" amount="-1" />
|
||||||
kerning first=98 second=122 amount=-1
|
<kerning first="109" second="34" amount="-3" />
|
||||||
kerning first=89 second=112 amount=-1
|
<kerning first="84" second="86" amount="1" />
|
||||||
kerning first=89 second=103 amount=-2
|
<kerning first="87" second="99" amount="-1" />
|
||||||
kerning first=65 second=116 amount=-1
|
<kerning first="32" second="84" amount="-2" />
|
||||||
kerning first=88 second=81 amount=-1
|
<kerning first="98" second="122" amount="-1" />
|
||||||
kerning first=102 second=34 amount=1
|
<kerning first="89" second="112" amount="-1" />
|
||||||
kerning first=109 second=39 amount=-3
|
<kerning first="89" second="103" amount="-2" />
|
||||||
kerning first=81 second=84 amount=-1
|
<kerning first="65" second="116" amount="-1" />
|
||||||
kerning first=121 second=97 amount=-1
|
<kerning first="88" second="81" amount="-1" />
|
||||||
kerning first=89 second=99 amount=-2
|
<kerning first="102" second="34" amount="1" />
|
||||||
kerning first=89 second=125 amount=1
|
<kerning first="109" second="39" amount="-3" />
|
||||||
kerning first=81 second=86 amount=-1
|
<kerning first="81" second="84" amount="-1" />
|
||||||
kerning first=114 second=116 amount=2
|
<kerning first="121" second="97" amount="-1" />
|
||||||
kerning first=114 second=119 amount=1
|
<kerning first="89" second="99" amount="-2" />
|
||||||
kerning first=84 second=44 amount=-9
|
<kerning first="89" second="125" amount="1" />
|
||||||
kerning first=102 second=39 amount=1
|
<kerning first="81" second="86" amount="-1" />
|
||||||
kerning first=44 second=34 amount=-10
|
<kerning first="114" second="116" amount="2" />
|
||||||
kerning first=34 second=109 amount=-1
|
<kerning first="114" second="119" amount="1" />
|
||||||
kerning first=84 second=101 amount=-3
|
<kerning first="84" second="44" amount="-9" />
|
||||||
kerning first=75 second=119 amount=-2
|
<kerning first="102" second="39" amount="1" />
|
||||||
kerning first=84 second=81 amount=-1
|
<kerning first="44" second="34" amount="-10" />
|
||||||
kerning first=76 second=121 amount=-4
|
<kerning first="34" second="109" amount="-1" />
|
||||||
kerning first=69 second=101 amount=-1
|
<kerning first="84" second="101" amount="-3" />
|
||||||
kerning first=80 second=90 amount=-1
|
<kerning first="75" second="119" amount="-2" />
|
||||||
kerning first=89 second=97 amount=-2
|
<kerning first="84" second="81" amount="-1" />
|
||||||
kerning first=89 second=109 amount=-1
|
<kerning first="76" second="121" amount="-4" />
|
||||||
kerning first=90 second=99 amount=-1
|
<kerning first="69" second="101" amount="-1" />
|
||||||
kerning first=79 second=88 amount=-1
|
<kerning first="80" second="90" amount="-1" />
|
||||||
kerning first=70 second=103 amount=-1
|
<kerning first="89" second="97" amount="-2" />
|
||||||
kerning first=34 second=103 amount=-2
|
<kerning first="89" second="109" amount="-1" />
|
||||||
kerning first=84 second=67 amount=-1
|
<kerning first="90" second="99" amount="-1" />
|
||||||
kerning first=76 second=79 amount=-2
|
<kerning first="79" second="88" amount="-1" />
|
||||||
kerning first=34 second=113 amount=-2
|
<kerning first="70" second="103" amount="-1" />
|
||||||
kerning first=89 second=41 amount=1
|
<kerning first="34" second="103" amount="-2" />
|
||||||
kerning first=75 second=71 amount=-1
|
<kerning first="84" second="67" amount="-1" />
|
||||||
kerning first=76 second=87 amount=-3
|
<kerning first="76" second="79" amount="-2" />
|
||||||
kerning first=77 second=89 amount=-1
|
<kerning first="34" second="113" amount="-2" />
|
||||||
kerning first=90 second=113 amount=-1
|
<kerning first="89" second="41" amount="1" />
|
||||||
kerning first=118 second=111 amount=-1
|
<kerning first="75" second="71" amount="-1" />
|
||||||
kerning first=118 second=97 amount=-1
|
<kerning first="76" second="87" amount="-3" />
|
||||||
kerning first=88 second=100 amount=-1
|
<kerning first="77" second="89" amount="-1" />
|
||||||
kerning first=89 second=111 amount=-2
|
<kerning first="90" second="113" amount="-1" />
|
||||||
kerning first=90 second=121 amount=-1
|
<kerning first="118" second="111" amount="-1" />
|
||||||
kerning first=89 second=113 amount=-2
|
<kerning first="118" second="97" amount="-1" />
|
||||||
kerning first=84 second=87 amount=1
|
<kerning first="88" second="100" amount="-1" />
|
||||||
kerning first=39 second=111 amount=-3
|
<kerning first="89" second="111" amount="-2" />
|
||||||
kerning first=39 second=100 amount=-2
|
<kerning first="90" second="121" amount="-1" />
|
||||||
kerning first=75 second=113 amount=-1
|
<kerning first="89" second="113" amount="-2" />
|
||||||
kerning first=88 second=111 amount=-1
|
<kerning first="84" second="87" amount="1" />
|
||||||
kerning first=87 second=111 amount=-1
|
<kerning first="39" second="111" amount="-3" />
|
||||||
kerning first=89 second=83 amount=-1
|
<kerning first="39" second="100" amount="-2" />
|
||||||
kerning first=84 second=89 amount=1
|
<kerning first="75" second="113" amount="-1" />
|
||||||
kerning first=84 second=103 amount=-3
|
<kerning first="88" second="111" amount="-1" />
|
||||||
kerning first=70 second=117 amount=-1
|
<kerning first="87" second="111" amount="-1" />
|
||||||
kerning first=67 second=41 amount=-1
|
<kerning first="89" second="83" amount="-1" />
|
||||||
kerning first=89 second=71 amount=-1
|
<kerning first="84" second="89" amount="1" />
|
||||||
kerning first=121 second=44 amount=-6
|
<kerning first="84" second="103" amount="-3" />
|
||||||
kerning first=97 second=121 amount=-1
|
<kerning first="70" second="117" amount="-1" />
|
||||||
kerning first=87 second=113 amount=-1
|
<kerning first="67" second="41" amount="-1" />
|
||||||
kerning first=73 second=84 amount=-1
|
<kerning first="89" second="71" amount="-1" />
|
||||||
kerning first=121 second=46 amount=-6
|
<kerning first="121" second="44" amount="-6" />
|
||||||
kerning first=75 second=99 amount=-1
|
<kerning first="97" second="121" amount="-1" />
|
||||||
kerning first=65 second=112 amount=-2
|
<kerning first="87" second="113" amount="-1" />
|
||||||
kerning first=65 second=85 amount=-1
|
<kerning first="73" second="84" amount="-1" />
|
||||||
kerning first=76 second=67 amount=-2
|
<kerning first="121" second="46" amount="-6" />
|
||||||
kerning first=76 second=81 amount=-2
|
<kerning first="75" second="99" amount="-1" />
|
||||||
kerning first=102 second=100 amount=-1
|
<kerning first="65" second="112" amount="-2" />
|
||||||
kerning first=75 second=79 amount=-1
|
<kerning first="65" second="85" amount="-1" />
|
||||||
kerning first=39 second=65 amount=-4
|
<kerning first="76" second="67" amount="-2" />
|
||||||
kerning first=65 second=84 amount=-4
|
<kerning first="76" second="81" amount="-2" />
|
||||||
kerning first=90 second=101 amount=-1
|
<kerning first="102" second="100" amount="-1" />
|
||||||
kerning first=84 second=121 amount=-3
|
<kerning first="75" second="79" amount="-1" />
|
||||||
kerning first=114 second=39 amount=1
|
<kerning first="39" second="65" amount="-4" />
|
||||||
kerning first=84 second=109 amount=-3
|
<kerning first="65" second="84" amount="-4" />
|
||||||
kerning first=123 second=74 amount=-1
|
<kerning first="90" second="101" amount="-1" />
|
||||||
kerning first=76 second=119 amount=-2
|
<kerning first="84" second="121" amount="-3" />
|
||||||
kerning first=84 second=117 amount=-2
|
<kerning first="114" second="39" amount="1" />
|
||||||
kerning first=76 second=85 amount=-1
|
<kerning first="84" second="109" amount="-3" />
|
||||||
kerning first=76 second=71 amount=-2
|
<kerning first="123" second="74" amount="-1" />
|
||||||
kerning first=79 second=90 amount=-1
|
<kerning first="76" second="119" amount="-2" />
|
||||||
kerning first=107 second=100 amount=-1
|
<kerning first="84" second="117" amount="-2" />
|
||||||
kerning first=90 second=111 amount=-1
|
<kerning first="76" second="85" amount="-1" />
|
||||||
kerning first=79 second=44 amount=-4
|
<kerning first="76" second="71" amount="-2" />
|
||||||
kerning first=75 second=45 amount=-6
|
<kerning first="79" second="90" amount="-1" />
|
||||||
kerning first=79 second=86 amount=-1
|
<kerning first="107" second="100" amount="-1" />
|
||||||
kerning first=79 second=46 amount=-4
|
<kerning first="90" second="111" amount="-1" />
|
||||||
kerning first=76 second=89 amount=-10
|
<kerning first="79" second="44" amount="-4" />
|
||||||
kerning first=68 second=65 amount=-1
|
<kerning first="75" second="45" amount="-6" />
|
||||||
kerning first=79 second=84 amount=-3
|
<kerning first="79" second="86" amount="-1" />
|
||||||
kerning first=87 second=100 amount=-1
|
<kerning first="79" second="46" amount="-4" />
|
||||||
kerning first=84 second=32 amount=-2
|
<kerning first="76" second="89" amount="-10" />
|
||||||
kerning first=90 second=67 amount=-1
|
<kerning first="68" second="65" amount="-1" />
|
||||||
kerning first=69 second=103 amount=-1
|
<kerning first="79" second="84" amount="-3" />
|
||||||
kerning first=90 second=71 amount=-1
|
<kerning first="87" second="100" amount="-1" />
|
||||||
kerning first=86 second=44 amount=-8
|
<kerning first="84" second="32" amount="-2" />
|
||||||
kerning first=69 second=121 amount=-1
|
<kerning first="90" second="67" amount="-1" />
|
||||||
kerning first=87 second=114 amount=-1
|
<kerning first="69" second="103" amount="-1" />
|
||||||
kerning first=118 second=39 amount=1
|
<kerning first="90" second="71" amount="-1" />
|
||||||
kerning first=46 second=39 amount=-10
|
<kerning first="86" second="44" amount="-8" />
|
||||||
kerning first=72 second=84 amount=-1
|
<kerning first="69" second="121" amount="-1" />
|
||||||
kerning first=86 second=46 amount=-8
|
<kerning first="87" second="114" amount="-1" />
|
||||||
kerning first=69 second=113 amount=-1
|
<kerning first="118" second="39" amount="1" />
|
||||||
kerning first=69 second=119 amount=-1
|
<kerning first="46" second="39" amount="-10" />
|
||||||
kerning first=73 second=89 amount=-1
|
<kerning first="72" second="84" amount="-1" />
|
||||||
kerning first=39 second=39 amount=-1
|
<kerning first="86" second="46" amount="-8" />
|
||||||
kerning first=69 second=117 amount=-1
|
<kerning first="69" second="113" amount="-1" />
|
||||||
kerning first=111 second=39 amount=-3
|
<kerning first="69" second="119" amount="-1" />
|
||||||
kerning first=90 second=81 amount=-1
|
<kerning first="73" second="89" amount="-1" />
|
||||||
|
<kerning first="39" second="39" amount="-1" />
|
||||||
|
<kerning first="69" second="117" amount="-1" />
|
||||||
|
<kerning first="111" second="39" amount="-3" />
|
||||||
|
<kerning first="90" second="81" amount="-1" />
|
||||||
|
</kernings>
|
||||||
|
</font>
|
||||||
|
|||||||
@@ -1,103 +1,109 @@
|
|||||||
info face="Roboto Mono" size=72 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,1,1,1 spacing=-2,-2
|
<?xml version="1.0"?>
|
||||||
common lineHeight=96 base=76 scaleW=512 scaleH=512 pages=1 packed=0
|
<font>
|
||||||
page id=0 file="RobotoMono72White.png"
|
<info face="Roboto Mono" size="72" bold="0" italic="0" charset="" unicode="0" stretchH="100" smooth="1" aa="1" padding="1,1,1,1" spacing="-2,-2" outline="0" />
|
||||||
chars count=98
|
<common lineHeight="96" base="76" scaleW="512" scaleH="512" pages="1" packed="0" alphaChnl="0" redChnl="0" greenChnl="0" blueChnl="0" />
|
||||||
char id=0 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=75 xadvance=0 page=0 chnl=0
|
<pages>
|
||||||
char id=10 x=0 y=0 width=45 height=99 xoffset=-1 yoffset=-2 xadvance=43 page=0 chnl=0
|
<page id="0" file="RobotoMono72White.png" /> </pages>
|
||||||
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=75 xadvance=43 page=0 chnl=0
|
<chars count="98">
|
||||||
char id=33 x=498 y=99 width=10 height=55 xoffset=16 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="0" x="0" y="0" width="0" height="0" xoffset="-1" yoffset="75" xadvance="0" page="0" chnl="0" />
|
||||||
char id=34 x=434 y=319 width=20 height=19 xoffset=11 yoffset=21 xadvance=43 page=0 chnl=0
|
<char id="10" x="0" y="0" width="45" height="99" xoffset="-1" yoffset="-2" xadvance="43" page="0" chnl="0" />
|
||||||
char id=35 x=175 y=265 width=41 height=54 xoffset=1 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="32" x="0" y="0" width="0" height="0" xoffset="-1" yoffset="75" xadvance="43" page="0" chnl="0" />
|
||||||
char id=36 x=200 y=0 width=35 height=69 xoffset=5 yoffset=15 xadvance=43 page=0 chnl=0
|
<char id="33" x="498" y="99" width="10" height="55" xoffset="16" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=37 x=0 y=155 width=42 height=56 xoffset=1 yoffset=22 xadvance=44 page=0 chnl=0
|
<char id="34" x="434" y="319" width="20" height="19" xoffset="11" yoffset="21" xadvance="43" page="0" chnl="0" />
|
||||||
char id=38 x=42 y=155 width=41 height=56 xoffset=3 yoffset=22 xadvance=44 page=0 chnl=0
|
<char id="35" x="175" y="265" width="41" height="54" xoffset="1" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=39 x=502 y=211 width=7 height=19 xoffset=16 yoffset=21 xadvance=43 page=0 chnl=0
|
<char id="36" x="200" y="0" width="35" height="69" xoffset="5" yoffset="15" xadvance="43" page="0" chnl="0" />
|
||||||
char id=40 x=45 y=0 width=21 height=78 xoffset=12 yoffset=16 xadvance=44 page=0 chnl=0
|
<char id="37" x="0" y="155" width="42" height="56" xoffset="1" yoffset="22" xadvance="44" page="0" chnl="0" />
|
||||||
char id=41 x=66 y=0 width=22 height=78 xoffset=9 yoffset=16 xadvance=43 page=0 chnl=0
|
<char id="38" x="42" y="155" width="41" height="56" xoffset="3" yoffset="22" xadvance="44" page="0" chnl="0" />
|
||||||
char id=42 x=256 y=319 width=37 height=37 xoffset=4 yoffset=32 xadvance=43 page=0 chnl=0
|
<char id="39" x="502" y="211" width="7" height="19" xoffset="16" yoffset="21" xadvance="43" page="0" chnl="0" />
|
||||||
char id=43 x=219 y=319 width=37 height=40 xoffset=3 yoffset=32 xadvance=43 page=0 chnl=0
|
<char id="40" x="45" y="0" width="21" height="78" xoffset="12" yoffset="16" xadvance="44" page="0" chnl="0" />
|
||||||
char id=44 x=421 y=319 width=13 height=22 xoffset=11 yoffset=67 xadvance=43 page=0 chnl=0
|
<char id="41" x="66" y="0" width="22" height="78" xoffset="9" yoffset="16" xadvance="43" page="0" chnl="0" />
|
||||||
char id=45 x=17 y=360 width=29 height=8 xoffset=7 yoffset=49 xadvance=44 page=0 chnl=0
|
<char id="42" x="256" y="319" width="37" height="37" xoffset="4" yoffset="32" xadvance="43" page="0" chnl="0" />
|
||||||
char id=46 x=496 y=319 width=12 height=13 xoffset=16 yoffset=65 xadvance=43 page=0 chnl=0
|
<char id="43" x="219" y="319" width="37" height="40" xoffset="3" yoffset="32" xadvance="43" page="0" chnl="0" />
|
||||||
char id=47 x=319 y=0 width=31 height=58 xoffset=7 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="44" x="421" y="319" width="13" height="22" xoffset="11" yoffset="67" xadvance="43" page="0" chnl="0" />
|
||||||
char id=48 x=431 y=99 width=35 height=56 xoffset=4 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="45" x="17" y="360" width="29" height="8" xoffset="7" yoffset="49" xadvance="44" page="0" chnl="0" />
|
||||||
char id=49 x=36 y=265 width=23 height=54 xoffset=6 yoffset=23 xadvance=44 page=0 chnl=0
|
<char id="46" x="496" y="319" width="12" height="13" xoffset="16" yoffset="65" xadvance="43" page="0" chnl="0" />
|
||||||
char id=50 x=189 y=155 width=37 height=55 xoffset=2 yoffset=22 xadvance=44 page=0 chnl=0
|
<char id="47" x="319" y="0" width="31" height="58" xoffset="7" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=51 x=361 y=99 width=35 height=56 xoffset=2 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="48" x="431" y="99" width="35" height="56" xoffset="4" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=52 x=59 y=265 width=39 height=54 xoffset=2 yoffset=23 xadvance=44 page=0 chnl=0
|
<char id="49" x="36" y="265" width="23" height="54" xoffset="6" yoffset="23" xadvance="44" page="0" chnl="0" />
|
||||||
char id=53 x=226 y=155 width=35 height=55 xoffset=5 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="50" x="189" y="155" width="37" height="55" xoffset="2" yoffset="22" xadvance="44" page="0" chnl="0" />
|
||||||
char id=54 x=261 y=155 width=35 height=55 xoffset=4 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="51" x="361" y="99" width="35" height="56" xoffset="2" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=55 x=98 y=265 width=37 height=54 xoffset=3 yoffset=23 xadvance=44 page=0 chnl=0
|
<char id="52" x="59" y="265" width="39" height="54" xoffset="2" yoffset="23" xadvance="44" page="0" chnl="0" />
|
||||||
char id=56 x=396 y=99 width=35 height=56 xoffset=5 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="53" x="226" y="155" width="35" height="55" xoffset="5" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=57 x=296 y=155 width=34 height=55 xoffset=4 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="54" x="261" y="155" width="35" height="55" xoffset="4" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=58 x=490 y=211 width=12 height=43 xoffset=18 yoffset=35 xadvance=43 page=0 chnl=0
|
<char id="55" x="98" y="265" width="37" height="54" xoffset="3" yoffset="23" xadvance="44" page="0" chnl="0" />
|
||||||
char id=59 x=486 y=0 width=14 height=55 xoffset=16 yoffset=35 xadvance=43 page=0 chnl=0
|
<char id="56" x="396" y="99" width="35" height="56" xoffset="5" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=60 x=293 y=319 width=32 height=35 xoffset=5 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="57" x="296" y="155" width="34" height="55" xoffset="4" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=61 x=388 y=319 width=33 height=23 xoffset=5 yoffset=41 xadvance=43 page=0 chnl=0
|
<char id="58" x="490" y="211" width="12" height="43" xoffset="18" yoffset="35" xadvance="43" page="0" chnl="0" />
|
||||||
char id=62 x=325 y=319 width=33 height=35 xoffset=5 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="59" x="486" y="0" width="14" height="55" xoffset="16" yoffset="35" xadvance="43" page="0" chnl="0" />
|
||||||
char id=63 x=466 y=99 width=32 height=56 xoffset=6 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="60" x="293" y="319" width="32" height="35" xoffset="5" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=64 x=135 y=265 width=40 height=54 xoffset=1 yoffset=23 xadvance=42 page=0 chnl=0
|
<char id="61" x="388" y="319" width="33" height="23" xoffset="5" yoffset="41" xadvance="43" page="0" chnl="0" />
|
||||||
char id=65 x=330 y=155 width=42 height=54 xoffset=1 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="62" x="325" y="319" width="33" height="35" xoffset="5" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=66 x=372 y=155 width=35 height=54 xoffset=5 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="63" x="466" y="99" width="32" height="56" xoffset="6" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=67 x=448 y=0 width=38 height=56 xoffset=3 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="64" x="135" y="265" width="40" height="54" xoffset="1" yoffset="23" xadvance="42" page="0" chnl="0" />
|
||||||
char id=68 x=407 y=155 width=37 height=54 xoffset=4 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="65" x="330" y="155" width="42" height="54" xoffset="1" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=69 x=444 y=155 width=34 height=54 xoffset=5 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="66" x="372" y="155" width="35" height="54" xoffset="5" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=70 x=0 y=211 width=34 height=54 xoffset=6 yoffset=23 xadvance=44 page=0 chnl=0
|
<char id="67" x="448" y="0" width="38" height="56" xoffset="3" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=71 x=0 y=99 width=38 height=56 xoffset=3 yoffset=22 xadvance=44 page=0 chnl=0
|
<char id="68" x="407" y="155" width="37" height="54" xoffset="4" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=72 x=34 y=211 width=36 height=54 xoffset=4 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="69" x="444" y="155" width="34" height="54" xoffset="5" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=73 x=478 y=155 width=33 height=54 xoffset=5 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="70" x="0" y="211" width="34" height="54" xoffset="6" yoffset="23" xadvance="44" page="0" chnl="0" />
|
||||||
char id=74 x=83 y=155 width=36 height=55 xoffset=2 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="71" x="0" y="99" width="38" height="56" xoffset="3" yoffset="22" xadvance="44" page="0" chnl="0" />
|
||||||
char id=75 x=70 y=211 width=38 height=54 xoffset=5 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="72" x="34" y="211" width="36" height="54" xoffset="4" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=76 x=108 y=211 width=34 height=54 xoffset=6 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="73" x="478" y="155" width="33" height="54" xoffset="5" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=77 x=142 y=211 width=36 height=54 xoffset=4 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="74" x="83" y="155" width="36" height="55" xoffset="2" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=78 x=178 y=211 width=35 height=54 xoffset=4 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="75" x="70" y="211" width="38" height="54" xoffset="5" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=79 x=38 y=99 width=38 height=56 xoffset=3 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="76" x="108" y="211" width="34" height="54" xoffset="6" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=80 x=213 y=211 width=36 height=54 xoffset=6 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="77" x="142" y="211" width="36" height="54" xoffset="4" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=81 x=242 y=0 width=40 height=64 xoffset=2 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="78" x="178" y="211" width="35" height="54" xoffset="4" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=82 x=249 y=211 width=36 height=54 xoffset=5 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="79" x="38" y="99" width="38" height="56" xoffset="3" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=83 x=76 y=99 width=38 height=56 xoffset=3 yoffset=22 xadvance=44 page=0 chnl=0
|
<char id="80" x="213" y="211" width="36" height="54" xoffset="6" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=84 x=285 y=211 width=40 height=54 xoffset=2 yoffset=23 xadvance=44 page=0 chnl=0
|
<char id="81" x="242" y="0" width="40" height="64" xoffset="2" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=85 x=119 y=155 width=36 height=55 xoffset=4 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="82" x="249" y="211" width="36" height="54" xoffset="5" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=86 x=325 y=211 width=41 height=54 xoffset=1 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="83" x="76" y="99" width="38" height="56" xoffset="3" yoffset="22" xadvance="44" page="0" chnl="0" />
|
||||||
char id=87 x=366 y=211 width=42 height=54 xoffset=1 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="84" x="285" y="211" width="40" height="54" xoffset="2" yoffset="23" xadvance="44" page="0" chnl="0" />
|
||||||
char id=88 x=408 y=211 width=41 height=54 xoffset=2 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="85" x="119" y="155" width="36" height="55" xoffset="4" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=89 x=449 y=211 width=41 height=54 xoffset=1 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="86" x="325" y="211" width="41" height="54" xoffset="1" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=90 x=0 y=265 width=36 height=54 xoffset=3 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="87" x="366" y="211" width="42" height="54" xoffset="1" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=91 x=88 y=0 width=16 height=72 xoffset=14 yoffset=16 xadvance=43 page=0 chnl=0
|
<char id="88" x="408" y="211" width="41" height="54" xoffset="2" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=92 x=350 y=0 width=30 height=58 xoffset=7 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="89" x="449" y="211" width="41" height="54" xoffset="1" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=93 x=104 y=0 width=17 height=72 xoffset=13 yoffset=16 xadvance=44 page=0 chnl=0
|
<char id="90" x="0" y="265" width="36" height="54" xoffset="3" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=94 x=358 y=319 width=30 height=30 xoffset=7 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="91" x="88" y="0" width="16" height="72" xoffset="14" yoffset="16" xadvance="43" page="0" chnl="0" />
|
||||||
char id=95 x=46 y=360 width=34 height=8 xoffset=4 yoffset=74 xadvance=43 page=0 chnl=0
|
<char id="92" x="350" y="0" width="30" height="58" xoffset="7" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=96 x=0 y=360 width=17 height=12 xoffset=13 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="93" x="104" y="0" width="17" height="72" xoffset="13" yoffset="16" xadvance="44" page="0" chnl="0" />
|
||||||
char id=97 x=251 y=265 width=35 height=42 xoffset=4 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="94" x="358" y="319" width="30" height="30" xoffset="7" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=98 x=380 y=0 width=34 height=57 xoffset=5 yoffset=21 xadvance=43 page=0 chnl=0
|
<char id="95" x="46" y="360" width="34" height="8" xoffset="4" yoffset="74" xadvance="43" page="0" chnl="0" />
|
||||||
char id=99 x=286 y=265 width=35 height=42 xoffset=4 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="96" x="0" y="360" width="17" height="12" xoffset="13" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=100 x=414 y=0 width=34 height=57 xoffset=4 yoffset=21 xadvance=43 page=0 chnl=0
|
<char id="97" x="251" y="265" width="35" height="42" xoffset="4" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=101 x=321 y=265 width=36 height=42 xoffset=4 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="98" x="380" y="0" width="34" height="57" xoffset="5" yoffset="21" xadvance="43" page="0" chnl="0" />
|
||||||
char id=102 x=282 y=0 width=37 height=58 xoffset=4 yoffset=19 xadvance=43 page=0 chnl=0
|
<char id="99" x="286" y="265" width="35" height="42" xoffset="4" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=103 x=114 y=99 width=34 height=56 xoffset=4 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="100" x="414" y="0" width="34" height="57" xoffset="4" yoffset="21" xadvance="43" page="0" chnl="0" />
|
||||||
char id=104 x=148 y=99 width=34 height=56 xoffset=5 yoffset=21 xadvance=43 page=0 chnl=0
|
<char id="101" x="321" y="265" width="36" height="42" xoffset="4" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=105 x=155 y=155 width=34 height=55 xoffset=6 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="102" x="282" y="0" width="37" height="58" xoffset="4" yoffset="19" xadvance="43" page="0" chnl="0" />
|
||||||
char id=106 x=121 y=0 width=26 height=71 xoffset=6 yoffset=22 xadvance=44 page=0 chnl=0
|
<char id="103" x="114" y="99" width="34" height="56" xoffset="4" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=107 x=182 y=99 width=36 height=56 xoffset=5 yoffset=21 xadvance=43 page=0 chnl=0
|
<char id="104" x="148" y="99" width="34" height="56" xoffset="5" yoffset="21" xadvance="43" page="0" chnl="0" />
|
||||||
char id=108 x=218 y=99 width=34 height=56 xoffset=6 yoffset=21 xadvance=43 page=0 chnl=0
|
<char id="105" x="155" y="155" width="34" height="55" xoffset="6" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=109 x=428 y=265 width=39 height=41 xoffset=2 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="106" x="121" y="0" width="26" height="71" xoffset="6" yoffset="22" xadvance="44" page="0" chnl="0" />
|
||||||
char id=110 x=467 y=265 width=34 height=41 xoffset=5 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="107" x="182" y="99" width="36" height="56" xoffset="5" yoffset="21" xadvance="43" page="0" chnl="0" />
|
||||||
char id=111 x=357 y=265 width=37 height=42 xoffset=3 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="108" x="218" y="99" width="34" height="56" xoffset="6" yoffset="21" xadvance="43" page="0" chnl="0" />
|
||||||
char id=112 x=252 y=99 width=34 height=56 xoffset=5 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="109" x="428" y="265" width="39" height="41" xoffset="2" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=113 x=286 y=99 width=34 height=56 xoffset=4 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="110" x="467" y="265" width="34" height="41" xoffset="5" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=114 x=0 y=319 width=29 height=41 xoffset=11 yoffset=36 xadvance=44 page=0 chnl=0
|
<char id="111" x="357" y="265" width="37" height="42" xoffset="3" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=115 x=394 y=265 width=34 height=42 xoffset=5 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="112" x="252" y="99" width="34" height="56" xoffset="5" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=116 x=216 y=265 width=35 height=51 xoffset=4 yoffset=27 xadvance=43 page=0 chnl=0
|
<char id="113" x="286" y="99" width="34" height="56" xoffset="4" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=117 x=29 y=319 width=33 height=41 xoffset=5 yoffset=37 xadvance=43 page=0 chnl=0
|
<char id="114" x="0" y="319" width="29" height="41" xoffset="11" yoffset="36" xadvance="44" page="0" chnl="0" />
|
||||||
char id=118 x=62 y=319 width=39 height=40 xoffset=2 yoffset=37 xadvance=43 page=0 chnl=0
|
<char id="115" x="394" y="265" width="34" height="42" xoffset="5" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=119 x=101 y=319 width=43 height=40 xoffset=0 yoffset=37 xadvance=43 page=0 chnl=0
|
<char id="116" x="216" y="265" width="35" height="51" xoffset="4" yoffset="27" xadvance="43" page="0" chnl="0" />
|
||||||
char id=120 x=144 y=319 width=40 height=40 xoffset=2 yoffset=37 xadvance=43 page=0 chnl=0
|
<char id="117" x="29" y="319" width="33" height="41" xoffset="5" yoffset="37" xadvance="43" page="0" chnl="0" />
|
||||||
char id=121 x=320 y=99 width=41 height=56 xoffset=1 yoffset=37 xadvance=43 page=0 chnl=0
|
<char id="118" x="62" y="319" width="39" height="40" xoffset="2" yoffset="37" xadvance="43" page="0" chnl="0" />
|
||||||
char id=122 x=184 y=319 width=35 height=40 xoffset=5 yoffset=37 xadvance=44 page=0 chnl=0
|
<char id="119" x="101" y="319" width="43" height="40" xoffset="0" yoffset="37" xadvance="43" page="0" chnl="0" />
|
||||||
char id=123 x=147 y=0 width=26 height=71 xoffset=10 yoffset=19 xadvance=43 page=0 chnl=0
|
<char id="120" x="144" y="319" width="40" height="40" xoffset="2" yoffset="37" xadvance="43" page="0" chnl="0" />
|
||||||
char id=124 x=235 y=0 width=7 height=68 xoffset=18 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="121" x="320" y="99" width="41" height="56" xoffset="1" yoffset="37" xadvance="43" page="0" chnl="0" />
|
||||||
char id=125 x=173 y=0 width=27 height=71 xoffset=10 yoffset=19 xadvance=44 page=0 chnl=0
|
<char id="122" x="184" y="319" width="35" height="40" xoffset="5" yoffset="37" xadvance="44" page="0" chnl="0" />
|
||||||
char id=126 x=454 y=319 width=42 height=16 xoffset=1 yoffset=47 xadvance=44 page=0 chnl=0
|
<char id="123" x="147" y="0" width="26" height="71" xoffset="10" yoffset="19" xadvance="43" page="0" chnl="0" />
|
||||||
char id=127 x=0 y=0 width=45 height=99 xoffset=-1 yoffset=-2 xadvance=43 page=0 chnl=0
|
<char id="124" x="235" y="0" width="7" height="68" xoffset="18" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
kernings count=0
|
<char id="125" x="173" y="0" width="27" height="71" xoffset="10" yoffset="19" xadvance="44" page="0" chnl="0" />
|
||||||
|
<char id="126" x="454" y="319" width="42" height="16" xoffset="1" yoffset="47" xadvance="44" page="0" chnl="0" />
|
||||||
|
<char id="127" x="0" y="0" width="45" height="99" xoffset="-1" yoffset="-2" xadvance="43" page="0" chnl="0" />
|
||||||
|
</chars>
|
||||||
|
<kernings count="0">
|
||||||
|
</kernings>
|
||||||
|
</font>
|
||||||
|
|||||||
@@ -1,492 +1,498 @@
|
|||||||
info face="Roboto Slab Regular" size=72 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,1,1,1 spacing=-2,-2
|
<?xml version="1.0"?>
|
||||||
common lineHeight=96 base=76 scaleW=512 scaleH=512 pages=1 packed=0
|
<font>
|
||||||
page id=0 file="RobotoSlab72White.png"
|
<info face="Roboto Slab Regular" size="72" bold="0" italic="0" charset="" unicode="0" stretchH="100" smooth="1" aa="1" padding="1,1,1,1" spacing="-2,-2" outline="0" />
|
||||||
chars count=98
|
<common lineHeight="96" base="76" scaleW="512" scaleH="512" pages="1" packed="0" alphaChnl="0" redChnl="0" greenChnl="0" blueChnl="0" />
|
||||||
char id=0 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=75 xadvance=0 page=0 chnl=0
|
<pages>
|
||||||
char id=10 x=0 y=0 width=70 height=98 xoffset=0 yoffset=-1 xadvance=70 page=0 chnl=0
|
<page id="0" file="RobotoSlab72White.png" /> </pages>
|
||||||
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=75 xadvance=18 page=0 chnl=0
|
<chars count="98">
|
||||||
char id=33 x=497 y=156 width=9 height=54 xoffset=4 yoffset=23 xadvance=17 page=0 chnl=0
|
<char id="0" x="0" y="0" width="0" height="0" xoffset="-1" yoffset="75" xadvance="0" page="0" chnl="0" />
|
||||||
char id=34 x=191 y=362 width=19 height=20 xoffset=5 yoffset=20 xadvance=28 page=0 chnl=0
|
<char id="10" x="0" y="0" width="70" height="98" xoffset="0" yoffset="-1" xadvance="70" page="0" chnl="0" />
|
||||||
char id=35 x=406 y=266 width=41 height=54 xoffset=1 yoffset=23 xadvance=43 page=0 chnl=0
|
<char id="32" x="0" y="0" width="0" height="0" xoffset="-1" yoffset="75" xadvance="18" page="0" chnl="0" />
|
||||||
char id=36 x=212 y=0 width=35 height=69 xoffset=2 yoffset=15 xadvance=39 page=0 chnl=0
|
<char id="33" x="497" y="156" width="9" height="54" xoffset="4" yoffset="23" xadvance="17" page="0" chnl="0" />
|
||||||
char id=37 x=174 y=156 width=48 height=56 xoffset=2 yoffset=22 xadvance=52 page=0 chnl=0
|
<char id="34" x="191" y="362" width="19" height="20" xoffset="5" yoffset="20" xadvance="28" page="0" chnl="0" />
|
||||||
char id=38 x=222 y=156 width=44 height=56 xoffset=2 yoffset=22 xadvance=46 page=0 chnl=0
|
<char id="35" x="406" y="266" width="41" height="54" xoffset="1" yoffset="23" xadvance="43" page="0" chnl="0" />
|
||||||
char id=39 x=210 y=362 width=8 height=20 xoffset=5 yoffset=20 xadvance=17 page=0 chnl=0
|
<char id="36" x="212" y="0" width="35" height="69" xoffset="2" yoffset="15" xadvance="39" page="0" chnl="0" />
|
||||||
char id=40 x=70 y=0 width=21 height=77 xoffset=3 yoffset=17 xadvance=23 page=0 chnl=0
|
<char id="37" x="174" y="156" width="48" height="56" xoffset="2" yoffset="22" xadvance="52" page="0" chnl="0" />
|
||||||
char id=41 x=91 y=0 width=21 height=77 xoffset=-1 yoffset=17 xadvance=23 page=0 chnl=0
|
<char id="38" x="222" y="156" width="44" height="56" xoffset="2" yoffset="22" xadvance="46" page="0" chnl="0" />
|
||||||
char id=42 x=100 y=362 width=31 height=33 xoffset=1 yoffset=23 xadvance=33 page=0 chnl=0
|
<char id="39" x="210" y="362" width="8" height="20" xoffset="5" yoffset="20" xadvance="17" page="0" chnl="0" />
|
||||||
char id=43 x=0 y=362 width=37 height=40 xoffset=2 yoffset=32 xadvance=41 page=0 chnl=0
|
<char id="40" x="70" y="0" width="21" height="77" xoffset="3" yoffset="17" xadvance="23" page="0" chnl="0" />
|
||||||
char id=44 x=492 y=320 width=13 height=21 xoffset=-1 yoffset=67 xadvance=14 page=0 chnl=0
|
<char id="41" x="91" y="0" width="21" height="77" xoffset="-1" yoffset="17" xadvance="23" page="0" chnl="0" />
|
||||||
char id=45 x=287 y=362 width=19 height=8 xoffset=4 yoffset=50 xadvance=27 page=0 chnl=0
|
<char id="42" x="100" y="362" width="31" height="33" xoffset="1" yoffset="23" xadvance="33" page="0" chnl="0" />
|
||||||
char id=46 x=278 y=362 width=9 height=9 xoffset=4 yoffset=68 xadvance=17 page=0 chnl=0
|
<char id="43" x="0" y="362" width="37" height="40" xoffset="2" yoffset="32" xadvance="41" page="0" chnl="0" />
|
||||||
char id=47 x=470 y=0 width=30 height=58 xoffset=-1 yoffset=23 xadvance=29 page=0 chnl=0
|
<char id="44" x="492" y="320" width="13" height="21" xoffset="-1" yoffset="67" xadvance="14" page="0" chnl="0" />
|
||||||
char id=48 x=139 y=156 width=35 height=56 xoffset=3 yoffset=22 xadvance=41 page=0 chnl=0
|
<char id="45" x="287" y="362" width="19" height="8" xoffset="4" yoffset="50" xadvance="27" page="0" chnl="0" />
|
||||||
char id=49 x=305 y=266 width=25 height=54 xoffset=3 yoffset=23 xadvance=30 page=0 chnl=0
|
<char id="46" x="278" y="362" width="9" height="9" xoffset="4" yoffset="68" xadvance="17" page="0" chnl="0" />
|
||||||
char id=50 x=357 y=156 width=36 height=55 xoffset=2 yoffset=22 xadvance=40 page=0 chnl=0
|
<char id="47" x="470" y="0" width="30" height="58" xoffset="-1" yoffset="23" xadvance="29" page="0" chnl="0" />
|
||||||
char id=51 x=0 y=156 width=34 height=56 xoffset=2 yoffset=22 xadvance=39 page=0 chnl=0
|
<char id="48" x="139" y="156" width="35" height="56" xoffset="3" yoffset="22" xadvance="41" page="0" chnl="0" />
|
||||||
char id=52 x=330 y=266 width=39 height=54 xoffset=1 yoffset=23 xadvance=42 page=0 chnl=0
|
<char id="49" x="305" y="266" width="25" height="54" xoffset="3" yoffset="23" xadvance="30" page="0" chnl="0" />
|
||||||
char id=53 x=393 y=156 width=33 height=55 xoffset=2 yoffset=23 xadvance=37 page=0 chnl=0
|
<char id="50" x="357" y="156" width="36" height="55" xoffset="2" yoffset="22" xadvance="40" page="0" chnl="0" />
|
||||||
char id=54 x=34 y=156 width=35 height=56 xoffset=3 yoffset=22 xadvance=40 page=0 chnl=0
|
<char id="51" x="0" y="156" width="34" height="56" xoffset="2" yoffset="22" xadvance="39" page="0" chnl="0" />
|
||||||
char id=55 x=369 y=266 width=37 height=54 xoffset=2 yoffset=23 xadvance=40 page=0 chnl=0
|
<char id="52" x="330" y="266" width="39" height="54" xoffset="1" yoffset="23" xadvance="42" page="0" chnl="0" />
|
||||||
char id=56 x=69 y=156 width=35 height=56 xoffset=2 yoffset=22 xadvance=39 page=0 chnl=0
|
<char id="53" x="393" y="156" width="33" height="55" xoffset="2" yoffset="23" xadvance="37" page="0" chnl="0" />
|
||||||
char id=57 x=104 y=156 width=35 height=56 xoffset=2 yoffset=22 xadvance=41 page=0 chnl=0
|
<char id="54" x="34" y="156" width="35" height="56" xoffset="3" yoffset="22" xadvance="40" page="0" chnl="0" />
|
||||||
char id=58 x=500 y=0 width=9 height=40 xoffset=4 yoffset=37 xadvance=15 page=0 chnl=0
|
<char id="55" x="369" y="266" width="37" height="54" xoffset="2" yoffset="23" xadvance="40" page="0" chnl="0" />
|
||||||
char id=59 x=447 y=266 width=13 height=52 xoffset=0 yoffset=37 xadvance=15 page=0 chnl=0
|
<char id="56" x="69" y="156" width="35" height="56" xoffset="2" yoffset="22" xadvance="39" page="0" chnl="0" />
|
||||||
char id=60 x=37 y=362 width=31 height=35 xoffset=2 yoffset=39 xadvance=36 page=0 chnl=0
|
<char id="57" x="104" y="156" width="35" height="56" xoffset="2" yoffset="22" xadvance="41" page="0" chnl="0" />
|
||||||
char id=61 x=160 y=362 width=31 height=23 xoffset=4 yoffset=40 xadvance=39 page=0 chnl=0
|
<char id="58" x="500" y="0" width="9" height="40" xoffset="4" yoffset="37" xadvance="15" page="0" chnl="0" />
|
||||||
char id=62 x=68 y=362 width=32 height=35 xoffset=3 yoffset=39 xadvance=37 page=0 chnl=0
|
<char id="59" x="447" y="266" width="13" height="52" xoffset="0" yoffset="37" xadvance="15" page="0" chnl="0" />
|
||||||
char id=63 x=480 y=98 width=31 height=55 xoffset=1 yoffset=22 xadvance=33 page=0 chnl=0
|
<char id="60" x="37" y="362" width="31" height="35" xoffset="2" yoffset="39" xadvance="36" page="0" chnl="0" />
|
||||||
char id=64 x=247 y=0 width=60 height=68 xoffset=1 yoffset=25 xadvance=64 page=0 chnl=0
|
<char id="61" x="160" y="362" width="31" height="23" xoffset="4" yoffset="40" xadvance="39" page="0" chnl="0" />
|
||||||
char id=65 x=426 y=156 width=51 height=54 xoffset=1 yoffset=23 xadvance=53 page=0 chnl=0
|
<char id="62" x="68" y="362" width="32" height="35" xoffset="3" yoffset="39" xadvance="37" page="0" chnl="0" />
|
||||||
char id=66 x=0 y=212 width=44 height=54 xoffset=1 yoffset=23 xadvance=47 page=0 chnl=0
|
<char id="63" x="480" y="98" width="31" height="55" xoffset="1" yoffset="22" xadvance="33" page="0" chnl="0" />
|
||||||
char id=67 x=191 y=98 width=42 height=56 xoffset=1 yoffset=22 xadvance=46 page=0 chnl=0
|
<char id="64" x="247" y="0" width="60" height="68" xoffset="1" yoffset="25" xadvance="64" page="0" chnl="0" />
|
||||||
char id=68 x=44 y=212 width=46 height=54 xoffset=1 yoffset=23 xadvance=50 page=0 chnl=0
|
<char id="65" x="426" y="156" width="51" height="54" xoffset="1" yoffset="23" xadvance="53" page="0" chnl="0" />
|
||||||
char id=69 x=90 y=212 width=42 height=54 xoffset=1 yoffset=23 xadvance=46 page=0 chnl=0
|
<char id="66" x="0" y="212" width="44" height="54" xoffset="1" yoffset="23" xadvance="47" page="0" chnl="0" />
|
||||||
char id=70 x=132 y=212 width=42 height=54 xoffset=1 yoffset=23 xadvance=44 page=0 chnl=0
|
<char id="67" x="191" y="98" width="42" height="56" xoffset="1" yoffset="22" xadvance="46" page="0" chnl="0" />
|
||||||
char id=71 x=233 y=98 width=43 height=56 xoffset=1 yoffset=22 xadvance=49 page=0 chnl=0
|
<char id="68" x="44" y="212" width="46" height="54" xoffset="1" yoffset="23" xadvance="50" page="0" chnl="0" />
|
||||||
char id=72 x=174 y=212 width=52 height=54 xoffset=1 yoffset=23 xadvance=55 page=0 chnl=0
|
<char id="69" x="90" y="212" width="42" height="54" xoffset="1" yoffset="23" xadvance="46" page="0" chnl="0" />
|
||||||
char id=73 x=477 y=156 width=20 height=54 xoffset=1 yoffset=23 xadvance=22 page=0 chnl=0
|
<char id="70" x="132" y="212" width="42" height="54" xoffset="1" yoffset="23" xadvance="44" page="0" chnl="0" />
|
||||||
char id=74 x=266 y=156 width=39 height=55 xoffset=1 yoffset=23 xadvance=41 page=0 chnl=0
|
<char id="71" x="233" y="98" width="43" height="56" xoffset="1" yoffset="22" xadvance="49" page="0" chnl="0" />
|
||||||
char id=75 x=226 y=212 width=48 height=54 xoffset=1 yoffset=23 xadvance=50 page=0 chnl=0
|
<char id="72" x="174" y="212" width="52" height="54" xoffset="1" yoffset="23" xadvance="55" page="0" chnl="0" />
|
||||||
char id=76 x=274 y=212 width=39 height=54 xoffset=1 yoffset=23 xadvance=42 page=0 chnl=0
|
<char id="73" x="477" y="156" width="20" height="54" xoffset="1" yoffset="23" xadvance="22" page="0" chnl="0" />
|
||||||
char id=77 x=313 y=212 width=64 height=54 xoffset=1 yoffset=23 xadvance=66 page=0 chnl=0
|
<char id="74" x="266" y="156" width="39" height="55" xoffset="1" yoffset="23" xadvance="41" page="0" chnl="0" />
|
||||||
char id=78 x=377 y=212 width=52 height=54 xoffset=1 yoffset=23 xadvance=54 page=0 chnl=0
|
<char id="75" x="226" y="212" width="48" height="54" xoffset="1" yoffset="23" xadvance="50" page="0" chnl="0" />
|
||||||
char id=79 x=276 y=98 width=47 height=56 xoffset=2 yoffset=22 xadvance=51 page=0 chnl=0
|
<char id="76" x="274" y="212" width="39" height="54" xoffset="1" yoffset="23" xadvance="42" page="0" chnl="0" />
|
||||||
char id=80 x=429 y=212 width=43 height=54 xoffset=1 yoffset=23 xadvance=45 page=0 chnl=0
|
<char id="77" x="313" y="212" width="64" height="54" xoffset="1" yoffset="23" xadvance="66" page="0" chnl="0" />
|
||||||
char id=81 x=307 y=0 width=48 height=64 xoffset=2 yoffset=22 xadvance=51 page=0 chnl=0
|
<char id="78" x="377" y="212" width="52" height="54" xoffset="1" yoffset="23" xadvance="54" page="0" chnl="0" />
|
||||||
char id=82 x=0 y=266 width=46 height=54 xoffset=1 yoffset=23 xadvance=48 page=0 chnl=0
|
<char id="79" x="276" y="98" width="47" height="56" xoffset="2" yoffset="22" xadvance="51" page="0" chnl="0" />
|
||||||
char id=83 x=323 y=98 width=38 height=56 xoffset=3 yoffset=22 xadvance=43 page=0 chnl=0
|
<char id="80" x="429" y="212" width="43" height="54" xoffset="1" yoffset="23" xadvance="45" page="0" chnl="0" />
|
||||||
char id=84 x=46 y=266 width=45 height=54 xoffset=0 yoffset=23 xadvance=45 page=0 chnl=0
|
<char id="81" x="307" y="0" width="48" height="64" xoffset="2" yoffset="22" xadvance="51" page="0" chnl="0" />
|
||||||
char id=85 x=305 y=156 width=52 height=55 xoffset=1 yoffset=23 xadvance=54 page=0 chnl=0
|
<char id="82" x="0" y="266" width="46" height="54" xoffset="1" yoffset="23" xadvance="48" page="0" chnl="0" />
|
||||||
char id=86 x=91 y=266 width=50 height=54 xoffset=1 yoffset=23 xadvance=52 page=0 chnl=0
|
<char id="83" x="323" y="98" width="38" height="56" xoffset="3" yoffset="22" xadvance="43" page="0" chnl="0" />
|
||||||
char id=87 x=141 y=266 width=67 height=54 xoffset=0 yoffset=23 xadvance=67 page=0 chnl=0
|
<char id="84" x="46" y="266" width="45" height="54" xoffset="0" yoffset="23" xadvance="45" page="0" chnl="0" />
|
||||||
char id=88 x=208 y=266 width=49 height=54 xoffset=1 yoffset=23 xadvance=51 page=0 chnl=0
|
<char id="85" x="305" y="156" width="52" height="55" xoffset="1" yoffset="23" xadvance="54" page="0" chnl="0" />
|
||||||
char id=89 x=257 y=266 width=48 height=54 xoffset=1 yoffset=23 xadvance=50 page=0 chnl=0
|
<char id="86" x="91" y="266" width="50" height="54" xoffset="1" yoffset="23" xadvance="52" page="0" chnl="0" />
|
||||||
char id=90 x=472 y=212 width=38 height=54 xoffset=2 yoffset=23 xadvance=42 page=0 chnl=0
|
<char id="87" x="141" y="266" width="67" height="54" xoffset="0" yoffset="23" xadvance="67" page="0" chnl="0" />
|
||||||
char id=91 x=180 y=0 width=16 height=72 xoffset=5 yoffset=16 xadvance=21 page=0 chnl=0
|
<char id="88" x="208" y="266" width="49" height="54" xoffset="1" yoffset="23" xadvance="51" page="0" chnl="0" />
|
||||||
char id=92 x=0 y=98 width=31 height=58 xoffset=0 yoffset=23 xadvance=30 page=0 chnl=0
|
<char id="89" x="257" y="266" width="48" height="54" xoffset="1" yoffset="23" xadvance="50" page="0" chnl="0" />
|
||||||
char id=93 x=196 y=0 width=16 height=72 xoffset=-1 yoffset=16 xadvance=19 page=0 chnl=0
|
<char id="90" x="472" y="212" width="38" height="54" xoffset="2" yoffset="23" xadvance="42" page="0" chnl="0" />
|
||||||
char id=94 x=131 y=362 width=29 height=28 xoffset=1 yoffset=23 xadvance=30 page=0 chnl=0
|
<char id="91" x="180" y="0" width="16" height="72" xoffset="5" yoffset="16" xadvance="21" page="0" chnl="0" />
|
||||||
char id=95 x=306 y=362 width=34 height=8 xoffset=3 yoffset=74 xadvance=40 page=0 chnl=0
|
<char id="92" x="0" y="98" width="31" height="58" xoffset="0" yoffset="23" xadvance="30" page="0" chnl="0" />
|
||||||
char id=96 x=260 y=362 width=18 height=12 xoffset=1 yoffset=22 xadvance=20 page=0 chnl=0
|
<char id="93" x="196" y="0" width="16" height="72" xoffset="-1" yoffset="16" xadvance="19" page="0" chnl="0" />
|
||||||
char id=97 x=0 y=320 width=36 height=42 xoffset=3 yoffset=36 xadvance=41 page=0 chnl=0
|
<char id="94" x="131" y="362" width="29" height="28" xoffset="1" yoffset="23" xadvance="30" page="0" chnl="0" />
|
||||||
char id=98 x=363 y=0 width=41 height=58 xoffset=-2 yoffset=20 xadvance=42 page=0 chnl=0
|
<char id="95" x="306" y="362" width="34" height="8" xoffset="3" yoffset="74" xadvance="40" page="0" chnl="0" />
|
||||||
char id=99 x=36 y=320 width=34 height=42 xoffset=2 yoffset=36 xadvance=39 page=0 chnl=0
|
<char id="96" x="260" y="362" width="18" height="12" xoffset="1" yoffset="22" xadvance="20" page="0" chnl="0" />
|
||||||
char id=100 x=404 y=0 width=40 height=58 xoffset=2 yoffset=20 xadvance=43 page=0 chnl=0
|
<char id="97" x="0" y="320" width="36" height="42" xoffset="3" yoffset="36" xadvance="41" page="0" chnl="0" />
|
||||||
char id=101 x=70 y=320 width=34 height=42 xoffset=2 yoffset=36 xadvance=39 page=0 chnl=0
|
<char id="98" x="363" y="0" width="41" height="58" xoffset="-2" yoffset="20" xadvance="42" page="0" chnl="0" />
|
||||||
char id=102 x=444 y=0 width=26 height=58 xoffset=1 yoffset=19 xadvance=25 page=0 chnl=0
|
<char id="99" x="36" y="320" width="34" height="42" xoffset="2" yoffset="36" xadvance="39" page="0" chnl="0" />
|
||||||
char id=103 x=31 y=98 width=34 height=57 xoffset=2 yoffset=36 xadvance=40 page=0 chnl=0
|
<char id="100" x="404" y="0" width="40" height="58" xoffset="2" yoffset="20" xadvance="43" page="0" chnl="0" />
|
||||||
char id=104 x=65 y=98 width=44 height=57 xoffset=1 yoffset=20 xadvance=46 page=0 chnl=0
|
<char id="101" x="70" y="320" width="34" height="42" xoffset="2" yoffset="36" xadvance="39" page="0" chnl="0" />
|
||||||
char id=105 x=109 y=98 width=20 height=57 xoffset=2 yoffset=20 xadvance=23 page=0 chnl=0
|
<char id="102" x="444" y="0" width="26" height="58" xoffset="1" yoffset="19" xadvance="25" page="0" chnl="0" />
|
||||||
char id=106 x=112 y=0 width=18 height=73 xoffset=-2 yoffset=20 xadvance=20 page=0 chnl=0
|
<char id="103" x="31" y="98" width="34" height="57" xoffset="2" yoffset="36" xadvance="40" page="0" chnl="0" />
|
||||||
char id=107 x=129 y=98 width=42 height=57 xoffset=1 yoffset=20 xadvance=44 page=0 chnl=0
|
<char id="104" x="65" y="98" width="44" height="57" xoffset="1" yoffset="20" xadvance="46" page="0" chnl="0" />
|
||||||
char id=108 x=171 y=98 width=20 height=57 xoffset=1 yoffset=20 xadvance=22 page=0 chnl=0
|
<char id="105" x="109" y="98" width="20" height="57" xoffset="2" yoffset="20" xadvance="23" page="0" chnl="0" />
|
||||||
char id=109 x=171 y=320 width=66 height=41 xoffset=1 yoffset=36 xadvance=68 page=0 chnl=0
|
<char id="106" x="112" y="0" width="18" height="73" xoffset="-2" yoffset="20" xadvance="20" page="0" chnl="0" />
|
||||||
char id=110 x=237 y=320 width=44 height=41 xoffset=1 yoffset=36 xadvance=46 page=0 chnl=0
|
<char id="107" x="129" y="98" width="42" height="57" xoffset="1" yoffset="20" xadvance="44" page="0" chnl="0" />
|
||||||
char id=111 x=104 y=320 width=36 height=42 xoffset=2 yoffset=36 xadvance=40 page=0 chnl=0
|
<char id="108" x="171" y="98" width="20" height="57" xoffset="1" yoffset="20" xadvance="22" page="0" chnl="0" />
|
||||||
char id=112 x=361 y=98 width=40 height=56 xoffset=1 yoffset=36 xadvance=43 page=0 chnl=0
|
<char id="109" x="171" y="320" width="66" height="41" xoffset="1" yoffset="36" xadvance="68" page="0" chnl="0" />
|
||||||
char id=113 x=401 y=98 width=39 height=56 xoffset=2 yoffset=36 xadvance=40 page=0 chnl=0
|
<char id="110" x="237" y="320" width="44" height="41" xoffset="1" yoffset="36" xadvance="46" page="0" chnl="0" />
|
||||||
char id=114 x=484 y=266 width=27 height=41 xoffset=2 yoffset=36 xadvance=30 page=0 chnl=0
|
<char id="111" x="104" y="320" width="36" height="42" xoffset="2" yoffset="36" xadvance="40" page="0" chnl="0" />
|
||||||
char id=115 x=140 y=320 width=31 height=42 xoffset=3 yoffset=36 xadvance=36 page=0 chnl=0
|
<char id="112" x="361" y="98" width="40" height="56" xoffset="1" yoffset="36" xadvance="43" page="0" chnl="0" />
|
||||||
char id=116 x=460 y=266 width=24 height=51 xoffset=1 yoffset=27 xadvance=26 page=0 chnl=0
|
<char id="113" x="401" y="98" width="39" height="56" xoffset="2" yoffset="36" xadvance="40" page="0" chnl="0" />
|
||||||
char id=117 x=281 y=320 width=43 height=41 xoffset=0 yoffset=37 xadvance=44 page=0 chnl=0
|
<char id="114" x="484" y="266" width="27" height="41" xoffset="2" yoffset="36" xadvance="30" page="0" chnl="0" />
|
||||||
char id=118 x=324 y=320 width=39 height=40 xoffset=0 yoffset=37 xadvance=40 page=0 chnl=0
|
<char id="115" x="140" y="320" width="31" height="42" xoffset="3" yoffset="36" xadvance="36" page="0" chnl="0" />
|
||||||
char id=119 x=363 y=320 width=57 height=40 xoffset=1 yoffset=37 xadvance=59 page=0 chnl=0
|
<char id="116" x="460" y="266" width="24" height="51" xoffset="1" yoffset="27" xadvance="26" page="0" chnl="0" />
|
||||||
char id=120 x=420 y=320 width=40 height=40 xoffset=1 yoffset=37 xadvance=42 page=0 chnl=0
|
<char id="117" x="281" y="320" width="43" height="41" xoffset="0" yoffset="37" xadvance="44" page="0" chnl="0" />
|
||||||
char id=121 x=440 y=98 width=40 height=56 xoffset=0 yoffset=37 xadvance=41 page=0 chnl=0
|
<char id="118" x="324" y="320" width="39" height="40" xoffset="0" yoffset="37" xadvance="40" page="0" chnl="0" />
|
||||||
char id=122 x=460 y=320 width=32 height=40 xoffset=3 yoffset=37 xadvance=38 page=0 chnl=0
|
<char id="119" x="363" y="320" width="57" height="40" xoffset="1" yoffset="37" xadvance="59" page="0" chnl="0" />
|
||||||
char id=123 x=130 y=0 width=25 height=73 xoffset=1 yoffset=18 xadvance=25 page=0 chnl=0
|
<char id="120" x="420" y="320" width="40" height="40" xoffset="1" yoffset="37" xadvance="42" page="0" chnl="0" />
|
||||||
char id=124 x=355 y=0 width=8 height=63 xoffset=4 yoffset=23 xadvance=16 page=0 chnl=0
|
<char id="121" x="440" y="98" width="40" height="56" xoffset="0" yoffset="37" xadvance="41" page="0" chnl="0" />
|
||||||
char id=125 x=155 y=0 width=25 height=73 xoffset=-1 yoffset=18 xadvance=25 page=0 chnl=0
|
<char id="122" x="460" y="320" width="32" height="40" xoffset="3" yoffset="37" xadvance="38" page="0" chnl="0" />
|
||||||
char id=126 x=218 y=362 width=42 height=16 xoffset=3 yoffset=47 xadvance=49 page=0 chnl=0
|
<char id="123" x="130" y="0" width="25" height="73" xoffset="1" yoffset="18" xadvance="25" page="0" chnl="0" />
|
||||||
char id=127 x=0 y=0 width=70 height=98 xoffset=0 yoffset=-1 xadvance=70 page=0 chnl=0
|
<char id="124" x="355" y="0" width="8" height="63" xoffset="4" yoffset="23" xadvance="16" page="0" chnl="0" />
|
||||||
kernings count=389
|
<char id="125" x="155" y="0" width="25" height="73" xoffset="-1" yoffset="18" xadvance="25" page="0" chnl="0" />
|
||||||
kerning first=86 second=45 amount=-1
|
<char id="126" x="218" y="362" width="42" height="16" xoffset="3" yoffset="47" xadvance="49" page="0" chnl="0" />
|
||||||
kerning first=114 second=46 amount=-4
|
<char id="127" x="0" y="0" width="70" height="98" xoffset="0" yoffset="-1" xadvance="70" page="0" chnl="0" />
|
||||||
kerning first=40 second=87 amount=1
|
</chars>
|
||||||
kerning first=70 second=99 amount=-1
|
<kernings count="389">
|
||||||
kerning first=84 second=110 amount=-3
|
<kerning first="86" second="45" amount="-1" />
|
||||||
kerning first=114 second=116 amount=1
|
<kerning first="114" second="46" amount="-4" />
|
||||||
kerning first=39 second=65 amount=-4
|
<kerning first="40" second="87" amount="1" />
|
||||||
kerning first=104 second=34 amount=-1
|
<kerning first="70" second="99" amount="-1" />
|
||||||
kerning first=89 second=71 amount=-1
|
<kerning first="84" second="110" amount="-3" />
|
||||||
kerning first=107 second=113 amount=-1
|
<kerning first="114" second="116" amount="1" />
|
||||||
kerning first=78 second=88 amount=1
|
<kerning first="39" second="65" amount="-4" />
|
||||||
kerning first=109 second=39 amount=-1
|
<kerning first="104" second="34" amount="-1" />
|
||||||
kerning first=120 second=100 amount=-1
|
<kerning first="89" second="71" amount="-1" />
|
||||||
kerning first=84 second=100 amount=-3
|
<kerning first="107" second="113" amount="-1" />
|
||||||
kerning first=68 second=90 amount=-1
|
<kerning first="78" second="88" amount="1" />
|
||||||
kerning first=68 second=44 amount=-4
|
<kerning first="109" second="39" amount="-1" />
|
||||||
kerning first=84 second=103 amount=-3
|
<kerning first="120" second="100" amount="-1" />
|
||||||
kerning first=34 second=97 amount=-2
|
<kerning first="84" second="100" amount="-3" />
|
||||||
kerning first=70 second=97 amount=-1
|
<kerning first="68" second="90" amount="-1" />
|
||||||
kerning first=76 second=81 amount=-2
|
<kerning first="68" second="44" amount="-4" />
|
||||||
kerning first=73 second=89 amount=-1
|
<kerning first="84" second="103" amount="-3" />
|
||||||
kerning first=84 second=44 amount=-8
|
<kerning first="34" second="97" amount="-2" />
|
||||||
kerning first=68 second=65 amount=-3
|
<kerning first="70" second="97" amount="-1" />
|
||||||
kerning first=97 second=34 amount=-2
|
<kerning first="76" second="81" amount="-2" />
|
||||||
kerning first=111 second=121 amount=-1
|
<kerning first="73" second="89" amount="-1" />
|
||||||
kerning first=79 second=90 amount=-1
|
<kerning first="84" second="44" amount="-8" />
|
||||||
kerning first=75 second=121 amount=-1
|
<kerning first="68" second="65" amount="-3" />
|
||||||
kerning first=75 second=118 amount=-1
|
<kerning first="97" second="34" amount="-2" />
|
||||||
kerning first=111 second=118 amount=-1
|
<kerning first="111" second="121" amount="-1" />
|
||||||
kerning first=89 second=65 amount=-9
|
<kerning first="79" second="90" amount="-1" />
|
||||||
kerning first=75 second=71 amount=-4
|
<kerning first="75" second="121" amount="-1" />
|
||||||
kerning first=39 second=99 amount=-2
|
<kerning first="75" second="118" amount="-1" />
|
||||||
kerning first=75 second=99 amount=-1
|
<kerning first="111" second="118" amount="-1" />
|
||||||
kerning first=90 second=121 amount=-1
|
<kerning first="89" second="65" amount="-9" />
|
||||||
kerning first=44 second=39 amount=-6
|
<kerning first="75" second="71" amount="-4" />
|
||||||
kerning first=89 second=46 amount=-7
|
<kerning first="39" second="99" amount="-2" />
|
||||||
kerning first=89 second=74 amount=-7
|
<kerning first="75" second="99" amount="-1" />
|
||||||
kerning first=34 second=103 amount=-2
|
<kerning first="90" second="121" amount="-1" />
|
||||||
kerning first=70 second=103 amount=-1
|
<kerning first="44" second="39" amount="-6" />
|
||||||
kerning first=112 second=39 amount=-1
|
<kerning first="89" second="46" amount="-7" />
|
||||||
kerning first=122 second=113 amount=-1
|
<kerning first="89" second="74" amount="-7" />
|
||||||
kerning first=86 second=113 amount=-2
|
<kerning first="34" second="103" amount="-2" />
|
||||||
kerning first=68 second=84 amount=-1
|
<kerning first="70" second="103" amount="-1" />
|
||||||
kerning first=89 second=110 amount=-1
|
<kerning first="112" second="39" amount="-1" />
|
||||||
kerning first=34 second=100 amount=-2
|
<kerning first="122" second="113" amount="-1" />
|
||||||
kerning first=68 second=86 amount=-1
|
<kerning first="86" second="113" amount="-2" />
|
||||||
kerning first=87 second=45 amount=-2
|
<kerning first="68" second="84" amount="-1" />
|
||||||
kerning first=39 second=34 amount=-4
|
<kerning first="89" second="110" amount="-1" />
|
||||||
kerning first=114 second=100 amount=-1
|
<kerning first="34" second="100" amount="-2" />
|
||||||
kerning first=84 second=81 amount=-1
|
<kerning first="68" second="86" amount="-1" />
|
||||||
kerning first=70 second=101 amount=-1
|
<kerning first="87" second="45" amount="-2" />
|
||||||
kerning first=68 second=89 amount=-2
|
<kerning first="39" second="34" amount="-4" />
|
||||||
kerning first=88 second=117 amount=-1
|
<kerning first="114" second="100" amount="-1" />
|
||||||
kerning first=112 second=34 amount=-1
|
<kerning first="84" second="81" amount="-1" />
|
||||||
kerning first=76 second=67 amount=-2
|
<kerning first="70" second="101" amount="-1" />
|
||||||
kerning first=76 second=34 amount=-5
|
<kerning first="68" second="89" amount="-2" />
|
||||||
kerning first=88 second=111 amount=-1
|
<kerning first="88" second="117" amount="-1" />
|
||||||
kerning first=66 second=86 amount=-1
|
<kerning first="112" second="34" amount="-1" />
|
||||||
kerning first=66 second=89 amount=-2
|
<kerning first="76" second="67" amount="-2" />
|
||||||
kerning first=122 second=101 amount=-1
|
<kerning first="76" second="34" amount="-5" />
|
||||||
kerning first=86 second=101 amount=-2
|
<kerning first="88" second="111" amount="-1" />
|
||||||
kerning first=76 second=121 amount=-5
|
<kerning first="66" second="86" amount="-1" />
|
||||||
kerning first=84 second=119 amount=-2
|
<kerning first="66" second="89" amount="-2" />
|
||||||
kerning first=84 second=112 amount=-3
|
<kerning first="122" second="101" amount="-1" />
|
||||||
kerning first=87 second=111 amount=-1
|
<kerning first="86" second="101" amount="-2" />
|
||||||
kerning first=69 second=118 amount=-1
|
<kerning first="76" second="121" amount="-5" />
|
||||||
kerning first=65 second=117 amount=-2
|
<kerning first="84" second="119" amount="-2" />
|
||||||
kerning first=65 second=89 amount=-9
|
<kerning first="84" second="112" amount="-3" />
|
||||||
kerning first=72 second=89 amount=-1
|
<kerning first="87" second="111" amount="-1" />
|
||||||
kerning first=119 second=44 amount=-4
|
<kerning first="69" second="118" amount="-1" />
|
||||||
kerning first=69 second=121 amount=-1
|
<kerning first="65" second="117" amount="-2" />
|
||||||
kerning first=84 second=109 amount=-3
|
<kerning first="65" second="89" amount="-9" />
|
||||||
kerning first=84 second=122 amount=-2
|
<kerning first="72" second="89" amount="-1" />
|
||||||
kerning first=89 second=99 amount=-2
|
<kerning first="119" second="44" amount="-4" />
|
||||||
kerning first=76 second=118 amount=-5
|
<kerning first="69" second="121" amount="-1" />
|
||||||
kerning first=90 second=99 amount=-1
|
<kerning first="84" second="109" amount="-3" />
|
||||||
kerning first=90 second=103 amount=-1
|
<kerning first="84" second="122" amount="-2" />
|
||||||
kerning first=79 second=89 amount=-2
|
<kerning first="89" second="99" amount="-2" />
|
||||||
kerning first=90 second=79 amount=-1
|
<kerning first="76" second="118" amount="-5" />
|
||||||
kerning first=84 second=115 amount=-4
|
<kerning first="90" second="99" amount="-1" />
|
||||||
kerning first=76 second=65 amount=1
|
<kerning first="90" second="103" amount="-1" />
|
||||||
kerning first=90 second=100 amount=-1
|
<kerning first="79" second="89" amount="-2" />
|
||||||
kerning first=118 second=46 amount=-4
|
<kerning first="90" second="79" amount="-1" />
|
||||||
kerning first=87 second=117 amount=-1
|
<kerning first="84" second="115" amount="-4" />
|
||||||
kerning first=118 second=34 amount=1
|
<kerning first="76" second="65" amount="1" />
|
||||||
kerning first=69 second=103 amount=-1
|
<kerning first="90" second="100" amount="-1" />
|
||||||
kerning first=97 second=121 amount=-1
|
<kerning first="118" second="46" amount="-4" />
|
||||||
kerning first=39 second=111 amount=-2
|
<kerning first="87" second="117" amount="-1" />
|
||||||
kerning first=72 second=88 amount=1
|
<kerning first="118" second="34" amount="1" />
|
||||||
kerning first=76 second=87 amount=-5
|
<kerning first="69" second="103" amount="-1" />
|
||||||
kerning first=69 second=119 amount=-1
|
<kerning first="97" second="121" amount="-1" />
|
||||||
kerning first=121 second=97 amount=-1
|
<kerning first="39" second="111" amount="-2" />
|
||||||
kerning first=75 second=45 amount=-8
|
<kerning first="72" second="88" amount="1" />
|
||||||
kerning first=65 second=86 amount=-9
|
<kerning first="76" second="87" amount="-5" />
|
||||||
kerning first=46 second=34 amount=-6
|
<kerning first="69" second="119" amount="-1" />
|
||||||
kerning first=76 second=84 amount=-10
|
<kerning first="121" second="97" amount="-1" />
|
||||||
kerning first=116 second=111 amount=-1
|
<kerning first="75" second="45" amount="-8" />
|
||||||
kerning first=87 second=113 amount=-1
|
<kerning first="65" second="86" amount="-9" />
|
||||||
kerning first=69 second=100 amount=-1
|
<kerning first="46" second="34" amount="-6" />
|
||||||
kerning first=97 second=118 amount=-1
|
<kerning first="76" second="84" amount="-10" />
|
||||||
kerning first=65 second=85 amount=-2
|
<kerning first="116" second="111" amount="-1" />
|
||||||
kerning first=90 second=71 amount=-1
|
<kerning first="87" second="113" amount="-1" />
|
||||||
kerning first=68 second=46 amount=-4
|
<kerning first="69" second="100" amount="-1" />
|
||||||
kerning first=65 second=79 amount=-3
|
<kerning first="97" second="118" amount="-1" />
|
||||||
kerning first=98 second=122 amount=-1
|
<kerning first="65" second="85" amount="-2" />
|
||||||
kerning first=86 second=41 amount=1
|
<kerning first="90" second="71" amount="-1" />
|
||||||
kerning first=84 second=118 amount=-3
|
<kerning first="68" second="46" amount="-4" />
|
||||||
kerning first=70 second=118 amount=-1
|
<kerning first="65" second="79" amount="-3" />
|
||||||
kerning first=121 second=111 amount=-1
|
<kerning first="98" second="122" amount="-1" />
|
||||||
kerning first=81 second=87 amount=-1
|
<kerning first="86" second="41" amount="1" />
|
||||||
kerning first=70 second=100 amount=-1
|
<kerning first="84" second="118" amount="-3" />
|
||||||
kerning first=102 second=93 amount=1
|
<kerning first="70" second="118" amount="-1" />
|
||||||
kerning first=114 second=101 amount=-1
|
<kerning first="121" second="111" amount="-1" />
|
||||||
kerning first=88 second=45 amount=-2
|
<kerning first="81" second="87" amount="-1" />
|
||||||
kerning first=39 second=103 amount=-2
|
<kerning first="70" second="100" amount="-1" />
|
||||||
kerning first=75 second=103 amount=-1
|
<kerning first="102" second="93" amount="1" />
|
||||||
kerning first=88 second=101 amount=-1
|
<kerning first="114" second="101" amount="-1" />
|
||||||
kerning first=89 second=103 amount=-2
|
<kerning first="88" second="45" amount="-2" />
|
||||||
kerning first=110 second=39 amount=-1
|
<kerning first="39" second="103" amount="-2" />
|
||||||
kerning first=89 second=89 amount=1
|
<kerning first="75" second="103" amount="-1" />
|
||||||
kerning first=87 second=65 amount=-2
|
<kerning first="88" second="101" amount="-1" />
|
||||||
kerning first=119 second=46 amount=-4
|
<kerning first="89" second="103" amount="-2" />
|
||||||
kerning first=34 second=34 amount=-4
|
<kerning first="110" second="39" amount="-1" />
|
||||||
kerning first=88 second=79 amount=-2
|
<kerning first="89" second="89" amount="1" />
|
||||||
kerning first=79 second=86 amount=-1
|
<kerning first="87" second="65" amount="-2" />
|
||||||
kerning first=76 second=119 amount=-3
|
<kerning first="119" second="46" amount="-4" />
|
||||||
kerning first=75 second=111 amount=-1
|
<kerning first="34" second="34" amount="-4" />
|
||||||
kerning first=65 second=116 amount=-4
|
<kerning first="88" second="79" amount="-2" />
|
||||||
kerning first=86 second=65 amount=-9
|
<kerning first="79" second="86" amount="-1" />
|
||||||
kerning first=70 second=84 amount=1
|
<kerning first="76" second="119" amount="-3" />
|
||||||
kerning first=75 second=117 amount=-1
|
<kerning first="75" second="111" amount="-1" />
|
||||||
kerning first=80 second=65 amount=-9
|
<kerning first="65" second="116" amount="-4" />
|
||||||
kerning first=34 second=112 amount=-1
|
<kerning first="86" second="65" amount="-9" />
|
||||||
kerning first=102 second=99 amount=-1
|
<kerning first="70" second="84" amount="1" />
|
||||||
kerning first=118 second=97 amount=-1
|
<kerning first="75" second="117" amount="-1" />
|
||||||
kerning first=89 second=81 amount=-1
|
<kerning first="80" second="65" amount="-9" />
|
||||||
kerning first=118 second=111 amount=-1
|
<kerning first="34" second="112" amount="-1" />
|
||||||
kerning first=102 second=101 amount=-1
|
<kerning first="102" second="99" amount="-1" />
|
||||||
kerning first=114 second=44 amount=-4
|
<kerning first="118" second="97" amount="-1" />
|
||||||
kerning first=90 second=119 amount=-1
|
<kerning first="89" second="81" amount="-1" />
|
||||||
kerning first=75 second=81 amount=-4
|
<kerning first="118" second="111" amount="-1" />
|
||||||
kerning first=88 second=121 amount=-1
|
<kerning first="102" second="101" amount="-1" />
|
||||||
kerning first=34 second=110 amount=-1
|
<kerning first="114" second="44" amount="-4" />
|
||||||
kerning first=86 second=100 amount=-2
|
<kerning first="90" second="119" amount="-1" />
|
||||||
kerning first=122 second=100 amount=-1
|
<kerning first="75" second="81" amount="-4" />
|
||||||
kerning first=89 second=67 amount=-1
|
<kerning first="88" second="121" amount="-1" />
|
||||||
kerning first=90 second=118 amount=-1
|
<kerning first="34" second="110" amount="-1" />
|
||||||
kerning first=84 second=84 amount=1
|
<kerning first="86" second="100" amount="-2" />
|
||||||
kerning first=121 second=34 amount=1
|
<kerning first="122" second="100" amount="-1" />
|
||||||
kerning first=91 second=74 amount=-1
|
<kerning first="89" second="67" amount="-1" />
|
||||||
kerning first=88 second=113 amount=-1
|
<kerning first="90" second="118" amount="-1" />
|
||||||
kerning first=77 second=88 amount=1
|
<kerning first="84" second="84" amount="1" />
|
||||||
kerning first=75 second=119 amount=-2
|
<kerning first="121" second="34" amount="1" />
|
||||||
kerning first=114 second=104 amount=-1
|
<kerning first="91" second="74" amount="-1" />
|
||||||
kerning first=68 second=88 amount=-2
|
<kerning first="88" second="113" amount="-1" />
|
||||||
kerning first=121 second=44 amount=-4
|
<kerning first="77" second="88" amount="1" />
|
||||||
kerning first=81 second=89 amount=-1
|
<kerning first="75" second="119" amount="-2" />
|
||||||
kerning first=102 second=39 amount=1
|
<kerning first="114" second="104" amount="-1" />
|
||||||
kerning first=74 second=65 amount=-2
|
<kerning first="68" second="88" amount="-2" />
|
||||||
kerning first=114 second=118 amount=1
|
<kerning first="121" second="44" amount="-4" />
|
||||||
kerning first=84 second=46 amount=-8
|
<kerning first="81" second="89" amount="-1" />
|
||||||
kerning first=111 second=34 amount=-1
|
<kerning first="102" second="39" amount="1" />
|
||||||
kerning first=88 second=71 amount=-2
|
<kerning first="74" second="65" amount="-2" />
|
||||||
kerning first=88 second=99 amount=-1
|
<kerning first="114" second="118" amount="1" />
|
||||||
kerning first=84 second=74 amount=-8
|
<kerning first="84" second="46" amount="-8" />
|
||||||
kerning first=39 second=109 amount=-1
|
<kerning first="111" second="34" amount="-1" />
|
||||||
kerning first=98 second=34 amount=-1
|
<kerning first="88" second="71" amount="-2" />
|
||||||
kerning first=86 second=114 amount=-1
|
<kerning first="88" second="99" amount="-1" />
|
||||||
kerning first=88 second=81 amount=-2
|
<kerning first="84" second="74" amount="-8" />
|
||||||
kerning first=70 second=74 amount=-11
|
<kerning first="39" second="109" amount="-1" />
|
||||||
kerning first=89 second=83 amount=-1
|
<kerning first="98" second="34" amount="-1" />
|
||||||
kerning first=87 second=41 amount=1
|
<kerning first="86" second="114" amount="-1" />
|
||||||
kerning first=89 second=97 amount=-3
|
<kerning first="88" second="81" amount="-2" />
|
||||||
kerning first=89 second=87 amount=1
|
<kerning first="70" second="74" amount="-11" />
|
||||||
kerning first=67 second=125 amount=-1
|
<kerning first="89" second="83" amount="-1" />
|
||||||
kerning first=89 second=93 amount=1
|
<kerning first="87" second="41" amount="1" />
|
||||||
kerning first=80 second=118 amount=1
|
<kerning first="89" second="97" amount="-3" />
|
||||||
kerning first=107 second=100 amount=-1
|
<kerning first="89" second="87" amount="1" />
|
||||||
kerning first=114 second=34 amount=1
|
<kerning first="67" second="125" amount="-1" />
|
||||||
kerning first=89 second=109 amount=-1
|
<kerning first="89" second="93" amount="1" />
|
||||||
kerning first=89 second=45 amount=-2
|
<kerning first="80" second="118" amount="1" />
|
||||||
kerning first=70 second=44 amount=-8
|
<kerning first="107" second="100" amount="-1" />
|
||||||
kerning first=34 second=39 amount=-4
|
<kerning first="114" second="34" amount="1" />
|
||||||
kerning first=88 second=67 amount=-2
|
<kerning first="89" second="109" amount="-1" />
|
||||||
kerning first=70 second=46 amount=-8
|
<kerning first="89" second="45" amount="-2" />
|
||||||
kerning first=102 second=41 amount=1
|
<kerning first="70" second="44" amount="-8" />
|
||||||
kerning first=89 second=117 amount=-1
|
<kerning first="34" second="39" amount="-4" />
|
||||||
kerning first=89 second=111 amount=-4
|
<kerning first="88" second="67" amount="-2" />
|
||||||
kerning first=89 second=115 amount=-4
|
<kerning first="70" second="46" amount="-8" />
|
||||||
kerning first=114 second=102 amount=1
|
<kerning first="102" second="41" amount="1" />
|
||||||
kerning first=89 second=125 amount=1
|
<kerning first="89" second="117" amount="-1" />
|
||||||
kerning first=89 second=121 amount=-1
|
<kerning first="89" second="111" amount="-4" />
|
||||||
kerning first=114 second=108 amount=-1
|
<kerning first="89" second="115" amount="-4" />
|
||||||
kerning first=47 second=47 amount=-8
|
<kerning first="114" second="102" amount="1" />
|
||||||
kerning first=65 second=63 amount=-2
|
<kerning first="89" second="125" amount="1" />
|
||||||
kerning first=75 second=67 amount=-4
|
<kerning first="89" second="121" amount="-1" />
|
||||||
kerning first=87 second=100 amount=-1
|
<kerning first="114" second="108" amount="-1" />
|
||||||
kerning first=111 second=104 amount=-1
|
<kerning first="47" second="47" amount="-8" />
|
||||||
kerning first=111 second=107 amount=-1
|
<kerning first="65" second="63" amount="-2" />
|
||||||
kerning first=75 second=109 amount=-1
|
<kerning first="75" second="67" amount="-4" />
|
||||||
kerning first=87 second=114 amount=-1
|
<kerning first="87" second="100" amount="-1" />
|
||||||
kerning first=111 second=120 amount=-1
|
<kerning first="111" second="104" amount="-1" />
|
||||||
kerning first=69 second=99 amount=-1
|
<kerning first="111" second="107" amount="-1" />
|
||||||
kerning first=65 second=84 amount=-6
|
<kerning first="75" second="109" amount="-1" />
|
||||||
kerning first=39 second=97 amount=-2
|
<kerning first="87" second="114" amount="-1" />
|
||||||
kerning first=121 second=46 amount=-4
|
<kerning first="111" second="120" amount="-1" />
|
||||||
kerning first=89 second=85 amount=-3
|
<kerning first="69" second="99" amount="-1" />
|
||||||
kerning first=75 second=79 amount=-4
|
<kerning first="65" second="84" amount="-6" />
|
||||||
kerning first=107 second=99 amount=-1
|
<kerning first="39" second="97" amount="-2" />
|
||||||
kerning first=102 second=100 amount=-1
|
<kerning first="121" second="46" amount="-4" />
|
||||||
kerning first=102 second=103 amount=-1
|
<kerning first="89" second="85" amount="-3" />
|
||||||
kerning first=75 second=110 amount=-1
|
<kerning first="75" second="79" amount="-4" />
|
||||||
kerning first=39 second=110 amount=-1
|
<kerning first="107" second="99" amount="-1" />
|
||||||
kerning first=69 second=84 amount=1
|
<kerning first="102" second="100" amount="-1" />
|
||||||
kerning first=84 second=111 amount=-3
|
<kerning first="102" second="103" amount="-1" />
|
||||||
kerning first=120 second=111 amount=-1
|
<kerning first="75" second="110" amount="-1" />
|
||||||
kerning first=84 second=114 amount=-3
|
<kerning first="39" second="110" amount="-1" />
|
||||||
kerning first=112 second=120 amount=-1
|
<kerning first="69" second="84" amount="1" />
|
||||||
kerning first=79 second=84 amount=-1
|
<kerning first="84" second="111" amount="-3" />
|
||||||
kerning first=84 second=117 amount=-3
|
<kerning first="120" second="111" amount="-1" />
|
||||||
kerning first=89 second=79 amount=-1
|
<kerning first="84" second="114" amount="-3" />
|
||||||
kerning first=75 second=113 amount=-1
|
<kerning first="112" second="120" amount="-1" />
|
||||||
kerning first=39 second=113 amount=-2
|
<kerning first="79" second="84" amount="-1" />
|
||||||
kerning first=80 second=44 amount=-11
|
<kerning first="84" second="117" amount="-3" />
|
||||||
kerning first=79 second=88 amount=-2
|
<kerning first="89" second="79" amount="-1" />
|
||||||
kerning first=98 second=39 amount=-1
|
<kerning first="75" second="113" amount="-1" />
|
||||||
kerning first=65 second=118 amount=-4
|
<kerning first="39" second="113" amount="-2" />
|
||||||
kerning first=65 second=34 amount=-4
|
<kerning first="80" second="44" amount="-11" />
|
||||||
kerning first=88 second=103 amount=-1
|
<kerning first="79" second="88" amount="-2" />
|
||||||
kerning first=77 second=89 amount=-1
|
<kerning first="98" second="39" amount="-1" />
|
||||||
kerning first=39 second=101 amount=-2
|
<kerning first="65" second="118" amount="-4" />
|
||||||
kerning first=75 second=101 amount=-1
|
<kerning first="65" second="34" amount="-4" />
|
||||||
kerning first=88 second=100 amount=-1
|
<kerning first="88" second="103" amount="-1" />
|
||||||
kerning first=78 second=65 amount=-3
|
<kerning first="77" second="89" amount="-1" />
|
||||||
kerning first=87 second=44 amount=-4
|
<kerning first="39" second="101" amount="-2" />
|
||||||
kerning first=67 second=41 amount=-1
|
<kerning first="75" second="101" amount="-1" />
|
||||||
kerning first=86 second=93 amount=1
|
<kerning first="88" second="100" amount="-1" />
|
||||||
kerning first=84 second=83 amount=-1
|
<kerning first="78" second="65" amount="-3" />
|
||||||
kerning first=102 second=113 amount=-1
|
<kerning first="87" second="44" amount="-4" />
|
||||||
kerning first=34 second=111 amount=-2
|
<kerning first="67" second="41" amount="-1" />
|
||||||
kerning first=70 second=111 amount=-1
|
<kerning first="86" second="93" amount="1" />
|
||||||
kerning first=86 second=99 amount=-2
|
<kerning first="84" second="83" amount="-1" />
|
||||||
kerning first=84 second=86 amount=1
|
<kerning first="102" second="113" amount="-1" />
|
||||||
kerning first=122 second=99 amount=-1
|
<kerning first="34" second="111" amount="-2" />
|
||||||
kerning first=84 second=89 amount=1
|
<kerning first="70" second="111" amount="-1" />
|
||||||
kerning first=70 second=114 amount=-1
|
<kerning first="86" second="99" amount="-2" />
|
||||||
kerning first=86 second=74 amount=-8
|
<kerning first="84" second="86" amount="1" />
|
||||||
kerning first=89 second=38 amount=-1
|
<kerning first="122" second="99" amount="-1" />
|
||||||
kerning first=87 second=97 amount=-1
|
<kerning first="84" second="89" amount="1" />
|
||||||
kerning first=76 second=86 amount=-9
|
<kerning first="70" second="114" amount="-1" />
|
||||||
kerning first=40 second=86 amount=1
|
<kerning first="86" second="74" amount="-8" />
|
||||||
kerning first=90 second=113 amount=-1
|
<kerning first="89" second="38" amount="-1" />
|
||||||
kerning first=39 second=39 amount=-4
|
<kerning first="87" second="97" amount="-1" />
|
||||||
kerning first=111 second=39 amount=-1
|
<kerning first="76" second="86" amount="-9" />
|
||||||
kerning first=90 second=117 amount=-1
|
<kerning first="40" second="86" amount="1" />
|
||||||
kerning first=89 second=41 amount=1
|
<kerning first="90" second="113" amount="-1" />
|
||||||
kerning first=65 second=121 amount=-4
|
<kerning first="39" second="39" amount="-4" />
|
||||||
kerning first=89 second=100 amount=-2
|
<kerning first="111" second="39" amount="-1" />
|
||||||
kerning first=89 second=42 amount=-2
|
<kerning first="90" second="117" amount="-1" />
|
||||||
kerning first=76 second=117 amount=-2
|
<kerning first="89" second="41" amount="1" />
|
||||||
kerning first=69 second=111 amount=-1
|
<kerning first="65" second="121" amount="-4" />
|
||||||
kerning first=46 second=39 amount=-6
|
<kerning first="89" second="100" amount="-2" />
|
||||||
kerning first=118 second=39 amount=1
|
<kerning first="89" second="42" amount="-2" />
|
||||||
kerning first=91 second=85 amount=-1
|
<kerning first="76" second="117" amount="-2" />
|
||||||
kerning first=80 second=90 amount=-1
|
<kerning first="69" second="111" amount="-1" />
|
||||||
kerning first=90 second=81 amount=-1
|
<kerning first="46" second="39" amount="-6" />
|
||||||
kerning first=69 second=117 amount=-1
|
<kerning first="118" second="39" amount="1" />
|
||||||
kerning first=76 second=39 amount=-5
|
<kerning first="91" second="85" amount="-1" />
|
||||||
kerning first=90 second=67 amount=-1
|
<kerning first="80" second="90" amount="-1" />
|
||||||
kerning first=87 second=103 amount=-1
|
<kerning first="90" second="81" amount="-1" />
|
||||||
kerning first=84 second=120 amount=-3
|
<kerning first="69" second="117" amount="-1" />
|
||||||
kerning first=89 second=101 amount=-2
|
<kerning first="76" second="39" amount="-5" />
|
||||||
kerning first=102 second=125 amount=1
|
<kerning first="90" second="67" amount="-1" />
|
||||||
kerning first=76 second=85 amount=-2
|
<kerning first="87" second="103" amount="-1" />
|
||||||
kerning first=79 second=65 amount=-3
|
<kerning first="84" second="120" amount="-3" />
|
||||||
kerning first=65 second=71 amount=-3
|
<kerning first="89" second="101" amount="-2" />
|
||||||
kerning first=79 second=44 amount=-4
|
<kerning first="102" second="125" amount="1" />
|
||||||
kerning first=97 second=39 amount=-2
|
<kerning first="76" second="85" amount="-2" />
|
||||||
kerning first=90 second=101 amount=-1
|
<kerning first="79" second="65" amount="-3" />
|
||||||
kerning first=65 second=87 amount=-5
|
<kerning first="65" second="71" amount="-3" />
|
||||||
kerning first=79 second=46 amount=-4
|
<kerning first="79" second="44" amount="-4" />
|
||||||
kerning first=87 second=99 amount=-1
|
<kerning first="97" second="39" amount="-2" />
|
||||||
kerning first=34 second=101 amount=-2
|
<kerning first="90" second="101" amount="-1" />
|
||||||
kerning first=40 second=89 amount=1
|
<kerning first="65" second="87" amount="-5" />
|
||||||
kerning first=76 second=89 amount=-8
|
<kerning first="79" second="46" amount="-4" />
|
||||||
kerning first=69 second=113 amount=-1
|
<kerning first="87" second="99" amount="-1" />
|
||||||
kerning first=120 second=103 amount=-1
|
<kerning first="34" second="101" amount="-2" />
|
||||||
kerning first=69 second=101 amount=-1
|
<kerning first="40" second="89" amount="1" />
|
||||||
kerning first=69 second=102 amount=-1
|
<kerning first="76" second="89" amount="-8" />
|
||||||
kerning first=104 second=39 amount=-1
|
<kerning first="69" second="113" amount="-1" />
|
||||||
kerning first=80 second=121 amount=1
|
<kerning first="120" second="103" amount="-1" />
|
||||||
kerning first=86 second=46 amount=-8
|
<kerning first="69" second="101" amount="-1" />
|
||||||
kerning first=65 second=81 amount=-3
|
<kerning first="69" second="102" amount="-1" />
|
||||||
kerning first=86 second=44 amount=-8
|
<kerning first="104" second="39" amount="-1" />
|
||||||
kerning first=120 second=99 amount=-1
|
<kerning first="80" second="121" amount="1" />
|
||||||
kerning first=98 second=120 amount=-1
|
<kerning first="86" second="46" amount="-8" />
|
||||||
kerning first=39 second=115 amount=-3
|
<kerning first="65" second="81" amount="-3" />
|
||||||
kerning first=121 second=39 amount=1
|
<kerning first="86" second="44" amount="-8" />
|
||||||
kerning first=88 second=118 amount=-1
|
<kerning first="120" second="99" amount="-1" />
|
||||||
kerning first=84 second=65 amount=-6
|
<kerning first="98" second="120" amount="-1" />
|
||||||
kerning first=65 second=39 amount=-4
|
<kerning first="39" second="115" amount="-3" />
|
||||||
kerning first=84 second=79 amount=-1
|
<kerning first="121" second="39" amount="1" />
|
||||||
kerning first=65 second=119 amount=-4
|
<kerning first="88" second="118" amount="-1" />
|
||||||
kerning first=70 second=117 amount=-1
|
<kerning first="84" second="65" amount="-6" />
|
||||||
kerning first=75 second=100 amount=-1
|
<kerning first="65" second="39" amount="-4" />
|
||||||
kerning first=86 second=111 amount=-2
|
<kerning first="84" second="79" amount="-1" />
|
||||||
kerning first=122 second=111 amount=-1
|
<kerning first="65" second="119" amount="-4" />
|
||||||
kerning first=81 second=84 amount=-2
|
<kerning first="70" second="117" amount="-1" />
|
||||||
kerning first=107 second=103 amount=-1
|
<kerning first="75" second="100" amount="-1" />
|
||||||
kerning first=118 second=44 amount=-4
|
<kerning first="86" second="111" amount="-2" />
|
||||||
kerning first=87 second=46 amount=-4
|
<kerning first="122" second="111" amount="-1" />
|
||||||
kerning first=87 second=101 amount=-1
|
<kerning first="81" second="84" amount="-2" />
|
||||||
kerning first=70 second=79 amount=-2
|
<kerning first="107" second="103" amount="-1" />
|
||||||
kerning first=87 second=74 amount=-2
|
<kerning first="118" second="44" amount="-4" />
|
||||||
kerning first=123 second=74 amount=-1
|
<kerning first="87" second="46" amount="-4" />
|
||||||
kerning first=76 second=71 amount=-2
|
<kerning first="87" second="101" amount="-1" />
|
||||||
kerning first=39 second=100 amount=-2
|
<kerning first="70" second="79" amount="-2" />
|
||||||
kerning first=80 second=88 amount=-1
|
<kerning first="87" second="74" amount="-2" />
|
||||||
kerning first=84 second=121 amount=-3
|
<kerning first="123" second="74" amount="-1" />
|
||||||
kerning first=112 second=122 amount=-1
|
<kerning first="76" second="71" amount="-2" />
|
||||||
kerning first=84 second=71 amount=-1
|
<kerning first="39" second="100" amount="-2" />
|
||||||
kerning first=89 second=86 amount=1
|
<kerning first="80" second="88" amount="-1" />
|
||||||
kerning first=84 second=113 amount=-3
|
<kerning first="84" second="121" amount="-3" />
|
||||||
kerning first=120 second=113 amount=-1
|
<kerning first="112" second="122" amount="-1" />
|
||||||
kerning first=89 second=44 amount=-7
|
<kerning first="84" second="71" amount="-1" />
|
||||||
kerning first=84 second=99 amount=-3
|
<kerning first="89" second="86" amount="1" />
|
||||||
kerning first=34 second=113 amount=-2
|
<kerning first="84" second="113" amount="-3" />
|
||||||
kerning first=80 second=46 amount=-11
|
<kerning first="120" second="113" amount="-1" />
|
||||||
kerning first=86 second=117 amount=-1
|
<kerning first="89" second="44" amount="-7" />
|
||||||
kerning first=110 second=34 amount=-1
|
<kerning first="84" second="99" amount="-3" />
|
||||||
kerning first=80 second=74 amount=-7
|
<kerning first="34" second="113" amount="-2" />
|
||||||
kerning first=120 second=101 amount=-1
|
<kerning first="80" second="46" amount="-11" />
|
||||||
kerning first=73 second=88 amount=1
|
<kerning first="86" second="117" amount="-1" />
|
||||||
kerning first=108 second=111 amount=-1
|
<kerning first="110" second="34" amount="-1" />
|
||||||
kerning first=34 second=115 amount=-3
|
<kerning first="80" second="74" amount="-7" />
|
||||||
kerning first=89 second=113 amount=-2
|
<kerning first="120" second="101" amount="-1" />
|
||||||
kerning first=82 second=86 amount=-3
|
<kerning first="73" second="88" amount="1" />
|
||||||
kerning first=114 second=39 amount=1
|
<kerning first="108" second="111" amount="-1" />
|
||||||
kerning first=34 second=109 amount=-1
|
<kerning first="34" second="115" amount="-3" />
|
||||||
kerning first=84 second=101 amount=-3
|
<kerning first="89" second="113" amount="-2" />
|
||||||
kerning first=70 second=121 amount=-1
|
<kerning first="82" second="86" amount="-3" />
|
||||||
kerning first=123 second=85 amount=-1
|
<kerning first="114" second="39" amount="1" />
|
||||||
kerning first=122 second=103 amount=-1
|
<kerning first="34" second="109" amount="-1" />
|
||||||
kerning first=86 second=97 amount=-2
|
<kerning first="84" second="101" amount="-3" />
|
||||||
kerning first=82 second=89 amount=-4
|
<kerning first="70" second="121" amount="-1" />
|
||||||
kerning first=66 second=84 amount=-1
|
<kerning first="123" second="85" amount="-1" />
|
||||||
kerning first=84 second=97 amount=-4
|
<kerning first="122" second="103" amount="-1" />
|
||||||
kerning first=86 second=103 amount=-2
|
<kerning first="86" second="97" amount="-2" />
|
||||||
kerning first=70 second=113 amount=-1
|
<kerning first="82" second="89" amount="-4" />
|
||||||
kerning first=84 second=87 amount=1
|
<kerning first="66" second="84" amount="-1" />
|
||||||
kerning first=75 second=112 amount=-1
|
<kerning first="84" second="97" amount="-4" />
|
||||||
kerning first=114 second=111 amount=-1
|
<kerning first="86" second="103" amount="-2" />
|
||||||
kerning first=39 second=112 amount=-1
|
<kerning first="70" second="113" amount="-1" />
|
||||||
kerning first=107 second=101 amount=-1
|
<kerning first="84" second="87" amount="1" />
|
||||||
kerning first=82 second=84 amount=-3
|
<kerning first="75" second="112" amount="-1" />
|
||||||
kerning first=114 second=121 amount=1
|
<kerning first="114" second="111" amount="-1" />
|
||||||
kerning first=34 second=99 amount=-2
|
<kerning first="39" second="112" amount="-1" />
|
||||||
kerning first=70 second=81 amount=-2
|
<kerning first="107" second="101" amount="-1" />
|
||||||
kerning first=111 second=122 amount=-1
|
<kerning first="82" second="84" amount="-3" />
|
||||||
kerning first=84 second=67 amount=-1
|
<kerning first="114" second="121" amount="1" />
|
||||||
kerning first=111 second=108 amount=-1
|
<kerning first="34" second="99" amount="-2" />
|
||||||
kerning first=89 second=84 amount=1
|
<kerning first="70" second="81" amount="-2" />
|
||||||
kerning first=76 second=79 amount=-2
|
<kerning first="111" second="122" amount="-1" />
|
||||||
kerning first=85 second=65 amount=-2
|
<kerning first="84" second="67" amount="-1" />
|
||||||
kerning first=44 second=34 amount=-6
|
<kerning first="111" second="108" amount="-1" />
|
||||||
kerning first=65 second=67 amount=-3
|
<kerning first="89" second="84" amount="1" />
|
||||||
kerning first=109 second=34 amount=-1
|
<kerning first="76" second="79" amount="-2" />
|
||||||
kerning first=114 second=103 amount=-1
|
<kerning first="85" second="65" amount="-2" />
|
||||||
kerning first=78 second=89 amount=-1
|
<kerning first="44" second="34" amount="-6" />
|
||||||
kerning first=89 second=114 amount=-1
|
<kerning first="65" second="67" amount="-3" />
|
||||||
kerning first=89 second=112 amount=-1
|
<kerning first="109" second="34" amount="-1" />
|
||||||
kerning first=34 second=65 amount=-4
|
<kerning first="114" second="103" amount="-1" />
|
||||||
kerning first=70 second=65 amount=-11
|
<kerning first="78" second="89" amount="-1" />
|
||||||
kerning first=81 second=86 amount=-1
|
<kerning first="89" second="114" amount="-1" />
|
||||||
kerning first=114 second=119 amount=1
|
<kerning first="89" second="112" amount="-1" />
|
||||||
kerning first=89 second=102 amount=-1
|
<kerning first="34" second="65" amount="-4" />
|
||||||
kerning first=84 second=45 amount=-8
|
<kerning first="70" second="65" amount="-11" />
|
||||||
kerning first=86 second=125 amount=1
|
<kerning first="81" second="86" amount="-1" />
|
||||||
kerning first=70 second=67 amount=-2
|
<kerning first="114" second="119" amount="1" />
|
||||||
kerning first=89 second=116 amount=-1
|
<kerning first="89" second="102" amount="-1" />
|
||||||
kerning first=102 second=34 amount=1
|
<kerning first="84" second="45" amount="-8" />
|
||||||
kerning first=114 second=99 amount=-1
|
<kerning first="86" second="125" amount="1" />
|
||||||
kerning first=67 second=84 amount=-1
|
<kerning first="70" second="67" amount="-2" />
|
||||||
kerning first=114 second=113 amount=-1
|
<kerning first="89" second="116" amount="-1" />
|
||||||
kerning first=89 second=122 amount=-1
|
<kerning first="102" second="34" amount="1" />
|
||||||
kerning first=89 second=118 amount=-1
|
<kerning first="114" second="99" amount="-1" />
|
||||||
kerning first=70 second=71 amount=-2
|
<kerning first="67" second="84" amount="-1" />
|
||||||
kerning first=114 second=107 amount=-1
|
<kerning first="114" second="113" amount="-1" />
|
||||||
kerning first=89 second=120 amount=-1
|
<kerning first="89" second="122" amount="-1" />
|
||||||
|
<kerning first="89" second="118" amount="-1" />
|
||||||
|
<kerning first="70" second="71" amount="-2" />
|
||||||
|
<kerning first="114" second="107" amount="-1" />
|
||||||
|
<kerning first="89" second="120" amount="-1" />
|
||||||
|
</kernings>
|
||||||
|
</font>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import sm from "sitemap";
|
import sm from "sitemap";
|
||||||
import OperationConfig from "../../core/config/OperationConfig.json" assert {type: "json"};
|
import OperationConfig from "../../core/config/OperationConfig.json" assert { type: "json" };
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an XML sitemap for all CyberChef operations and a number of recipes.
|
* Generates an XML sitemap for all CyberChef operations and a number of recipes.
|
||||||
@@ -10,25 +9,25 @@ import OperationConfig from "../../core/config/OperationConfig.json" assert {typ
|
|||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const smStream = new sm.SitemapStream({
|
const baseUrl = "https://gchq.github.io/CyberChef/";
|
||||||
hostname: "https://gchq.github.io/CyberChef",
|
|
||||||
});
|
const smStream = new sm.SitemapStream({});
|
||||||
|
|
||||||
smStream.write({
|
smStream.write({
|
||||||
url: "/",
|
url: baseUrl,
|
||||||
changefreq: "weekly",
|
changefreq: "weekly",
|
||||||
priority: 1.0
|
priority: 1.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const op in OperationConfig) {
|
for (const op in OperationConfig) {
|
||||||
smStream.write({
|
smStream.write({
|
||||||
url: `/?op=${encodeURIComponent(op)}`,
|
url: `${baseUrl}?op=${encodeURIComponent(op)}`,
|
||||||
changeFreq: "yearly",
|
changeFreq: "yearly",
|
||||||
priority: 0.5
|
priority: 0.5,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
smStream.end();
|
smStream.end();
|
||||||
|
|
||||||
sm.streamToPromise(smStream).then(
|
sm.streamToPromise(smStream).then(
|
||||||
buffer => console.log(buffer.toString()) // eslint-disable-line no-console
|
(buffer) => console.log(buffer.toString()), // eslint-disable-line no-console
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -151,8 +151,20 @@ class InputWaiter {
|
|||||||
// Event handlers
|
// Event handlers
|
||||||
EditorView.domEventHandlers({
|
EditorView.domEventHandlers({
|
||||||
paste(event, view) {
|
paste(event, view) {
|
||||||
|
const clipboardData = event.clipboardData;
|
||||||
|
const items = clipboardData.items;
|
||||||
|
const files = [];
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const item = items[i];
|
||||||
|
if (item.kind === "file") {
|
||||||
|
const file = item.getAsFile();
|
||||||
|
files.push(file);
|
||||||
|
|
||||||
|
event.preventDefault(); // Prevent the default paste behavior
|
||||||
|
}
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
self.afterPaste(event);
|
self.afterPaste(files);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -914,9 +926,12 @@ class InputWaiter {
|
|||||||
* Handler that fires just after input paste events.
|
* Handler that fires just after input paste events.
|
||||||
* Checks whether the EOL separator or character encoding should be updated.
|
* Checks whether the EOL separator or character encoding should be updated.
|
||||||
*
|
*
|
||||||
* @param {event} e
|
* @param {File[]} files - An array of any files that were included in the paste event
|
||||||
*/
|
*/
|
||||||
afterPaste(e) {
|
afterPaste(files) {
|
||||||
|
if (files.length > 0) {
|
||||||
|
this.loadUIFiles(files);
|
||||||
|
}
|
||||||
// If EOL has been fixed, skip this.
|
// If EOL has been fixed, skip this.
|
||||||
if (this.eolState > 1) return;
|
if (this.eolState > 1) return;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Dish from "../../core/Dish.mjs";
|
import Dish from "../../core/Dish.mjs";
|
||||||
|
import DishError from "../../core/errors/DishError.mjs";
|
||||||
|
import { CHR_ENC_SIMPLE_REVERSE_LOOKUP } from "../../core/lib/ChrEnc.mjs";
|
||||||
import Utils from "../../core/Utils.mjs";
|
import Utils from "../../core/Utils.mjs";
|
||||||
import cptable from "codepage";
|
import cptable from "codepage";
|
||||||
import loglevelMessagePrefix from "loglevel-message-prefix";
|
import loglevelMessagePrefix from "loglevel-message-prefix";
|
||||||
@@ -98,7 +100,7 @@ async function bufferToStr(data) {
|
|||||||
try {
|
try {
|
||||||
str = cptable.utils.decode(data.encoding, new Uint8Array(data.buffer));
|
str = cptable.utils.decode(data.encoding, new Uint8Array(data.buffer));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
str = err;
|
str = new DishError(`Error decoding buffer with encoding ${CHR_ENC_SIMPLE_REVERSE_LOOKUP[data.encoding]}: ${err.message}`).toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ module.exports = {
|
|||||||
testOp(browser, "AND", "test input", "4$04 $044", [{ "option": "Hex", "string": "34" }]);
|
testOp(browser, "AND", "test input", "4$04 $044", [{ "option": "Hex", "string": "34" }]);
|
||||||
testOp(browser, "Add line numbers", "test input", "1 test input");
|
testOp(browser, "Add line numbers", "test input", "1 test input");
|
||||||
testOp(browser, ["From Hex", "Add Text To Image", "To Base64"], Images.PNG_HEX, Images.PNG_CHEF_B64, [[], ["Chef", "Center", "Middle", 0, 0, 16], []]);
|
testOp(browser, ["From Hex", "Add Text To Image", "To Base64"], Images.PNG_HEX, Images.PNG_CHEF_B64, [[], ["Chef", "Center", "Middle", 0, 0, 16], []]);
|
||||||
|
testOp(browser, ["From Hex", "Dither Image", "SHA2"], Images.PNG_HEX, "cbf587a78915cfb14546ba83080b13e5054800802488dd0cb786b8951e7dc0b48f055260917bd0ccfc075e422b9d6aff112948562653995d74e70f0b66367ac3", [[], [], []]);
|
||||||
|
testOp(browser, ["From Hex", "Generate Image", "SHA2"], Images.PNG_HEX, "2c451762a6c9192fd31dc80765eab3f447be70ea51f6fdb6911ade4d89d4a98bd0a1ff00b08d76aac472faeceb54b66092e3f3be7bbf899bf3e55ca9c96a56aa", [[], [], []]);
|
||||||
|
testOp(browser, ["From Hex", "Image Hue/Saturation/Lightness", "SHA2"], Images.PNG_HEX, "522dfc0bbef00e05c5d6861a002039fa2952e4bbb7fe8d21d0d538ef6f9d65da82065929b4150dc5b8b49460ee6c9bef7f660b86f8d4e7442a07c61c0a152a4b", [[], [50, 50, 50], []]);
|
||||||
|
testOp(browser, ["From Hex", "Resize Image", "SHA2"], Images.PNG_HEX, "654bfbf0a0537c901459c4bc22c5fb0bacbf01af775a0733e3a1c46cda5b699bcc4ed85322d813c7bb9b245d62d64425c0766fe03d3d20bc63634e2a4df17626", [[], [64, 64], []]);
|
||||||
testOp(browser, "Adler-32 Checksum", "test input", "16160411");
|
testOp(browser, "Adler-32 Checksum", "test input", "16160411");
|
||||||
testOp(browser, "Affine Cipher Decode", "test input", "rcqr glnsr", [1, 2]);
|
testOp(browser, "Affine Cipher Decode", "test input", "rcqr glnsr", [1, 2]);
|
||||||
testOp(browser, "Affine Cipher Encode", "test input", "gndg zoujg", [3, 1]);
|
testOp(browser, "Affine Cipher Encode", "test input", "gndg zoujg", [3, 1]);
|
||||||
@@ -58,7 +62,10 @@ module.exports = {
|
|||||||
testOp(browser, "Bit shift right", "test input", ":29:\u0010478::");
|
testOp(browser, "Bit shift right", "test input", ":29:\u0010478::");
|
||||||
testOp(browser, "Blowfish Decrypt", "10884e15427dd84ec35204e9c8e921ae", "test_output", [{"option": "Hex", "string": "1234567801234567"}, {"option": "Hex", "string": "0011223344556677"}, "CBC", "Hex", "Raw"]);
|
testOp(browser, "Blowfish Decrypt", "10884e15427dd84ec35204e9c8e921ae", "test_output", [{"option": "Hex", "string": "1234567801234567"}, {"option": "Hex", "string": "0011223344556677"}, "CBC", "Hex", "Raw"]);
|
||||||
testOp(browser, "Blowfish Encrypt", "test input", "f0fadbd1d90d774f714248cf26b96410", [{"option": "Hex", "string": "1234567801234567"}, {"option": "Hex", "string": "0011223344556677"}, "CBC", "Raw", "Hex"]);
|
testOp(browser, "Blowfish Encrypt", "test input", "f0fadbd1d90d774f714248cf26b96410", [{"option": "Hex", "string": "1234567801234567"}, {"option": "Hex", "string": "0011223344556677"}, "CBC", "Raw", "Hex"]);
|
||||||
testOp(browser, ["From Hex", "Blur Image", "To Base64"], Images.PNG_HEX, Images.PNG_BLUR_B64);
|
testOp(browser, ["From Hex", "Blur Image", "SHA2"], Images.PNG_HEX, "24f2e89f3e00cc35f551bbc48ea82e76474946ce0282183494d1ca3d3b0012c27b6102c4368ae056dc7fecb6df7886d86ff3d29b7e5965493f30c371eee9a24e");
|
||||||
|
testOp(browser, ["From Hex", "Blur Image", "SHA2"], Images.PNG_HEX, "2c49d89fc10c94352c9a19f82de353c37928831d6f976a6b36eb918825a0ba027980801838228a4a0da63f1886e4fa59b6666f992ad2d2b7d4622253dc034052", [[], [5, "Gaussian"], []]);
|
||||||
|
testOp(browser, ["From Hex", "Sharpen Image", "SHA2"], Images.PNG_HEX, "acc7027642c2eeb67d7356a80ed8a1bdce9adabf656ea1294e47723f506626a7aa41f1660fa844a1e1e83b17180017ab0d5bccd7f6a341692832020dc887eaa5");
|
||||||
|
testOp(browser, ["From Hex", "Contain Image", "SHA2"], Images.PNG_HEX, "cb871ad0722d487d56a2b18247b1aa30ecc244eb717e08e23a55cae78759553312dc1717196d7cb9daa04743e57c56fc3901ba92be5a68fb03c377f718e8efe7");
|
||||||
testOpHtml(browser, "Bombe", "XTSYN WAEUG EZALY NRQIM AMLZX MFUOD AWXLY LZCUZ QOQBQ JLCPK NDDRW F", "table tr:last-child td:first-child", "ECG", ["3-rotor", "LEYJVCNIXWPBQMDRTAKZGFUHOS", "BDFHJLCPRTXVZNYEIWGAKMUSQO<W", "AJDKSIRUXBLHWTMCQGZNPYFVOE<F", "ESOVPZJAYQUIRHXLNFTGKDCMWB<K", "AY BR CU DH EQ FS GL IP JX KN MO TZ VW", "HELLO CYBER CHEFU SER", 0, true]);
|
testOpHtml(browser, "Bombe", "XTSYN WAEUG EZALY NRQIM AMLZX MFUOD AWXLY LZCUZ QOQBQ JLCPK NDDRW F", "table tr:last-child td:first-child", "ECG", ["3-rotor", "LEYJVCNIXWPBQMDRTAKZGFUHOS", "BDFHJLCPRTXVZNYEIWGAKMUSQO<W", "AJDKSIRUXBLHWTMCQGZNPYFVOE<F", "ESOVPZJAYQUIRHXLNFTGKDCMWB<K", "AY BR CU DH EQ FS GL IP JX KN MO TZ VW", "HELLO CYBER CHEFU SER", 0, true]);
|
||||||
testOp(browser, ["Bzip2 Compress", "To Hex"], "test input", "42 5a 68 39 31 41 59 26 53 59 cf 96 82 1d 00 00 03 91 80 40 00 02 21 4e 00 20 00 21 90 c2 10 c0 88 33 92 8e df 17 72 45 38 50 90 cf 96 82 1d");
|
testOp(browser, ["Bzip2 Compress", "To Hex"], "test input", "42 5a 68 39 31 41 59 26 53 59 cf 96 82 1d 00 00 03 91 80 40 00 02 21 4e 00 20 00 21 90 c2 10 c0 88 33 92 8e df 17 72 45 38 50 90 cf 96 82 1d");
|
||||||
testOp(browser, ["From Hex", "Bzip2 Decompress"], "425a68393141592653597b0884b7000003038000008200ce00200021a647a4218013709517c5dc914e14241ec2212dc0", "test_output", [[], [true]]);
|
testOp(browser, ["From Hex", "Bzip2 Decompress"], "425a68393141592653597b0884b7000003038000008200ce00200021a647a4218013709517c5dc914e14241ec2212dc0", "test_output", [[], [true]]);
|
||||||
|
|||||||
@@ -20,4 +20,10 @@ TestRegister.addApiTests([
|
|||||||
assert.equal(Utils.parseEscapedChars("\\\\\\'"), "\\'");
|
assert.equal(Utils.parseEscapedChars("\\\\\\'"), "\\'");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
it("Utils: should replace delete character", () => {
|
||||||
|
assert.equal(
|
||||||
|
Utils.printable("\x7e\x7f\x80\xa7", false, true),
|
||||||
|
"\x7e...",
|
||||||
|
);
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -345,6 +345,42 @@ TestRegister.addApiTests([
|
|||||||
assert.strictEqual(result.toString(), "begin_something_aaaaaaaaaaaaaa_end_something");
|
assert.strictEqual(result.toString(), "begin_something_aaaaaaaaaaaaaa_end_something");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept operation names from Chef Website which contain forward slash", () => {
|
||||||
|
const result = chef.bake("I'll have the test salmon", [
|
||||||
|
{ "op": "Find / Replace",
|
||||||
|
"args": [{ "option": "Regex", "string": "test" }, "good", true, false, true, false]}
|
||||||
|
]);
|
||||||
|
assert.strictEqual(result.toString(), "I'll have the good salmon");
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept operation names from Chef Website which contain a hyphen", () => {
|
||||||
|
const result = chef.bake("I'll have the test salmon", [
|
||||||
|
{ "op": "Adler-32 Checksum",
|
||||||
|
"args": [] }
|
||||||
|
]);
|
||||||
|
assert.strictEqual(result.toString(), "6e4208f8");
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("chef.bake: should accept operation names from Chef Website which contain a period", () => {
|
||||||
|
const result = chef.bake("30 13 02 01 05 16 0e 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f", [
|
||||||
|
{ "op": "Parse ASN.1 hex string",
|
||||||
|
"args": [0, 32] }
|
||||||
|
]);
|
||||||
|
assert.strictEqual(result.toString(), `SEQUENCE
|
||||||
|
INTEGER 05
|
||||||
|
IA5String 'Anybody there?'
|
||||||
|
`);
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("Excluded operations: throw a sensible error when you try and call one", () => {
|
||||||
|
try {
|
||||||
|
chef.fork();
|
||||||
|
} catch (e) {
|
||||||
|
assert.strictEqual(e.type, "ExcludedOperationError");
|
||||||
|
assert.strictEqual(e.message, "Sorry, the Fork operation is not available in the Node.js version of CyberChef.");
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
it("chef.bake: cannot accept flowControl operations in recipe", () => {
|
it("chef.bake: cannot accept flowControl operations in recipe", () => {
|
||||||
assert.throws(() => chef.bake("some input", "magic"), {
|
assert.throws(() => chef.bake("some input", "magic"), {
|
||||||
name: "TypeError",
|
name: "TypeError",
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import "./tests/Base64.mjs";
|
|||||||
import "./tests/Base85.mjs";
|
import "./tests/Base85.mjs";
|
||||||
import "./tests/Base92.mjs";
|
import "./tests/Base92.mjs";
|
||||||
import "./tests/BCD.mjs";
|
import "./tests/BCD.mjs";
|
||||||
|
import "./tests/Bech32.mjs";
|
||||||
import "./tests/BitwiseOp.mjs";
|
import "./tests/BitwiseOp.mjs";
|
||||||
import "./tests/BLAKE2b.mjs";
|
import "./tests/BLAKE2b.mjs";
|
||||||
import "./tests/BLAKE2s.mjs";
|
import "./tests/BLAKE2s.mjs";
|
||||||
|
|||||||
702
tests/operations/tests/Bech32.mjs
Normal file
702
tests/operations/tests/Bech32.mjs
Normal file
@@ -0,0 +1,702 @@
|
|||||||
|
/**
|
||||||
|
* Bech32 tests.
|
||||||
|
*
|
||||||
|
* Test vectors from official BIP specifications:
|
||||||
|
* BIP-0173: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
|
||||||
|
* BIP-0350: https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki
|
||||||
|
*
|
||||||
|
* AGE key test vectors from:
|
||||||
|
* https://asecuritysite.com/age/go_age5
|
||||||
|
*
|
||||||
|
* @author Medjedtxm
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
// ============= To Bech32 Tests =============
|
||||||
|
{
|
||||||
|
name: "To Bech32: empty input",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "bc1gmk9yu",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32: single byte",
|
||||||
|
input: "A",
|
||||||
|
expectedOutput: "bc1gyufle22",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32: Hello",
|
||||||
|
input: "Hello",
|
||||||
|
expectedOutput: "bc1fpjkcmr0gzsgcg",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32: custom HRP",
|
||||||
|
input: "test",
|
||||||
|
expectedOutput: "custom1w3jhxaq593qur",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["custom", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32: testnet HRP",
|
||||||
|
input: "data",
|
||||||
|
expectedOutput: "tb1v3shgcg3x07jr",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["tb", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32m: empty input",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "bc1a8xfp7",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32m", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32m: single byte",
|
||||||
|
input: "A",
|
||||||
|
expectedOutput: "bc1gyf4040g",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32m", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32m: Hello",
|
||||||
|
input: "Hello",
|
||||||
|
expectedOutput: "bc1fpjkcmr0a7qya2",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32m", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32: empty HRP error",
|
||||||
|
input: "test",
|
||||||
|
expectedOutput: "Human-Readable Part (HRP) cannot be empty.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= From Bech32 Tests (Raw output) =============
|
||||||
|
{
|
||||||
|
name: "From Bech32: decode single byte (Raw)",
|
||||||
|
input: "bc1gyufle22",
|
||||||
|
expectedOutput: "A",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: decode Hello (Raw)",
|
||||||
|
input: "bc1fpjkcmr0gzsgcg",
|
||||||
|
expectedOutput: "Hello",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: auto-detect Bech32 (Raw)",
|
||||||
|
input: "bc1fpjkcmr0gzsgcg",
|
||||||
|
expectedOutput: "Hello",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32m: decode Hello (Raw)",
|
||||||
|
input: "bc1fpjkcmr0a7qya2",
|
||||||
|
expectedOutput: "Hello",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: auto-detect Bech32m (Raw)",
|
||||||
|
input: "bc1fpjkcmr0a7qya2",
|
||||||
|
expectedOutput: "Hello",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: uppercase input (Raw)",
|
||||||
|
input: "BC1FPJKCMR0GZSGCG",
|
||||||
|
expectedOutput: "Hello",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: custom HRP (Raw)",
|
||||||
|
input: "custom1w3jhxaq593qur",
|
||||||
|
expectedOutput: "test",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: empty input",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: empty data part (Hex)",
|
||||||
|
input: "bc1gmk9yu",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= From Bech32 HRP Output Tests =============
|
||||||
|
{
|
||||||
|
name: "From Bech32: HRP: Hex output format",
|
||||||
|
input: "bc1fpjkcmr0gzsgcg",
|
||||||
|
expectedOutput: "bc: 48656c6c6f",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: JSON output format",
|
||||||
|
input: "bc1fpjkcmr0gzsgcg",
|
||||||
|
expectedOutput: "{\n \"hrp\": \"bc\",\n \"encoding\": \"Bech32\",\n \"data\": \"48656c6c6f\"\n}",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "JSON"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: Hex output format",
|
||||||
|
input: "bc1fpjkcmr0gzsgcg",
|
||||||
|
expectedOutput: "48656c6c6f",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= AGE Key Test Vectors =============
|
||||||
|
// From: https://asecuritysite.com/age/go_age5
|
||||||
|
{
|
||||||
|
name: "From Bech32: AGE public key 1 (HRP: Hex)",
|
||||||
|
input: "age1kk86t4lr4s9uwvnqjzp2e35rflvcpnjt33q99547ct23xzk0ssss3ma49j",
|
||||||
|
expectedOutput: "age: b58fa5d7e3ac0bc732609082acc6834fd980ce4b8c4052d2bec2d5130acf8421",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: AGE private key 1 (HRP: Hex)",
|
||||||
|
input: "AGE-SECRET-KEY-1Z5N23X54Y4E9NLMPNH6EZDQQX9V883TMKJ3ZJF5QXXMKNZ2RPFXQUQF74G",
|
||||||
|
expectedOutput: "age-secret-key-: 1526a89a95257259ff619df5913400315873c57bb4a229268031b76989430a4c",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: AGE public key 2 (HRP: Hex)",
|
||||||
|
input: "age1nwt7gkq7udvalagqn7l8a4jgju7wtenkg925pvuqvn7cfcry6u2qkae4ad",
|
||||||
|
expectedOutput: "age: 9b97e4581ee359dff5009fbe7ed648973ce5e676415540b38064fd84e064d714",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: AGE private key 2 (HRP: Hex)",
|
||||||
|
input: "AGE-SECRET-KEY-137M0YVE3CL6M8C4ET9L2KU67FPQHJZTW547QD5CK0R5A5T09ZGJSQGR9LX",
|
||||||
|
expectedOutput: "age-secret-key-: 8fb6f23331c7f5b3e2b9597eab735e484179096ea57c06d31678e9da2de51225",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: AGE public key 1 (JSON)",
|
||||||
|
input: "age1kk86t4lr4s9uwvnqjzp2e35rflvcpnjt33q99547ct23xzk0ssss3ma49j",
|
||||||
|
expectedOutput: "{\n \"hrp\": \"age\",\n \"encoding\": \"Bech32\",\n \"data\": \"b58fa5d7e3ac0bc732609082acc6834fd980ce4b8c4052d2bec2d5130acf8421\"\n}",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "JSON"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= Error Cases =============
|
||||||
|
{
|
||||||
|
name: "From Bech32: mixed case error",
|
||||||
|
input: "bc1FpjKcmr0gzsgcg",
|
||||||
|
expectedOutput: "Invalid Bech32 string: mixed case is not allowed. Use all uppercase or all lowercase.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: no separator error",
|
||||||
|
input: "noseparator",
|
||||||
|
expectedOutput: "Invalid Bech32 string: no separator '1' found.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: empty HRP error",
|
||||||
|
input: "1qqqqqqqqqqqqqqqq",
|
||||||
|
expectedOutput: "Invalid Bech32 string: Human-Readable Part (HRP) cannot be empty.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: invalid checksum",
|
||||||
|
input: "bc1fpjkcmr0gzsgcx",
|
||||||
|
expectedOutput: "Invalid Bech32/Bech32m string: checksum verification failed.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: data too short",
|
||||||
|
input: "bc1abc",
|
||||||
|
expectedOutput: "Invalid Bech32 string: data part is too short (minimum 6 characters for checksum).",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: wrong encoding specified",
|
||||||
|
input: "bc1fpjkcmr0gzsgcg",
|
||||||
|
expectedOutput: "Invalid Bech32m checksum.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= BIP-0173 Test Vectors (Bech32) =============
|
||||||
|
{
|
||||||
|
name: "From Bech32: BIP-0173 A12UEL5L (empty data)",
|
||||||
|
input: "A12UEL5L",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: BIP-0173 a12uel5l lowercase",
|
||||||
|
input: "a12uel5l",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: BIP-0173 long HRP with bio",
|
||||||
|
input: "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: BIP-0173 abcdef with data",
|
||||||
|
input: "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw",
|
||||||
|
expectedOutput: "abcdef: 00443214c74254b635cf84653a56d7c675be77df",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: BIP-0173 split HRP",
|
||||||
|
input: "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w",
|
||||||
|
expectedOutput: "split: c5f38b70305f519bf66d85fb6cf03058f3dde463ecd7918f2dc743918f2d",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: BIP-0173 question mark HRP",
|
||||||
|
input: "?1ezyfcl",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= BIP-0350 Test Vectors (Bech32m) =============
|
||||||
|
{
|
||||||
|
name: "From Bech32m: BIP-0350 A1LQFN3A (empty data)",
|
||||||
|
input: "A1LQFN3A",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32m: BIP-0350 a1lqfn3a lowercase",
|
||||||
|
input: "a1lqfn3a",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32m: BIP-0350 long HRP",
|
||||||
|
input: "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32m: BIP-0350 abcdef with data",
|
||||||
|
input: "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx",
|
||||||
|
expectedOutput: "abcdef: ffbbcdeb38bdab49ca307b9ac5a928398a418820",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32m: BIP-0350 split HRP",
|
||||||
|
input: "split1checkupstagehandshakeupstreamerranterredcaperredlc445v",
|
||||||
|
expectedOutput: "split: c5f38b70305f519bf66d85fb6cf03058f3dde463ecd7918f2dc743918f2d",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "HRP: Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32m: BIP-0350 question mark HRP",
|
||||||
|
input: "?1v759aa",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= Bitcoin scriptPubKey Output Format Tests =============
|
||||||
|
// Test vectors from BIP-0173 and BIP-0350
|
||||||
|
{
|
||||||
|
name: "From Bech32: Bitcoin scriptPubKey v0 P2WPKH",
|
||||||
|
input: "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
|
||||||
|
expectedOutput: "0014751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Bitcoin scriptPubKey"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: Bitcoin scriptPubKey v0 P2WSH",
|
||||||
|
input: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
|
||||||
|
expectedOutput: "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Bitcoin scriptPubKey"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: Bitcoin scriptPubKey v1 Taproot (Bech32m)",
|
||||||
|
input: "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0",
|
||||||
|
expectedOutput: "512079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Bitcoin scriptPubKey"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: Bitcoin scriptPubKey v16",
|
||||||
|
input: "BC1SW50QGDZ25J",
|
||||||
|
expectedOutput: "6002751e",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Bitcoin scriptPubKey"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Bech32: Bitcoin scriptPubKey v2",
|
||||||
|
input: "bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs",
|
||||||
|
expectedOutput: "5210751e76e8199196d454941c45d1b3a323",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Bitcoin scriptPubKey"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= Bitcoin SegWit Encoding Tests =============
|
||||||
|
{
|
||||||
|
name: "To Bech32: Bitcoin SegWit v0 P2WPKH",
|
||||||
|
input: "751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||||
|
expectedOutput: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32", "Hex", "Bitcoin SegWit", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32: Bitcoin SegWit v0 P2WSH testnet",
|
||||||
|
input: "1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
|
||||||
|
expectedOutput: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["tb", "Bech32", "Hex", "Bitcoin SegWit", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32m: Bitcoin Taproot v1",
|
||||||
|
input: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
||||||
|
expectedOutput: "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32m", "Hex", "Bitcoin SegWit", 1]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To Bech32m: Bitcoin SegWit v16",
|
||||||
|
input: "751e",
|
||||||
|
expectedOutput: "bc1sw50qgdz25j",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32m", "Hex", "Bitcoin SegWit", 16]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= Round-trip Tests =============
|
||||||
|
{
|
||||||
|
name: "Bech32: encode then decode round-trip",
|
||||||
|
input: "The quick brown fox jumps over the lazy dog",
|
||||||
|
expectedOutput: "The quick brown fox jumps over the lazy dog",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["test", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bech32m: encode then decode round-trip",
|
||||||
|
input: "The quick brown fox jumps over the lazy dog",
|
||||||
|
expectedOutput: "The quick brown fox jumps over the lazy dog",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["test", "Bech32m", "Raw bytes", "Generic", 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32m", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bech32: binary data round-trip",
|
||||||
|
input: "0001020304050607",
|
||||||
|
expectedOutput: "0001020304050607",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["Auto"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["bc", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Bech32", "Hex"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bech32: auto-detect round-trip",
|
||||||
|
input: "CyberChef Bech32 Test",
|
||||||
|
expectedOutput: "CyberChef Bech32 Test",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["cyberchef", "Bech32", "Raw bytes", "Generic", 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bech32m: auto-detect round-trip",
|
||||||
|
input: "CyberChef Bech32m Test",
|
||||||
|
expectedOutput: "CyberChef Bech32m Test",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Bech32",
|
||||||
|
"args": ["cyberchef", "Bech32m", "Raw bytes", "Generic", 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "From Bech32",
|
||||||
|
"args": ["Auto-detect", "Raw"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
@@ -322,8 +322,21 @@ TestRegister.addTests([
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
expectedMatch: /^Invalid JPath expression: jsonPath: self is not defined:/
|
expectedMatch: /^Invalid JPath expression: Unexpected "{" at character 1/
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "JPath Expression: Script-based RCE",
|
||||||
|
input: "[{}]",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "JPath expression",
|
||||||
|
"args": [
|
||||||
|
"$..[?(p=\"console.log(this.process.mainModule.require('child_process').execSync('id').toString())\";a=''[['constructor']][['constructor']](p);a())]",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
expectedMatch: /^Invalid JPath expression: jsonPath: Cannot read properties of {2}\(reading 'constructor'\): / },
|
||||||
{
|
{
|
||||||
name: "CSS selector",
|
name: "CSS selector",
|
||||||
input: '<div id="test">\n<p class="a">hello</p>\n<p>world</p>\n<p class="a">again</p>\n</div>',
|
input: '<div id="test">\n<p class="a">hello</p>\n<p>world</p>\n<p class="a">again</p>\n</div>',
|
||||||
|
|||||||
@@ -43,6 +43,20 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ASCII to Hex with percent deliminator",
|
||||||
|
input: "aberystwyth",
|
||||||
|
expectedOutput: "%61%62%65%72%79%73%74%77%79%74%68",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Hex",
|
||||||
|
"args": [
|
||||||
|
"Percent",
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ASCII to 0x Hex with comma and line breaks",
|
name: "ASCII to 0x Hex with comma and line breaks",
|
||||||
input: "aberystwyth",
|
input: "aberystwyth",
|
||||||
|
|||||||
@@ -152,6 +152,17 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "From Hexdump: xxd format, odd number of bytes",
|
||||||
|
input: "00000000: 6162 6364 65 abcde",
|
||||||
|
expectedOutput: "abcde",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hexdump",
|
||||||
|
args: []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "From Hexdump: Wireshark",
|
name: "From Hexdump: Wireshark",
|
||||||
input: `00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........
|
input: `00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........
|
||||||
|
|||||||
@@ -30,6 +30,28 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "JA4 Fingerprint: TLS 1.3 with whitespace-only ALPN",
|
||||||
|
input: "1603010200010001fc0303ed338a18e711d670cdc472ff570a5b59f1ace12e5365918bf68bf845019147b6207e4437bfb062d98a4aeb753be8f09022a9dc9413d7694dad4db57fcdcf076e820024130213031301c02cc030c02bc02fcca9cca8c024c028c023c027009f009e006b006700ff0100018f0000001800160000136465762e636f6e74656e74677261622e6e6574000b000403000102000a00160014001d0017001e00190018010001010102010301040023000000100004000201200016000000170000000d002a0028040305030603080708080809080a080b080408050806040105010601030303010302040205020602002b00050403040303002d00020101003300260024001d00207af053336d5e2c1675aa4c6ce78de5e5fdbd296538113f051ea17ccb64289f22001500d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "t13d181220_85036bcba153_d41ae481755e",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "JA4 Fingerprint",
|
||||||
|
"args": ["Hex", "JA4"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "JA4 Fingerprint: TLS 1.3 with ALPN containing a whitespace",
|
||||||
|
input: "1603010200010001fc0303273682a603be3f64dd025df4ad0f4d2d13043c3a233405a68bb29b865808749a20f4dfc40242b2fce38fae26c516ef9bef20a1b9349eba3c003780168d72471f5c0024130213031301c02cc030c02bc02fcca9cca8c024c028c023c027009f009e006b006700ff0100018f0000001800160000136465762e636f6e74656e74677261622e6e6574000b000403000102000a00160014001d0017001e0019001801000101010201030104002300000010000500030261200016000000170000000d002a0028040305030603080708080809080a080b080408050806040105010601030303010302040205020602002b00050403040303002d00020101003300260024001d0020f4dd1567bd858d3a9f1d88db1fee6a10ab0ea1aa6afe96ffb6a7c4d79dea4075001500d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "t13d181260_85036bcba153_d41ae481755e",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "JA4 Fingerprint",
|
||||||
|
"args": ["Hex", "JA4"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "JA4 Fingerprint: TLS 1.2",
|
name: "JA4 Fingerprint: TLS 1.2",
|
||||||
input: "1603010200010001fc0303ecb2691addb2bf6c599c7aaae23de5f42561cc04eb41029acc6fc050a16ac1d22046f8617b580ac9358e2aa44e306d52466bcc989c87c8ca64309f5faf50ba7b4d0022130113031302c02bc02fcca9cca8c02cc030c00ac009c013c014009c009d002f00350100019100000021001f00001c636f6e74696c652e73657276696365732e6d6f7a696c6c612e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000022000a000804030503060302030033006b0069001d00208909858fbeb6ed2f1248ba5b9e2978bead0e840110192c61daed0096798b184400170041044d183d91f5eed35791fa982464e3b0214aaa5f5d1b78616d9b9fbebc22d11f535b2f94c686143136aa795e6e5a875d6c08064ad5b76d44caad766e2483012748002b00050403040303000d0018001604030503060308040805080604010501060102030201002d00020101001c000240010015007a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
input: "1603010200010001fc0303ecb2691addb2bf6c599c7aaae23de5f42561cc04eb41029acc6fc050a16ac1d22046f8617b580ac9358e2aa44e306d52466bcc989c87c8ca64309f5faf50ba7b4d0022130113031302c02bc02fcca9cca8c02cc030c00ac009c013c014009c009d002f00350100019100000021001f00001c636f6e74696c652e73657276696365732e6d6f7a696c6c612e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000022000a000804030503060302030033006b0069001d00208909858fbeb6ed2f1248ba5b9e2978bead0e840110192c61daed0096798b184400170041044d183d91f5eed35791fa982464e3b0214aaa5f5d1b78616d9b9fbebc22d11f535b2f94c686143136aa795e6e5a875d6c08064ad5b76d44caad766e2483012748002b00050403040303000d0018001604030503060308040805080604010501060102030201002d00020101001c000240010015007a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
|||||||
@@ -24,12 +24,6 @@ export const PNG_HEX = "89504e470d0a1a0a0000000d49484452000000200000002008060000
|
|||||||
*/
|
*/
|
||||||
export const PNG_CHEF_B64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAHqElEQVR4AcXBfUyU9wEH8O/v9zz3PHfPvXLewXHnxYKgYCFW6ktHmXUySIdKcVlFs2ZkrRB1m6kx00XTbGJjFrvVTSexZusGviQqwsxImM5laOZclG3EisEXWK2cvBwcuYN7456XPawQb+fx4l/7fAji5Obmvrlx48ZKjUZjlyTpaXNz89nOzs42TDp37lzLwMCAcefOnWtPnz6d53A4CsPhMNPb2/v37du3/wuADIACUADImIZer3e3tLS0rVy50k2gIqo9e/b8et++fd8+ceLEqXA47Jk3b97SmpqaDTU1NT+ur68/BICeOXPmEsuyzry8vAcWi+XtQCCAYDBIASiBQOAPIyMjd+x2+7poNPpZSUnJuwAkJLFr165j1dXVlQUFBa+yUBUXF79TW1tbtWTJkrXd3d3XMam9vb325MmTH27durXc4XAwBoPh1Z6eHqSkpCzDl2R8iZhMpnKj0biBqHiez+I47v2GhoavabVaa0VFxacAZEwqLy/Pa2xsbI9EIk8YqA4ePPhJa2tre2Nj40d4hnz88cerMzMz1/T29rrS0tKcLMvC7/eDUooJg4ODBCpCCAghICqoxsfH+aqqqr2CIFTabLbykpIS74ULF24zDKPbvXv3nuLi4rUmk0mfmppqoQzDGMvKyl55+PDhdcRpampavnjx4v3d3d1wOByY4nQ6IQgCIpEIrFYrVq1aBVEUMcXv9yMjIwNOpxPp6emw2WzIz8//lUajMQNg9Xp9oSiKxvT0dLsgCF+hPM/rLRaL9tGjRwN4hmRnZ2+nlGoMBgMEQcAUk8mEkZERmM1mqORbt24hJSUFExRFgcVigc/ng9frxejoKHp6eiRRFCPl5eU7JEkaPXDgwPq+vr67p06d+lttbe0GCoBAJUmSjGcoz/N5SKKrqws2mw0TiMrv98PlcmFCIBBAQUEBBgYGEI1GEQqFwLIsA0C7Y8eOQwAIJlFKCVSsLMsSVHa73YRnFFUEsyOKooAQggmiKGJCcXExEoVCIagoAAlx2Gg0OtzR0dHndruz8YwcDAavGQyGr46NjSEQCMDlciEJBQBBgpaWFpjNZkyJRqOxYDB4DoCMBFRRFOnixYstmzdvrmQYRodJra2tx30+HxYtWgRZlpGMokIcnuchiiIcDgcEQYAgCGAYZrCysvKlioqKKgAKElCo6urqDmZnZxuOHDlyRhCEBZRSXV1dXaYgCLh//z7S09MxFwaDAbdv30ZWVhZ8Ph+i0SiCwWBqZ2enp6ys7H0kwULl8/me5OXlrTl+/PinwWDwc6gikYh49OjR39fX139w5cqVfwLQMAwDQgjiEUJAKcUUhmHQ1dWF1atXg+d5yLKMtrY2XL169beIwzAMhYogDiGE8jyfrtVqrcFgsDcWi40AMPT29g5TSrlwOAxFUSAIAib4/X55ZGSEiqIIQRAwRZKkUFFRUf6xY8c2m81mecuWLYcByJjEsqxJUUmSNMoijqIociQS8UQiEQ+S0Ol0SMRxHDiOQzxZliOxWKxv27Zth5CEKIoBTKL4P6OYnYIXRAhRAMiYAxazC9+4cePPRqPxG0jw9OlT9Pf3I1E4HL4GIIY5YDE7TVZWVjbDMEjEcRwsFgsSybK8EAADQMYsWMxgSZpeu6Uo53vMF//IIJQins46XzHrjIrH41E8Hg/iiaKYvWbNmq+3tbW1YhYE06OH38o5sfa1gmqe0+B/EWSseRdfxDi5/cED2tTUBEmSEE9RlJgq//Lly/cxA4ppvLM83WXXs9992N0DkfKYEohISF/+TehtCzAhJSUFK8pWIJoSxRSGYcBx3F99qtLS0ixGhWkwmMa3ljrWW3Ts28FwBK9t/gBpOYU4cPYKvNZcGMxpSLNa8dm9exA1GrKf7IdmqQbLVi7DG+43kJOTg6GhIafNZiuzWq0HMzMzuzs7O+8gCYoktr/uznCZ+aOYRCkDncmOFSuK8KDzHjKcToQDAYT8fjI2Nob33O/hSegJMvlM2O12aLVanyiK/+Y4bilRsSybimmwSCI3Vb+LoWQeElRv2oTqTZsgyTKC/f2YMDQ0hEJjIQoNhUAY/8Xz/LDX693rcrkuBYPB35w9e/YXmAbF86iGJQWYQTQahZZlMWF4eBiJZFmmBoOhCCqe518vLS3NwDQonqfIMgYwA57nMQ4VIUogEICiKIgXiUQyTSbTD6FiWTbX4XB8H9Ng8TzFOzb+icDp3iIEDJJgKIXebkd2fj6owwFCCBKQ8fHxjkAg8KHRaCz3eDxHMA0WSfzkcveffro+e0eqgfsIgAmTZFmGJxCAXqcDw7K409VF/tjWpoiiCL1eL61bt45REahisdhfmpubLwK4iBmwSE75UcvDk5tecVzKmKd7k+V0vwRgppTCodNh8NEjhIeHIQ0MKG63W3E6nXC73QxRQcVx3BOPx/NzzAGLGZzv6B8A0PCdQW80S9D/jNNoXBqeh+vllzEh1tenWLxeijiSJD0NhUI/uHbtmgdzwGAO6hoa7sqy/LuchQtHeY57iWWYFKiGxsaUkVCIQCVJUm8oFDpy8+bNqr1793ZgjgheEKWUu37+/JIF8+cv/dznM/d4vWOqu4cPH+54/PjxOF7QfwCiFwbr9BCaBwAAAABJRU5ErkJggg==";
|
export const PNG_CHEF_B64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAHqElEQVR4AcXBfUyU9wEH8O/v9zz3PHfPvXLewXHnxYKgYCFW6ktHmXUySIdKcVlFs2ZkrRB1m6kx00XTbGJjFrvVTSexZusGviQqwsxImM5laOZclG3EisEXWK2cvBwcuYN7456XPawQb+fx4l/7fAji5Obmvrlx48ZKjUZjlyTpaXNz89nOzs42TDp37lzLwMCAcefOnWtPnz6d53A4CsPhMNPb2/v37du3/wuADIACUADImIZer3e3tLS0rVy50k2gIqo9e/b8et++fd8+ceLEqXA47Jk3b97SmpqaDTU1NT+ur68/BICeOXPmEsuyzry8vAcWi+XtQCCAYDBIASiBQOAPIyMjd+x2+7poNPpZSUnJuwAkJLFr165j1dXVlQUFBa+yUBUXF79TW1tbtWTJkrXd3d3XMam9vb325MmTH27durXc4XAwBoPh1Z6eHqSkpCzDl2R8iZhMpnKj0biBqHiez+I47v2GhoavabVaa0VFxacAZEwqLy/Pa2xsbI9EIk8YqA4ePPhJa2tre2Nj40d4hnz88cerMzMz1/T29rrS0tKcLMvC7/eDUooJg4ODBCpCCAghICqoxsfH+aqqqr2CIFTabLbykpIS74ULF24zDKPbvXv3nuLi4rUmk0mfmppqoQzDGMvKyl55+PDhdcRpampavnjx4v3d3d1wOByY4nQ6IQgCIpEIrFYrVq1aBVEUMcXv9yMjIwNOpxPp6emw2WzIz8//lUajMQNg9Xp9oSiKxvT0dLsgCF+hPM/rLRaL9tGjRwN4hmRnZ2+nlGoMBgMEQcAUk8mEkZERmM1mqORbt24hJSUFExRFgcVigc/ng9frxejoKHp6eiRRFCPl5eU7JEkaPXDgwPq+vr67p06d+lttbe0GCoBAJUmSjGcoz/N5SKKrqws2mw0TiMrv98PlcmFCIBBAQUEBBgYGEI1GEQqFwLIsA0C7Y8eOQwAIJlFKCVSsLMsSVHa73YRnFFUEsyOKooAQggmiKGJCcXExEoVCIagoAAlx2Gg0OtzR0dHndruz8YwcDAavGQyGr46NjSEQCMDlciEJBQBBgpaWFpjNZkyJRqOxYDB4DoCMBFRRFOnixYstmzdvrmQYRodJra2tx30+HxYtWgRZlpGMokIcnuchiiIcDgcEQYAgCGAYZrCysvKlioqKKgAKElCo6urqDmZnZxuOHDlyRhCEBZRSXV1dXaYgCLh//z7S09MxFwaDAbdv30ZWVhZ8Ph+i0SiCwWBqZ2enp6ys7H0kwULl8/me5OXlrTl+/PinwWDwc6gikYh49OjR39fX139w5cqVfwLQMAwDQgjiEUJAKcUUhmHQ1dWF1atXg+d5yLKMtrY2XL169beIwzAMhYogDiGE8jyfrtVqrcFgsDcWi40AMPT29g5TSrlwOAxFUSAIAib4/X55ZGSEiqIIQRAwRZKkUFFRUf6xY8c2m81mecuWLYcByJjEsqxJUUmSNMoijqIociQS8UQiEQ+S0Ol0SMRxHDiOQzxZliOxWKxv27Zth5CEKIoBTKL4P6OYnYIXRAhRAMiYAxazC9+4cePPRqPxG0jw9OlT9Pf3I1E4HL4GIIY5YDE7TVZWVjbDMEjEcRwsFgsSybK8EAADQMYsWMxgSZpeu6Uo53vMF//IIJQins46XzHrjIrH41E8Hg/iiaKYvWbNmq+3tbW1YhYE06OH38o5sfa1gmqe0+B/EWSseRdfxDi5/cED2tTUBEmSEE9RlJgq//Lly/cxA4ppvLM83WXXs9992N0DkfKYEohISF/+TehtCzAhJSUFK8pWIJoSxRSGYcBx3F99qtLS0ixGhWkwmMa3ljrWW3Ts28FwBK9t/gBpOYU4cPYKvNZcGMxpSLNa8dm9exA1GrKf7IdmqQbLVi7DG+43kJOTg6GhIafNZiuzWq0HMzMzuzs7O+8gCYoktr/uznCZ+aOYRCkDncmOFSuK8KDzHjKcToQDAYT8fjI2Nob33O/hSegJMvlM2O12aLVanyiK/+Y4bilRsSybimmwSCI3Vb+LoWQeElRv2oTqTZsgyTKC/f2YMDQ0hEJjIQoNhUAY/8Xz/LDX693rcrkuBYPB35w9e/YXmAbF86iGJQWYQTQahZZlMWF4eBiJZFmmBoOhCCqe518vLS3NwDQonqfIMgYwA57nMQ4VIUogEICiKIgXiUQyTSbTD6FiWTbX4XB8H9Ng8TzFOzb+icDp3iIEDJJgKIXebkd2fj6owwFCCBKQ8fHxjkAg8KHRaCz3eDxHMA0WSfzkcveffro+e0eqgfsIgAmTZFmGJxCAXqcDw7K409VF/tjWpoiiCL1eL61bt45REahisdhfmpubLwK4iBmwSE75UcvDk5tecVzKmKd7k+V0vwRgppTCodNh8NEjhIeHIQ0MKG63W3E6nXC73QxRQcVx3BOPx/NzzAGLGZzv6B8A0PCdQW80S9D/jNNoXBqeh+vllzEh1tenWLxeijiSJD0NhUI/uHbtmgdzwGAO6hoa7sqy/LuchQtHeY57iWWYFKiGxsaUkVCIQCVJUm8oFDpy8+bNqr1793ZgjgheEKWUu37+/JIF8+cv/dznM/d4vWOqu4cPH+54/PjxOF7QfwCiFwbr9BCaBwAAAABJRU5ErkJggg==";
|
||||||
|
|
||||||
/**
|
|
||||||
* The CyberChef logo with blur
|
|
||||||
* 32x32
|
|
||||||
*/
|
|
||||||
export const PNG_BLUR_B64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAANT0lEQVR4AS3BC5CV1X0A8P8553s/7mMvyz5gWUFApEKpEtloSQdLDDDoREXMDK1Zx8dg4xjHqdWpQwgI29QoFrE6gyFJ6YhmoDNMapIBYhzHqgg1ZAvRdIVld5Vl9+597N17v+8779NNJ78fklL6GzdutJ955hnnrbfect98803vxIkTwccffxwdOnQoGhoaihuNRiilDKvValCr1XzGmNtqtdz29naru7sburq6dG9vr1i6dClbtWoV7evryzZv3pw8/PDDSX9/f+vIkSPN/fv3t86cOZMYY7KBgQFarVY5AAjr4MGD6KOPPsK1Wg0bY4ht25Y9q1gs2h0dHW6apm5PT4/HGPMrlYpv23aQJIk3y8nn85bneYgQopVSglJq1et1Mjk5iS5fvqzPnz+vzp49K44fP85uueUW++jRozalVDz77LOkUCjg/v5+hI8dO4YajQZSSuE0TYnW2rJneZ7nlEolt7293SuVSn5nZ6ff1tYWtrW1hcViMczn81EYhpHjOBFCKNJah5TSsNVqBZVKJRgdHQ0uXLjgnzt3znv77bfdo0ePOkeOHLEPHTpkHThwgKxbt46sWLECk4sXL3ozMzPWmTNnnEaj4QwPD3vbt2/3a7VaeOXKlVBKGRFCIsdxIilluGPHjnDXrl0BQsh3Xdf3PM8dGBiwXNe1fN/Hvu8jz/MgjmP98ssvq3379qkoiuTrr78ub731VvHhhx+qbdu2qf7+frV69WqNq9UqmpycxK7rYtu2ied5VhAEdj6ftwuFglssFr1SqeTncrkgn88HuVwuCMMwCsMw8jwvtCwrJISExpiQcx6maRq0Wi2/Uqn4X375pTcyMuIODg46586ds9977z373LlzZHx8HJ8+fRoXCgVEDh486D755JN2uVx2xsfH3eHhYf+JJ57wa7VaVC6XIyFERAiJACBijEWMscgYE+zcuTPYs2ePZ9u2Y9u25TgOdl0XeZ4HnufpKIpUHMfqtddeEwMDA2LZsmX85MmTYnx8XGit5djYmHznnXcUNsagKIqQbdvYsixSKBRIGIZWGIZ2oVBwCoWCm8vlvCiK/GBWGIbBrDAIgtBxnJAQEgJAqJQKpZQB59xPksRvNptuvV53JiYmnMuXL9vDw8PW+Pg4GRoaIrVaDc+dOxeVSiWE169fD3PnzkVdXV2oVCqhfD6P4zgm+Xye5PN5K45jO5fLObNcjLFHCPEAwEMIeUopXwjhc869LMu8VqvlzszMOI1Gw6nX6061WrUbjYY1PT1Nrl69SkZGRvDZs2fxBx98gF599VX0/vvvg3XvvffCyMgILFiwADzPQ/l8HsVBgKMowgBAQGsiGLNZltmcMZtS6lBKXZplLmXMUlIiTDC2bQdmScdx7DiOSZqmmDGG0zTFjDEkhEBSSlQqlaC3txd6e3vhtttuA7xo/U3w1W+uN/kFeQgLIfixBcR3QAFHQDQSWmHGKU7ThCRJy8rS1Mqy1KKUWlma2hmlVpZRizFGKKWEMYYZpVgIgYQQIIQwWmswsxhjptFomMnJSTMxMWFGR0cN/un3vmX65gLc3NtrlnTnTGQBBJYCDzT4WANIhjRniGUJZlmGGU0Jp5QwmhEhOBaMYc4Z5oxhKTkSgiMuBCiljBDCKKU0xlgbY7SUUgshtBBC53I5PTg4aPC2mwEe2txjruuYhqXzjJmf12ZOwE3B48ZDythGGC0YSEpB8AxxRpHgDEkhkOQcCcmRFAIJKUBKZaSURv8JIUTZtq3iOFBxHKv29nbl+77u7OzU9XrdvPTSSxofe+4ec20nwI2LPFOEFnQEyrR5yoRYGFdnAJKB4RQES0EyCkowkIKDksJIJY1S0mgltdZSKyW11koBAomQkRiDJDaRYZyTxWJRBkGg2tvblW3buqurS1+6dMngB5ZWIPnlHLN9QwPuukmba4t1mAMzUCDceIoZWzEDghkpqJGcghLCKMGNUsJoKYxWSisttVZaaa2UBiOVlkoDSESIAAAZBZG0bVs5gaOKxaJatmyZWrBggR4YGND4ujv/F368+HO4zxuBlfAFdMsyBGwSSFIFyJogswaIrAkqS0FxaiSnoJUwWnKjlDBKCaOU0lJJrZTUUkqt1Syp/h8QkEEcSMdxlOu6KteeU8YY3dHRoc+cOWPw/i9+jrak/42+VZiG7mQUdcsy5NIKqOkJBHQadNYEmTaBpy0ksxRpRkEwiiQXoIQwUgijpDBKcCOl1FJyLaVUUnOllFCUUi200MY1iraoHjo/ZJIk0fPnz9eHDx/W+HH/12gd/gA5w+/iztZFBONDmE2N4GxyDNPaBGb1Ck4bVcyTJhI0QYJlSHEKklOkBAfJOXDOQChhhOBGcGY4Zyaj1LSyluFZpgFAN5tNM1GdMIwxff78efPuu++aU6dOgfVt979QbvBXeKU8iMbGz2OYvIhVdQyLX43jrDpJ0ukqyWamMU9nMM+qmNMUS8aQ5BQJqZAEZLAhIAgBJhhwLkxKU6BZZrI0MzNJYrjgZmZmxkxVpsyJ/zwBr7zyCnz66adw3333GXz29ZfwzewjhC++jxuffkySkQskHf2cVL8Ytmh9ktDpCskadUJbM0RkCRY0xZJnWAqOpOBIco6E5CAEA8E4MMaAMgpZlkCz2YR6ow6N6QZUK1UYGx2Der1uyq2y4ZybO+64A/BN079GldO/wJfOvEPY+CCuj1wg5dE/WDMTo2RmatLKGjXCZupEZgmWNMWKUywZw5JzrKRASnKkhEBCCCQlBy4yxBmFJElQo9lA1WoVVWtlNDE5AZ999hkc/tlh9MjfPIKGhobQ7t27AV/+xXEMnw3i4MolTEcvEqt2FaNqGbNKhdBalfCZBmFZiwhKsRQcGyGRURIZJUEribRWoLQGrRVorUAqDZxzxIWAjGbQSmZQlmZQmaqgNE2h2WxCpVKBsbExGB8fB3wDrqP6l5/hrDqC82wa6Zk6pq0Gps0ZTFtNLFmGNOfIaIlAKQBjAAEYBAaQAYMAGYSMQQjMHwFoAwBGSA5SStAKIOMcwaxas4bK5TKCP7nzzjuR1YMFKhhAJZCo2qKYMIkMk0hQgUBrwNoAwdhYCBvHsnSVSG0RrW3LKI0MQoCUsSxlWZayLEtb2NKEEI3nYYPAzJJGKWVaSQsajQZUKhX4zUe/QfPa5qGTJ08CXpJJdG9vAW4qRtDrW9DmAoQA4CNsbGwZxyLGd2zl25byHVsFriN9x5G+6wrf9YTneSJwPRF4vgh8XwS+LwPPU0HgKdfxtesF2nd843u+ieLItOfazZL5S8ymTZsMzMLJvwHA+wA9dd8sJLF2pWdsJ9DY97Tju8oLA+n5vgziiHthyP0wYn4UMtcPeRCGLA5DFoUxi4KQ5+KYx1Ek4lxO5OKcbCsU5JxiUXV1zVVd87r00oVLdU9PjwmCAP7o2LFjhry3d2N4+O57rHXXbrceXFN12r7ZdNY8IJwNZeVeyoxzRex2ptCAXdu5x2ruskn6nIWetmwQjqvBcRXxfGEHAQtzuSzOFdK2A6WkY25H0tXdnSy8ZnFy3fLl6e8G/yfp+0pftmHDBlq+WmYHDhzg99xzj5yamlLk0Z9sCcJ3P7YW5bZbz94urTm/Z/aND0rnzjo4f5va9rhy7Wnjkgb+J9zAe3HzuQFI93haOp4CJxA4iJgd5TK/WMj2zfnXpK2jM5nX29vqXXRta8Wfr2itX7eudfHzS+mWLVvSx7/7OH3hn19gfX19or+/X65evVpZA3/do89vvVHNt1dKtuoTma4SYskKwntO+WxOo0Bj08hcXHeQk1nIaWLldxk6l0tFhUW0QTYQ5bou87u6szn5Qlrq6Uk7FvRmi66/Plu+chW7Zc0tfNfePeL2zbfLPd/fo3bs2KFaqKURQnrFihXGemP9Tfr03YPq9xNfqN1fvUGOfh+LNZditvgvYtZZLdO8PZ15uGwTr0mM30Ki0TKMSoEYt4hQiBBL2a7L/TkhzRXb0tKSpen8xQuzJStW0r6vraUbH3iQbd26lX9y7hOx43s7JG1QFcexPn78uFm7dq0h8Vs/cb+9Zht56FSAH97yPH7hoX3kuvJu646nI3L3EzEZsfJ4nNl4yg3RlBPCd93I1N1QGz9SVhALLy6yuNROCws6s+6enuSalSuT6//shuTmvjXJ3Z/8Lnnq0UfS3c/tyfYO7KXLFy9nzWaT7927V7744oty06ZNmtzK1zul+/4R/3uvwVu3tuOd93vkmseeJxv4D8iG7+wn255rw2MU4yt2iCZIgL7j5syUH2vsx8rLFbmfL/GX2jtp+7Xzsnm916SLb1ydrl79leT2D7+e3L/l3nTgqX/Ifvyjn2Zv/OwN+tsLv+Wff/q5LJfLIgxDjTHWZN8f9ts3tp5HT/3gGXz6/g789GNz8DWPReSvdkTk1OUfki279uPhp3bii8jDV6wAHvYiMxHntRXmlBvlZVTsYP/S3sU6li3IehYuypavXZv+5dfeSU5//RvZ3//do+nCMMiOHv0PeuKXJ9iVkSvirv67xOGfH5aPP/i4unr1qv4/bGwpHb1ZNmYAAAAASUVORK5CYII=";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sunglasses smiley
|
* Sunglasses smiley
|
||||||
* 32x32
|
* 32x32
|
||||||
|
|||||||
Reference in New Issue
Block a user