Compare commits
18 Commits
terminal-w
...
main
Author | SHA1 | Date | |
---|---|---|---|
5299b3ec4c | |||
03ff18d178 | |||
169d6eaa7e | |||
c5367db84f | |||
fe6ba39d74 | |||
19e42fb13e | |||
6b9f1dcffe | |||
d2a6882ffe | |||
8f78887d0c | |||
e0b72ac64d | |||
88bcead736 | |||
535ce54d67 | |||
591c9ee7a8 | |||
7812867a01 | |||
c60251359c | |||
20cd951cde | |||
9180bc84de | |||
14c7ba87f7 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,7 +11,7 @@ cmake_install.cmake
|
||||
Makefile
|
||||
build
|
||||
tools
|
||||
|
||||
node_modules/
|
||||
# Resulting binary files
|
||||
*.a
|
||||
*.so
|
||||
|
47
.idea/codeStyles/Project.xml
generated
47
.idea/codeStyles/Project.xml
generated
@ -1,54 +1,7 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<Objective-C>
|
||||
<option name="INDENT_NAMESPACE_MEMBERS" value="2" />
|
||||
<option name="INDENT_C_STRUCT_MEMBERS" value="2" />
|
||||
<option name="INDENT_CLASS_MEMBERS" value="2" />
|
||||
<option name="INDENT_INSIDE_CODE_BLOCK" value="2" />
|
||||
<option name="INDENT_DIRECTIVE_AS_CODE" value="true" />
|
||||
<option name="SPACE_BEFORE_TEMPLATE_DECLARATION_LT" value="true" />
|
||||
<option name="SPACE_BEFORE_POINTER_IN_DECLARATION" value="false" />
|
||||
<option name="SPACE_AFTER_POINTER_IN_DECLARATION" value="true" />
|
||||
<option name="SPACE_BEFORE_REFERENCE_IN_DECLARATION" value="false" />
|
||||
<option name="SPACE_AFTER_REFERENCE_IN_DECLARATION" value="true" />
|
||||
</Objective-C>
|
||||
<Objective-C-extensions>
|
||||
<rules>
|
||||
<rule entity="NAMESPACE" visibility="ANY" specifier="ANY" prefix="" style="PASCAL_CASE" suffix="" />
|
||||
<rule entity="MACRO" visibility="ANY" specifier="ANY" prefix="" style="SCREAMING_SNAKE_CASE" suffix="" />
|
||||
<rule entity="CLASS" visibility="ANY" specifier="ANY" prefix="" style="PASCAL_CASE" suffix="" />
|
||||
<rule entity="STRUCT" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="ENUM" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="ENUMERATOR" visibility="ANY" specifier="ANY" prefix="" style="PASCAL_CASE" suffix="" />
|
||||
<rule entity="TYPEDEF" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="UNION" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="CLASS_MEMBER_FUNCTION" visibility="ANY" specifier="ANY" prefix="" style="PASCAL_CASE" suffix="" />
|
||||
<rule entity="STRUCT_MEMBER_FUNCTION" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="CLASS_MEMBER_FIELD" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="STRUCT_MEMBER_FIELD" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="GLOBAL_FUNCTION" visibility="ANY" specifier="ANY" prefix="" style="PASCAL_CASE" suffix="" />
|
||||
<rule entity="GLOBAL_VARIABLE" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="PARAMETER" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
<rule entity="LOCAL_VARIABLE" visibility="ANY" specifier="ANY" prefix="" style="CAMEL_CASE" suffix="" />
|
||||
</rules>
|
||||
</Objective-C-extensions>
|
||||
<clangFormatSettings>
|
||||
<option name="ENABLED" value="true" />
|
||||
</clangFormatSettings>
|
||||
<codeStyleSettings language="ObjectiveC">
|
||||
<option name="RIGHT_MARGIN" value="140" />
|
||||
<option name="IF_BRACE_FORCE" value="3" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||
<option name="FOR_BRACE_FORCE" value="3" />
|
||||
<option name="WRAP_ON_TYPING" value="1" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="true" />
|
||||
<option name="KEEP_INDENTS_ON_EMPTY_LINES" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
113
node_modules/.package-lock.json
generated
vendored
Normal file
113
node_modules/.package-lock.json
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
{
|
||||
"name": "InfiniTime",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"node_modules/lv_font_conv": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/lv_font_conv/-/lv_font_conv-1.5.2.tgz",
|
||||
"integrity": "sha512-0UapRSTkVP/pnB8Z4r2HDHx5p2dJx/xUG1+14u/WXo59mwuC7BahR+Bnx/66jKoDrG1wFQwn9ZzoyMxRHOD9bg==",
|
||||
"bundleDependencies": [
|
||||
"argparse",
|
||||
"bit-buffer",
|
||||
"debug",
|
||||
"make-error",
|
||||
"mkdirp",
|
||||
"opentype.js",
|
||||
"pngjs"
|
||||
],
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.0",
|
||||
"bit-buffer": "^0.2.5",
|
||||
"debug": "^4.1.1",
|
||||
"make-error": "^1.3.5",
|
||||
"mkdirp": "^1.0.4",
|
||||
"opentype.js": "^1.1.0",
|
||||
"pngjs": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"lv_font_conv": "lv_font_conv.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"inBundle": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/bit-buffer": {
|
||||
"version": "0.2.5",
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/debug": {
|
||||
"version": "4.3.1",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"inBundle": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/opentype.js": {
|
||||
"version": "1.3.3",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"string.prototype.codepointat": "^0.2.1",
|
||||
"tiny-inflate": "^1.0.3"
|
||||
},
|
||||
"bin": {
|
||||
"ot": "bin/ot"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/pngjs": {
|
||||
"version": "6.0.0",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/string.prototype.codepointat": {
|
||||
"version": "0.2.1",
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/tiny-inflate": {
|
||||
"version": "1.0.3",
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
164
node_modules/lv_font_conv/CHANGELOG.md
generated
vendored
Normal file
164
node_modules/lv_font_conv/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
1.5.2 / 2021-07-18
|
||||
------------------
|
||||
|
||||
- Fixed lvgl version check for v8+, #64.
|
||||
|
||||
|
||||
1.5.1 / 2021-04-06
|
||||
------------------
|
||||
|
||||
- Fixed fail of CMAP generation for edge cases, #62.
|
||||
- Dev deps bump.
|
||||
|
||||
|
||||
1.5.0 / 2021-03-08
|
||||
------------------
|
||||
|
||||
- More `const` in generated font (for v8+), #59.
|
||||
|
||||
|
||||
1.4.1 / 2021-01-26
|
||||
------------------
|
||||
|
||||
- Fix charcodes padding in comments, #54.
|
||||
|
||||
|
||||
1.4.0 / 2021-01-03
|
||||
------------------
|
||||
|
||||
- Added OTF fonts support.
|
||||
- Added `--use-color-info` for limited multi-tone glyphs support.
|
||||
|
||||
|
||||
1.3.1 / 2020-12-28
|
||||
------------------
|
||||
|
||||
- Unify `lvgl.h` include.
|
||||
- Updated repo refs (littlevgl => lvgl).
|
||||
- Deps bump.
|
||||
- Moved CI to github actions.
|
||||
|
||||
|
||||
1.3.0 / 2020-10-25
|
||||
------------------
|
||||
|
||||
- Drop `lodash` use.
|
||||
- Deps bump.
|
||||
|
||||
|
||||
1.2.1 / 2020-10-24
|
||||
------------------
|
||||
|
||||
- Reduced npm package size (drop unneeded files before publish).
|
||||
|
||||
|
||||
1.2.0 / 2020-10-24
|
||||
------------------
|
||||
|
||||
- Bump FreeType to 2.10.4.
|
||||
- Bundle dependencies to npm package.
|
||||
|
||||
|
||||
1.1.3 / 2020-09-22
|
||||
------------------
|
||||
|
||||
- lvgl: added `LV_FONT_FMT_TXT_LARGE` check or very large fonts.
|
||||
|
||||
|
||||
1.1.2 / 2020-08-23
|
||||
------------------
|
||||
|
||||
- Fix: skip `glyph.advanceWidth` for monospace fonts, #43.
|
||||
- Spec fix: version size should be 4 bytes, #44.
|
||||
- Spec fix: bbox x/y bits => unsigned, #45.
|
||||
- Bump argparse.
|
||||
- Cleanup help formatter.
|
||||
|
||||
|
||||
1.1.1 / 2020-08-01
|
||||
------------------
|
||||
|
||||
- `--version` should show number from `package.json`.
|
||||
|
||||
|
||||
1.1.0 / 2020-07-27
|
||||
------------------
|
||||
|
||||
- Added `post.underlinePosition` & `post.underlineThickness` info to font header.
|
||||
|
||||
|
||||
1.0.0 / 2020-06-26
|
||||
------------------
|
||||
|
||||
- Maintenance release.
|
||||
- Set package version 1.x, to label package as stable.
|
||||
- Deps bump.
|
||||
|
||||
|
||||
0.4.3 / 2020-03-05
|
||||
------------------
|
||||
|
||||
- Enabled `--bpp 8` mode.
|
||||
|
||||
|
||||
0.4.2 / 2020-01-05
|
||||
------------------
|
||||
|
||||
- Added `--lv_include` option to set alternate `lvgl.h` path.
|
||||
- Added guards to hide `.subpx` property for lvgl 6.0 (supported from 6.1 only), #32.
|
||||
- Dev deps bump
|
||||
|
||||
|
||||
0.4.1 / 2019-12-09
|
||||
------------------
|
||||
|
||||
- Allow memory growth for FreeType build, #29.
|
||||
- Dev deps bump.
|
||||
- Web build update.
|
||||
|
||||
|
||||
0.4.0 / 2019-11-29
|
||||
------------------
|
||||
|
||||
- Note, this release is for lvgl 6.1 and has potentially breaking changes
|
||||
(see below). If you have compatibility issues with lvgl 6.0 - use previous
|
||||
versions or update your code.
|
||||
- Spec change: added subpixels info field to font header (header size increased).
|
||||
- Updated `bin` & `lvgl` writers to match new spec.
|
||||
- lvgl: fixed data type for kerning values (needs appropriate update
|
||||
in LittlevGL 6.1+).
|
||||
- Fix errors display (disable emscripten error catcher).
|
||||
|
||||
|
||||
0.3.1 / 2019-10-24
|
||||
------------------
|
||||
|
||||
- Fixed "out of range" error for big `--size`.
|
||||
|
||||
|
||||
0.3.0 / 2019-10-12
|
||||
------------------
|
||||
|
||||
- Added beta options `--lcd` & `--lcd-v` for subpixel rendering (still need
|
||||
header info update).
|
||||
- Added FreeType data properties to dump info.
|
||||
- Fixed glyph width (missed fractional part after switch to FreeType).
|
||||
- Fixed missed sigh for negative X/Y bitmap offsets.
|
||||
- Deps bump.
|
||||
|
||||
|
||||
0.2.0 / 2019-09-26
|
||||
------------------
|
||||
|
||||
- Use FreeType renderer. Should solve all regressions, reported in 0.1.0.
|
||||
- Enforced light autohinting (horizontal lines only).
|
||||
- Use special hinter for monochrome output (improve quality).
|
||||
- API changed to async.
|
||||
- Fix: added missed `.bitmap_format` field to lvgl writer.
|
||||
- Fix: changed struct fields init order to match declaration, #25.
|
||||
|
||||
|
||||
0.1.0 / 2019-09-03
|
||||
------------------
|
||||
|
||||
- First release.
|
22
node_modules/lv_font_conv/LICENSE
generated
vendored
Normal file
22
node_modules/lv_font_conv/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
Copyright (c) 2018 authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
150
node_modules/lv_font_conv/README.md
generated
vendored
Normal file
150
node_modules/lv_font_conv/README.md
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
lv_font_conv - font convertor to compact bitmap format
|
||||
======================================================
|
||||
|
||||
[![CI](https://github.com/lvgl/lv_font_conv/workflows/CI/badge.svg?branch=master)](https://github.com/lvgl/lv_font_conv/actions)
|
||||
[![NPM version](https://img.shields.io/npm/v/lv_font_conv.svg?style=flat)](https://www.npmjs.org/package/lv_font_conv)
|
||||
|
||||
Converts TTF/WOFF/OTF fonts to __[compact format](https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md)__, suitable for small embedded systems. Main features are:
|
||||
|
||||
- Allows bitonal and anti-aliased glyphs (1-4 bits per pixel).
|
||||
- Preserves kerning info.
|
||||
- Compression.
|
||||
- Users can select required glyphs only (subsetting).
|
||||
- Multiple font sources can be merged.
|
||||
- Simple CLI interface, easy to integrate into external build systems.
|
||||
|
||||
|
||||
## Install the script
|
||||
|
||||
[node.js](https://nodejs.org/en/download/) v10+ required.
|
||||
|
||||
Global install of the last version, execute as "lv_font_conv"
|
||||
|
||||
```sh
|
||||
# install release from npm registry
|
||||
npm i lv_font_conv -g
|
||||
# install from github's repo, master branch
|
||||
npm i lvgl/lv_font_conv -g
|
||||
```
|
||||
|
||||
**run via [npx](https://www.npmjs.com/package/npx) without install**
|
||||
|
||||
```sh
|
||||
# run from npm registry
|
||||
npx lv_font_conv -h
|
||||
# run from github master
|
||||
npx github:lvgl/lv_font_conv -h
|
||||
```
|
||||
|
||||
Note, runing via `npx` may take some time until modules installed, be patient.
|
||||
|
||||
|
||||
## CLI params
|
||||
|
||||
Common:
|
||||
|
||||
- `--bpp` - bits per pixel (antialiasing).
|
||||
- `--size` - output font size (pixels).
|
||||
- `-o`, `--output` - output path (file or directory, depends on format).
|
||||
- `--format` - output format.
|
||||
- `--format dump` - dump glyph images and font info, useful for debug.
|
||||
- `--format bin` - dump font in binary form (as described in [spec](https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md)).
|
||||
- `--format lvgl` - dump font in [LittlevGL](https://github.com/lvgl/lvgl) format.
|
||||
- `--force-fast-kern-format` - always use more fast kering storage format,
|
||||
at cost of some size. If size difference appears, it will be displayed.
|
||||
- `--lcd` - generate bitmaps with 3x horizontal resolution, for subpixel
|
||||
smoothing.
|
||||
- `--lcd-v` - generate bitmaps with 3x vertical resolution, for subpixel
|
||||
smoothing.
|
||||
- `--use-color-info` - try to use glyph color info from font to create
|
||||
grayscale icons. Since gray tones are emulated via transparency, result
|
||||
will be good on contrast background only.
|
||||
- `--lv-include` - only with `--format lvgl`, set alternate path for `lvgl.h`.
|
||||
|
||||
Per font:
|
||||
|
||||
- `--font` - path to font file (ttf/woff/woff2/otf). May be used multiple time for
|
||||
merge.
|
||||
- `-r`, `--range` - single glyph or range + optional mapping, belongs to
|
||||
previously declared `--font`. Can be used multiple times. Examples:
|
||||
- `-r 0x1F450` - single value, dec or hex format.
|
||||
- `-r 0x1F450-0x1F470` - range.
|
||||
- `-r '0x1F450=>0xF005'` - single glyph with mapping.
|
||||
- `-r '0x1F450-0x1F470=>0xF005'` - range with mapping.
|
||||
- `-r 0x1F450 -r 0x1F451-0x1F470` - 2 ranges.
|
||||
- `-r 0x1F450,0x1F451-0x1F470` - the same as above, but defined with single `-r`.
|
||||
- `--symbols` - list of characters to copy (instead of numeric format in `-r`).
|
||||
- `--symbols 0123456789.,` - extract chars to display numbers.
|
||||
- `--autohint-off` - do not force autohinting ("light" is on by default).
|
||||
- `--autohint-strong` - use more strong autohinting (will break kerning).
|
||||
|
||||
Additional debug options:
|
||||
|
||||
- `--no-compress` - disable built-in RLE compression.
|
||||
- `--no-prefilter` - disable bitmap lines filter (XOR), used to improve
|
||||
compression ratio.
|
||||
- `--no-kerning` - drop kerning info to reduce size (not recommended).
|
||||
- `--full-info` - don't shorten 'font_info.json' (include pixels data).
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Merge english from Roboto Regular and icons from Font Awesome, and show debug
|
||||
info:
|
||||
|
||||
`env DEBUG=* lv_font_conv --font Roboto-Regular.ttf -r 0x20-0x7F --font FontAwesome.ttf -r 0xFE00=>0x81 --size 16 --format bin --bpp 3 --no-compress -o output.font`
|
||||
|
||||
Merge english & russian from Roboto Regular, and show debug info:
|
||||
|
||||
`env DEBUG=* lv_font_conv --font Roboto-Regular.ttf -r 0x20-0x7F -r 0x401,0x410-0x44F,0x451 --size 16 --format bin --bpp 3 --no-compress -o output.font`
|
||||
|
||||
Dump all Roboto glyphs to inspect icons and font details:
|
||||
|
||||
`lv_font_conv --font Roboto-Regular.ttf -r 0x20-0x7F --size 16 --format dump --bpp 3 -o ./dump`
|
||||
|
||||
**Note**. Option `--no-compress` exists temporary, to avoid confusion until LVGL
|
||||
adds compression support.
|
||||
|
||||
|
||||
## Technical notes
|
||||
|
||||
### Supported output formats
|
||||
|
||||
1. **bin** - universal binary format, as described in https://github.com/lvgl/lv_font_conv/tree/master/doc.
|
||||
2. **lvgl** - format for LittlevGL, C file. Has minor limitations and a bit
|
||||
bigger size, because C does not allow to effectively define relative offsets
|
||||
in data blocks.
|
||||
3. **dump** - create folder with each glyph in separate image, and other font
|
||||
data as `json`. Useful for debug.
|
||||
|
||||
### Merged font metrics
|
||||
|
||||
When multiple fonts merged into one, sources can have different metrics. Result
|
||||
will follow principles below:
|
||||
|
||||
1. No scaling. Glyphs will have exactly the same size, as intended by font authors.
|
||||
2. The same baseline.
|
||||
3. `OS/2` metrics (`sTypoAscender`, `sTypoDescender`, `sTypoLineGap`) will be
|
||||
used from the first font in list.
|
||||
4. `hhea` metrics (`ascender`, `descender`), defined as max/min point of all
|
||||
font glyphs, are recalculated, according to new glyphs set.
|
||||
|
||||
|
||||
## Development
|
||||
|
||||
Current package includes WebAssembly build of FreeType with some helper
|
||||
functions. Everything is wrapped into Docker and requires zero knowledge about
|
||||
additional tools install. See `package.json` for additional commands. You may
|
||||
need those if decide to upgrade FreeType or update helpers.
|
||||
|
||||
This builds image with emscripten & freetype, usually should be done only once:
|
||||
|
||||
```
|
||||
npm run build:dockerimage
|
||||
```
|
||||
|
||||
This compiles helpers and creates WebAssembly files:
|
||||
|
||||
```
|
||||
npm run build:freetype
|
||||
```
|
9
node_modules/lv_font_conv/lib/app_error.js
generated
vendored
Normal file
9
node_modules/lv_font_conv/lib/app_error.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
// Custom Error type to simplify error messaging
|
||||
//
|
||||
'use strict';
|
||||
|
||||
|
||||
//const ExtendableError = require('es6-error');
|
||||
//module.exports = class AppError extends ExtendableError {};
|
||||
|
||||
module.exports = require('make-error')('AppError');
|
318
node_modules/lv_font_conv/lib/cli.js
generated
vendored
Normal file
318
node_modules/lv_font_conv/lib/cli.js
generated
vendored
Normal file
@ -0,0 +1,318 @@
|
||||
// Parse input arguments and execute convertor
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
const argparse = require('argparse');
|
||||
const fs = require('fs');
|
||||
const mkdirp = require('mkdirp');
|
||||
const path = require('path');
|
||||
const convert = require('./convert');
|
||||
|
||||
|
||||
class ActionFontAdd extends argparse.Action {
|
||||
call(parser, namespace, value/*, option_string*/) {
|
||||
let items = (namespace[this.dest] || []).slice();
|
||||
items.push({ source_path: value, ranges: [] });
|
||||
namespace[this.dest] = items;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add range or symbols to font;
|
||||
// need to merge them into one array here so overrides work correctly
|
||||
class ActionFontRangeAdd extends argparse.Action {
|
||||
call(parser, namespace, value, option_string) {
|
||||
let fonts = namespace.font || [];
|
||||
|
||||
if (fonts.length === 0) {
|
||||
parser.error(`argument ${option_string}: Only allowed after --font`);
|
||||
}
|
||||
|
||||
let lastFont = fonts[fonts.length - 1];
|
||||
|
||||
// { symbols: 'ABC' }, or { range: [ 65, 67, 65 ] }
|
||||
lastFont.ranges.push({ [this.dest]: value });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add hinting option to font;
|
||||
class ActionFontStoreTrue extends argparse.Action {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
options.const = true;
|
||||
options.default = options.default !== null ? options.default : false;
|
||||
options.nargs = 0;
|
||||
super(options);
|
||||
}
|
||||
|
||||
call(parser, namespace, value, option_string) {
|
||||
let fonts = namespace.font || [];
|
||||
|
||||
if (fonts.length === 0) {
|
||||
parser.error(`argument ${option_string}: Only allowed after --font`);
|
||||
}
|
||||
|
||||
let lastFont = fonts[fonts.length - 1];
|
||||
|
||||
lastFont[this.dest] = this.const;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Formatter with support of `\n` in Help texts.
|
||||
class RawTextHelpFormatter2 extends argparse.RawDescriptionHelpFormatter {
|
||||
// executes parent _split_lines for each line of the help, then flattens the result
|
||||
_split_lines(text, width) {
|
||||
return [].concat(...text.split('\n').map(line => super._split_lines(line, width)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// parse decimal or hex code in unicode range
|
||||
function unicode_point(str) {
|
||||
let m = /^(?:(?:0x([0-9a-f]+))|([0-9]+))$/i.exec(str.trim());
|
||||
|
||||
if (!m) throw new TypeError(`${str} is not a number`);
|
||||
|
||||
let [ , hex, dec ] = m;
|
||||
|
||||
let value = hex ? parseInt(hex, 16) : parseInt(dec, 10);
|
||||
|
||||
if (value > 0x10FFFF) throw new TypeError(`${str} is out of unicode range`);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// parse range
|
||||
function range(str) {
|
||||
let result = [];
|
||||
|
||||
for (let s of str.split(',')) {
|
||||
let m = /^(.+?)(?:-(.+?))?(?:=>(.+?))?$/i.exec(s);
|
||||
|
||||
let [ , start, end, mapped_start ] = m;
|
||||
|
||||
if (!end) end = start;
|
||||
if (!mapped_start) mapped_start = start;
|
||||
|
||||
start = unicode_point(start);
|
||||
end = unicode_point(end);
|
||||
|
||||
if (start > end) throw new TypeError(`Invalid range: ${s}`);
|
||||
|
||||
mapped_start = unicode_point(mapped_start);
|
||||
|
||||
result.push(start, end, mapped_start);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// exclude negative numbers and non-numbers
|
||||
function positive_int(str) {
|
||||
if (!/^\d+$/.test(str)) throw new TypeError(`${str} is not a valid number`);
|
||||
|
||||
let n = parseInt(str, 10);
|
||||
|
||||
if (n <= 0) throw new TypeError(`${str} is not a valid number`);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
module.exports.run = async function (argv, debug = false) {
|
||||
|
||||
//
|
||||
// Configure CLI
|
||||
//
|
||||
|
||||
let parser = new argparse.ArgumentParser({
|
||||
add_help: true,
|
||||
formatter_class: RawTextHelpFormatter2
|
||||
});
|
||||
|
||||
if (debug) {
|
||||
parser.exit = function (status, message) {
|
||||
throw new Error(message);
|
||||
};
|
||||
}
|
||||
|
||||
parser.add_argument('-v', '--version', {
|
||||
action: 'version',
|
||||
version: require('../package.json').version
|
||||
});
|
||||
|
||||
parser.add_argument('--size', {
|
||||
metavar: 'PIXELS',
|
||||
type: positive_int,
|
||||
required: true,
|
||||
help: 'Output font size, pixels.'
|
||||
});
|
||||
|
||||
parser.add_argument('-o', '--output', {
|
||||
metavar: '<path>',
|
||||
help: 'Output path.'
|
||||
});
|
||||
|
||||
parser.add_argument('--bpp', {
|
||||
choices: [ 1, 2, 3, 4, 8 ],
|
||||
type: positive_int,
|
||||
required: true,
|
||||
help: 'Bits per pixel, for antialiasing.'
|
||||
});
|
||||
|
||||
let lcd_group = parser.add_mutually_exclusive_group();
|
||||
|
||||
lcd_group.add_argument('--lcd', {
|
||||
action: 'store_true',
|
||||
default: false,
|
||||
help: 'Enable subpixel rendering (horizontal pixel layout).'
|
||||
});
|
||||
|
||||
lcd_group.add_argument('--lcd-v', {
|
||||
action: 'store_true',
|
||||
default: false,
|
||||
help: 'Enable subpixel rendering (vertical pixel layout).'
|
||||
});
|
||||
|
||||
parser.add_argument('--use-color-info', {
|
||||
dest: 'use_color_info',
|
||||
action: 'store_true',
|
||||
default: false,
|
||||
help: 'Try to use glyph color info from font to create grayscale icons. ' +
|
||||
'Since gray tones are emulated via transparency, result will be good on contrast background only.'
|
||||
});
|
||||
|
||||
parser.add_argument('--format', {
|
||||
choices: convert.formats,
|
||||
required: true,
|
||||
help: 'Output format.'
|
||||
});
|
||||
|
||||
parser.add_argument('--font', {
|
||||
metavar: '<path>',
|
||||
action: ActionFontAdd,
|
||||
required: true,
|
||||
help: 'Source font path. Can be used multiple times to merge glyphs from different fonts.'
|
||||
});
|
||||
|
||||
parser.add_argument('-r', '--range', {
|
||||
type: range,
|
||||
action: ActionFontRangeAdd,
|
||||
help: `
|
||||
Range of glyphs to copy. Can be used multiple times, belongs to previously declared "--font". Examples:
|
||||
-r 0x1F450
|
||||
-r 0x20-0x7F
|
||||
-r 32-127
|
||||
-r 32-127,0x1F450
|
||||
-r '0x1F450=>0xF005'
|
||||
-r '0x1F450-0x1F470=>0xF005'
|
||||
`
|
||||
});
|
||||
|
||||
parser.add_argument('--symbols', {
|
||||
action: ActionFontRangeAdd,
|
||||
help: `
|
||||
List of characters to copy, belongs to previously declared "--font". Examples:
|
||||
--symbols ,.0123456789
|
||||
--symbols abcdefghigklmnopqrstuvwxyz
|
||||
`
|
||||
});
|
||||
|
||||
parser.add_argument('--autohint-off', {
|
||||
type: range,
|
||||
action: ActionFontStoreTrue,
|
||||
help: 'Disable autohinting for previously declared "--font"'
|
||||
});
|
||||
|
||||
parser.add_argument('--autohint-strong', {
|
||||
type: range,
|
||||
action: ActionFontStoreTrue,
|
||||
help: 'Use more strong autohinting for previously declared "--font" (will break kerning)'
|
||||
});
|
||||
|
||||
parser.add_argument('--force-fast-kern-format', {
|
||||
dest: 'fast_kerning',
|
||||
action: 'store_true',
|
||||
default: false,
|
||||
help: 'Always use kern classes instead of pairs (might be larger but faster).'
|
||||
});
|
||||
|
||||
parser.add_argument('--no-compress', {
|
||||
dest: 'no_compress',
|
||||
action: 'store_true',
|
||||
default: false,
|
||||
help: 'Disable built-in RLE compression.'
|
||||
});
|
||||
|
||||
parser.add_argument('--no-prefilter', {
|
||||
dest: 'no_prefilter',
|
||||
action: 'store_true',
|
||||
default: false,
|
||||
help: 'Disable bitmap lines filter (XOR), used to improve compression ratio.'
|
||||
});
|
||||
|
||||
parser.add_argument('--no-kerning', {
|
||||
dest: 'no_kerning',
|
||||
action: 'store_true',
|
||||
default: false,
|
||||
help: 'Drop kerning info to reduce size (not recommended).'
|
||||
});
|
||||
|
||||
parser.add_argument('--lv-include', {
|
||||
metavar: '<path>',
|
||||
help: 'Set alternate "lvgl.h" path (for --format lvgl).'
|
||||
});
|
||||
|
||||
parser.add_argument('--full-info', {
|
||||
dest: 'full_info',
|
||||
action: 'store_true',
|
||||
default: false,
|
||||
help: 'Don\'t shorten "font_info.json" (include pixels data).'
|
||||
});
|
||||
|
||||
//
|
||||
// Process CLI options
|
||||
//
|
||||
|
||||
let args = parser.parse_args(argv.length ? argv : [ '-h' ]);
|
||||
|
||||
for (let font of args.font) {
|
||||
if (font.ranges.length === 0) {
|
||||
parser.error(`You need to specify either "--range" or "--symbols" for font "${font.source_path}"`);
|
||||
}
|
||||
|
||||
try {
|
||||
font.source_bin = fs.readFileSync(font.source_path);
|
||||
} catch (err) {
|
||||
parser.error(`Cannot read file "${font.source_path}": ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Convert
|
||||
//
|
||||
|
||||
let files = await convert(args);
|
||||
|
||||
//
|
||||
// Store files
|
||||
//
|
||||
|
||||
for (let [ filename, data ] of Object.entries(files)) {
|
||||
let dir = path.dirname(filename);
|
||||
|
||||
mkdirp.sync(dir);
|
||||
|
||||
fs.writeFileSync(filename, data);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// export for tests
|
||||
module.exports._range = range;
|
173
node_modules/lv_font_conv/lib/collect_font_data.js
generated
vendored
Normal file
173
node_modules/lv_font_conv/lib/collect_font_data.js
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
// Read fonts
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
const opentype = require('opentype.js');
|
||||
const ft_render = require('./freetype');
|
||||
const AppError = require('./app_error');
|
||||
const Ranger = require('./ranger');
|
||||
|
||||
|
||||
module.exports = async function collect_font_data(args) {
|
||||
await ft_render.init();
|
||||
|
||||
// Duplicate font options as k/v for quick access
|
||||
let fonts_options = {};
|
||||
args.font.forEach(f => { fonts_options[f.source_path] = f; });
|
||||
|
||||
// read fonts
|
||||
let fonts_opentype = {};
|
||||
let fonts_freetype = {};
|
||||
|
||||
for (let { source_path, source_bin } of args.font) {
|
||||
// don't load font again if it's specified multiple times in args
|
||||
if (fonts_opentype[source_path]) continue;
|
||||
|
||||
try {
|
||||
let b = source_bin;
|
||||
|
||||
if (Buffer.isBuffer(b)) {
|
||||
// node.js Buffer -> ArrayBuffer
|
||||
b = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
|
||||
}
|
||||
|
||||
fonts_opentype[source_path] = opentype.parse(b);
|
||||
} catch (err) {
|
||||
throw new AppError(`Cannot load font "${source_path}": ${err.message}`);
|
||||
}
|
||||
|
||||
fonts_freetype[source_path] = ft_render.fontface_create(source_bin, args.size);
|
||||
}
|
||||
|
||||
// merge all ranges
|
||||
let ranger = new Ranger();
|
||||
|
||||
for (let { source_path, ranges } of args.font) {
|
||||
let font = fonts_freetype[source_path];
|
||||
|
||||
for (let item of ranges) {
|
||||
/* eslint-disable max-depth */
|
||||
if (item.range) {
|
||||
for (let i = 0; i < item.range.length; i += 3) {
|
||||
let range = item.range.slice(i, i + 3);
|
||||
let chars = ranger.add_range(source_path, ...range);
|
||||
let is_empty = true;
|
||||
|
||||
for (let code of chars) {
|
||||
if (ft_render.glyph_exists(font, code)) {
|
||||
is_empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_empty) {
|
||||
let a = '0x' + range[0].toString(16);
|
||||
let b = '0x' + range[1].toString(16);
|
||||
throw new AppError(`Font "${source_path}" doesn't have any characters included in range ${a}-${b}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item.symbols) {
|
||||
let chars = ranger.add_symbols(source_path, item.symbols);
|
||||
let is_empty = true;
|
||||
|
||||
for (let code of chars) {
|
||||
if (ft_render.glyph_exists(font, code)) {
|
||||
is_empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_empty) {
|
||||
throw new AppError(`Font "${source_path}" doesn't have any characters included in "${item.symbols}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mapping = ranger.get();
|
||||
let glyphs = [];
|
||||
let all_dst_charcodes = Object.keys(mapping).sort((a, b) => a - b).map(Number);
|
||||
|
||||
for (let dst_code of all_dst_charcodes) {
|
||||
let src_code = mapping[dst_code].code;
|
||||
let src_font = mapping[dst_code].font;
|
||||
|
||||
if (!ft_render.glyph_exists(fonts_freetype[src_font], src_code)) continue;
|
||||
|
||||
let ft_result = ft_render.glyph_render(
|
||||
fonts_freetype[src_font],
|
||||
src_code,
|
||||
{
|
||||
autohint_off: fonts_options[src_font].autohint_off,
|
||||
autohint_strong: fonts_options[src_font].autohint_strong,
|
||||
lcd: args.lcd,
|
||||
lcd_v: args.lcd_v,
|
||||
mono: !args.lcd && !args.lcd_v && args.bpp === 1,
|
||||
use_color_info: args.use_color_info
|
||||
}
|
||||
);
|
||||
|
||||
glyphs.push({
|
||||
code: dst_code,
|
||||
advanceWidth: ft_result.advance_x,
|
||||
bbox: {
|
||||
x: ft_result.x,
|
||||
y: ft_result.y - ft_result.height,
|
||||
width: ft_result.width,
|
||||
height: ft_result.height
|
||||
},
|
||||
kerning: {},
|
||||
freetype: ft_result.freetype,
|
||||
pixels: ft_result.pixels
|
||||
});
|
||||
}
|
||||
|
||||
if (!args.no_kerning) {
|
||||
let existing_dst_charcodes = glyphs.map(g => g.code);
|
||||
|
||||
for (let { code, kerning } of glyphs) {
|
||||
let src_code = mapping[code].code;
|
||||
let src_font = mapping[code].font;
|
||||
let font = fonts_opentype[src_font];
|
||||
let glyph = font.charToGlyph(String.fromCodePoint(src_code));
|
||||
|
||||
for (let dst_code2 of existing_dst_charcodes) {
|
||||
// can't merge kerning values from 2 different fonts
|
||||
if (mapping[dst_code2].font !== src_font) continue;
|
||||
|
||||
let src_code2 = mapping[dst_code2].code;
|
||||
let glyph2 = font.charToGlyph(String.fromCodePoint(src_code2));
|
||||
let krn_value = font.getKerningValue(glyph, glyph2);
|
||||
|
||||
if (krn_value) kerning[dst_code2] = krn_value * args.size / font.unitsPerEm;
|
||||
|
||||
//let krn_value = ft_render.get_kerning(font, src_code, src_code2).x;
|
||||
//if (krn_value) kerning[dst_code2] = krn_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let first_font = fonts_freetype[args.font[0].source_path];
|
||||
let first_font_scale = args.size / first_font.units_per_em;
|
||||
let os2_metrics = ft_render.fontface_os2_table(first_font);
|
||||
let post_table = fonts_opentype[args.font[0].source_path].tables.post;
|
||||
|
||||
for (let font of Object.values(fonts_freetype)) ft_render.fontface_destroy(font);
|
||||
|
||||
ft_render.destroy();
|
||||
|
||||
return {
|
||||
ascent: Math.max(...glyphs.map(g => g.bbox.y + g.bbox.height)),
|
||||
descent: Math.min(...glyphs.map(g => g.bbox.y)),
|
||||
typoAscent: Math.round(os2_metrics.typoAscent * first_font_scale),
|
||||
typoDescent: Math.round(os2_metrics.typoDescent * first_font_scale),
|
||||
typoLineGap: Math.round(os2_metrics.typoLineGap * first_font_scale),
|
||||
size: args.size,
|
||||
glyphs,
|
||||
underlinePosition: Math.round(post_table.underlinePosition * first_font_scale),
|
||||
underlineThickness: Math.round(post_table.underlineThickness * first_font_scale)
|
||||
};
|
||||
};
|
30
node_modules/lv_font_conv/lib/convert.js
generated
vendored
Normal file
30
node_modules/lv_font_conv/lib/convert.js
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// Internal API to convert input data into output font data
|
||||
// Used by both CLI and Web wrappers.
|
||||
'use strict';
|
||||
|
||||
const collect_font_data = require('./collect_font_data');
|
||||
|
||||
let writers = {
|
||||
dump: require('./writers/dump'),
|
||||
bin: require('./writers/bin'),
|
||||
lvgl: require('./writers/lvgl')
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Input:
|
||||
// - args like from CLI (optionally extended with binary content of files)
|
||||
//
|
||||
// Output:
|
||||
// - { name1: bin_data1, name2: bin_data2, ... }
|
||||
//
|
||||
// returns hash with files to write
|
||||
//
|
||||
module.exports = async function convert(args) {
|
||||
let font_data = await collect_font_data(args);
|
||||
let files = writers[args.format](args, font_data);
|
||||
|
||||
return files;
|
||||
};
|
||||
|
||||
module.exports.formats = Object.keys(writers);
|
105
node_modules/lv_font_conv/lib/font/cmap_build_subtables.js
generated
vendored
Normal file
105
node_modules/lv_font_conv/lib/font/cmap_build_subtables.js
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
// Find an optimal configuration of cmap tables representing set of codepoints,
|
||||
// using simple breadth-first algorithm
|
||||
//
|
||||
// Assume that:
|
||||
// - codepoints have one-to-one correspondence to glyph ids
|
||||
// - glyph ids are always bigger for bigger codepoints
|
||||
// - glyph ids are always consecutive (1..N without gaps)
|
||||
//
|
||||
// This way we can omit glyph ids from all calculations entirely: if codepoints
|
||||
// fit in format0, then glyph ids also will.
|
||||
//
|
||||
// format6 is not considered, because if glyph ids can be delta-coded,
|
||||
// multiple format0 tables are guaranteed to be smaller than a single format6.
|
||||
//
|
||||
// sparse format is not used because as long as glyph ids are consecutive,
|
||||
// sparse_tiny will always be preferred.
|
||||
//
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
function estimate_format0_tiny_size(/*start_code, end_code*/) {
|
||||
return 16;
|
||||
}
|
||||
|
||||
function estimate_format0_size(start_code, end_code) {
|
||||
return 16 + (end_code - start_code + 1);
|
||||
}
|
||||
|
||||
//function estimate_sparse_size(count) {
|
||||
// return 16 + count * 4;
|
||||
//}
|
||||
|
||||
function estimate_sparse_tiny_size(count) {
|
||||
return 16 + count * 2;
|
||||
}
|
||||
|
||||
module.exports = function cmap_split(all_codepoints) {
|
||||
all_codepoints = all_codepoints.sort((a, b) => a - b);
|
||||
|
||||
let min_paths = [];
|
||||
|
||||
for (let i = 0; i < all_codepoints.length; i++) {
|
||||
let min = { dist: Infinity };
|
||||
|
||||
for (let j = 0; j <= i; j++) {
|
||||
let prev_dist = (j - 1 >= 0) ? min_paths[j - 1].dist : 0;
|
||||
let s;
|
||||
|
||||
if (all_codepoints[i] - all_codepoints[j] < 256) {
|
||||
s = estimate_format0_size(all_codepoints[j], all_codepoints[i]);
|
||||
|
||||
/* eslint-disable max-depth */
|
||||
if (prev_dist + s < min.dist) {
|
||||
min = {
|
||||
dist: prev_dist + s,
|
||||
start: j,
|
||||
end: i,
|
||||
format: 'format0'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (all_codepoints[i] - all_codepoints[j] < 256 && all_codepoints[i] - i === all_codepoints[j] - j) {
|
||||
s = estimate_format0_tiny_size(all_codepoints[j], all_codepoints[i]);
|
||||
|
||||
/* eslint-disable max-depth */
|
||||
if (prev_dist + s < min.dist) {
|
||||
min = {
|
||||
dist: prev_dist + s,
|
||||
start: j,
|
||||
end: i,
|
||||
format: 'format0_tiny'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// tiny sparse will always be preferred over full sparse because glyph ids are consecutive
|
||||
if (all_codepoints[i] - all_codepoints[j] < 65536) {
|
||||
s = estimate_sparse_tiny_size(i - j + 1);
|
||||
|
||||
if (prev_dist + s < min.dist) {
|
||||
min = {
|
||||
dist: prev_dist + s,
|
||||
start: j,
|
||||
end: i,
|
||||
format: 'sparse_tiny'
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
min_paths[i] = min;
|
||||
}
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i = all_codepoints.length - 1; i >= 0;) {
|
||||
let path = min_paths[i];
|
||||
result.unshift([ path.format, all_codepoints.slice(path.start, path.end + 1) ]);
|
||||
i = path.start - 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
107
node_modules/lv_font_conv/lib/font/compress.js
generated
vendored
Normal file
107
node_modules/lv_font_conv/lib/font/compress.js
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
'use strict';
|
||||
|
||||
//const debug = require('debug')('compress');
|
||||
|
||||
function count_same(arr, offset) {
|
||||
let same = 1;
|
||||
let val = arr[offset];
|
||||
|
||||
for (let i = offset + 1; i < arr.length; i++) {
|
||||
if (arr[i] !== val) break;
|
||||
same++;
|
||||
}
|
||||
|
||||
return same;
|
||||
}
|
||||
|
||||
//
|
||||
// Compress pixels with RLE-like algorythm (modified I3BN)
|
||||
//
|
||||
// 1. Require minimal repeat count (1) to enter I3BN mode
|
||||
// 2. Increased 1-bit-replaced repeat limit (2 => 10)
|
||||
// 3. Length of direct repetition counter reduced (8 => 6 bits).
|
||||
//
|
||||
// pixels - flat array of pixels (one per entry)
|
||||
// options.bpp - bits per pixels
|
||||
//
|
||||
module.exports = function compress(bitStream, pixels, options) {
|
||||
const opts = Object.assign({}, { repeat: 1 }, options);
|
||||
|
||||
// Minimal repetitions count to enable RLE mode.
|
||||
const RLE_SKIP_COUNT = 1;
|
||||
// Number of repeats, when `1` used to replace data
|
||||
// If more - write as number
|
||||
const RLE_BIT_COLLAPSED_COUNT = 10;
|
||||
|
||||
const RLE_COUNTER_BITS = 6; // (2^bits - 1) - max value
|
||||
const RLE_COUNTER_MAX = (1 << RLE_COUNTER_BITS) - 1;
|
||||
// Force flush if counter dencity exceeded.
|
||||
const RLE_MAX_REPEATS = RLE_COUNTER_MAX + RLE_BIT_COLLAPSED_COUNT + 1;
|
||||
|
||||
//let bits_start_offset = bitStream.index;
|
||||
|
||||
let offset = 0;
|
||||
|
||||
while (offset < pixels.length) {
|
||||
const p = pixels[offset];
|
||||
|
||||
let same = count_same(pixels, offset);
|
||||
|
||||
// Clamp value because RLE counter density is limited
|
||||
if (same > RLE_MAX_REPEATS + RLE_SKIP_COUNT) {
|
||||
same = RLE_MAX_REPEATS + RLE_SKIP_COUNT;
|
||||
}
|
||||
|
||||
//debug(`offset: ${offset}, count: ${same}, pixel: ${p}`);
|
||||
|
||||
offset += same;
|
||||
|
||||
// If not enough for RLE - write as is.
|
||||
if (same <= RLE_SKIP_COUNT) {
|
||||
for (let i = 0; i < same; i++) {
|
||||
bitStream.writeBits(p, opts.bpp);
|
||||
//debug(`==> ${opts.bpp} bits`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// First, write "skipped" head as is.
|
||||
for (let i = 0; i < RLE_SKIP_COUNT; i++) {
|
||||
bitStream.writeBits(p, opts.bpp);
|
||||
//debug(`==> ${opts.bpp} bits`);
|
||||
}
|
||||
|
||||
same -= RLE_SKIP_COUNT;
|
||||
|
||||
// Not reached state to use counter => dump bit-extended
|
||||
if (same <= RLE_BIT_COLLAPSED_COUNT) {
|
||||
bitStream.writeBits(p, opts.bpp);
|
||||
//debug(`==> ${opts.bpp} bits (val)`);
|
||||
for (let i = 0; i < same; i++) {
|
||||
/*eslint-disable max-depth*/
|
||||
if (i < same - 1) {
|
||||
bitStream.writeBits(1, 1);
|
||||
//debug('==> 1 bit (rle repeat)');
|
||||
} else {
|
||||
bitStream.writeBits(0, 1);
|
||||
//debug('==> 1 bit (rle repeat last)');
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
same -= RLE_BIT_COLLAPSED_COUNT + 1;
|
||||
|
||||
bitStream.writeBits(p, opts.bpp);
|
||||
//debug(`==> ${opts.bpp} bits (val)`);
|
||||
|
||||
for (let i = 0; i < RLE_BIT_COLLAPSED_COUNT + 1; i++) {
|
||||
bitStream.writeBits(1, 1);
|
||||
//debug('==> 1 bit (rle repeat)');
|
||||
}
|
||||
bitStream.writeBits(same, RLE_COUNTER_BITS);
|
||||
//debug(`==> 4 bits (rle repeat count ${same})`);
|
||||
}
|
||||
|
||||
//debug(`output bits: ${bitStream.index - bits_start_offset}`);
|
||||
};
|
131
node_modules/lv_font_conv/lib/font/font.js
generated
vendored
Normal file
131
node_modules/lv_font_conv/lib/font/font.js
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
// Font class to generate tables
|
||||
'use strict';
|
||||
|
||||
const u = require('../utils');
|
||||
const debug = require('debug')('font');
|
||||
const Head = require('./table_head');
|
||||
const Cmap = require('./table_cmap');
|
||||
const Glyf = require('./table_glyf');
|
||||
const Loca = require('./table_loca');
|
||||
const Kern = require('./table_kern');
|
||||
|
||||
class Font {
|
||||
constructor(fontData, options) {
|
||||
this.src = fontData;
|
||||
|
||||
this.opts = options;
|
||||
|
||||
// Map chars to IDs (zero is reserved)
|
||||
this.glyph_id = { 0: 0 };
|
||||
|
||||
this.last_id = 1;
|
||||
this.createIDs();
|
||||
debug(`last_id: ${this.last_id}`);
|
||||
|
||||
this.init_tables();
|
||||
|
||||
this.minY = Math.min(...this.src.glyphs.map(g => g.bbox.y));
|
||||
debug(`minY: ${this.minY}`);
|
||||
this.maxY = Math.max(...this.src.glyphs.map(g => g.bbox.y + g.bbox.height));
|
||||
debug(`maxY: ${this.maxY}`);
|
||||
|
||||
// 0 => 1 byte, 1 => 2 bytes
|
||||
this.glyphIdFormat = Math.max(...Object.values(this.glyph_id)) > 255 ? 1 : 0;
|
||||
debug(`glyphIdFormat: ${this.glyphIdFormat}`);
|
||||
|
||||
// 1.0 by default, will be stored in font as FP12.4
|
||||
this.kerningScale = 1.0;
|
||||
let kerningMax = Math.max(...this.src.glyphs.map(g => Object.values(g.kerning).map(Math.abs)).flat());
|
||||
if (kerningMax >= 7.5) this.kerningScale = Math.ceil(kerningMax / 7.5 * 16) / 16;
|
||||
debug(`kerningScale: ${this.kerningScale}`);
|
||||
|
||||
// 0 => int, 1 => FP4
|
||||
this.advanceWidthFormat = this.hasKerning() ? 1 : 0;
|
||||
debug(`advanceWidthFormat: ${this.advanceWidthFormat}`);
|
||||
|
||||
this.xy_bits = Math.max(...this.src.glyphs.map(g => Math.max(
|
||||
u.signed_bits(g.bbox.x), u.signed_bits(g.bbox.y)
|
||||
)));
|
||||
debug(`xy_bits: ${this.xy_bits}`);
|
||||
|
||||
this.wh_bits = Math.max(...this.src.glyphs.map(g => Math.max(
|
||||
u.unsigned_bits(g.bbox.width), u.unsigned_bits(g.bbox.height)
|
||||
)));
|
||||
debug(`wh_bits: ${this.wh_bits}`);
|
||||
|
||||
this.advanceWidthBits = Math.max(...this.src.glyphs.map(
|
||||
g => u.signed_bits(this.widthToInt(g.advanceWidth))
|
||||
));
|
||||
debug(`advanceWidthBits: ${this.advanceWidthBits}`);
|
||||
|
||||
let glyphs = this.src.glyphs;
|
||||
|
||||
this.monospaced = glyphs.every((v, i, arr) => v.advanceWidth === arr[0].advanceWidth);
|
||||
debug(`monospaced: ${this.monospaced}`);
|
||||
|
||||
// This should stay in the end, because depends on previous variables
|
||||
// 0 => 2 bytes, 1 => 4 bytes
|
||||
this.indexToLocFormat = this.glyf.getSize() > 65535 ? 1 : 0;
|
||||
debug(`indexToLocFormat: ${this.indexToLocFormat}`);
|
||||
|
||||
this.subpixels_mode = options.lcd ? 1 : (options.lcd_v ? 2 : 0);
|
||||
debug(`subpixels_mode: ${this.subpixels_mode}`);
|
||||
}
|
||||
|
||||
init_tables() {
|
||||
this.head = new Head(this);
|
||||
this.glyf = new Glyf(this);
|
||||
this.cmap = new Cmap(this);
|
||||
this.loca = new Loca(this);
|
||||
this.kern = new Kern(this);
|
||||
}
|
||||
|
||||
createIDs() {
|
||||
// Simplified, don't check dupes
|
||||
this.last_id = 1;
|
||||
|
||||
for (let i = 0; i < this.src.glyphs.length; i++) {
|
||||
// reserve zero for special cases
|
||||
this.glyph_id[this.src.glyphs[i].code] = this.last_id;
|
||||
this.last_id++;
|
||||
}
|
||||
}
|
||||
|
||||
hasKerning() {
|
||||
if (this.opts.no_kerning) return false;
|
||||
|
||||
for (let glyph of this.src.glyphs) {
|
||||
if (glyph.kerning && Object.keys(glyph.kerning).length) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns integer width, depending on format
|
||||
widthToInt(val) {
|
||||
if (this.advanceWidthFormat === 0) return Math.round(val);
|
||||
|
||||
return Math.round(val * 16);
|
||||
}
|
||||
|
||||
// Convert kerning to FP4.4, useable for writer. Apply `kerningScale`.
|
||||
kernToFP(val) {
|
||||
return Math.round(val / this.kerningScale * 16);
|
||||
}
|
||||
|
||||
toBin() {
|
||||
const result = Buffer.concat([
|
||||
this.head.toBin(),
|
||||
this.cmap.toBin(),
|
||||
this.loca.toBin(),
|
||||
this.glyf.toBin(),
|
||||
this.kern.toBin()
|
||||
]);
|
||||
|
||||
debug(`font size: ${result.length}`);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = Font;
|
201
node_modules/lv_font_conv/lib/font/table_cmap.js
generated
vendored
Normal file
201
node_modules/lv_font_conv/lib/font/table_cmap.js
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const build_subtables = require('./cmap_build_subtables');
|
||||
const u = require('../utils');
|
||||
const debug = require('debug')('font.table.cmap');
|
||||
|
||||
|
||||
const O_SIZE = 0;
|
||||
const O_LABEL = O_SIZE + 4;
|
||||
const O_COUNT = O_LABEL + 4;
|
||||
|
||||
const HEAD_LENGTH = O_COUNT + 4;
|
||||
|
||||
const SUB_FORMAT_0 = 0;
|
||||
const SUB_FORMAT_0_TINY = 2;
|
||||
const SUB_FORMAT_SPARSE = 1;
|
||||
const SUB_FORMAT_SPARSE_TINY = 3;
|
||||
|
||||
|
||||
class Cmap {
|
||||
constructor(font) {
|
||||
this.font = font;
|
||||
this.label = 'cmap';
|
||||
|
||||
this.sub_heads = [];
|
||||
this.sub_data = [];
|
||||
|
||||
this.compiled = false;
|
||||
}
|
||||
|
||||
compile() {
|
||||
if (this.compiled) return;
|
||||
this.compiled = true;
|
||||
|
||||
const f = this.font;
|
||||
|
||||
let subtables_plan = build_subtables(f.src.glyphs.map(g => g.code));
|
||||
|
||||
const count_format0 = subtables_plan.filter(s => s[0] === 'format0').length;
|
||||
const count_sparse = subtables_plan.length - count_format0;
|
||||
debug(`${subtables_plan.length} subtable(s): ${count_format0} "format 0", ${count_sparse} "sparse"`);
|
||||
|
||||
for (let [ format, codepoints ] of subtables_plan) {
|
||||
let g = this.glyphByCode(codepoints[0]);
|
||||
let start_glyph_id = f.glyph_id[g.code];
|
||||
let min_code = codepoints[0];
|
||||
let max_code = codepoints[codepoints.length - 1];
|
||||
let entries_count = max_code - min_code + 1;
|
||||
let format_code = 0;
|
||||
|
||||
if (format === 'format0_tiny') {
|
||||
format_code = SUB_FORMAT_0_TINY;
|
||||
this.sub_data.push(Buffer.alloc(0));
|
||||
} else if (format === 'format0') {
|
||||
format_code = SUB_FORMAT_0;
|
||||
this.sub_data.push(this.create_format0_data(min_code, max_code, start_glyph_id));
|
||||
} else if (format === 'sparse_tiny') {
|
||||
entries_count = codepoints.length;
|
||||
format_code = SUB_FORMAT_SPARSE_TINY;
|
||||
this.sub_data.push(this.create_sparse_tiny_data(codepoints, start_glyph_id));
|
||||
} else { // assume format === 'sparse'
|
||||
entries_count = codepoints.length;
|
||||
format_code = SUB_FORMAT_SPARSE;
|
||||
this.sub_data.push(this.create_sparse_data(codepoints, start_glyph_id));
|
||||
}
|
||||
|
||||
this.sub_heads.push(this.createSubHeader(
|
||||
min_code,
|
||||
max_code - min_code + 1,
|
||||
start_glyph_id,
|
||||
entries_count,
|
||||
format_code
|
||||
));
|
||||
}
|
||||
|
||||
this.subHeaderUpdateAllOffsets();
|
||||
}
|
||||
|
||||
createSubHeader(rangeStart, rangeLen, glyphIdOffset, total, type) {
|
||||
const buf = Buffer.alloc(16);
|
||||
|
||||
// buf.writeUInt32LE(offset, 0); offset unknown at this moment
|
||||
buf.writeUInt32LE(rangeStart, 4);
|
||||
buf.writeUInt16LE(rangeLen, 8);
|
||||
buf.writeUInt16LE(glyphIdOffset, 10);
|
||||
buf.writeUInt16LE(total, 12);
|
||||
buf.writeUInt8(type, 14);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
subHeaderUpdateOffset(header, val) {
|
||||
header.writeUInt32LE(val, 0);
|
||||
}
|
||||
|
||||
subHeaderUpdateAllOffsets() {
|
||||
for (let i = 0; i < this.sub_heads.length; i++) {
|
||||
const offset = HEAD_LENGTH +
|
||||
u.sum(this.sub_heads.map(h => h.length)) +
|
||||
u.sum(this.sub_data.slice(0, i).map(d => d.length));
|
||||
|
||||
this.subHeaderUpdateOffset(this.sub_heads[i], offset);
|
||||
}
|
||||
}
|
||||
|
||||
glyphByCode(code) {
|
||||
for (let g of this.font.src.glyphs) {
|
||||
if (g.code === code) return g;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
collect_format0_data(min_code, max_code, start_glyph_id) {
|
||||
let data = [];
|
||||
|
||||
for (let i = min_code; i <= max_code; i++) {
|
||||
const g = this.glyphByCode(i);
|
||||
|
||||
if (!g) {
|
||||
data.push(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const id_delta = this.font.glyph_id[g.code] - start_glyph_id;
|
||||
|
||||
if (id_delta < 0 || id_delta > 255) throw new Error('Glyph ID delta out of Format 0 range');
|
||||
|
||||
data.push(id_delta);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
create_format0_data(min_code, max_code, start_glyph_id) {
|
||||
const data = this.collect_format0_data(min_code, max_code, start_glyph_id);
|
||||
|
||||
return u.balign4(Buffer.from(data));
|
||||
}
|
||||
|
||||
collect_sparse_data(codepoints, start_glyph_id) {
|
||||
let codepoints_list = [];
|
||||
let ids_list = [];
|
||||
|
||||
for (let code of codepoints) {
|
||||
let g = this.glyphByCode(code);
|
||||
let id = this.font.glyph_id[g.code];
|
||||
|
||||
let code_delta = code - codepoints[0];
|
||||
let id_delta = id - start_glyph_id;
|
||||
|
||||
if (code_delta < 0 || code_delta > 65535) throw new Error('Codepoint delta out of range');
|
||||
if (id_delta < 0 || id_delta > 65535) throw new Error('Glyph ID delta out of range');
|
||||
|
||||
codepoints_list.push(code_delta);
|
||||
ids_list.push(id_delta);
|
||||
}
|
||||
|
||||
return {
|
||||
codes: codepoints_list,
|
||||
ids: ids_list
|
||||
};
|
||||
}
|
||||
|
||||
create_sparse_data(codepoints, start_glyph_id) {
|
||||
const data = this.collect_sparse_data(codepoints, start_glyph_id);
|
||||
|
||||
return u.balign4(Buffer.concat([
|
||||
u.bFromA16(data.codes),
|
||||
u.bFromA16(data.ids)
|
||||
]));
|
||||
}
|
||||
|
||||
create_sparse_tiny_data(codepoints, start_glyph_id) {
|
||||
const data = this.collect_sparse_data(codepoints, start_glyph_id);
|
||||
|
||||
return u.balign4(u.bFromA16(data.codes));
|
||||
}
|
||||
|
||||
toBin() {
|
||||
if (!this.compiled) this.compile();
|
||||
|
||||
const buf = Buffer.concat([
|
||||
Buffer.alloc(HEAD_LENGTH),
|
||||
Buffer.concat(this.sub_heads),
|
||||
Buffer.concat(this.sub_data)
|
||||
]);
|
||||
debug(`table size = ${buf.length}`);
|
||||
|
||||
buf.writeUInt32LE(buf.length, O_SIZE);
|
||||
buf.write(this.label, O_LABEL);
|
||||
buf.writeUInt32LE(this.sub_heads.length, O_COUNT);
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = Cmap;
|
147
node_modules/lv_font_conv/lib/font/table_glyf.js
generated
vendored
Normal file
147
node_modules/lv_font_conv/lib/font/table_glyf.js
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
'use strict';
|
||||
|
||||
const u = require('../utils');
|
||||
const { BitStream } = require('bit-buffer');
|
||||
const debug = require('debug')('font.table.glyf');
|
||||
const compress = require('./compress');
|
||||
|
||||
|
||||
const O_SIZE = 0;
|
||||
const O_LABEL = O_SIZE + 4;
|
||||
|
||||
const HEAD_LENGTH = O_LABEL + 4;
|
||||
|
||||
|
||||
class Glyf {
|
||||
constructor(font) {
|
||||
this.font = font;
|
||||
this.label = 'glyf';
|
||||
|
||||
this.compiled = false;
|
||||
|
||||
this.binData = [];
|
||||
}
|
||||
|
||||
// convert 8-bit opacity to bpp-bit
|
||||
pixelsToBpp(pixels) {
|
||||
const bpp = this.font.opts.bpp;
|
||||
return pixels.map(line => line.map(p => (p >>> (8 - bpp))));
|
||||
}
|
||||
|
||||
// Returns "binary stream" (Buffer) of compiled glyph data
|
||||
compileGlyph(glyph) {
|
||||
// Allocate memory, enough for eny storage formats
|
||||
const buf = Buffer.alloc(100 + glyph.bbox.width * glyph.bbox.height * 4);
|
||||
const bs = new BitStream(buf);
|
||||
bs.bigEndian = true;
|
||||
const f = this.font;
|
||||
|
||||
// Store Width
|
||||
if (!f.monospaced) {
|
||||
let w = f.widthToInt(glyph.advanceWidth);
|
||||
bs.writeBits(w, f.advanceWidthBits);
|
||||
}
|
||||
|
||||
// Store X, Y
|
||||
bs.writeBits(glyph.bbox.x, f.xy_bits);
|
||||
bs.writeBits(glyph.bbox.y, f.xy_bits);
|
||||
bs.writeBits(glyph.bbox.width, f.wh_bits);
|
||||
bs.writeBits(glyph.bbox.height, f.wh_bits);
|
||||
|
||||
const pixels = this.pixelsToBpp(glyph.pixels);
|
||||
|
||||
this.storePixels(bs, pixels);
|
||||
|
||||
// Shrink size
|
||||
const result = Buffer.alloc(bs.byteIndex);
|
||||
buf.copy(result, 0, 0, bs.byteIndex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
storePixels(bitStream, pixels) {
|
||||
if (this.getCompressionCode() === 0) this.storePixelsRaw(bitStream, pixels);
|
||||
else this.storePixelsCompressed(bitStream, pixels);
|
||||
}
|
||||
|
||||
storePixelsRaw(bitStream, pixels) {
|
||||
const bpp = this.font.opts.bpp;
|
||||
|
||||
for (let y = 0; y < pixels.length; y++) {
|
||||
const line = pixels[y];
|
||||
for (let x = 0; x < line.length; x++) {
|
||||
bitStream.writeBits(line[x], bpp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
storePixelsCompressed(bitStream, pixels) {
|
||||
let p;
|
||||
|
||||
if (this.font.opts.no_prefilter) p = pixels.flat();
|
||||
else p = u.prefilter(pixels).flat();
|
||||
|
||||
compress(bitStream, p, this.font.opts);
|
||||
}
|
||||
|
||||
// Create internal struct with binary data for each glyph
|
||||
// Needed to calculate offsets & build final result
|
||||
compile() {
|
||||
this.compiled = true;
|
||||
|
||||
this.binData = [
|
||||
Buffer.alloc(0) // Reserve id 0
|
||||
];
|
||||
|
||||
const f = this.font;
|
||||
|
||||
f.src.glyphs.forEach(g => {
|
||||
const id = f.glyph_id[g.code];
|
||||
|
||||
this.binData[id] = this.compileGlyph(g);
|
||||
});
|
||||
}
|
||||
|
||||
toBin() {
|
||||
if (!this.compiled) this.compile();
|
||||
|
||||
const buf = u.balign4(Buffer.concat([
|
||||
Buffer.alloc(HEAD_LENGTH),
|
||||
Buffer.concat(this.binData)
|
||||
]));
|
||||
|
||||
buf.writeUInt32LE(buf.length, O_SIZE);
|
||||
buf.write(this.label, O_LABEL);
|
||||
|
||||
debug(`table size = ${buf.length}`);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
getSize() {
|
||||
if (!this.compiled) this.compile();
|
||||
|
||||
return u.align4(HEAD_LENGTH + u.sum(this.binData.map(b => b.length)));
|
||||
}
|
||||
|
||||
getOffset(id) {
|
||||
if (!this.compiled) this.compile();
|
||||
|
||||
let offset = HEAD_LENGTH;
|
||||
|
||||
for (let i = 0; i < id; i++) offset += this.binData[i].length;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
getCompressionCode() {
|
||||
if (this.font.opts.no_compress) return 0;
|
||||
if (this.font.opts.bpp === 1) return 0;
|
||||
|
||||
if (this.font.opts.no_prefilter) return 2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = Glyf;
|
99
node_modules/lv_font_conv/lib/font/table_head.js
generated
vendored
Normal file
99
node_modules/lv_font_conv/lib/font/table_head.js
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const u = require('../utils');
|
||||
const debug = require('debug')('font.table.head');
|
||||
|
||||
const O_SIZE = 0;
|
||||
const O_LABEL = O_SIZE + 4;
|
||||
const O_VERSION = O_LABEL + 4;
|
||||
const O_TABLES = O_VERSION + 4;
|
||||
const O_FONT_SIZE = O_TABLES + 2;
|
||||
const O_ASCENT = O_FONT_SIZE + 2;
|
||||
const O_DESCENT = O_ASCENT + 2;
|
||||
const O_TYPO_ASCENT = O_DESCENT + 2;
|
||||
const O_TYPO_DESCENT = O_TYPO_ASCENT + 2;
|
||||
const O_TYPO_LINE_GAP = O_TYPO_DESCENT + 2;
|
||||
const O_MIN_Y = O_TYPO_LINE_GAP + 2;
|
||||
const O_MAX_Y = O_MIN_Y + 2;
|
||||
const O_DEF_ADVANCE_WIDTH = O_MAX_Y + 2;
|
||||
const O_KERNING_SCALE = O_DEF_ADVANCE_WIDTH + 2;
|
||||
const O_INDEX_TO_LOC_FORMAT = O_KERNING_SCALE + 2;
|
||||
const O_GLYPH_ID_FORMAT = O_INDEX_TO_LOC_FORMAT + 1;
|
||||
const O_ADVANCE_WIDTH_FORMAT = O_GLYPH_ID_FORMAT + 1;
|
||||
const O_BITS_PER_PIXEL = O_ADVANCE_WIDTH_FORMAT + 1;
|
||||
const O_XY_BITS = O_BITS_PER_PIXEL + 1;
|
||||
const O_WH_BITS = O_XY_BITS + 1;
|
||||
const O_ADVANCE_WIDTH_BITS = O_WH_BITS + 1;
|
||||
const O_COMPRESSION_ID = O_ADVANCE_WIDTH_BITS + 1;
|
||||
const O_SUBPIXELS_MODE = O_COMPRESSION_ID + 1;
|
||||
const O_TMP_RESERVED1 = O_SUBPIXELS_MODE + 1;
|
||||
const O_UNDERLINE_POSITION = O_TMP_RESERVED1 + 1;
|
||||
const O_UNDERLINE_THICKNESS = O_UNDERLINE_POSITION + 2;
|
||||
const HEAD_LENGTH = u.align4(O_UNDERLINE_THICKNESS + 2);
|
||||
|
||||
|
||||
class Head {
|
||||
constructor(font) {
|
||||
this.font = font;
|
||||
this.label = 'head';
|
||||
this.version = 1;
|
||||
}
|
||||
|
||||
toBin() {
|
||||
const buf = Buffer.alloc(HEAD_LENGTH);
|
||||
debug(`table size = ${buf.length}`);
|
||||
|
||||
buf.writeUInt32LE(HEAD_LENGTH, O_SIZE);
|
||||
buf.write(this.label, O_LABEL);
|
||||
buf.writeUInt32LE(this.version, O_VERSION);
|
||||
|
||||
const f = this.font;
|
||||
|
||||
const tables_count = f.hasKerning() ? 4 : 3;
|
||||
|
||||
buf.writeUInt16LE(tables_count, O_TABLES);
|
||||
|
||||
buf.writeUInt16LE(f.src.size, O_FONT_SIZE);
|
||||
buf.writeUInt16LE(f.src.ascent, O_ASCENT);
|
||||
buf.writeInt16LE(f.src.descent, O_DESCENT);
|
||||
|
||||
buf.writeUInt16LE(f.src.typoAscent, O_TYPO_ASCENT);
|
||||
buf.writeInt16LE(f.src.typoDescent, O_TYPO_DESCENT);
|
||||
buf.writeUInt16LE(f.src.typoLineGap, O_TYPO_LINE_GAP);
|
||||
|
||||
buf.writeInt16LE(f.minY, O_MIN_Y);
|
||||
buf.writeInt16LE(f.maxY, O_MAX_Y);
|
||||
|
||||
if (f.monospaced) {
|
||||
buf.writeUInt16LE(f.widthToInt(f.src.glyphs[0].advanceWidth), O_DEF_ADVANCE_WIDTH);
|
||||
} else {
|
||||
buf.writeUInt16LE(0, O_DEF_ADVANCE_WIDTH);
|
||||
}
|
||||
|
||||
buf.writeUInt16LE(Math.round(f.kerningScale * 16), O_KERNING_SCALE); // FP12.4
|
||||
|
||||
buf.writeUInt8(f.indexToLocFormat, O_INDEX_TO_LOC_FORMAT);
|
||||
buf.writeUInt8(f.glyphIdFormat, O_GLYPH_ID_FORMAT);
|
||||
buf.writeUInt8(f.advanceWidthFormat, O_ADVANCE_WIDTH_FORMAT);
|
||||
|
||||
buf.writeUInt8(f.opts.bpp, O_BITS_PER_PIXEL);
|
||||
buf.writeUInt8(f.xy_bits, O_XY_BITS);
|
||||
buf.writeUInt8(f.wh_bits, O_WH_BITS);
|
||||
|
||||
if (f.monospaced) buf.writeUInt8(0, O_ADVANCE_WIDTH_BITS);
|
||||
else buf.writeUInt8(f.advanceWidthBits, O_ADVANCE_WIDTH_BITS);
|
||||
|
||||
buf.writeUInt8(f.glyf.getCompressionCode(), O_COMPRESSION_ID);
|
||||
|
||||
buf.writeUInt8(f.subpixels_mode, O_SUBPIXELS_MODE);
|
||||
|
||||
buf.writeInt16LE(f.src.underlinePosition, O_UNDERLINE_POSITION);
|
||||
buf.writeUInt16LE(f.src.underlineThickness, O_UNDERLINE_POSITION);
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = Head;
|
256
node_modules/lv_font_conv/lib/font/table_kern.js
generated
vendored
Normal file
256
node_modules/lv_font_conv/lib/font/table_kern.js
generated
vendored
Normal file
@ -0,0 +1,256 @@
|
||||
'use strict';
|
||||
|
||||
const u = require('../utils');
|
||||
const debug = require('debug')('font.table.kern');
|
||||
|
||||
|
||||
const O_SIZE = 0;
|
||||
const O_LABEL = O_SIZE + 4;
|
||||
const O_FORMAT = O_LABEL + 4;
|
||||
|
||||
const HEAD_LENGTH = u.align4(O_FORMAT + 1);
|
||||
|
||||
|
||||
class Kern {
|
||||
constructor(font) {
|
||||
this.font = font;
|
||||
this.label = 'kern';
|
||||
this.format3_forced = false;
|
||||
}
|
||||
|
||||
collect_format0_data() {
|
||||
const f = this.font;
|
||||
const glyphs = u.sort_by(this.font.src.glyphs, g => f.glyph_id[g.code]);
|
||||
const kernSorted = [];
|
||||
|
||||
for (let g of glyphs) {
|
||||
if (!g.kerning || !Object.keys(g.kerning).length) continue;
|
||||
|
||||
const glyph_id = f.glyph_id[g.code];
|
||||
const paired = u.sort_by(Object.keys(g.kerning), code => f.glyph_id[code]);
|
||||
|
||||
for (let code of paired) {
|
||||
const glyph_id2 = f.glyph_id[code];
|
||||
kernSorted.push([ glyph_id, glyph_id2, g.kerning[code] ]);
|
||||
}
|
||||
}
|
||||
|
||||
return kernSorted;
|
||||
}
|
||||
|
||||
create_format0_data() {
|
||||
const f = this.font;
|
||||
const glyphs = this.font.src.glyphs;
|
||||
const kernSorted = this.collect_format0_data();
|
||||
|
||||
const count = kernSorted.length;
|
||||
|
||||
const kerned_glyphs = glyphs.filter(g => Object.keys(g.kerning).length).length;
|
||||
const kerning_list_max = Math.max(...glyphs.map(g => Object.keys(g.kerning).length));
|
||||
debug(`${kerned_glyphs} kerned glyphs of ${glyphs.length}, ${kerning_list_max} max list, ${count} total pairs`);
|
||||
|
||||
const subheader = Buffer.alloc(4);
|
||||
|
||||
subheader.writeUInt32LE(count, 0);
|
||||
|
||||
const pairs_buf = Buffer.alloc((f.glyphIdFormat ? 4 : 2) * count);
|
||||
|
||||
// Write kerning pairs
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (f.glyphIdFormat === 0) {
|
||||
pairs_buf.writeUInt8(kernSorted[i][0], 2 * i);
|
||||
pairs_buf.writeUInt8(kernSorted[i][1], 2 * i + 1);
|
||||
} else {
|
||||
pairs_buf.writeUInt16LE(kernSorted[i][0], 4 * i);
|
||||
pairs_buf.writeUInt16LE(kernSorted[i][1], 4 * i + 2);
|
||||
}
|
||||
}
|
||||
|
||||
const values_buf = Buffer.alloc(count);
|
||||
|
||||
// Write kerning values
|
||||
for (let i = 0; i < count; i++) {
|
||||
values_buf.writeInt8(f.kernToFP(kernSorted[i][2]), i); // FP4.4
|
||||
}
|
||||
|
||||
let buf = Buffer.concat([
|
||||
subheader,
|
||||
pairs_buf,
|
||||
values_buf
|
||||
]);
|
||||
|
||||
let buf_aligned = u.balign4(buf);
|
||||
|
||||
debug(`table format0 size = ${buf_aligned.length}`);
|
||||
return buf_aligned;
|
||||
}
|
||||
|
||||
collect_format3_data() {
|
||||
const f = this.font;
|
||||
const glyphs = u.sort_by(this.font.src.glyphs, g => f.glyph_id[g.code]);
|
||||
|
||||
// extract kerning pairs for each character;
|
||||
// left kernings are kerning values based on left char (already there),
|
||||
// right kernings are kerning values based on right char (extracted from left)
|
||||
const left_kernings = {};
|
||||
const right_kernings = {};
|
||||
|
||||
for (let g of glyphs) {
|
||||
if (!g.kerning || !Object.keys(g.kerning).length) continue;
|
||||
|
||||
const paired = Object.keys(g.kerning);
|
||||
|
||||
left_kernings[g.code] = g.kerning;
|
||||
|
||||
for (let code of paired) {
|
||||
right_kernings[code] = right_kernings[code] || {};
|
||||
right_kernings[code][g.code] = g.kerning[code];
|
||||
}
|
||||
}
|
||||
|
||||
// input:
|
||||
// - kernings, char => { hash: String, [char1]: Number, [char2]: Number, ... }
|
||||
//
|
||||
// returns:
|
||||
// - array of [ char1, char2, ... ]
|
||||
//
|
||||
function build_classes(kernings) {
|
||||
const classes = [];
|
||||
|
||||
for (let code of Object.keys(kernings)) {
|
||||
// for each kerning table calculate unique value representing it;
|
||||
// keys needs to be sorted for this (but we're using numeric keys, so
|
||||
// sorting happens automatically and can't be changed)
|
||||
const hash = JSON.stringify(kernings[code]);
|
||||
|
||||
classes[hash] = classes[hash] || [];
|
||||
classes[hash].push(Number(code));
|
||||
}
|
||||
|
||||
return Object.values(classes);
|
||||
}
|
||||
|
||||
const left_classes = build_classes(left_kernings);
|
||||
debug(`unique left classes: ${left_classes.length}`);
|
||||
|
||||
const right_classes = build_classes(right_kernings);
|
||||
debug(`unique right classes: ${right_classes.length}`);
|
||||
|
||||
if (left_classes.length >= 255 || right_classes.length >= 255) {
|
||||
debug('too many classes for format3 subtable');
|
||||
return null;
|
||||
}
|
||||
|
||||
function kern_class_mapping(classes) {
|
||||
const arr = Array(f.last_id).fill(0);
|
||||
|
||||
classes.forEach((members, idx) => {
|
||||
for (let code of members) {
|
||||
arr[f.glyph_id[code]] = idx + 1;
|
||||
}
|
||||
});
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
function kern_class_values() {
|
||||
const arr = [];
|
||||
|
||||
for (let left_class of left_classes) {
|
||||
for (let right_class of right_classes) {
|
||||
let code1 = left_class[0];
|
||||
let code2 = right_class[0];
|
||||
arr.push(left_kernings[code1][code2] || 0);
|
||||
}
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
return {
|
||||
left_classes: left_classes.length,
|
||||
right_classes: right_classes.length,
|
||||
left_mapping: kern_class_mapping(left_classes),
|
||||
right_mapping: kern_class_mapping(right_classes),
|
||||
values: kern_class_values()
|
||||
};
|
||||
}
|
||||
|
||||
create_format3_data() {
|
||||
const f = this.font;
|
||||
const {
|
||||
left_classes,
|
||||
right_classes,
|
||||
left_mapping,
|
||||
right_mapping,
|
||||
values
|
||||
} = this.collect_format3_data();
|
||||
|
||||
const subheader = Buffer.alloc(4);
|
||||
subheader.writeUInt16LE(f.last_id);
|
||||
subheader.writeUInt8(left_classes, 2);
|
||||
subheader.writeUInt8(right_classes, 3);
|
||||
|
||||
let buf = Buffer.concat([
|
||||
subheader,
|
||||
Buffer.from(left_mapping),
|
||||
Buffer.from(right_mapping),
|
||||
Buffer.from(values.map(v => f.kernToFP(v)))
|
||||
]);
|
||||
|
||||
let buf_aligned = u.balign4(buf);
|
||||
|
||||
debug(`table format3 size = ${buf_aligned.length}`);
|
||||
return buf_aligned;
|
||||
}
|
||||
|
||||
should_use_format3() {
|
||||
if (!this.font.hasKerning()) return false;
|
||||
|
||||
const format0_data = this.create_format0_data();
|
||||
const format3_data = this.create_format3_data();
|
||||
|
||||
if (format3_data && format3_data.length <= format0_data.length) return true;
|
||||
|
||||
if (this.font.opts.fast_kerning && format3_data) {
|
||||
this.format3_forced = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
toBin() {
|
||||
if (!this.font.hasKerning()) return Buffer.alloc(0);
|
||||
|
||||
const format0_data = this.create_format0_data();
|
||||
const format3_data = this.create_format3_data();
|
||||
|
||||
let header = Buffer.alloc(HEAD_LENGTH);
|
||||
|
||||
let data = format0_data;
|
||||
header.writeUInt8(0, O_FORMAT);
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
if (this.should_use_format3()) {
|
||||
data = format3_data;
|
||||
header.writeUInt8(3, O_FORMAT);
|
||||
|
||||
if (this.format3_forced) {
|
||||
let diff = format3_data.length - format0_data.length;
|
||||
console.log(`Forced faster kerning format (via classes). Size increase is ${diff} bytes.`);
|
||||
}
|
||||
} else if (this.font.opts.fast_kerning) {
|
||||
console.log('Forced faster kerning format (via classes), but data exceeds it\'s limits. Continue use pairs.');
|
||||
}
|
||||
|
||||
header.writeUInt32LE(header.length + data.length, O_SIZE);
|
||||
header.write(this.label, O_LABEL);
|
||||
|
||||
return Buffer.concat([ header, data ]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = Kern;
|
42
node_modules/lv_font_conv/lib/font/table_loca.js
generated
vendored
Normal file
42
node_modules/lv_font_conv/lib/font/table_loca.js
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const u = require('../utils');
|
||||
const debug = require('debug')('font.table.loca');
|
||||
|
||||
|
||||
const O_SIZE = 0;
|
||||
const O_LABEL = O_SIZE + 4;
|
||||
const O_COUNT = O_LABEL + 4;
|
||||
|
||||
const HEAD_LENGTH = O_COUNT + 4;
|
||||
|
||||
|
||||
class Loca {
|
||||
constructor(font) {
|
||||
this.font = font;
|
||||
this.label = 'loca';
|
||||
}
|
||||
|
||||
toBin() {
|
||||
const f = this.font;
|
||||
|
||||
const offsets = [ ...Array(f.last_id).keys() ].map(i => f.glyf.getOffset(i));
|
||||
|
||||
const buf = u.balign4(Buffer.concat([
|
||||
Buffer.alloc(HEAD_LENGTH),
|
||||
f.indexToLocFormat ? u.bFromA32(offsets) : u.bFromA16(offsets)
|
||||
]));
|
||||
|
||||
buf.writeUInt32LE(buf.length, O_SIZE);
|
||||
buf.write(this.label, O_LABEL);
|
||||
buf.writeUInt32LE(f.last_id, O_COUNT);
|
||||
|
||||
debug(`table size = ${buf.length}`);
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = Loca;
|
317
node_modules/lv_font_conv/lib/freetype/index.js
generated
vendored
Normal file
317
node_modules/lv_font_conv/lib/freetype/index.js
generated
vendored
Normal file
@ -0,0 +1,317 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const ft_render_fabric = require('./build/ft_render');
|
||||
|
||||
let m = null; // compiled module instance
|
||||
let library = 0; // pointer to library struct in wasm memory
|
||||
|
||||
|
||||
// workaround because of bug in emscripten:
|
||||
// https://github.com/emscripten-core/emscripten/issues/5820
|
||||
const runtime_initialized = new Promise(resolve => {
|
||||
ft_render_fabric().then(module_instance => {
|
||||
m = module_instance;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
function from_16_16(fixed_point) {
|
||||
return fixed_point / (1 << 16);
|
||||
}
|
||||
|
||||
function from_26_6(fixed_point) {
|
||||
return fixed_point / (1 << 6);
|
||||
}
|
||||
|
||||
function int8_to_uint8(value) {
|
||||
return value >= 0 ? value : value + 0x100;
|
||||
}
|
||||
|
||||
let FT_New_Memory_Face,
|
||||
FT_Set_Char_Size,
|
||||
FT_Set_Pixel_Sizes,
|
||||
FT_Get_Char_Index,
|
||||
FT_Load_Glyph,
|
||||
FT_Get_Sfnt_Table,
|
||||
FT_Get_Kerning,
|
||||
FT_Done_Face;
|
||||
|
||||
module.exports.init = async function () {
|
||||
await runtime_initialized;
|
||||
m._init_constants();
|
||||
|
||||
FT_New_Memory_Face = module.exports.FT_New_Memory_Face =
|
||||
m.cwrap('FT_New_Memory_Face', 'number', [ 'number', 'number', 'number', 'number', 'number' ]);
|
||||
|
||||
FT_Set_Char_Size = module.exports.FT_Set_Char_Size =
|
||||
m.cwrap('FT_Set_Char_Size', 'number', [ 'number', 'number', 'number', 'number', 'number' ]);
|
||||
|
||||
FT_Set_Pixel_Sizes = module.exports.FT_Set_Pixel_Sizes =
|
||||
m.cwrap('FT_Set_Pixel_Sizes', 'number', [ 'number', 'number', 'number' ]);
|
||||
|
||||
FT_Get_Char_Index = module.exports.FT_Get_Char_Index =
|
||||
m.cwrap('FT_Get_Char_Index', 'number', [ 'number', 'number' ]);
|
||||
|
||||
FT_Load_Glyph = module.exports.FT_Load_Glyph =
|
||||
m.cwrap('FT_Load_Glyph', 'number', [ 'number', 'number', 'number' ]);
|
||||
|
||||
FT_Get_Sfnt_Table = module.exports.FT_Get_Sfnt_Table =
|
||||
m.cwrap('FT_Get_Sfnt_Table', 'number', [ 'number', 'number' ]);
|
||||
|
||||
FT_Get_Kerning = module.exports.FT_Get_Kerning =
|
||||
m.cwrap('FT_Get_Kerning', 'number', [ 'number', 'number', 'number', 'number', 'number' ]);
|
||||
|
||||
FT_Done_Face = module.exports.FT_Done_Face =
|
||||
m.cwrap('FT_Done_Face', 'number', [ 'number' ]);
|
||||
|
||||
if (!library) {
|
||||
let ptr = m._malloc(4);
|
||||
|
||||
try {
|
||||
let error = m.ccall('FT_Init_FreeType', 'number', [ 'number' ], [ ptr ]);
|
||||
|
||||
if (error) throw new Error(`error in FT_Init_FreeType: ${error}`);
|
||||
|
||||
library = m.getValue(ptr, 'i32');
|
||||
} finally {
|
||||
m._free(ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports.fontface_create = function (source, size) {
|
||||
let error;
|
||||
let face = {
|
||||
ptr: 0,
|
||||
font: m._malloc(source.length)
|
||||
};
|
||||
|
||||
m.writeArrayToMemory(source, face.font);
|
||||
|
||||
let ptr = m._malloc(4);
|
||||
|
||||
try {
|
||||
error = FT_New_Memory_Face(library, face.font, source.length, 0, ptr);
|
||||
|
||||
if (error) throw new Error(`error in FT_New_Memory_Face: ${error}`);
|
||||
|
||||
face.ptr = m.getValue(ptr, 'i32');
|
||||
} finally {
|
||||
m._free(ptr);
|
||||
}
|
||||
|
||||
error = FT_Set_Char_Size(face.ptr, 0, size * 64, 300, 300);
|
||||
|
||||
if (error) throw new Error(`error in FT_Set_Char_Size: ${error}`);
|
||||
|
||||
error = FT_Set_Pixel_Sizes(face.ptr, 0, size);
|
||||
|
||||
if (error) throw new Error(`error in FT_Set_Pixel_Sizes: ${error}`);
|
||||
|
||||
let units_per_em = m.getValue(face.ptr + m.OFFSET_FACE_UNITS_PER_EM, 'i16');
|
||||
let ascender = m.getValue(face.ptr + m.OFFSET_FACE_ASCENDER, 'i16');
|
||||
let descender = m.getValue(face.ptr + m.OFFSET_FACE_DESCENDER, 'i16');
|
||||
let height = m.getValue(face.ptr + m.OFFSET_FACE_HEIGHT, 'i16');
|
||||
|
||||
return Object.assign(face, {
|
||||
units_per_em,
|
||||
ascender,
|
||||
descender,
|
||||
height
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
module.exports.fontface_os2_table = function (face) {
|
||||
let sfnt_ptr = FT_Get_Sfnt_Table(face.ptr, m.FT_SFNT_OS2);
|
||||
|
||||
if (!sfnt_ptr) throw new Error('os/2 table not found for this font');
|
||||
|
||||
let typoAscent = m.getValue(sfnt_ptr + m.OFFSET_TT_OS2_ASCENDER, 'i16');
|
||||
let typoDescent = m.getValue(sfnt_ptr + m.OFFSET_TT_OS2_DESCENDER, 'i16');
|
||||
let typoLineGap = m.getValue(sfnt_ptr + m.OFFSET_TT_OS2_LINEGAP, 'i16');
|
||||
|
||||
return {
|
||||
typoAscent,
|
||||
typoDescent,
|
||||
typoLineGap
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
module.exports.get_kerning = function (face, code1, code2) {
|
||||
let glyph1 = FT_Get_Char_Index(face.ptr, code1);
|
||||
let glyph2 = FT_Get_Char_Index(face.ptr, code2);
|
||||
let ptr = m._malloc(4 * 2);
|
||||
|
||||
try {
|
||||
let error = FT_Get_Kerning(face.ptr, glyph1, glyph2, m.FT_KERNING_DEFAULT, ptr);
|
||||
|
||||
if (error) throw new Error(`error in FT_Get_Kerning: ${error}`);
|
||||
} finally {
|
||||
m._free(ptr);
|
||||
}
|
||||
|
||||
return {
|
||||
x: from_26_6(m.getValue(ptr, 'i32')),
|
||||
y: from_26_6(m.getValue(ptr + 4, 'i32'))
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
module.exports.glyph_exists = function (face, code) {
|
||||
let glyph_index = FT_Get_Char_Index(face.ptr, code);
|
||||
|
||||
return glyph_index !== 0;
|
||||
};
|
||||
|
||||
|
||||
module.exports.glyph_render = function (face, code, opts = {}) {
|
||||
let glyph_index = FT_Get_Char_Index(face.ptr, code);
|
||||
|
||||
if (glyph_index === 0) throw new Error(`glyph does not exist for codepoint ${code}`);
|
||||
|
||||
let load_flags = m.FT_LOAD_RENDER;
|
||||
|
||||
if (opts.mono) {
|
||||
load_flags |= m.FT_LOAD_TARGET_MONO;
|
||||
|
||||
} else if (opts.lcd) {
|
||||
load_flags |= m.FT_LOAD_TARGET_LCD;
|
||||
|
||||
} else if (opts.lcd_v) {
|
||||
load_flags |= m.FT_LOAD_TARGET_LCD_V;
|
||||
|
||||
} else {
|
||||
/* eslint-disable no-lonely-if */
|
||||
|
||||
// Use "light" by default, it changes horizontal lines only.
|
||||
// "normal" is more strong (with vertical lines), but will break kerning, if
|
||||
// no additional care taken. More advanced rendering requires upper level
|
||||
// layout support (via Harfbuzz, for example).
|
||||
if (!opts.autohint_strong) load_flags |= m.FT_LOAD_TARGET_LIGHT;
|
||||
else load_flags |= m.FT_LOAD_TARGET_NORMAL;
|
||||
}
|
||||
|
||||
if (opts.autohint_off) load_flags |= m.FT_LOAD_NO_AUTOHINT;
|
||||
else load_flags |= m.FT_LOAD_FORCE_AUTOHINT;
|
||||
|
||||
if (opts.use_color_info) load_flags |= m.FT_LOAD_COLOR;
|
||||
|
||||
let error = FT_Load_Glyph(face.ptr, glyph_index, load_flags);
|
||||
|
||||
if (error) throw new Error(`error in FT_Load_Glyph: ${error}`);
|
||||
|
||||
let glyph = m.getValue(face.ptr + m.OFFSET_FACE_GLYPH, 'i32');
|
||||
|
||||
let glyph_data = {
|
||||
glyph_index: m.getValue(glyph + m.OFFSET_GLYPH_INDEX, 'i32'),
|
||||
metrics: {
|
||||
width: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_METRICS_WIDTH, 'i32')),
|
||||
height: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_METRICS_HEIGHT, 'i32')),
|
||||
horiBearingX: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_METRICS_HORI_BEARING_X, 'i32')),
|
||||
horiBearingY: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_METRICS_HORI_BEARING_Y, 'i32')),
|
||||
horiAdvance: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_METRICS_HORI_ADVANCE, 'i32')),
|
||||
vertBearingX: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_METRICS_VERT_BEARING_X, 'i32')),
|
||||
vertBearingY: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_METRICS_VERT_BEARING_Y, 'i32')),
|
||||
vertAdvance: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_METRICS_VERT_ADVANCE, 'i32'))
|
||||
},
|
||||
linearHoriAdvance: from_16_16(m.getValue(glyph + m.OFFSET_GLYPH_LINEAR_HORI_ADVANCE, 'i32')),
|
||||
linearVertAdvance: from_16_16(m.getValue(glyph + m.OFFSET_GLYPH_LINEAR_VERT_ADVANCE, 'i32')),
|
||||
advance: {
|
||||
x: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_ADVANCE_X, 'i32')),
|
||||
y: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_ADVANCE_Y, 'i32'))
|
||||
},
|
||||
bitmap: {
|
||||
width: m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_WIDTH, 'i32'),
|
||||
rows: m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_ROWS, 'i32'),
|
||||
pitch: m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_PITCH, 'i32'),
|
||||
num_grays: m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_NUM_GRAYS, 'i16'),
|
||||
pixel_mode: m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_PIXEL_MODE, 'i8'),
|
||||
palette_mode: m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_PALETTE_MODE, 'i8')
|
||||
},
|
||||
bitmap_left: m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_LEFT, 'i32'),
|
||||
bitmap_top: m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_TOP, 'i32'),
|
||||
lsb_delta: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_LSB_DELTA, 'i32')),
|
||||
rsb_delta: from_26_6(m.getValue(glyph + m.OFFSET_GLYPH_RSB_DELTA, 'i32'))
|
||||
};
|
||||
|
||||
let g_w = glyph_data.bitmap.width;
|
||||
let g_h = glyph_data.bitmap.rows;
|
||||
let g_x = glyph_data.bitmap_left;
|
||||
let g_y = glyph_data.bitmap_top;
|
||||
|
||||
let buffer = m.getValue(glyph + m.OFFSET_GLYPH_BITMAP_BUFFER, 'i32');
|
||||
let pitch = Math.abs(glyph_data.bitmap.pitch);
|
||||
|
||||
let advance_x = glyph_data.linearHoriAdvance;
|
||||
let advance_y = glyph_data.linearVertAdvance;
|
||||
|
||||
let pixel_mode = glyph_data.bitmap.pixel_mode;
|
||||
|
||||
let output = [];
|
||||
|
||||
for (let y = 0; y < g_h; y++) {
|
||||
let row_start = buffer + y * pitch;
|
||||
let line = [];
|
||||
|
||||
for (let x = 0; x < g_w; x++) {
|
||||
if (pixel_mode === m.FT_PIXEL_MODE_MONO) {
|
||||
let value = m.getValue(row_start + ~~(x / 8), 'i8');
|
||||
line.push(value & (1 << (7 - (x % 8))) ? 255 : 0);
|
||||
} else if (pixel_mode === m.FT_PIXEL_MODE_BGRA) {
|
||||
let blue = int8_to_uint8(m.getValue(row_start + (x * 4) + 0, 'i8'));
|
||||
let green = int8_to_uint8(m.getValue(row_start + (x * 4) + 1, 'i8'));
|
||||
let red = int8_to_uint8(m.getValue(row_start + (x * 4) + 2, 'i8'));
|
||||
let alpha = int8_to_uint8(m.getValue(row_start + (x * 4) + 3, 'i8'));
|
||||
// convert RGBA to grayscale
|
||||
let grayscale = Math.round(0.299 * red + 0.587 * green + 0.114 * blue);
|
||||
if (grayscale > 255) grayscale = 255;
|
||||
// meld grayscale into alpha channel
|
||||
alpha = ((255 - grayscale) * alpha) / 255;
|
||||
line.push(alpha);
|
||||
} else {
|
||||
let value = m.getValue(row_start + x, 'i8');
|
||||
line.push(int8_to_uint8(value));
|
||||
}
|
||||
}
|
||||
|
||||
output.push(line);
|
||||
}
|
||||
|
||||
return {
|
||||
x: g_x,
|
||||
y: g_y,
|
||||
width: g_w,
|
||||
height: g_h,
|
||||
advance_x,
|
||||
advance_y,
|
||||
pixels: output,
|
||||
freetype: glyph_data
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
module.exports.fontface_destroy = function (face) {
|
||||
let error = FT_Done_Face(face.ptr);
|
||||
|
||||
if (error) throw new Error(`error in FT_Done_Face: ${error}`);
|
||||
|
||||
m._free(face.font);
|
||||
face.ptr = 0;
|
||||
face.font = 0;
|
||||
};
|
||||
|
||||
|
||||
module.exports.destroy = function () {
|
||||
let error = m.ccall('FT_Done_FreeType', 'number', [ 'number' ], [ library ]);
|
||||
|
||||
if (error) throw new Error(`error in FT_Done_FreeType: ${error}`);
|
||||
|
||||
library = 0;
|
||||
|
||||
// don't unload wasm - slows down tests too much
|
||||
//m = null;
|
||||
};
|
83
node_modules/lv_font_conv/lib/freetype/render.c
generated
vendored
Normal file
83
node_modules/lv_font_conv/lib/freetype/render.c
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
#include <emscripten.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_TRUETYPE_TABLES_H
|
||||
|
||||
static void set_js_variable(char* name, int value) {
|
||||
char buffer[strlen(name) + 32];
|
||||
sprintf(buffer, "Module.%s = %d;", name, value);
|
||||
emscripten_run_script(buffer);
|
||||
}
|
||||
|
||||
// Expose constants, used in calls from js
|
||||
void init_constants()
|
||||
{
|
||||
set_js_variable("FT_LOAD_DEFAULT", FT_LOAD_DEFAULT);
|
||||
set_js_variable("FT_LOAD_NO_HINTING", FT_LOAD_NO_HINTING);
|
||||
set_js_variable("FT_LOAD_RENDER", FT_LOAD_RENDER);
|
||||
set_js_variable("FT_LOAD_FORCE_AUTOHINT", FT_LOAD_FORCE_AUTOHINT);
|
||||
set_js_variable("FT_LOAD_PEDANTIC", FT_LOAD_PEDANTIC);
|
||||
set_js_variable("FT_LOAD_MONOCHROME", FT_LOAD_MONOCHROME);
|
||||
set_js_variable("FT_LOAD_NO_AUTOHINT", FT_LOAD_NO_AUTOHINT);
|
||||
set_js_variable("FT_LOAD_COLOR", FT_LOAD_COLOR);
|
||||
|
||||
set_js_variable("FT_LOAD_TARGET_NORMAL", FT_LOAD_TARGET_NORMAL);
|
||||
set_js_variable("FT_LOAD_TARGET_LIGHT", FT_LOAD_TARGET_LIGHT);
|
||||
set_js_variable("FT_LOAD_TARGET_MONO", FT_LOAD_TARGET_MONO);
|
||||
set_js_variable("FT_LOAD_TARGET_LCD", FT_LOAD_TARGET_LCD);
|
||||
set_js_variable("FT_LOAD_TARGET_LCD_V", FT_LOAD_TARGET_LCD_V);
|
||||
|
||||
set_js_variable("FT_RENDER_MODE_NORMAL", FT_RENDER_MODE_NORMAL);
|
||||
set_js_variable("FT_RENDER_MODE_MONO", FT_RENDER_MODE_MONO);
|
||||
set_js_variable("FT_RENDER_MODE_LCD", FT_RENDER_MODE_LCD);
|
||||
set_js_variable("FT_RENDER_MODE_LCD_V", FT_RENDER_MODE_LCD_V);
|
||||
|
||||
set_js_variable("FT_KERNING_DEFAULT", FT_KERNING_DEFAULT);
|
||||
set_js_variable("FT_KERNING_UNFITTED", FT_KERNING_UNFITTED);
|
||||
set_js_variable("FT_KERNING_UNSCALED", FT_KERNING_UNSCALED);
|
||||
|
||||
set_js_variable("FT_SFNT_OS2", FT_SFNT_OS2);
|
||||
|
||||
set_js_variable("FT_FACE_FLAG_COLOR", FT_FACE_FLAG_COLOR);
|
||||
|
||||
set_js_variable("FT_PIXEL_MODE_MONO", FT_PIXEL_MODE_MONO);
|
||||
set_js_variable("FT_PIXEL_MODE_BGRA", FT_PIXEL_MODE_BGRA);
|
||||
|
||||
set_js_variable("OFFSET_FACE_GLYPH", offsetof(FT_FaceRec, glyph));
|
||||
set_js_variable("OFFSET_FACE_UNITS_PER_EM", offsetof(FT_FaceRec, units_per_EM));
|
||||
set_js_variable("OFFSET_FACE_ASCENDER", offsetof(FT_FaceRec, ascender));
|
||||
set_js_variable("OFFSET_FACE_DESCENDER", offsetof(FT_FaceRec, descender));
|
||||
set_js_variable("OFFSET_FACE_HEIGHT", offsetof(FT_FaceRec, height));
|
||||
set_js_variable("OFFSET_FACE_FACE_FLAGS", offsetof(FT_FaceRec, face_flags));
|
||||
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_WIDTH", offsetof(FT_GlyphSlotRec, bitmap.width));
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_ROWS", offsetof(FT_GlyphSlotRec, bitmap.rows));
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_PITCH", offsetof(FT_GlyphSlotRec, bitmap.pitch));
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_BUFFER", offsetof(FT_GlyphSlotRec, bitmap.buffer));
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_NUM_GRAYS", offsetof(FT_GlyphSlotRec, bitmap.num_grays));
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_PIXEL_MODE", offsetof(FT_GlyphSlotRec, bitmap.pixel_mode));
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_PALETTE_MODE", offsetof(FT_GlyphSlotRec, bitmap.palette_mode));
|
||||
|
||||
set_js_variable("OFFSET_GLYPH_METRICS_WIDTH", offsetof(FT_GlyphSlotRec, metrics.width));
|
||||
set_js_variable("OFFSET_GLYPH_METRICS_HEIGHT", offsetof(FT_GlyphSlotRec, metrics.height));
|
||||
set_js_variable("OFFSET_GLYPH_METRICS_HORI_BEARING_X", offsetof(FT_GlyphSlotRec, metrics.horiBearingX));
|
||||
set_js_variable("OFFSET_GLYPH_METRICS_HORI_BEARING_Y", offsetof(FT_GlyphSlotRec, metrics.horiBearingY));
|
||||
set_js_variable("OFFSET_GLYPH_METRICS_HORI_ADVANCE", offsetof(FT_GlyphSlotRec, metrics.horiAdvance));
|
||||
set_js_variable("OFFSET_GLYPH_METRICS_VERT_BEARING_X", offsetof(FT_GlyphSlotRec, metrics.vertBearingX));
|
||||
set_js_variable("OFFSET_GLYPH_METRICS_VERT_BEARING_Y", offsetof(FT_GlyphSlotRec, metrics.vertBearingY));
|
||||
set_js_variable("OFFSET_GLYPH_METRICS_VERT_ADVANCE", offsetof(FT_GlyphSlotRec, metrics.vertAdvance));
|
||||
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_LEFT", offsetof(FT_GlyphSlotRec, bitmap_left));
|
||||
set_js_variable("OFFSET_GLYPH_BITMAP_TOP", offsetof(FT_GlyphSlotRec, bitmap_top));
|
||||
set_js_variable("OFFSET_GLYPH_INDEX", offsetof(FT_GlyphSlotRec, glyph_index));
|
||||
set_js_variable("OFFSET_GLYPH_LINEAR_HORI_ADVANCE", offsetof(FT_GlyphSlotRec, linearHoriAdvance));
|
||||
set_js_variable("OFFSET_GLYPH_LINEAR_VERT_ADVANCE", offsetof(FT_GlyphSlotRec, linearVertAdvance));
|
||||
set_js_variable("OFFSET_GLYPH_ADVANCE_X", offsetof(FT_GlyphSlotRec, advance.x));
|
||||
set_js_variable("OFFSET_GLYPH_ADVANCE_Y", offsetof(FT_GlyphSlotRec, advance.y));
|
||||
set_js_variable("OFFSET_GLYPH_LSB_DELTA", offsetof(FT_GlyphSlotRec, lsb_delta));
|
||||
set_js_variable("OFFSET_GLYPH_RSB_DELTA", offsetof(FT_GlyphSlotRec, rsb_delta));
|
||||
|
||||
set_js_variable("OFFSET_TT_OS2_ASCENDER", offsetof(TT_OS2, sTypoAscender));
|
||||
set_js_variable("OFFSET_TT_OS2_DESCENDER", offsetof(TT_OS2, sTypoDescender));
|
||||
set_js_variable("OFFSET_TT_OS2_LINEGAP", offsetof(TT_OS2, sTypoLineGap));
|
||||
}
|
51
node_modules/lv_font_conv/lib/ranger.js
generated
vendored
Normal file
51
node_modules/lv_font_conv/lib/ranger.js
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
// Merge ranges into single object
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
class Ranger {
|
||||
constructor() {
|
||||
this.data = {};
|
||||
}
|
||||
|
||||
// input:
|
||||
// -r 0x1F450 - single value, dec or hex format
|
||||
// -r 0x1F450-0x1F470 - range
|
||||
// -r 0x1F450=>0xF005 - single glyph with mapping
|
||||
// -r 0x1F450-0x1F470=>0xF005 - range with mapping
|
||||
add_range(font, start, end, mapped_start) {
|
||||
let offset = mapped_start - start;
|
||||
let output = [];
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
this._set_char(font, i, i + offset);
|
||||
output.push(i);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// input: characters to copy, e.g. '1234567890abcdef'
|
||||
add_symbols(font, str) {
|
||||
let output = [];
|
||||
|
||||
for (let chr of str) {
|
||||
let code = chr.codePointAt(0);
|
||||
this._set_char(font, code, code);
|
||||
output.push(code);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
_set_char(font, code, mapped_to) {
|
||||
this.data[mapped_to] = { font, code };
|
||||
}
|
||||
|
||||
get() {
|
||||
return this.data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = Ranger;
|
131
node_modules/lv_font_conv/lib/utils.js
generated
vendored
Normal file
131
node_modules/lv_font_conv/lib/utils.js
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
function set_byte_depth(depth) {
|
||||
return function (byte) {
|
||||
// calculate significant bits, e.g. for depth=2 it's 0, 1, 2 or 3
|
||||
let value = ~~(byte / (256 >> depth));
|
||||
|
||||
// spread those bits around 0..255 range, e.g. for depth=2 it's 0, 85, 170 or 255
|
||||
let scale = (2 << (depth - 1)) - 1;
|
||||
|
||||
return (value * 0xFFFF / scale) >> 8;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.set_depth = function set_depth(glyph, depth) {
|
||||
let pixels = [];
|
||||
let fn = set_byte_depth(depth);
|
||||
|
||||
for (let y = 0; y < glyph.bbox.height; y++) {
|
||||
pixels.push(glyph.pixels[y].map(fn));
|
||||
}
|
||||
|
||||
return Object.assign({}, glyph, { pixels });
|
||||
};
|
||||
|
||||
|
||||
function count_bits(val) {
|
||||
let count = 0;
|
||||
val = ~~val;
|
||||
|
||||
while (val) {
|
||||
count++;
|
||||
val >>= 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Minimal number of bits to store unsigned value
|
||||
module.exports.unsigned_bits = count_bits;
|
||||
|
||||
// Minimal number of bits to store signed value
|
||||
module.exports.signed_bits = function signed_bits(val) {
|
||||
if (val >= 0) return count_bits(val) + 1;
|
||||
|
||||
return count_bits(Math.abs(val) - 1) + 1;
|
||||
};
|
||||
|
||||
// Align value to 4x - useful to create word-aligned arrays
|
||||
function align4(size) {
|
||||
if (size % 4 === 0) return size;
|
||||
return size + 4 - (size % 4);
|
||||
}
|
||||
module.exports.align4 = align4;
|
||||
|
||||
// Align buffer length to 4x (returns copy with zero-filled tail)
|
||||
module.exports.balign4 = function balign4(buf) {
|
||||
let buf_aligned = Buffer.alloc(align4(buf.length));
|
||||
buf.copy(buf_aligned);
|
||||
return buf_aligned;
|
||||
};
|
||||
|
||||
// Pre-filter image to improve compression ratio
|
||||
// In this case - XOR lines, because it's very effective
|
||||
// in decompressor and does not depend on bpp.
|
||||
module.exports.prefilter = function prefilter(pixels) {
|
||||
return pixels.map((line, l_idx, arr) => {
|
||||
if (l_idx === 0) return line.slice();
|
||||
|
||||
return line.map((p, idx) => p ^ arr[l_idx - 1][idx]);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Convert array with uint16 data to buffer
|
||||
module.exports.bFromA16 = function bFromA16(arr) {
|
||||
const buf = Buffer.alloc(arr.length * 2);
|
||||
|
||||
for (let i = 0; i < arr.length; i++) buf.writeUInt16LE(arr[i], i * 2);
|
||||
|
||||
return buf;
|
||||
};
|
||||
|
||||
// Convert array with uint32 data to buffer
|
||||
module.exports.bFromA32 = function bFromA32(arr) {
|
||||
const buf = Buffer.alloc(arr.length * 4);
|
||||
|
||||
for (let i = 0; i < arr.length; i++) buf.writeUInt32LE(arr[i], i * 4);
|
||||
|
||||
return buf;
|
||||
};
|
||||
|
||||
|
||||
function chunk(arr, size) {
|
||||
const result = [];
|
||||
for (let i = 0; i < arr.length; i += size) {
|
||||
result.push(arr.slice(i, i + size));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Dump long array to multiline format with X columns and Y indent
|
||||
module.exports.long_dump = function long_dump(arr, options = {}) {
|
||||
const defaults = {
|
||||
col: 8,
|
||||
indent: 4,
|
||||
hex: false
|
||||
};
|
||||
|
||||
let opts = Object.assign({}, defaults, options);
|
||||
let indent = ' '.repeat(opts.indent);
|
||||
|
||||
return chunk(Array.from(arr), opts.col)
|
||||
.map(l => l.map(v => (opts.hex ? `0x${v.toString(16)}` : v.toString())))
|
||||
.map(l => `${indent}${l.join(', ')}`)
|
||||
.join(',\n');
|
||||
};
|
||||
|
||||
// stable sort by pick() result
|
||||
module.exports.sort_by = function sort_by(arr, pick) {
|
||||
return arr
|
||||
.map((el, idx) => ({ el, idx }))
|
||||
.sort((a, b) => (pick(a.el) - pick(b.el)) || (a.idx - b.idx))
|
||||
.map(({ el }) => el);
|
||||
};
|
||||
|
||||
module.exports.sum = function sum(arr) {
|
||||
return arr.reduce((a, v) => a + v, 0);
|
||||
};
|
17
node_modules/lv_font_conv/lib/writers/bin.js
generated
vendored
Normal file
17
node_modules/lv_font_conv/lib/writers/bin.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
// Write font in binary format
|
||||
'use strict';
|
||||
|
||||
|
||||
const AppError = require('../app_error');
|
||||
const Font = require('../font/font');
|
||||
|
||||
|
||||
module.exports = function write_images(args, fontData) {
|
||||
if (!args.output) throw new AppError('Output is required for "bin" writer');
|
||||
|
||||
const font = new Font(fontData, args);
|
||||
|
||||
return {
|
||||
[args.output]: font.toBin()
|
||||
};
|
||||
};
|
68
node_modules/lv_font_conv/lib/writers/dump.js
generated
vendored
Normal file
68
node_modules/lv_font_conv/lib/writers/dump.js
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
// Write font data into png images
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
const path = require('path');
|
||||
const { PNG } = require('pngjs');
|
||||
const AppError = require('../app_error');
|
||||
const utils = require('../utils');
|
||||
|
||||
const normal_color = [ 255, 255, 255 ];
|
||||
const outside_color = [ 255, 127, 184 ];
|
||||
|
||||
|
||||
module.exports = function write_images(args, font) {
|
||||
if (!args.output) throw new AppError('Output is required for "dump" writer');
|
||||
|
||||
let files = {};
|
||||
|
||||
let glyphs = font.glyphs.map(glyph => utils.set_depth(glyph, args.bpp));
|
||||
|
||||
for (let glyph of glyphs) {
|
||||
let { code, advanceWidth, bbox, pixels } = glyph;
|
||||
|
||||
advanceWidth = Math.round(advanceWidth);
|
||||
|
||||
let minX = bbox.x;
|
||||
let maxX = Math.max(bbox.x + bbox.width - 1, bbox.x);
|
||||
let minY = Math.min(bbox.y, font.typoDescent);
|
||||
let maxY = Math.max(bbox.y + bbox.height - 1, font.typoAscent);
|
||||
|
||||
let png = new PNG({ width: maxX - minX + 1, height: maxY - minY + 1 });
|
||||
|
||||
/* eslint-disable max-depth */
|
||||
for (let pos = 0, y = maxY; y >= minY; y--) {
|
||||
for (let x = minX; x <= maxX; x++) {
|
||||
let value = 0;
|
||||
|
||||
if (x >= bbox.x && x < bbox.x + bbox.width && y >= bbox.y && y < bbox.y + bbox.height) {
|
||||
value = pixels[bbox.height - (y - bbox.y) - 1][x - bbox.x];
|
||||
}
|
||||
|
||||
let r, g, b;
|
||||
|
||||
if (x < 0 || x >= advanceWidth || y < font.typoDescent || y > font.typoAscent) {
|
||||
[ r, g, b ] = outside_color;
|
||||
} else {
|
||||
[ r, g, b ] = normal_color;
|
||||
}
|
||||
|
||||
png.data[pos++] = (255 - value) * r / 255;
|
||||
png.data[pos++] = (255 - value) * g / 255;
|
||||
png.data[pos++] = (255 - value) * b / 255;
|
||||
png.data[pos++] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
files[path.join(args.output, `${code.toString(16)}.png`)] = PNG.sync.write(png);
|
||||
}
|
||||
|
||||
files[path.join(args.output, 'font_info.json')] = JSON.stringify(
|
||||
font,
|
||||
(k, v) => (k === 'pixels' && !args.full_info ? undefined : v),
|
||||
2);
|
||||
|
||||
return files;
|
||||
};
|
17
node_modules/lv_font_conv/lib/writers/lvgl/index.js
generated
vendored
Normal file
17
node_modules/lv_font_conv/lib/writers/lvgl/index.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
// Write font in lvgl format
|
||||
'use strict';
|
||||
|
||||
|
||||
const AppError = require('../../app_error');
|
||||
const Font = require('./lv_font');
|
||||
|
||||
|
||||
module.exports = function write_images(args, fontData) {
|
||||
if (!args.output) throw new AppError('Output is required for "lvgl" writer');
|
||||
|
||||
const font = new Font(fontData, args);
|
||||
|
||||
return {
|
||||
[args.output]: font.toLVGL()
|
||||
};
|
||||
};
|
98
node_modules/lv_font_conv/lib/writers/lvgl/lv_font.js
generated
vendored
Normal file
98
node_modules/lv_font_conv/lib/writers/lvgl/lv_font.js
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const Font = require('../../font/font');
|
||||
const Head = require('./lv_table_head');
|
||||
const Cmap = require('./lv_table_cmap');
|
||||
const Glyf = require('./lv_table_glyf');
|
||||
const Kern = require('./lv_table_kern');
|
||||
const AppError = require('../../app_error');
|
||||
|
||||
|
||||
class LvFont extends Font {
|
||||
constructor(fontData, options) {
|
||||
super(fontData, options);
|
||||
|
||||
const ext = path.extname(options.output);
|
||||
this.font_name = path.basename(options.output, ext);
|
||||
|
||||
if (options.bpp === 3 & options.no_compress) {
|
||||
throw new AppError('LittlevGL supports "--bpp 3" with compression only');
|
||||
}
|
||||
}
|
||||
|
||||
init_tables() {
|
||||
this.head = new Head(this);
|
||||
this.glyf = new Glyf(this);
|
||||
this.cmap = new Cmap(this);
|
||||
this.kern = new Kern(this);
|
||||
}
|
||||
|
||||
large_format_guard() {
|
||||
let guard_required = false;
|
||||
let glyphs_bin_size = 0;
|
||||
|
||||
this.glyf.lv_data.forEach(d => {
|
||||
glyphs_bin_size += d.bin.length;
|
||||
|
||||
if (d.glyph.bbox.width > 255 ||
|
||||
d.glyph.bbox.height > 255 ||
|
||||
Math.abs(d.glyph.bbox.x) > 127 ||
|
||||
Math.abs(d.glyph.bbox.y) > 127 ||
|
||||
Math.round(d.glyph.advanceWidth * 16) > 4096) {
|
||||
guard_required = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (glyphs_bin_size > 1024 * 1024) guard_required = true;
|
||||
|
||||
if (!guard_required) return '';
|
||||
|
||||
return `
|
||||
#if (LV_FONT_FMT_TXT_LARGE == 0)
|
||||
# error "Too large font or glyphs in ${this.font_name.toUpperCase()}. Enable LV_FONT_FMT_TXT_LARGE in lv_conf.h")
|
||||
#endif
|
||||
`.trimLeft();
|
||||
}
|
||||
|
||||
toLVGL() {
|
||||
let guard_name = this.font_name.toUpperCase();
|
||||
|
||||
return `/*******************************************************************************
|
||||
* Size: ${this.src.size} px
|
||||
* Bpp: ${this.opts.bpp}
|
||||
* Opts: ${process.argv.slice(2).join(' ')}
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "${this.opts.lv_include || 'lvgl/lvgl.h'}"
|
||||
#endif
|
||||
|
||||
#ifndef ${guard_name}
|
||||
#define ${guard_name} 1
|
||||
#endif
|
||||
|
||||
#if ${guard_name}
|
||||
|
||||
${this.glyf.toLVGL()}
|
||||
|
||||
${this.cmap.toLVGL()}
|
||||
|
||||
${this.kern.toLVGL()}
|
||||
|
||||
${this.head.toLVGL()}
|
||||
|
||||
${this.large_format_guard()}
|
||||
|
||||
#endif /*#if ${guard_name}*/
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = LvFont;
|
125
node_modules/lv_font_conv/lib/writers/lvgl/lv_table_cmap.js
generated
vendored
Normal file
125
node_modules/lv_font_conv/lib/writers/lvgl/lv_table_cmap.js
generated
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const u = require('../../utils');
|
||||
const build_subtables = require('../../font/cmap_build_subtables');
|
||||
const Cmap = require('../../font/table_cmap');
|
||||
|
||||
|
||||
class LvCmap extends Cmap {
|
||||
constructor(font) {
|
||||
super(font);
|
||||
|
||||
this.lv_compiled = false;
|
||||
this.lv_subtables = [];
|
||||
}
|
||||
|
||||
lv_format2enum(name) {
|
||||
switch (name) {
|
||||
case 'format0_tiny': return 'LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY';
|
||||
case 'format0': return 'LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL';
|
||||
case 'sparse_tiny': return 'LV_FONT_FMT_TXT_CMAP_SPARSE_TINY';
|
||||
case 'sparse': return 'LV_FONT_FMT_TXT_CMAP_SPARSE_FULL';
|
||||
default: throw new Error('Unknown subtable format');
|
||||
}
|
||||
}
|
||||
|
||||
lv_compile() {
|
||||
if (this.lv_compiled) return;
|
||||
this.lv_compiled = true;
|
||||
|
||||
const f = this.font;
|
||||
|
||||
let subtables_plan = build_subtables(f.src.glyphs.map(g => g.code));
|
||||
let idx = 0;
|
||||
|
||||
for (let [ format, codepoints ] of subtables_plan) {
|
||||
let g = this.glyphByCode(codepoints[0]);
|
||||
let start_glyph_id = f.glyph_id[g.code];
|
||||
let min_code = codepoints[0];
|
||||
let max_code = codepoints[codepoints.length - 1];
|
||||
|
||||
let has_charcodes = false;
|
||||
let has_ids = false;
|
||||
let defs = '';
|
||||
let entries_count = 0;
|
||||
|
||||
if (format === 'format0_tiny') {
|
||||
// use default empty values
|
||||
} else if (format === 'format0') {
|
||||
has_ids = true;
|
||||
let d = this.collect_format0_data(min_code, max_code, start_glyph_id);
|
||||
entries_count = d.length;
|
||||
|
||||
defs = `
|
||||
static const uint8_t glyph_id_ofs_list_${idx}[] = {
|
||||
${u.long_dump(d)}
|
||||
};
|
||||
`.trim();
|
||||
|
||||
} else if (format === 'sparse_tiny') {
|
||||
has_charcodes = true;
|
||||
let d = this.collect_sparse_data(codepoints, start_glyph_id);
|
||||
entries_count = d.codes.length;
|
||||
|
||||
defs = `
|
||||
static const uint16_t unicode_list_${idx}[] = {
|
||||
${u.long_dump(d.codes, { hex: true })}
|
||||
};
|
||||
`.trim();
|
||||
|
||||
} else { // assume format === 'sparse'
|
||||
has_charcodes = true;
|
||||
has_ids = true;
|
||||
let d = this.collect_sparse_data(codepoints, start_glyph_id);
|
||||
entries_count = d.codes.length;
|
||||
|
||||
defs = `
|
||||
static const uint16_t unicode_list_${idx}[] = {
|
||||
${u.long_dump(d.codes, { hex: true })}
|
||||
};
|
||||
static const uint16_t glyph_id_ofs_list_${idx}[] = {
|
||||
${u.long_dump(d.ids)}
|
||||
};
|
||||
`.trim();
|
||||
}
|
||||
|
||||
const u_list = has_charcodes ? `unicode_list_${idx}` : 'NULL';
|
||||
const id_list = has_ids ? `glyph_id_ofs_list_${idx}` : 'NULL';
|
||||
|
||||
/* eslint-disable max-len */
|
||||
const head = ` {
|
||||
.range_start = ${min_code}, .range_length = ${max_code - min_code + 1}, .glyph_id_start = ${start_glyph_id},
|
||||
.unicode_list = ${u_list}, .glyph_id_ofs_list = ${id_list}, .list_length = ${entries_count}, .type = ${this.lv_format2enum(format)}
|
||||
}`;
|
||||
|
||||
this.lv_subtables.push({
|
||||
defs,
|
||||
head
|
||||
});
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
toLVGL() {
|
||||
this.lv_compile();
|
||||
|
||||
return `
|
||||
/*---------------------
|
||||
* CHARACTER MAPPING
|
||||
*--------------------*/
|
||||
|
||||
${this.lv_subtables.map(d => d.defs).filter(Boolean).join('\n\n')}
|
||||
|
||||
/*Collect the unicode lists and glyph_id offsets*/
|
||||
static const lv_font_fmt_txt_cmap_t cmaps[] =
|
||||
{
|
||||
${this.lv_subtables.map(d => d.head).join(',\n')}
|
||||
};
|
||||
`.trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = LvCmap;
|
121
node_modules/lv_font_conv/lib/writers/lvgl/lv_table_glyf.js
generated
vendored
Normal file
121
node_modules/lv_font_conv/lib/writers/lvgl/lv_table_glyf.js
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const { BitStream } = require('bit-buffer');
|
||||
const u = require('../../utils');
|
||||
const Glyf = require('../../font/table_glyf');
|
||||
|
||||
|
||||
class LvGlyf extends Glyf {
|
||||
constructor(font) {
|
||||
super(font);
|
||||
|
||||
this.lv_data = [];
|
||||
this.lv_compiled = false;
|
||||
}
|
||||
|
||||
lv_bitmap(glyph) {
|
||||
const buf = Buffer.alloc(100 + glyph.bbox.width * glyph.bbox.height * 4);
|
||||
const bs = new BitStream(buf);
|
||||
bs.bigEndian = true;
|
||||
|
||||
const pixels = this.font.glyf.pixelsToBpp(glyph.pixels);
|
||||
|
||||
this.font.glyf.storePixels(bs, pixels);
|
||||
|
||||
const glyph_bitmap = Buffer.alloc(bs.byteIndex);
|
||||
buf.copy(glyph_bitmap, 0, 0, bs.byteIndex);
|
||||
|
||||
return glyph_bitmap;
|
||||
}
|
||||
|
||||
lv_compile() {
|
||||
if (this.lv_compiled) return;
|
||||
|
||||
this.lv_compiled = true;
|
||||
|
||||
const f = this.font;
|
||||
this.lv_data = [];
|
||||
let offset = 0;
|
||||
|
||||
f.src.glyphs.forEach(g => {
|
||||
const id = f.glyph_id[g.code];
|
||||
const bin = this.lv_bitmap(g);
|
||||
this.lv_data[id] = {
|
||||
bin,
|
||||
offset,
|
||||
glyph: g
|
||||
};
|
||||
offset += bin.length;
|
||||
});
|
||||
}
|
||||
|
||||
to_lv_bitmaps() {
|
||||
this.lv_compile();
|
||||
|
||||
let result = [];
|
||||
this.lv_data.forEach((d, idx) => {
|
||||
if (idx === 0) return;
|
||||
const code_hex = d.glyph.code.toString(16).toUpperCase();
|
||||
const code_str = JSON.stringify(String.fromCodePoint(d.glyph.code));
|
||||
|
||||
let txt = ` /* U+${code_hex.padStart(4, '0')} ${code_str} */
|
||||
${u.long_dump(d.bin, { hex: true })}`;
|
||||
|
||||
if (idx < this.lv_data.length - 1) {
|
||||
// skip comma for zero data
|
||||
txt += d.bin.length ? ',\n\n' : '\n';
|
||||
}
|
||||
|
||||
result.push(txt);
|
||||
});
|
||||
|
||||
return result.join('');
|
||||
}
|
||||
|
||||
to_lv_glyph_dsc() {
|
||||
this.lv_compile();
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
let result = [ ' {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */' ];
|
||||
|
||||
this.lv_data.forEach(d => {
|
||||
const idx = d.offset,
|
||||
adv_w = Math.round(d.glyph.advanceWidth * 16),
|
||||
h = d.glyph.bbox.height,
|
||||
w = d.glyph.bbox.width,
|
||||
x = d.glyph.bbox.x,
|
||||
y = d.glyph.bbox.y;
|
||||
result.push(` {.bitmap_index = ${idx}, .adv_w = ${adv_w}, .box_w = ${w}, .box_h = ${h}, .ofs_x = ${x}, .ofs_y = ${y}}`);
|
||||
});
|
||||
|
||||
return result.join(',\n');
|
||||
}
|
||||
|
||||
|
||||
toLVGL() {
|
||||
return `
|
||||
/*-----------------
|
||||
* BITMAPS
|
||||
*----------------*/
|
||||
|
||||
/*Store the image of the glyphs*/
|
||||
static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
${this.to_lv_bitmaps()}
|
||||
};
|
||||
|
||||
|
||||
/*---------------------
|
||||
* GLYPH DESCRIPTION
|
||||
*--------------------*/
|
||||
|
||||
static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
${this.to_lv_glyph_dsc()}
|
||||
};
|
||||
`.trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = LvGlyf;
|
99
node_modules/lv_font_conv/lib/writers/lvgl/lv_table_head.js
generated
vendored
Normal file
99
node_modules/lv_font_conv/lib/writers/lvgl/lv_table_head.js
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const Head = require('../../font/table_head');
|
||||
|
||||
|
||||
class LvHead extends Head {
|
||||
constructor(font) {
|
||||
super(font);
|
||||
}
|
||||
|
||||
kern_ref() {
|
||||
const f = this.font;
|
||||
|
||||
if (!f.hasKerning()) {
|
||||
return {
|
||||
scale: '0',
|
||||
dsc: 'NULL',
|
||||
classes: '0'
|
||||
};
|
||||
}
|
||||
|
||||
if (!f.kern.should_use_format3()) {
|
||||
return {
|
||||
scale: `${Math.round(f.kerningScale * 16)}`,
|
||||
dsc: '&kern_pairs',
|
||||
classes: '0'
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
scale: `${Math.round(f.kerningScale * 16)}`,
|
||||
dsc: '&kern_classes',
|
||||
classes: '1'
|
||||
};
|
||||
}
|
||||
|
||||
toLVGL() {
|
||||
const f = this.font;
|
||||
const kern = this.kern_ref();
|
||||
const subpixels = (f.subpixels_mode === 0) ? 'LV_FONT_SUBPX_NONE' :
|
||||
(f.subpixels_mode === 1) ? 'LV_FONT_SUBPX_HOR' : 'LV_FONT_SUBPX_VER';
|
||||
|
||||
return `
|
||||
/*--------------------
|
||||
* ALL CUSTOM DATA
|
||||
*--------------------*/
|
||||
|
||||
#if LV_VERSION_CHECK(8, 0, 0)
|
||||
/*Store all the custom data of the font*/
|
||||
static lv_font_fmt_txt_glyph_cache_t cache;
|
||||
static const lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
#else
|
||||
static lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
#endif
|
||||
.glyph_bitmap = glyph_bitmap,
|
||||
.glyph_dsc = glyph_dsc,
|
||||
.cmaps = cmaps,
|
||||
.kern_dsc = ${kern.dsc},
|
||||
.kern_scale = ${kern.scale},
|
||||
.cmap_num = ${f.cmap.toBin().readUInt32LE(8)},
|
||||
.bpp = ${f.opts.bpp},
|
||||
.kern_classes = ${kern.classes},
|
||||
.bitmap_format = ${f.glyf.getCompressionCode()},
|
||||
#if LV_VERSION_CHECK(8, 0, 0)
|
||||
.cache = &cache
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/*-----------------
|
||||
* PUBLIC FONT
|
||||
*----------------*/
|
||||
|
||||
/*Initialize a public general font descriptor*/
|
||||
#if LV_VERSION_CHECK(8, 0, 0)
|
||||
const lv_font_t ${f.font_name} = {
|
||||
#else
|
||||
lv_font_t ${f.font_name} = {
|
||||
#endif
|
||||
.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
|
||||
.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
|
||||
.line_height = ${f.src.ascent - f.src.descent}, /*The maximum line height required by the font*/
|
||||
.base_line = ${-f.src.descent}, /*Baseline measured from the bottom of the line*/
|
||||
#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0)
|
||||
.subpx = ${subpixels},
|
||||
#endif
|
||||
#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8
|
||||
.underline_position = ${f.src.underlinePosition},
|
||||
.underline_thickness = ${f.src.underlineThickness},
|
||||
#endif
|
||||
.dsc = &font_dsc /*The custom font data. Will be accessed by \`get_glyph_bitmap/dsc\` */
|
||||
};
|
||||
`.trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = LvHead;
|
121
node_modules/lv_font_conv/lib/writers/lvgl/lv_table_kern.js
generated
vendored
Normal file
121
node_modules/lv_font_conv/lib/writers/lvgl/lv_table_kern.js
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const u = require('../../utils');
|
||||
const Kern = require('../../font/table_kern');
|
||||
|
||||
|
||||
class LvKern extends Kern {
|
||||
constructor(font) {
|
||||
super(font);
|
||||
}
|
||||
|
||||
to_lv_format0() {
|
||||
const f = this.font;
|
||||
let kern_pairs = this.collect_format0_data();
|
||||
|
||||
return `
|
||||
/*-----------------
|
||||
* KERNING
|
||||
*----------------*/
|
||||
|
||||
|
||||
/*Pair left and right glyphs for kerning*/
|
||||
static const ${f.glyphIdFormat ? 'uint16_t' : 'uint8_t'} kern_pair_glyph_ids[] =
|
||||
{
|
||||
${kern_pairs.map(pair => ` ${pair[0]}, ${pair[1]}`).join(',\n')}
|
||||
};
|
||||
|
||||
/* Kerning between the respective left and right glyphs
|
||||
* 4.4 format which needs to scaled with \`kern_scale\`*/
|
||||
static const int8_t kern_pair_values[] =
|
||||
{
|
||||
${u.long_dump(kern_pairs.map(pair => f.kernToFP(pair[2])))}
|
||||
};
|
||||
|
||||
/*Collect the kern pair's data in one place*/
|
||||
static const lv_font_fmt_txt_kern_pair_t kern_pairs =
|
||||
{
|
||||
.glyph_ids = kern_pair_glyph_ids,
|
||||
.values = kern_pair_values,
|
||||
.pair_cnt = ${kern_pairs.length},
|
||||
.glyph_ids_size = ${f.glyphIdFormat}
|
||||
};
|
||||
|
||||
|
||||
`.trim();
|
||||
}
|
||||
|
||||
to_lv_format3() {
|
||||
const f = this.font;
|
||||
const {
|
||||
left_classes,
|
||||
right_classes,
|
||||
left_mapping,
|
||||
right_mapping,
|
||||
values
|
||||
} = this.collect_format3_data();
|
||||
|
||||
return `
|
||||
/*-----------------
|
||||
* KERNING
|
||||
*----------------*/
|
||||
|
||||
|
||||
/*Map glyph_ids to kern left classes*/
|
||||
static const uint8_t kern_left_class_mapping[] =
|
||||
{
|
||||
${u.long_dump(left_mapping)}
|
||||
};
|
||||
|
||||
/*Map glyph_ids to kern right classes*/
|
||||
static const uint8_t kern_right_class_mapping[] =
|
||||
{
|
||||
${u.long_dump(right_mapping)}
|
||||
};
|
||||
|
||||
/*Kern values between classes*/
|
||||
static const int8_t kern_class_values[] =
|
||||
{
|
||||
${u.long_dump(values.map(v => f.kernToFP(v)))}
|
||||
};
|
||||
|
||||
|
||||
/*Collect the kern class' data in one place*/
|
||||
static const lv_font_fmt_txt_kern_classes_t kern_classes =
|
||||
{
|
||||
.class_pair_values = kern_class_values,
|
||||
.left_class_mapping = kern_left_class_mapping,
|
||||
.right_class_mapping = kern_right_class_mapping,
|
||||
.left_class_cnt = ${left_classes},
|
||||
.right_class_cnt = ${right_classes},
|
||||
};
|
||||
|
||||
|
||||
`.trim();
|
||||
}
|
||||
|
||||
toLVGL() {
|
||||
const f = this.font;
|
||||
|
||||
if (!f.hasKerning()) return '';
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
if (f.kern.should_use_format3()) {
|
||||
if (f.kern.format3_forced) {
|
||||
let diff = this.create_format3_data().length - this.create_format0_data().length;
|
||||
console.log(`Forced faster kerning format (via classes). Size increase is ${diff} bytes.`);
|
||||
}
|
||||
return this.to_lv_format3();
|
||||
}
|
||||
|
||||
if (this.font.opts.fast_kerning) {
|
||||
console.log('Forced faster kerning format (via classes), but data exceeds it\'s limits. Continue use pairs.');
|
||||
}
|
||||
return this.to_lv_format0();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = LvKern;
|
17
node_modules/lv_font_conv/lv_font_conv.js
generated
vendored
Executable file
17
node_modules/lv_font_conv/lv_font_conv.js
generated
vendored
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
const AppError = require('./lib/app_error');
|
||||
|
||||
require('./lib/cli').run(process.argv.slice(2)).catch(err => {
|
||||
/*eslint-disable no-console*/
|
||||
if (err instanceof AppError) {
|
||||
// Try to beautify normal errors
|
||||
console.error(err.message.trim());
|
||||
} else {
|
||||
// Print crashes
|
||||
console.error(err.stack);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
216
node_modules/lv_font_conv/node_modules/argparse/CHANGELOG.md
generated
vendored
Normal file
216
node_modules/lv_font_conv/node_modules/argparse/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [2.0.1] - 2020-08-29
|
||||
### Fixed
|
||||
- Fix issue with `process.argv` when used with interpreters (`coffee`, `ts-node`, etc.), #150.
|
||||
|
||||
|
||||
## [2.0.0] - 2020-08-14
|
||||
### Changed
|
||||
- Full rewrite. Now port from python 3.9.0 & more precise following.
|
||||
See [doc](./doc) for difference and migration info.
|
||||
- node.js 10+ required
|
||||
- Removed most of local docs in favour of original ones.
|
||||
|
||||
|
||||
## [1.0.10] - 2018-02-15
|
||||
### Fixed
|
||||
- Use .concat instead of + for arrays, #122.
|
||||
|
||||
|
||||
## [1.0.9] - 2016-09-29
|
||||
### Changed
|
||||
- Rerelease after 1.0.8 - deps cleanup.
|
||||
|
||||
|
||||
## [1.0.8] - 2016-09-29
|
||||
### Changed
|
||||
- Maintenance (deps bump, fix node 6.5+ tests, coverage report).
|
||||
|
||||
|
||||
## [1.0.7] - 2016-03-17
|
||||
### Changed
|
||||
- Teach `addArgument` to accept string arg names. #97, @tomxtobin.
|
||||
|
||||
|
||||
## [1.0.6] - 2016-02-06
|
||||
### Changed
|
||||
- Maintenance: moved to eslint & updated CS.
|
||||
|
||||
|
||||
## [1.0.5] - 2016-02-05
|
||||
### Changed
|
||||
- Removed lodash dependency to significantly reduce install size.
|
||||
Thanks to @mourner.
|
||||
|
||||
|
||||
## [1.0.4] - 2016-01-17
|
||||
### Changed
|
||||
- Maintenance: lodash update to 4.0.0.
|
||||
|
||||
|
||||
## [1.0.3] - 2015-10-27
|
||||
### Fixed
|
||||
- Fix parse `=` in args: `--examplepath="C:\myfolder\env=x64"`. #84, @CatWithApple.
|
||||
|
||||
|
||||
## [1.0.2] - 2015-03-22
|
||||
### Changed
|
||||
- Relaxed lodash version dependency.
|
||||
|
||||
|
||||
## [1.0.1] - 2015-02-20
|
||||
### Changed
|
||||
- Changed dependencies to be compatible with ancient nodejs.
|
||||
|
||||
|
||||
## [1.0.0] - 2015-02-19
|
||||
### Changed
|
||||
- Maintenance release.
|
||||
- Replaced `underscore` with `lodash`.
|
||||
- Bumped version to 1.0.0 to better reflect semver meaning.
|
||||
- HISTORY.md -> CHANGELOG.md
|
||||
|
||||
|
||||
## [0.1.16] - 2013-12-01
|
||||
### Changed
|
||||
- Maintenance release. Updated dependencies and docs.
|
||||
|
||||
|
||||
## [0.1.15] - 2013-05-13
|
||||
### Fixed
|
||||
- Fixed #55, @trebor89
|
||||
|
||||
|
||||
## [0.1.14] - 2013-05-12
|
||||
### Fixed
|
||||
- Fixed #62, @maxtaco
|
||||
|
||||
|
||||
## [0.1.13] - 2013-04-08
|
||||
### Changed
|
||||
- Added `.npmignore` to reduce package size
|
||||
|
||||
|
||||
## [0.1.12] - 2013-02-10
|
||||
### Fixed
|
||||
- Fixed conflictHandler (#46), @hpaulj
|
||||
|
||||
|
||||
## [0.1.11] - 2013-02-07
|
||||
### Added
|
||||
- Added 70+ tests (ported from python), @hpaulj
|
||||
- Added conflictHandler, @applepicke
|
||||
- Added fromfilePrefixChar, @hpaulj
|
||||
|
||||
### Fixed
|
||||
- Multiple bugfixes, @hpaulj
|
||||
|
||||
|
||||
## [0.1.10] - 2012-12-30
|
||||
### Added
|
||||
- Added [mutual exclusion](http://docs.python.org/dev/library/argparse.html#mutual-exclusion)
|
||||
support, thanks to @hpaulj
|
||||
|
||||
### Fixed
|
||||
- Fixed options check for `storeConst` & `appendConst` actions, thanks to @hpaulj
|
||||
|
||||
|
||||
## [0.1.9] - 2012-12-27
|
||||
### Fixed
|
||||
- Fixed option dest interferens with other options (issue #23), thanks to @hpaulj
|
||||
- Fixed default value behavior with `*` positionals, thanks to @hpaulj
|
||||
- Improve `getDefault()` behavior, thanks to @hpaulj
|
||||
- Improve negative argument parsing, thanks to @hpaulj
|
||||
|
||||
|
||||
## [0.1.8] - 2012-12-01
|
||||
### Fixed
|
||||
- Fixed parser parents (issue #19), thanks to @hpaulj
|
||||
- Fixed negative argument parse (issue #20), thanks to @hpaulj
|
||||
|
||||
|
||||
## [0.1.7] - 2012-10-14
|
||||
### Fixed
|
||||
- Fixed 'choices' argument parse (issue #16)
|
||||
- Fixed stderr output (issue #15)
|
||||
|
||||
|
||||
## [0.1.6] - 2012-09-09
|
||||
### Fixed
|
||||
- Fixed check for conflict of options (thanks to @tomxtobin)
|
||||
|
||||
|
||||
## [0.1.5] - 2012-09-03
|
||||
### Fixed
|
||||
- Fix parser #setDefaults method (thanks to @tomxtobin)
|
||||
|
||||
|
||||
## [0.1.4] - 2012-07-30
|
||||
### Fixed
|
||||
- Fixed pseudo-argument support (thanks to @CGamesPlay)
|
||||
- Fixed addHelp default (should be true), if not set (thanks to @benblank)
|
||||
|
||||
|
||||
## [0.1.3] - 2012-06-27
|
||||
### Fixed
|
||||
- Fixed formatter api name: Formatter -> HelpFormatter
|
||||
|
||||
|
||||
## [0.1.2] - 2012-05-29
|
||||
### Fixed
|
||||
- Removed excess whitespace in help
|
||||
- Fixed error reporting, when parcer with subcommands
|
||||
called with empty arguments
|
||||
|
||||
### Added
|
||||
- Added basic tests
|
||||
|
||||
|
||||
## [0.1.1] - 2012-05-23
|
||||
### Fixed
|
||||
- Fixed line wrapping in help formatter
|
||||
- Added better error reporting on invalid arguments
|
||||
|
||||
|
||||
## [0.1.0] - 2012-05-16
|
||||
### Added
|
||||
- First release.
|
||||
|
||||
|
||||
[2.0.1]: https://github.com/nodeca/argparse/compare/2.0.0...2.0.1
|
||||
[2.0.0]: https://github.com/nodeca/argparse/compare/1.0.10...2.0.0
|
||||
[1.0.10]: https://github.com/nodeca/argparse/compare/1.0.9...1.0.10
|
||||
[1.0.9]: https://github.com/nodeca/argparse/compare/1.0.8...1.0.9
|
||||
[1.0.8]: https://github.com/nodeca/argparse/compare/1.0.7...1.0.8
|
||||
[1.0.7]: https://github.com/nodeca/argparse/compare/1.0.6...1.0.7
|
||||
[1.0.6]: https://github.com/nodeca/argparse/compare/1.0.5...1.0.6
|
||||
[1.0.5]: https://github.com/nodeca/argparse/compare/1.0.4...1.0.5
|
||||
[1.0.4]: https://github.com/nodeca/argparse/compare/1.0.3...1.0.4
|
||||
[1.0.3]: https://github.com/nodeca/argparse/compare/1.0.2...1.0.3
|
||||
[1.0.2]: https://github.com/nodeca/argparse/compare/1.0.1...1.0.2
|
||||
[1.0.1]: https://github.com/nodeca/argparse/compare/1.0.0...1.0.1
|
||||
[1.0.0]: https://github.com/nodeca/argparse/compare/0.1.16...1.0.0
|
||||
[0.1.16]: https://github.com/nodeca/argparse/compare/0.1.15...0.1.16
|
||||
[0.1.15]: https://github.com/nodeca/argparse/compare/0.1.14...0.1.15
|
||||
[0.1.14]: https://github.com/nodeca/argparse/compare/0.1.13...0.1.14
|
||||
[0.1.13]: https://github.com/nodeca/argparse/compare/0.1.12...0.1.13
|
||||
[0.1.12]: https://github.com/nodeca/argparse/compare/0.1.11...0.1.12
|
||||
[0.1.11]: https://github.com/nodeca/argparse/compare/0.1.10...0.1.11
|
||||
[0.1.10]: https://github.com/nodeca/argparse/compare/0.1.9...0.1.10
|
||||
[0.1.9]: https://github.com/nodeca/argparse/compare/0.1.8...0.1.9
|
||||
[0.1.8]: https://github.com/nodeca/argparse/compare/0.1.7...0.1.8
|
||||
[0.1.7]: https://github.com/nodeca/argparse/compare/0.1.6...0.1.7
|
||||
[0.1.6]: https://github.com/nodeca/argparse/compare/0.1.5...0.1.6
|
||||
[0.1.5]: https://github.com/nodeca/argparse/compare/0.1.4...0.1.5
|
||||
[0.1.4]: https://github.com/nodeca/argparse/compare/0.1.3...0.1.4
|
||||
[0.1.3]: https://github.com/nodeca/argparse/compare/0.1.2...0.1.3
|
||||
[0.1.2]: https://github.com/nodeca/argparse/compare/0.1.1...0.1.2
|
||||
[0.1.1]: https://github.com/nodeca/argparse/compare/0.1.0...0.1.1
|
||||
[0.1.0]: https://github.com/nodeca/argparse/releases/tag/0.1.0
|
254
node_modules/lv_font_conv/node_modules/argparse/LICENSE
generated
vendored
Normal file
254
node_modules/lv_font_conv/node_modules/argparse/LICENSE
generated
vendored
Normal file
@ -0,0 +1,254 @@
|
||||
A. HISTORY OF THE SOFTWARE
|
||||
==========================
|
||||
|
||||
Python was created in the early 1990s by Guido van Rossum at Stichting
|
||||
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
|
||||
as a successor of a language called ABC. Guido remains Python's
|
||||
principal author, although it includes many contributions from others.
|
||||
|
||||
In 1995, Guido continued his work on Python at the Corporation for
|
||||
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
|
||||
in Reston, Virginia where he released several versions of the
|
||||
software.
|
||||
|
||||
In May 2000, Guido and the Python core development team moved to
|
||||
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
|
||||
year, the PythonLabs team moved to Digital Creations, which became
|
||||
Zope Corporation. In 2001, the Python Software Foundation (PSF, see
|
||||
https://www.python.org/psf/) was formed, a non-profit organization
|
||||
created specifically to own Python-related Intellectual Property.
|
||||
Zope Corporation was a sponsoring member of the PSF.
|
||||
|
||||
All Python releases are Open Source (see http://www.opensource.org for
|
||||
the Open Source Definition). Historically, most, but not all, Python
|
||||
releases have also been GPL-compatible; the table below summarizes
|
||||
the various releases.
|
||||
|
||||
Release Derived Year Owner GPL-
|
||||
from compatible? (1)
|
||||
|
||||
0.9.0 thru 1.2 1991-1995 CWI yes
|
||||
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
|
||||
1.6 1.5.2 2000 CNRI no
|
||||
2.0 1.6 2000 BeOpen.com no
|
||||
1.6.1 1.6 2001 CNRI yes (2)
|
||||
2.1 2.0+1.6.1 2001 PSF no
|
||||
2.0.1 2.0+1.6.1 2001 PSF yes
|
||||
2.1.1 2.1+2.0.1 2001 PSF yes
|
||||
2.1.2 2.1.1 2002 PSF yes
|
||||
2.1.3 2.1.2 2002 PSF yes
|
||||
2.2 and above 2.1.1 2001-now PSF yes
|
||||
|
||||
Footnotes:
|
||||
|
||||
(1) GPL-compatible doesn't mean that we're distributing Python under
|
||||
the GPL. All Python licenses, unlike the GPL, let you distribute
|
||||
a modified version without making your changes open source. The
|
||||
GPL-compatible licenses make it possible to combine Python with
|
||||
other software that is released under the GPL; the others don't.
|
||||
|
||||
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
|
||||
because its license has a choice of law clause. According to
|
||||
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
|
||||
is "not incompatible" with the GPL.
|
||||
|
||||
Thanks to the many outside volunteers who have worked under Guido's
|
||||
direction to make these releases possible.
|
||||
|
||||
|
||||
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
|
||||
===============================================================
|
||||
|
||||
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||
--------------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||
otherwise using this software ("Python") in source or binary form and
|
||||
its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, PSF hereby
|
||||
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
|
||||
analyze, test, perform and/or display publicly, prepare derivative works,
|
||||
distribute, and otherwise use Python alone or in any derivative version,
|
||||
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
||||
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
|
||||
All Rights Reserved" are retained in Python alone or in any derivative version
|
||||
prepared by Licensee.
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python.
|
||||
|
||||
4. PSF is making Python available to Licensee on an "AS IS"
|
||||
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. Nothing in this License Agreement shall be deemed to create any
|
||||
relationship of agency, partnership, or joint venture between PSF and
|
||||
Licensee. This License Agreement does not grant permission to use PSF
|
||||
trademarks or trade name in a trademark sense to endorse or promote
|
||||
products or services of Licensee, or any third party.
|
||||
|
||||
8. By copying, installing or otherwise using Python, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
|
||||
-------------------------------------------
|
||||
|
||||
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
|
||||
|
||||
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
|
||||
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
|
||||
Individual or Organization ("Licensee") accessing and otherwise using
|
||||
this software in source or binary form and its associated
|
||||
documentation ("the Software").
|
||||
|
||||
2. Subject to the terms and conditions of this BeOpen Python License
|
||||
Agreement, BeOpen hereby grants Licensee a non-exclusive,
|
||||
royalty-free, world-wide license to reproduce, analyze, test, perform
|
||||
and/or display publicly, prepare derivative works, distribute, and
|
||||
otherwise use the Software alone or in any derivative version,
|
||||
provided, however, that the BeOpen Python License is retained in the
|
||||
Software, alone or in any derivative version prepared by Licensee.
|
||||
|
||||
3. BeOpen is making the Software available to Licensee on an "AS IS"
|
||||
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
|
||||
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
|
||||
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
|
||||
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
5. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
6. This License Agreement shall be governed by and interpreted in all
|
||||
respects by the law of the State of California, excluding conflict of
|
||||
law provisions. Nothing in this License Agreement shall be deemed to
|
||||
create any relationship of agency, partnership, or joint venture
|
||||
between BeOpen and Licensee. This License Agreement does not grant
|
||||
permission to use BeOpen trademarks or trade names in a trademark
|
||||
sense to endorse or promote products or services of Licensee, or any
|
||||
third party. As an exception, the "BeOpen Python" logos available at
|
||||
http://www.pythonlabs.com/logos.html may be used according to the
|
||||
permissions granted on that web page.
|
||||
|
||||
7. By copying, installing or otherwise using the software, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
|
||||
---------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Corporation for National
|
||||
Research Initiatives, having an office at 1895 Preston White Drive,
|
||||
Reston, VA 20191 ("CNRI"), and the Individual or Organization
|
||||
("Licensee") accessing and otherwise using Python 1.6.1 software in
|
||||
source or binary form and its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, CNRI
|
||||
hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||
license to reproduce, analyze, test, perform and/or display publicly,
|
||||
prepare derivative works, distribute, and otherwise use Python 1.6.1
|
||||
alone or in any derivative version, provided, however, that CNRI's
|
||||
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
|
||||
1995-2001 Corporation for National Research Initiatives; All Rights
|
||||
Reserved" are retained in Python 1.6.1 alone or in any derivative
|
||||
version prepared by Licensee. Alternately, in lieu of CNRI's License
|
||||
Agreement, Licensee may substitute the following text (omitting the
|
||||
quotes): "Python 1.6.1 is made available subject to the terms and
|
||||
conditions in CNRI's License Agreement. This Agreement together with
|
||||
Python 1.6.1 may be located on the Internet using the following
|
||||
unique, persistent identifier (known as a handle): 1895.22/1013. This
|
||||
Agreement may also be obtained from a proxy server on the Internet
|
||||
using the following URL: http://hdl.handle.net/1895.22/1013".
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python 1.6.1 or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python 1.6.1.
|
||||
|
||||
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
|
||||
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. This License Agreement shall be governed by the federal
|
||||
intellectual property law of the United States, including without
|
||||
limitation the federal copyright law, and, to the extent such
|
||||
U.S. federal law does not apply, by the law of the Commonwealth of
|
||||
Virginia, excluding Virginia's conflict of law provisions.
|
||||
Notwithstanding the foregoing, with regard to derivative works based
|
||||
on Python 1.6.1 that incorporate non-separable material that was
|
||||
previously distributed under the GNU General Public License (GPL), the
|
||||
law of the Commonwealth of Virginia shall govern this License
|
||||
Agreement only as to issues arising under or with respect to
|
||||
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
|
||||
License Agreement shall be deemed to create any relationship of
|
||||
agency, partnership, or joint venture between CNRI and Licensee. This
|
||||
License Agreement does not grant permission to use CNRI trademarks or
|
||||
trade name in a trademark sense to endorse or promote products or
|
||||
services of Licensee, or any third party.
|
||||
|
||||
8. By clicking on the "ACCEPT" button where indicated, or by copying,
|
||||
installing or otherwise using Python 1.6.1, Licensee agrees to be
|
||||
bound by the terms and conditions of this License Agreement.
|
||||
|
||||
ACCEPT
|
||||
|
||||
|
||||
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
|
||||
--------------------------------------------------
|
||||
|
||||
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
|
||||
The Netherlands. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior
|
||||
permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
84
node_modules/lv_font_conv/node_modules/argparse/README.md
generated
vendored
Normal file
84
node_modules/lv_font_conv/node_modules/argparse/README.md
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
argparse
|
||||
========
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/nodeca/argparse.svg?branch=master)](http://travis-ci.org/nodeca/argparse)
|
||||
[![NPM version](https://img.shields.io/npm/v/argparse.svg)](https://www.npmjs.org/package/argparse)
|
||||
|
||||
CLI arguments parser for node.js, with [sub-commands](https://docs.python.org/3.9/library/argparse.html#sub-commands) support. Port of python's [argparse](http://docs.python.org/dev/library/argparse.html) (version [3.9.0](https://github.com/python/cpython/blob/v3.9.0rc1/Lib/argparse.py)).
|
||||
|
||||
**Difference with original.**
|
||||
|
||||
- JS has no keyword arguments support.
|
||||
- Pass options instead: `new ArgumentParser({ description: 'example', add_help: true })`.
|
||||
- JS has no python's types `int`, `float`, ...
|
||||
- Use string-typed names: `.add_argument('-b', { type: 'int', help: 'help' })`.
|
||||
- `%r` format specifier uses `require('util').inspect()`.
|
||||
|
||||
More details in [doc](./doc).
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
`test.js` file:
|
||||
|
||||
```javascript
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const { ArgumentParser } = require('argparse');
|
||||
const { version } = require('./package.json');
|
||||
|
||||
const parser = new ArgumentParser({
|
||||
description: 'Argparse example'
|
||||
});
|
||||
|
||||
parser.add_argument('-v', '--version', { action: 'version', version });
|
||||
parser.add_argument('-f', '--foo', { help: 'foo bar' });
|
||||
parser.add_argument('-b', '--bar', { help: 'bar foo' });
|
||||
parser.add_argument('--baz', { help: 'baz bar' });
|
||||
|
||||
console.dir(parser.parse_args());
|
||||
```
|
||||
|
||||
Display help:
|
||||
|
||||
```
|
||||
$ ./test.js -h
|
||||
usage: test.js [-h] [-v] [-f FOO] [-b BAR] [--baz BAZ]
|
||||
|
||||
Argparse example
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-v, --version show program's version number and exit
|
||||
-f FOO, --foo FOO foo bar
|
||||
-b BAR, --bar BAR bar foo
|
||||
--baz BAZ baz bar
|
||||
```
|
||||
|
||||
Parse arguments:
|
||||
|
||||
```
|
||||
$ ./test.js -f=3 --bar=4 --baz 5
|
||||
{ foo: '3', bar: '4', baz: '5' }
|
||||
```
|
||||
|
||||
|
||||
API docs
|
||||
--------
|
||||
|
||||
Since this is a port with minimal divergence, there's no separate documentation.
|
||||
Use original one instead, with notes about difference.
|
||||
|
||||
1. [Original doc](https://docs.python.org/3.9/library/argparse.html).
|
||||
2. [Original tutorial](https://docs.python.org/3.9/howto/argparse.html).
|
||||
3. [Difference with python](./doc).
|
||||
|
||||
|
||||
argparse for enterprise
|
||||
-----------------------
|
||||
|
||||
Available as part of the Tidelift Subscription
|
||||
|
||||
The maintainers of argparse and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-argparse?utm_source=npm-argparse&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
|
3707
node_modules/lv_font_conv/node_modules/argparse/argparse.js
generated
vendored
Normal file
3707
node_modules/lv_font_conv/node_modules/argparse/argparse.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
67
node_modules/lv_font_conv/node_modules/argparse/lib/sub.js
generated
vendored
Normal file
67
node_modules/lv_font_conv/node_modules/argparse/lib/sub.js
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
// Limited implementation of python % string operator, supports only %s and %r for now
|
||||
// (other formats are not used here, but may appear in custom templates)
|
||||
|
||||
'use strict'
|
||||
|
||||
const { inspect } = require('util')
|
||||
|
||||
|
||||
module.exports = function sub(pattern, ...values) {
|
||||
let regex = /%(?:(%)|(-)?(\*)?(?:\((\w+)\))?([A-Za-z]))/g
|
||||
|
||||
let result = pattern.replace(regex, function (_, is_literal, is_left_align, is_padded, name, format) {
|
||||
if (is_literal) return '%'
|
||||
|
||||
let padded_count = 0
|
||||
if (is_padded) {
|
||||
if (values.length === 0) throw new TypeError('not enough arguments for format string')
|
||||
padded_count = values.shift()
|
||||
if (!Number.isInteger(padded_count)) throw new TypeError('* wants int')
|
||||
}
|
||||
|
||||
let str
|
||||
if (name !== undefined) {
|
||||
let dict = values[0]
|
||||
if (typeof dict !== 'object' || dict === null) throw new TypeError('format requires a mapping')
|
||||
if (!(name in dict)) throw new TypeError(`no such key: '${name}'`)
|
||||
str = dict[name]
|
||||
} else {
|
||||
if (values.length === 0) throw new TypeError('not enough arguments for format string')
|
||||
str = values.shift()
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case 's':
|
||||
str = String(str)
|
||||
break
|
||||
case 'r':
|
||||
str = inspect(str)
|
||||
break
|
||||
case 'd':
|
||||
case 'i':
|
||||
if (typeof str !== 'number') {
|
||||
throw new TypeError(`%${format} format: a number is required, not ${typeof str}`)
|
||||
}
|
||||
str = String(str.toFixed(0))
|
||||
break
|
||||
default:
|
||||
throw new TypeError(`unsupported format character '${format}'`)
|
||||
}
|
||||
|
||||
if (padded_count > 0) {
|
||||
return is_left_align ? str.padEnd(padded_count) : str.padStart(padded_count)
|
||||
} else {
|
||||
return str
|
||||
}
|
||||
})
|
||||
|
||||
if (values.length) {
|
||||
if (values.length === 1 && typeof values[0] === 'object' && values[0] !== null) {
|
||||
// mapping
|
||||
} else {
|
||||
throw new TypeError('not all arguments converted during string formatting')
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
440
node_modules/lv_font_conv/node_modules/argparse/lib/textwrap.js
generated
vendored
Normal file
440
node_modules/lv_font_conv/node_modules/argparse/lib/textwrap.js
generated
vendored
Normal file
@ -0,0 +1,440 @@
|
||||
// Partial port of python's argparse module, version 3.9.0 (only wrap and fill functions):
|
||||
// https://github.com/python/cpython/blob/v3.9.0b4/Lib/textwrap.py
|
||||
|
||||
'use strict'
|
||||
|
||||
/*
|
||||
* Text wrapping and filling.
|
||||
*/
|
||||
|
||||
// Copyright (C) 1999-2001 Gregory P. Ward.
|
||||
// Copyright (C) 2002, 2003 Python Software Foundation.
|
||||
// Copyright (C) 2020 argparse.js authors
|
||||
// Originally written by Greg Ward <gward@python.net>
|
||||
|
||||
// Hardcode the recognized whitespace characters to the US-ASCII
|
||||
// whitespace characters. The main reason for doing this is that
|
||||
// some Unicode spaces (like \u00a0) are non-breaking whitespaces.
|
||||
//
|
||||
// This less funky little regex just split on recognized spaces. E.g.
|
||||
// "Hello there -- you goof-ball, use the -b option!"
|
||||
// splits into
|
||||
// Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/
|
||||
const wordsep_simple_re = /([\t\n\x0b\x0c\r ]+)/
|
||||
|
||||
class TextWrapper {
|
||||
/*
|
||||
* Object for wrapping/filling text. The public interface consists of
|
||||
* the wrap() and fill() methods; the other methods are just there for
|
||||
* subclasses to override in order to tweak the default behaviour.
|
||||
* If you want to completely replace the main wrapping algorithm,
|
||||
* you'll probably have to override _wrap_chunks().
|
||||
*
|
||||
* Several instance attributes control various aspects of wrapping:
|
||||
* width (default: 70)
|
||||
* the maximum width of wrapped lines (unless break_long_words
|
||||
* is false)
|
||||
* initial_indent (default: "")
|
||||
* string that will be prepended to the first line of wrapped
|
||||
* output. Counts towards the line's width.
|
||||
* subsequent_indent (default: "")
|
||||
* string that will be prepended to all lines save the first
|
||||
* of wrapped output; also counts towards each line's width.
|
||||
* expand_tabs (default: true)
|
||||
* Expand tabs in input text to spaces before further processing.
|
||||
* Each tab will become 0 .. 'tabsize' spaces, depending on its position
|
||||
* in its line. If false, each tab is treated as a single character.
|
||||
* tabsize (default: 8)
|
||||
* Expand tabs in input text to 0 .. 'tabsize' spaces, unless
|
||||
* 'expand_tabs' is false.
|
||||
* replace_whitespace (default: true)
|
||||
* Replace all whitespace characters in the input text by spaces
|
||||
* after tab expansion. Note that if expand_tabs is false and
|
||||
* replace_whitespace is true, every tab will be converted to a
|
||||
* single space!
|
||||
* fix_sentence_endings (default: false)
|
||||
* Ensure that sentence-ending punctuation is always followed
|
||||
* by two spaces. Off by default because the algorithm is
|
||||
* (unavoidably) imperfect.
|
||||
* break_long_words (default: true)
|
||||
* Break words longer than 'width'. If false, those words will not
|
||||
* be broken, and some lines might be longer than 'width'.
|
||||
* break_on_hyphens (default: true)
|
||||
* Allow breaking hyphenated words. If true, wrapping will occur
|
||||
* preferably on whitespaces and right after hyphens part of
|
||||
* compound words.
|
||||
* drop_whitespace (default: true)
|
||||
* Drop leading and trailing whitespace from lines.
|
||||
* max_lines (default: None)
|
||||
* Truncate wrapped lines.
|
||||
* placeholder (default: ' [...]')
|
||||
* Append to the last line of truncated text.
|
||||
*/
|
||||
|
||||
constructor(options = {}) {
|
||||
let {
|
||||
width = 70,
|
||||
initial_indent = '',
|
||||
subsequent_indent = '',
|
||||
expand_tabs = true,
|
||||
replace_whitespace = true,
|
||||
fix_sentence_endings = false,
|
||||
break_long_words = true,
|
||||
drop_whitespace = true,
|
||||
break_on_hyphens = true,
|
||||
tabsize = 8,
|
||||
max_lines = undefined,
|
||||
placeholder=' [...]'
|
||||
} = options
|
||||
|
||||
this.width = width
|
||||
this.initial_indent = initial_indent
|
||||
this.subsequent_indent = subsequent_indent
|
||||
this.expand_tabs = expand_tabs
|
||||
this.replace_whitespace = replace_whitespace
|
||||
this.fix_sentence_endings = fix_sentence_endings
|
||||
this.break_long_words = break_long_words
|
||||
this.drop_whitespace = drop_whitespace
|
||||
this.break_on_hyphens = break_on_hyphens
|
||||
this.tabsize = tabsize
|
||||
this.max_lines = max_lines
|
||||
this.placeholder = placeholder
|
||||
}
|
||||
|
||||
|
||||
// -- Private methods -----------------------------------------------
|
||||
// (possibly useful for subclasses to override)
|
||||
|
||||
_munge_whitespace(text) {
|
||||
/*
|
||||
* _munge_whitespace(text : string) -> string
|
||||
*
|
||||
* Munge whitespace in text: expand tabs and convert all other
|
||||
* whitespace characters to spaces. Eg. " foo\\tbar\\n\\nbaz"
|
||||
* becomes " foo bar baz".
|
||||
*/
|
||||
if (this.expand_tabs) {
|
||||
text = text.replace(/\t/g, ' '.repeat(this.tabsize)) // not strictly correct in js
|
||||
}
|
||||
if (this.replace_whitespace) {
|
||||
text = text.replace(/[\t\n\x0b\x0c\r]/g, ' ')
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
_split(text) {
|
||||
/*
|
||||
* _split(text : string) -> [string]
|
||||
*
|
||||
* Split the text to wrap into indivisible chunks. Chunks are
|
||||
* not quite the same as words; see _wrap_chunks() for full
|
||||
* details. As an example, the text
|
||||
* Look, goof-ball -- use the -b option!
|
||||
* breaks into the following chunks:
|
||||
* 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
|
||||
* 'use', ' ', 'the', ' ', '-b', ' ', 'option!'
|
||||
* if break_on_hyphens is True, or in:
|
||||
* 'Look,', ' ', 'goof-ball', ' ', '--', ' ',
|
||||
* 'use', ' ', 'the', ' ', '-b', ' ', option!'
|
||||
* otherwise.
|
||||
*/
|
||||
let chunks = text.split(wordsep_simple_re)
|
||||
chunks = chunks.filter(Boolean)
|
||||
return chunks
|
||||
}
|
||||
|
||||
_handle_long_word(reversed_chunks, cur_line, cur_len, width) {
|
||||
/*
|
||||
* _handle_long_word(chunks : [string],
|
||||
* cur_line : [string],
|
||||
* cur_len : int, width : int)
|
||||
*
|
||||
* Handle a chunk of text (most likely a word, not whitespace) that
|
||||
* is too long to fit in any line.
|
||||
*/
|
||||
// Figure out when indent is larger than the specified width, and make
|
||||
// sure at least one character is stripped off on every pass
|
||||
let space_left
|
||||
if (width < 1) {
|
||||
space_left = 1
|
||||
} else {
|
||||
space_left = width - cur_len
|
||||
}
|
||||
|
||||
// If we're allowed to break long words, then do so: put as much
|
||||
// of the next chunk onto the current line as will fit.
|
||||
if (this.break_long_words) {
|
||||
cur_line.push(reversed_chunks[reversed_chunks.length - 1].slice(0, space_left))
|
||||
reversed_chunks[reversed_chunks.length - 1] = reversed_chunks[reversed_chunks.length - 1].slice(space_left)
|
||||
|
||||
// Otherwise, we have to preserve the long word intact. Only add
|
||||
// it to the current line if there's nothing already there --
|
||||
// that minimizes how much we violate the width constraint.
|
||||
} else if (!cur_line) {
|
||||
cur_line.push(...reversed_chunks.pop())
|
||||
}
|
||||
|
||||
// If we're not allowed to break long words, and there's already
|
||||
// text on the current line, do nothing. Next time through the
|
||||
// main loop of _wrap_chunks(), we'll wind up here again, but
|
||||
// cur_len will be zero, so the next line will be entirely
|
||||
// devoted to the long word that we can't handle right now.
|
||||
}
|
||||
|
||||
_wrap_chunks(chunks) {
|
||||
/*
|
||||
* _wrap_chunks(chunks : [string]) -> [string]
|
||||
*
|
||||
* Wrap a sequence of text chunks and return a list of lines of
|
||||
* length 'self.width' or less. (If 'break_long_words' is false,
|
||||
* some lines may be longer than this.) Chunks correspond roughly
|
||||
* to words and the whitespace between them: each chunk is
|
||||
* indivisible (modulo 'break_long_words'), but a line break can
|
||||
* come between any two chunks. Chunks should not have internal
|
||||
* whitespace; ie. a chunk is either all whitespace or a "word".
|
||||
* Whitespace chunks will be removed from the beginning and end of
|
||||
* lines, but apart from that whitespace is preserved.
|
||||
*/
|
||||
let lines = []
|
||||
let indent
|
||||
if (this.width <= 0) {
|
||||
throw Error(`invalid width ${this.width} (must be > 0)`)
|
||||
}
|
||||
if (this.max_lines !== undefined) {
|
||||
if (this.max_lines > 1) {
|
||||
indent = this.subsequent_indent
|
||||
} else {
|
||||
indent = this.initial_indent
|
||||
}
|
||||
if (indent.length + this.placeholder.trimStart().length > this.width) {
|
||||
throw Error('placeholder too large for max width')
|
||||
}
|
||||
}
|
||||
|
||||
// Arrange in reverse order so items can be efficiently popped
|
||||
// from a stack of chucks.
|
||||
chunks = chunks.reverse()
|
||||
|
||||
while (chunks.length > 0) {
|
||||
|
||||
// Start the list of chunks that will make up the current line.
|
||||
// cur_len is just the length of all the chunks in cur_line.
|
||||
let cur_line = []
|
||||
let cur_len = 0
|
||||
|
||||
// Figure out which static string will prefix this line.
|
||||
let indent
|
||||
if (lines) {
|
||||
indent = this.subsequent_indent
|
||||
} else {
|
||||
indent = this.initial_indent
|
||||
}
|
||||
|
||||
// Maximum width for this line.
|
||||
let width = this.width - indent.length
|
||||
|
||||
// First chunk on line is whitespace -- drop it, unless this
|
||||
// is the very beginning of the text (ie. no lines started yet).
|
||||
if (this.drop_whitespace && chunks[chunks.length - 1].trim() === '' && lines.length > 0) {
|
||||
chunks.pop()
|
||||
}
|
||||
|
||||
while (chunks.length > 0) {
|
||||
let l = chunks[chunks.length - 1].length
|
||||
|
||||
// Can at least squeeze this chunk onto the current line.
|
||||
if (cur_len + l <= width) {
|
||||
cur_line.push(chunks.pop())
|
||||
cur_len += l
|
||||
|
||||
// Nope, this line is full.
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// The current line is full, and the next chunk is too big to
|
||||
// fit on *any* line (not just this one).
|
||||
if (chunks.length && chunks[chunks.length - 1].length > width) {
|
||||
this._handle_long_word(chunks, cur_line, cur_len, width)
|
||||
cur_len = cur_line.map(l => l.length).reduce((a, b) => a + b, 0)
|
||||
}
|
||||
|
||||
// If the last chunk on this line is all whitespace, drop it.
|
||||
if (this.drop_whitespace && cur_line.length > 0 && cur_line[cur_line.length - 1].trim() === '') {
|
||||
cur_len -= cur_line[cur_line.length - 1].length
|
||||
cur_line.pop()
|
||||
}
|
||||
|
||||
if (cur_line) {
|
||||
if (this.max_lines === undefined ||
|
||||
lines.length + 1 < this.max_lines ||
|
||||
(chunks.length === 0 ||
|
||||
this.drop_whitespace &&
|
||||
chunks.length === 1 &&
|
||||
!chunks[0].trim()) && cur_len <= width) {
|
||||
// Convert current line back to a string and store it in
|
||||
// list of all lines (return value).
|
||||
lines.push(indent + cur_line.join(''))
|
||||
} else {
|
||||
let had_break = false
|
||||
while (cur_line) {
|
||||
if (cur_line[cur_line.length - 1].trim() &&
|
||||
cur_len + this.placeholder.length <= width) {
|
||||
cur_line.push(this.placeholder)
|
||||
lines.push(indent + cur_line.join(''))
|
||||
had_break = true
|
||||
break
|
||||
}
|
||||
cur_len -= cur_line[-1].length
|
||||
cur_line.pop()
|
||||
}
|
||||
if (!had_break) {
|
||||
if (lines) {
|
||||
let prev_line = lines[lines.length - 1].trimEnd()
|
||||
if (prev_line.length + this.placeholder.length <=
|
||||
this.width) {
|
||||
lines[lines.length - 1] = prev_line + this.placeholder
|
||||
break
|
||||
}
|
||||
}
|
||||
lines.push(indent + this.placeholder.lstrip())
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
_split_chunks(text) {
|
||||
text = this._munge_whitespace(text)
|
||||
return this._split(text)
|
||||
}
|
||||
|
||||
// -- Public interface ----------------------------------------------
|
||||
|
||||
wrap(text) {
|
||||
/*
|
||||
* wrap(text : string) -> [string]
|
||||
*
|
||||
* Reformat the single paragraph in 'text' so it fits in lines of
|
||||
* no more than 'self.width' columns, and return a list of wrapped
|
||||
* lines. Tabs in 'text' are expanded with string.expandtabs(),
|
||||
* and all other whitespace characters (including newline) are
|
||||
* converted to space.
|
||||
*/
|
||||
let chunks = this._split_chunks(text)
|
||||
// not implemented in js
|
||||
//if (this.fix_sentence_endings) {
|
||||
// this._fix_sentence_endings(chunks)
|
||||
//}
|
||||
return this._wrap_chunks(chunks)
|
||||
}
|
||||
|
||||
fill(text) {
|
||||
/*
|
||||
* fill(text : string) -> string
|
||||
*
|
||||
* Reformat the single paragraph in 'text' to fit in lines of no
|
||||
* more than 'self.width' columns, and return a new string
|
||||
* containing the entire wrapped paragraph.
|
||||
*/
|
||||
return this.wrap(text).join('\n')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- Convenience interface ---------------------------------------------
|
||||
|
||||
function wrap(text, options = {}) {
|
||||
/*
|
||||
* Wrap a single paragraph of text, returning a list of wrapped lines.
|
||||
*
|
||||
* Reformat the single paragraph in 'text' so it fits in lines of no
|
||||
* more than 'width' columns, and return a list of wrapped lines. By
|
||||
* default, tabs in 'text' are expanded with string.expandtabs(), and
|
||||
* all other whitespace characters (including newline) are converted to
|
||||
* space. See TextWrapper class for available keyword args to customize
|
||||
* wrapping behaviour.
|
||||
*/
|
||||
let { width = 70, ...kwargs } = options
|
||||
let w = new TextWrapper(Object.assign({ width }, kwargs))
|
||||
return w.wrap(text)
|
||||
}
|
||||
|
||||
function fill(text, options = {}) {
|
||||
/*
|
||||
* Fill a single paragraph of text, returning a new string.
|
||||
*
|
||||
* Reformat the single paragraph in 'text' to fit in lines of no more
|
||||
* than 'width' columns, and return a new string containing the entire
|
||||
* wrapped paragraph. As with wrap(), tabs are expanded and other
|
||||
* whitespace characters converted to space. See TextWrapper class for
|
||||
* available keyword args to customize wrapping behaviour.
|
||||
*/
|
||||
let { width = 70, ...kwargs } = options
|
||||
let w = new TextWrapper(Object.assign({ width }, kwargs))
|
||||
return w.fill(text)
|
||||
}
|
||||
|
||||
// -- Loosely related functionality -------------------------------------
|
||||
|
||||
let _whitespace_only_re = /^[ \t]+$/mg
|
||||
let _leading_whitespace_re = /(^[ \t]*)(?:[^ \t\n])/mg
|
||||
|
||||
function dedent(text) {
|
||||
/*
|
||||
* Remove any common leading whitespace from every line in `text`.
|
||||
*
|
||||
* This can be used to make triple-quoted strings line up with the left
|
||||
* edge of the display, while still presenting them in the source code
|
||||
* in indented form.
|
||||
*
|
||||
* Note that tabs and spaces are both treated as whitespace, but they
|
||||
* are not equal: the lines " hello" and "\\thello" are
|
||||
* considered to have no common leading whitespace.
|
||||
*
|
||||
* Entirely blank lines are normalized to a newline character.
|
||||
*/
|
||||
// Look for the longest leading string of spaces and tabs common to
|
||||
// all lines.
|
||||
let margin = undefined
|
||||
text = text.replace(_whitespace_only_re, '')
|
||||
let indents = text.match(_leading_whitespace_re) || []
|
||||
for (let indent of indents) {
|
||||
indent = indent.slice(0, -1)
|
||||
|
||||
if (margin === undefined) {
|
||||
margin = indent
|
||||
|
||||
// Current line more deeply indented than previous winner:
|
||||
// no change (previous winner is still on top).
|
||||
} else if (indent.startsWith(margin)) {
|
||||
// pass
|
||||
|
||||
// Current line consistent with and no deeper than previous winner:
|
||||
// it's the new winner.
|
||||
} else if (margin.startsWith(indent)) {
|
||||
margin = indent
|
||||
|
||||
// Find the largest common whitespace between current line and previous
|
||||
// winner.
|
||||
} else {
|
||||
for (let i = 0; i < margin.length && i < indent.length; i++) {
|
||||
if (margin[i] !== indent[i]) {
|
||||
margin = margin.slice(0, i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (margin) {
|
||||
text = text.replace(new RegExp('^' + margin, 'mg'), '')
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
module.exports = { wrap, fill, dedent }
|
67
node_modules/lv_font_conv/node_modules/argparse/package.json
generated
vendored
Normal file
67
node_modules/lv_font_conv/node_modules/argparse/package.json
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"argparse@2.0.1",
|
||||
"/home/vitaly/Dropbox/Coding/lv_font_conv"
|
||||
]
|
||||
],
|
||||
"_from": "argparse@2.0.1",
|
||||
"_id": "argparse@2.0.1",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"_location": "/argparse",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "argparse@2.0.1",
|
||||
"name": "argparse",
|
||||
"escapedName": "argparse",
|
||||
"rawSpec": "2.0.1",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "2.0.1"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/",
|
||||
"/mocha/js-yaml"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"_spec": "2.0.1",
|
||||
"_where": "/home/vitaly/Dropbox/Coding/lv_font_conv",
|
||||
"bugs": {
|
||||
"url": "https://github.com/nodeca/argparse/issues"
|
||||
},
|
||||
"description": "CLI arguments parser. Native port of python's argparse.",
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.11.0",
|
||||
"@babel/plugin-syntax-class-properties": "^7.10.4",
|
||||
"eslint": "^7.5.0",
|
||||
"mocha": "^8.0.1",
|
||||
"nyc": "^15.1.0"
|
||||
},
|
||||
"files": [
|
||||
"argparse.js",
|
||||
"lib/"
|
||||
],
|
||||
"homepage": "https://github.com/nodeca/argparse#readme",
|
||||
"keywords": [
|
||||
"cli",
|
||||
"parser",
|
||||
"argparse",
|
||||
"option",
|
||||
"args"
|
||||
],
|
||||
"license": "Python-2.0",
|
||||
"main": "argparse.js",
|
||||
"name": "argparse",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nodeca/argparse.git"
|
||||
},
|
||||
"scripts": {
|
||||
"coverage": "npm run test && nyc report --reporter html",
|
||||
"lint": "eslint .",
|
||||
"test": "npm run lint && nyc mocha"
|
||||
},
|
||||
"version": "2.0.1"
|
||||
}
|
36
node_modules/lv_font_conv/node_modules/bit-buffer/.github/workflows/ci.yml
generated
vendored
Normal file
36
node_modules/lv_font_conv/node_modules/bit-buffer/.github/workflows/ci.yml
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: Node.js CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [10.x, 12.x, 14.x, 15.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [10.x, 12.x, 14.x, 15.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
21
node_modules/lv_font_conv/node_modules/bit-buffer/LICENSE
generated
vendored
Normal file
21
node_modules/lv_font_conv/node_modules/bit-buffer/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 bit-buffer developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
148
node_modules/lv_font_conv/node_modules/bit-buffer/README.md
generated
vendored
Normal file
148
node_modules/lv_font_conv/node_modules/bit-buffer/README.md
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
# BitBuffer
|
||||
|
||||
![Node.js CI](https://github.com/inolen/bit-buffer/workflows/Node.js%20CI/badge.svg)
|
||||
|
||||
BitBuffer provides two objects, `BitView` and `BitStream`. `BitView` is a wrapper for ArrayBuffers, similar to JavaScript's [DataView](https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays/DataView), but with support for bit-level reads and writes. `BitStream` is a wrapper for a `BitView` used to help maintain your current buffer position, as well as to provide higher-level read / write operations such as for ASCII strings.
|
||||
|
||||
## BitView
|
||||
|
||||
### Attributes
|
||||
|
||||
```javascript
|
||||
bb.buffer // Underlying ArrayBuffer.
|
||||
```
|
||||
|
||||
```javascript
|
||||
bb.bigEndian = true; // Switch to big endian (default is little)
|
||||
```
|
||||
|
||||
### Methods
|
||||
|
||||
#### BitView(buffer, optional byteOffset, optional byteLength)
|
||||
|
||||
Default constructor, takes in a single argument of an ArrayBuffer. Optional are the `byteOffset` and `byteLength` arguments to offset and truncate the view's representation of the buffer.
|
||||
|
||||
### getBits(offset, bits, signed)
|
||||
|
||||
Reads `bits` number of bits starting at `offset`, twiddling the bits appropriately to return a proper 32-bit signed or unsigned value. NOTE: While JavaScript numbers are 64-bit floating-point values, we don't bother with anything other than the first 32 bits.
|
||||
|
||||
### getInt8, getUint8, getInt16, getUint16, getInt32, getUint32(offset)
|
||||
|
||||
Shortcuts for getBits, setting the correct `bits` / `signed` values.
|
||||
|
||||
### getFloat32(offset)
|
||||
|
||||
Gets 32 bits from `offset`, and coerces and returns as a proper float32 value.
|
||||
|
||||
### getFloat64(offset)
|
||||
|
||||
Gets 64 bits from `offset`, and coerces and returns as a proper float64 value.
|
||||
|
||||
### setBits(offset, value, bits)
|
||||
|
||||
Sets `bits` number of bits at `offset`.
|
||||
|
||||
### setInt8, setUint8, setInt16, setUint16, setInt32, setUint32(offset)
|
||||
|
||||
Shortcuts for setBits, setting the correct `bits` count.
|
||||
|
||||
### setFloat32(offset)
|
||||
|
||||
Coerces a float32 to uint32 and sets at `offset`.
|
||||
|
||||
### setFloat64(offset)
|
||||
|
||||
Coerces a float64 to two uint32s and sets at `offset`.
|
||||
|
||||
|
||||
## BitStream
|
||||
|
||||
### Attributes
|
||||
|
||||
```javascript
|
||||
bb.byteIndex; // Get current index in bytes.
|
||||
bb.byteIndex = 0; // Set current index in bytes.
|
||||
```
|
||||
|
||||
```javascript
|
||||
bb.view; // Underlying BitView
|
||||
```
|
||||
|
||||
```javascript
|
||||
bb.length; // Get the length of the stream in bits
|
||||
```
|
||||
|
||||
```javascript
|
||||
bb.bitsLeft; // The number of bits left in the stream
|
||||
```
|
||||
|
||||
```javascript
|
||||
bb.index; // Get the current index in bits
|
||||
bb.index = 0// Set the current index in bits
|
||||
```
|
||||
|
||||
```javascript
|
||||
bb.bigEndian = true; // Switch to big endian (default is little)
|
||||
```
|
||||
|
||||
### Methods
|
||||
|
||||
#### BitStream(view)
|
||||
|
||||
Default constructor, takes in a single argument of a `BitView`, `ArrayBuffer` or node `Buffer`.
|
||||
|
||||
#### BitSteam(buffer, optional byteOffset, optional byteLength)
|
||||
|
||||
Shortcut constructor that initializes a new `BitView(buffer, byteOffset, byteLength)` for the stream to use.
|
||||
|
||||
#### readBits(bits, signed)
|
||||
|
||||
Returns `bits` numbers of bits from the view at the current index, updating the index.
|
||||
|
||||
#### writeBits(value, bits)
|
||||
|
||||
Sets `bits` numbers of bits from `value` in the view at the current index, updating the index.
|
||||
|
||||
#### readUint8(), readUint16(), readUint32(), readInt8(), readInt16(), readInt32()
|
||||
|
||||
Read a 8, 16 or 32 bits (unsigned) integer at the current index, updating the index.
|
||||
|
||||
#### writeUint8(value), writeUint16(value), writeUint32(value), writeInt8(value), writeInt16(value), writeInt32(value)
|
||||
|
||||
Write 8, 16 or 32 bits from `value` as (unsigned) integer at the current index, updating the index.
|
||||
|
||||
#### readFloat32(), readFloat64()
|
||||
|
||||
Read a 32 or 64 bit floating point number at the current index, updating the index.
|
||||
|
||||
#### writeFloat32(value), writeFloat64()
|
||||
|
||||
Set 32 or 64 bits from `value` as floating point value at the current index, updating the index.
|
||||
|
||||
#### readBoolean()
|
||||
|
||||
Read a single bit from the view at the current index, updating the index.
|
||||
|
||||
#### writeBoolean(value)
|
||||
|
||||
Write a single bit to the view at the current index, updating the index.
|
||||
|
||||
#### readASCIIString(optional bytes), readUTF8String(optional bytes)
|
||||
|
||||
Reads bytes from the underlying view at the current index until either `bytes` count is reached or a 0x00 terminator is reached.
|
||||
|
||||
#### writeASCIIString(string, optional bytes), writeUTF8String(string, optional bytes)
|
||||
|
||||
Writes a string followed by a NULL character to the underlying view starting at the current index. If the string is longer than `bytes` it will be truncated, and if it is shorter 0x00 will be written in its place.
|
||||
|
||||
#### readBitStream(length)
|
||||
|
||||
Create a new `BitStream` from the underlying view starting the the current index and a length of `length` bits. Updating the index of the existing `BitStream`
|
||||
|
||||
#### readArrayBuffer(byteLength)
|
||||
|
||||
Read `byteLength` bytes of data from the underlying view as `ArrayBuffer`, updating the index.
|
||||
|
||||
## license
|
||||
|
||||
MIT
|
115
node_modules/lv_font_conv/node_modules/bit-buffer/bit-buffer.d.ts
generated
vendored
Normal file
115
node_modules/lv_font_conv/node_modules/bit-buffer/bit-buffer.d.ts
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
declare module 'bit-buffer' {
|
||||
import {Buffer} from 'buffer';
|
||||
|
||||
export class BitView {
|
||||
constructor(buffer: ArrayBuffer | Buffer, byteLength?: number);
|
||||
|
||||
readonly buffer: Buffer;
|
||||
readonly byteLength: number;
|
||||
bigEndian: boolean;
|
||||
|
||||
getBits(offset: number, bits: number, signed?: boolean): number;
|
||||
|
||||
getInt8(offset: number): number;
|
||||
|
||||
getInt16(offset: number): number;
|
||||
|
||||
getInt32(offset: number): number;
|
||||
|
||||
getUint8(offset: number): number;
|
||||
|
||||
getUint16(offset: number): number;
|
||||
|
||||
getUint32(offset: number): number;
|
||||
|
||||
getFloat32(offset: number): number;
|
||||
|
||||
getFloat64(offset: number): number;
|
||||
|
||||
setBits(offset: number, value: number, bits: number);
|
||||
|
||||
setInt8(offset: number);
|
||||
|
||||
setInt16(offset: number);
|
||||
|
||||
setInt32(offset: number);
|
||||
|
||||
setUint8(offset: number);
|
||||
|
||||
setUint16(offset: number);
|
||||
|
||||
setUint32(offset: number);
|
||||
|
||||
setFloat32(offset: number, value: number);
|
||||
|
||||
setFloat64(offset: number, value: number);
|
||||
}
|
||||
|
||||
export class BitStream {
|
||||
constructor(source: ArrayBuffer | Buffer | BitView, byteOffset?: number, byteLength?: number)
|
||||
|
||||
readonly length: number;
|
||||
readonly bitsLeft: number;
|
||||
readonly buffer: Buffer;
|
||||
readonly view: BitView;
|
||||
byteIndex: number;
|
||||
index: number;
|
||||
bigEndian: boolean;
|
||||
|
||||
readBits(bits: number, signed?: boolean): number;
|
||||
|
||||
writeBits(value: number, bits: number);
|
||||
|
||||
readBoolean(): boolean;
|
||||
|
||||
readInt8(): number;
|
||||
|
||||
readUint8(): number;
|
||||
|
||||
readInt16(): number;
|
||||
|
||||
readUint16(): number;
|
||||
|
||||
readInt32(): number;
|
||||
|
||||
readUint32(): number;
|
||||
|
||||
readFloat32(): number;
|
||||
|
||||
readFloat64(): number;
|
||||
|
||||
writeBoolean(value: boolean);
|
||||
|
||||
writeInt8(value: number);
|
||||
|
||||
writeUint8(value: number);
|
||||
|
||||
writeInt16(value: number);
|
||||
|
||||
writeUint16(value: number);
|
||||
|
||||
writeInt32(value: number);
|
||||
|
||||
writeUint32(value: number);
|
||||
|
||||
writeFloat32(value: number);
|
||||
|
||||
writeFloat64(value: number);
|
||||
|
||||
readASCIIString(length?: number): string;
|
||||
|
||||
readUTF8String(length?: number): string;
|
||||
|
||||
writeASCIIString(data: string, length?: number);
|
||||
|
||||
writeUTF8String(data: string, length?: number);
|
||||
|
||||
readBitStream(length: number): BitStream;
|
||||
|
||||
readArrayBuffer(byteLength: number): Uint8Array;
|
||||
|
||||
writeBitStream(stream: BitStream, length?: number);
|
||||
|
||||
writeArrayBuffer(buffer: BitStream, length?: number);
|
||||
}
|
||||
}
|
502
node_modules/lv_font_conv/node_modules/bit-buffer/bit-buffer.js
generated
vendored
Normal file
502
node_modules/lv_font_conv/node_modules/bit-buffer/bit-buffer.js
generated
vendored
Normal file
@ -0,0 +1,502 @@
|
||||
(function (root) {
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
* BitView
|
||||
*
|
||||
* BitView provides a similar interface to the standard
|
||||
* DataView, but with support for bit-level reads / writes.
|
||||
*
|
||||
**********************************************************/
|
||||
var BitView = function (source, byteOffset, byteLength) {
|
||||
var isBuffer = source instanceof ArrayBuffer ||
|
||||
(typeof Buffer !== 'undefined' && source instanceof Buffer);
|
||||
|
||||
if (!isBuffer) {
|
||||
throw new Error('Must specify a valid ArrayBuffer or Buffer.');
|
||||
}
|
||||
|
||||
byteOffset = byteOffset || 0;
|
||||
byteLength = byteLength || source.byteLength /* ArrayBuffer */ || source.length /* Buffer */;
|
||||
|
||||
this._view = new Uint8Array(source.buffer || source, byteOffset, byteLength);
|
||||
|
||||
this.bigEndian = false;
|
||||
};
|
||||
|
||||
// Used to massage fp values so we can operate on them
|
||||
// at the bit level.
|
||||
BitView._scratch = new DataView(new ArrayBuffer(8));
|
||||
|
||||
Object.defineProperty(BitView.prototype, 'buffer', {
|
||||
get: function () { return typeof Buffer !== 'undefined' ? Buffer.from(this._view.buffer) : this._view.buffer; },
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
|
||||
Object.defineProperty(BitView.prototype, 'byteLength', {
|
||||
get: function () { return this._view.length; },
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
|
||||
BitView.prototype._setBit = function (offset, on) {
|
||||
if (on) {
|
||||
this._view[offset >> 3] |= 1 << (offset & 7);
|
||||
} else {
|
||||
this._view[offset >> 3] &= ~(1 << (offset & 7));
|
||||
}
|
||||
};
|
||||
|
||||
BitView.prototype.getBits = function (offset, bits, signed) {
|
||||
var available = (this._view.length * 8 - offset);
|
||||
|
||||
if (bits > available) {
|
||||
throw new Error('Cannot get ' + bits + ' bit(s) from offset ' + offset + ', ' + available + ' available');
|
||||
}
|
||||
|
||||
var value = 0;
|
||||
for (var i = 0; i < bits;) {
|
||||
var remaining = bits - i;
|
||||
var bitOffset = offset & 7;
|
||||
var currentByte = this._view[offset >> 3];
|
||||
|
||||
// the max number of bits we can read from the current byte
|
||||
var read = Math.min(remaining, 8 - bitOffset);
|
||||
|
||||
var mask, readBits;
|
||||
if (this.bigEndian) {
|
||||
// create a mask with the correct bit width
|
||||
mask = ~(0xFF << read);
|
||||
// shift the bits we want to the start of the byte and mask of the rest
|
||||
readBits = (currentByte >> (8 - read - bitOffset)) & mask;
|
||||
|
||||
value <<= read;
|
||||
value |= readBits;
|
||||
} else {
|
||||
// create a mask with the correct bit width
|
||||
mask = ~(0xFF << read);
|
||||
// shift the bits we want to the start of the byte and mask off the rest
|
||||
readBits = (currentByte >> bitOffset) & mask;
|
||||
|
||||
value |= readBits << i;
|
||||
}
|
||||
|
||||
offset += read;
|
||||
i += read;
|
||||
}
|
||||
|
||||
if (signed) {
|
||||
// If we're not working with a full 32 bits, check the
|
||||
// imaginary MSB for this bit count and convert to a
|
||||
// valid 32-bit signed value if set.
|
||||
if (bits !== 32 && value & (1 << (bits - 1))) {
|
||||
value |= -1 ^ ((1 << bits) - 1);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
return value >>> 0;
|
||||
};
|
||||
|
||||
BitView.prototype.setBits = function (offset, value, bits) {
|
||||
var available = (this._view.length * 8 - offset);
|
||||
|
||||
if (bits > available) {
|
||||
throw new Error('Cannot set ' + bits + ' bit(s) from offset ' + offset + ', ' + available + ' available');
|
||||
}
|
||||
|
||||
for (var i = 0; i < bits;) {
|
||||
var remaining = bits - i;
|
||||
var bitOffset = offset & 7;
|
||||
var byteOffset = offset >> 3;
|
||||
var wrote = Math.min(remaining, 8 - bitOffset);
|
||||
|
||||
var mask, writeBits, destMask;
|
||||
if (this.bigEndian) {
|
||||
// create a mask with the correct bit width
|
||||
mask = ~(~0 << wrote);
|
||||
// shift the bits we want to the start of the byte and mask of the rest
|
||||
writeBits = (value >> (bits - i - wrote)) & mask;
|
||||
|
||||
var destShift = 8 - bitOffset - wrote;
|
||||
// destination mask to zero all the bits we're changing first
|
||||
destMask = ~(mask << destShift);
|
||||
|
||||
this._view[byteOffset] =
|
||||
(this._view[byteOffset] & destMask)
|
||||
| (writeBits << destShift);
|
||||
|
||||
} else {
|
||||
// create a mask with the correct bit width
|
||||
mask = ~(0xFF << wrote);
|
||||
// shift the bits we want to the start of the byte and mask of the rest
|
||||
writeBits = value & mask;
|
||||
value >>= wrote;
|
||||
|
||||
// destination mask to zero all the bits we're changing first
|
||||
destMask = ~(mask << bitOffset);
|
||||
|
||||
this._view[byteOffset] =
|
||||
(this._view[byteOffset] & destMask)
|
||||
| (writeBits << bitOffset);
|
||||
}
|
||||
|
||||
offset += wrote;
|
||||
i += wrote;
|
||||
}
|
||||
};
|
||||
|
||||
BitView.prototype.getBoolean = function (offset) {
|
||||
return this.getBits(offset, 1, false) !== 0;
|
||||
};
|
||||
BitView.prototype.getInt8 = function (offset) {
|
||||
return this.getBits(offset, 8, true);
|
||||
};
|
||||
BitView.prototype.getUint8 = function (offset) {
|
||||
return this.getBits(offset, 8, false);
|
||||
};
|
||||
BitView.prototype.getInt16 = function (offset) {
|
||||
return this.getBits(offset, 16, true);
|
||||
};
|
||||
BitView.prototype.getUint16 = function (offset) {
|
||||
return this.getBits(offset, 16, false);
|
||||
};
|
||||
BitView.prototype.getInt32 = function (offset) {
|
||||
return this.getBits(offset, 32, true);
|
||||
};
|
||||
BitView.prototype.getUint32 = function (offset) {
|
||||
return this.getBits(offset, 32, false);
|
||||
};
|
||||
BitView.prototype.getFloat32 = function (offset) {
|
||||
BitView._scratch.setUint32(0, this.getUint32(offset));
|
||||
return BitView._scratch.getFloat32(0);
|
||||
};
|
||||
BitView.prototype.getFloat64 = function (offset) {
|
||||
BitView._scratch.setUint32(0, this.getUint32(offset));
|
||||
// DataView offset is in bytes.
|
||||
BitView._scratch.setUint32(4, this.getUint32(offset+32));
|
||||
return BitView._scratch.getFloat64(0);
|
||||
};
|
||||
|
||||
BitView.prototype.setBoolean = function (offset, value) {
|
||||
this.setBits(offset, value ? 1 : 0, 1);
|
||||
};
|
||||
BitView.prototype.setInt8 =
|
||||
BitView.prototype.setUint8 = function (offset, value) {
|
||||
this.setBits(offset, value, 8);
|
||||
};
|
||||
BitView.prototype.setInt16 =
|
||||
BitView.prototype.setUint16 = function (offset, value) {
|
||||
this.setBits(offset, value, 16);
|
||||
};
|
||||
BitView.prototype.setInt32 =
|
||||
BitView.prototype.setUint32 = function (offset, value) {
|
||||
this.setBits(offset, value, 32);
|
||||
};
|
||||
BitView.prototype.setFloat32 = function (offset, value) {
|
||||
BitView._scratch.setFloat32(0, value);
|
||||
this.setBits(offset, BitView._scratch.getUint32(0), 32);
|
||||
};
|
||||
BitView.prototype.setFloat64 = function (offset, value) {
|
||||
BitView._scratch.setFloat64(0, value);
|
||||
this.setBits(offset, BitView._scratch.getUint32(0), 32);
|
||||
this.setBits(offset+32, BitView._scratch.getUint32(4), 32);
|
||||
};
|
||||
BitView.prototype.getArrayBuffer = function (offset, byteLength) {
|
||||
var buffer = new Uint8Array(byteLength);
|
||||
for (var i = 0; i < byteLength; i++) {
|
||||
buffer[i] = this.getUint8(offset + (i * 8));
|
||||
}
|
||||
return buffer;
|
||||
};
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
* BitStream
|
||||
*
|
||||
* Small wrapper for a BitView to maintain your position,
|
||||
* as well as to handle reading / writing of string data
|
||||
* to the underlying buffer.
|
||||
*
|
||||
**********************************************************/
|
||||
var reader = function (name, size) {
|
||||
return function () {
|
||||
if (this._index + size > this._length) {
|
||||
throw new Error('Trying to read past the end of the stream');
|
||||
}
|
||||
var val = this._view[name](this._index);
|
||||
this._index += size;
|
||||
return val;
|
||||
};
|
||||
};
|
||||
|
||||
var writer = function (name, size) {
|
||||
return function (value) {
|
||||
this._view[name](this._index, value);
|
||||
this._index += size;
|
||||
};
|
||||
};
|
||||
|
||||
function readASCIIString(stream, bytes) {
|
||||
return readString(stream, bytes, false);
|
||||
}
|
||||
|
||||
function readUTF8String(stream, bytes) {
|
||||
return readString(stream, bytes, true);
|
||||
}
|
||||
|
||||
function readString(stream, bytes, utf8) {
|
||||
if (bytes === 0) {
|
||||
return '';
|
||||
}
|
||||
var i = 0;
|
||||
var chars = [];
|
||||
var append = true;
|
||||
var fixedLength = !!bytes;
|
||||
if (!bytes) {
|
||||
bytes = Math.floor((stream._length - stream._index) / 8);
|
||||
}
|
||||
|
||||
// Read while we still have space available, or until we've
|
||||
// hit the fixed byte length passed in.
|
||||
while (i < bytes) {
|
||||
var c = stream.readUint8();
|
||||
|
||||
// Stop appending chars once we hit 0x00
|
||||
if (c === 0x00) {
|
||||
append = false;
|
||||
|
||||
// If we don't have a fixed length to read, break out now.
|
||||
if (!fixedLength) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (append) {
|
||||
chars.push(c);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
var string = String.fromCharCode.apply(null, chars);
|
||||
if (utf8) {
|
||||
try {
|
||||
return decodeURIComponent(escape(string)); // https://stackoverflow.com/a/17192845
|
||||
} catch (e) {
|
||||
return string;
|
||||
}
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
function writeASCIIString(stream, string, bytes) {
|
||||
var length = bytes || string.length + 1; // + 1 for NULL
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
stream.writeUint8(i < string.length ? string.charCodeAt(i) : 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
function writeUTF8String(stream, string, bytes) {
|
||||
var byteArray = stringToByteArray(string);
|
||||
|
||||
var length = bytes || byteArray.length + 1; // + 1 for NULL
|
||||
for (var i = 0; i < length; i++) {
|
||||
stream.writeUint8(i < byteArray.length ? byteArray[i] : 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
function stringToByteArray(str) { // https://gist.github.com/volodymyr-mykhailyk/2923227
|
||||
var b = [], i, unicode;
|
||||
for (i = 0; i < str.length; i++) {
|
||||
unicode = str.charCodeAt(i);
|
||||
// 0x00000000 - 0x0000007f -> 0xxxxxxx
|
||||
if (unicode <= 0x7f) {
|
||||
b.push(unicode);
|
||||
// 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
|
||||
} else if (unicode <= 0x7ff) {
|
||||
b.push((unicode >> 6) | 0xc0);
|
||||
b.push((unicode & 0x3F) | 0x80);
|
||||
// 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
|
||||
} else if (unicode <= 0xffff) {
|
||||
b.push((unicode >> 12) | 0xe0);
|
||||
b.push(((unicode >> 6) & 0x3f) | 0x80);
|
||||
b.push((unicode & 0x3f) | 0x80);
|
||||
// 0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
} else {
|
||||
b.push((unicode >> 18) | 0xf0);
|
||||
b.push(((unicode >> 12) & 0x3f) | 0x80);
|
||||
b.push(((unicode >> 6) & 0x3f) | 0x80);
|
||||
b.push((unicode & 0x3f) | 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
var BitStream = function (source, byteOffset, byteLength) {
|
||||
var isBuffer = source instanceof ArrayBuffer ||
|
||||
(typeof Buffer !== 'undefined' && source instanceof Buffer);
|
||||
|
||||
if (!(source instanceof BitView) && !isBuffer) {
|
||||
throw new Error('Must specify a valid BitView, ArrayBuffer or Buffer');
|
||||
}
|
||||
|
||||
if (isBuffer) {
|
||||
this._view = new BitView(source, byteOffset, byteLength);
|
||||
} else {
|
||||
this._view = source;
|
||||
}
|
||||
|
||||
this._index = 0;
|
||||
this._startIndex = 0;
|
||||
this._length = this._view.byteLength * 8;
|
||||
};
|
||||
|
||||
Object.defineProperty(BitStream.prototype, 'index', {
|
||||
get: function () { return this._index - this._startIndex; },
|
||||
set: function (val) { this._index = val + this._startIndex; },
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(BitStream.prototype, 'length', {
|
||||
get: function () { return this._length - this._startIndex; },
|
||||
set: function (val) { this._length = val + this._startIndex; },
|
||||
enumerable : true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(BitStream.prototype, 'bitsLeft', {
|
||||
get: function () { return this._length - this._index; },
|
||||
enumerable : true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(BitStream.prototype, 'byteIndex', {
|
||||
// Ceil the returned value, over compensating for the amount of
|
||||
// bits written to the stream.
|
||||
get: function () { return Math.ceil(this._index / 8); },
|
||||
set: function (val) { this._index = val * 8; },
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(BitStream.prototype, 'buffer', {
|
||||
get: function () { return this._view.buffer; },
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
|
||||
Object.defineProperty(BitStream.prototype, 'view', {
|
||||
get: function () { return this._view; },
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
|
||||
Object.defineProperty(BitStream.prototype, 'bigEndian', {
|
||||
get: function () { return this._view.bigEndian; },
|
||||
set: function (val) { this._view.bigEndian = val; },
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
|
||||
BitStream.prototype.readBits = function (bits, signed) {
|
||||
var val = this._view.getBits(this._index, bits, signed);
|
||||
this._index += bits;
|
||||
return val;
|
||||
};
|
||||
|
||||
BitStream.prototype.writeBits = function (value, bits) {
|
||||
this._view.setBits(this._index, value, bits);
|
||||
this._index += bits;
|
||||
};
|
||||
|
||||
BitStream.prototype.readBoolean = reader('getBoolean', 1);
|
||||
BitStream.prototype.readInt8 = reader('getInt8', 8);
|
||||
BitStream.prototype.readUint8 = reader('getUint8', 8);
|
||||
BitStream.prototype.readInt16 = reader('getInt16', 16);
|
||||
BitStream.prototype.readUint16 = reader('getUint16', 16);
|
||||
BitStream.prototype.readInt32 = reader('getInt32', 32);
|
||||
BitStream.prototype.readUint32 = reader('getUint32', 32);
|
||||
BitStream.prototype.readFloat32 = reader('getFloat32', 32);
|
||||
BitStream.prototype.readFloat64 = reader('getFloat64', 64);
|
||||
|
||||
BitStream.prototype.writeBoolean = writer('setBoolean', 1);
|
||||
BitStream.prototype.writeInt8 = writer('setInt8', 8);
|
||||
BitStream.prototype.writeUint8 = writer('setUint8', 8);
|
||||
BitStream.prototype.writeInt16 = writer('setInt16', 16);
|
||||
BitStream.prototype.writeUint16 = writer('setUint16', 16);
|
||||
BitStream.prototype.writeInt32 = writer('setInt32', 32);
|
||||
BitStream.prototype.writeUint32 = writer('setUint32', 32);
|
||||
BitStream.prototype.writeFloat32 = writer('setFloat32', 32);
|
||||
BitStream.prototype.writeFloat64 = writer('setFloat64', 64);
|
||||
|
||||
BitStream.prototype.readASCIIString = function (bytes) {
|
||||
return readASCIIString(this, bytes);
|
||||
};
|
||||
|
||||
BitStream.prototype.readUTF8String = function (bytes) {
|
||||
return readUTF8String(this, bytes);
|
||||
};
|
||||
|
||||
BitStream.prototype.writeASCIIString = function (string, bytes) {
|
||||
writeASCIIString(this, string, bytes);
|
||||
};
|
||||
|
||||
BitStream.prototype.writeUTF8String = function (string, bytes) {
|
||||
writeUTF8String(this, string, bytes);
|
||||
};
|
||||
BitStream.prototype.readBitStream = function(bitLength) {
|
||||
var slice = new BitStream(this._view);
|
||||
slice._startIndex = this._index;
|
||||
slice._index = this._index;
|
||||
slice.length = bitLength;
|
||||
this._index += bitLength;
|
||||
return slice;
|
||||
};
|
||||
|
||||
BitStream.prototype.writeBitStream = function(stream, length) {
|
||||
if (!length) {
|
||||
length = stream.bitsLeft;
|
||||
}
|
||||
|
||||
var bitsToWrite;
|
||||
while (length > 0) {
|
||||
bitsToWrite = Math.min(length, 32);
|
||||
this.writeBits(stream.readBits(bitsToWrite), bitsToWrite);
|
||||
length -= bitsToWrite;
|
||||
}
|
||||
};
|
||||
|
||||
BitStream.prototype.readArrayBuffer = function(byteLength) {
|
||||
var buffer = this._view.getArrayBuffer(this._index, byteLength);
|
||||
this._index += (byteLength * 8);
|
||||
return buffer;
|
||||
};
|
||||
|
||||
BitStream.prototype.writeArrayBuffer = function(buffer, byteLength) {
|
||||
this.writeBitStream(new BitStream(buffer), byteLength * 8);
|
||||
};
|
||||
|
||||
// AMD / RequireJS
|
||||
if (typeof define !== 'undefined' && define.amd) {
|
||||
define(function () {
|
||||
return {
|
||||
BitView: BitView,
|
||||
BitStream: BitStream
|
||||
};
|
||||
});
|
||||
}
|
||||
// Node.js
|
||||
else if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = {
|
||||
BitView: BitView,
|
||||
BitStream: BitStream
|
||||
};
|
||||
}
|
||||
|
||||
}(this));
|
71
node_modules/lv_font_conv/node_modules/bit-buffer/package.json
generated
vendored
Normal file
71
node_modules/lv_font_conv/node_modules/bit-buffer/package.json
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"bit-buffer@0.2.5",
|
||||
"/home/vitaly/Dropbox/Coding/lv_font_conv"
|
||||
]
|
||||
],
|
||||
"_from": "bit-buffer@0.2.5",
|
||||
"_id": "bit-buffer@0.2.5",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-x1yGnmXvFg6e3DiyRztElbcn1bsCTFSoM/ncAzY62uE0JdTl5xlKJd0ooqLYoPbhdsnpehSIQrdIvclcZJYwiA==",
|
||||
"_location": "/bit-buffer",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "bit-buffer@0.2.5",
|
||||
"name": "bit-buffer",
|
||||
"escapedName": "bit-buffer",
|
||||
"rawSpec": "0.2.5",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "0.2.5"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/bit-buffer/-/bit-buffer-0.2.5.tgz",
|
||||
"_spec": "0.2.5",
|
||||
"_where": "/home/vitaly/Dropbox/Coding/lv_font_conv",
|
||||
"author": {
|
||||
"name": "Anthony Pesch"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/inolen/bit-buffer/issues"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Robin Appelman"
|
||||
}
|
||||
],
|
||||
"description": "Bit-level reads and writes for ArrayBuffers",
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.22",
|
||||
"jshint": "^2.12.0",
|
||||
"mocha": "^8.2.1"
|
||||
},
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"gitHead": "cd4417237bed1f22dd5adfd8a6b961ea7234d9c9",
|
||||
"homepage": "https://github.com/inolen/bit-buffer#readme",
|
||||
"keywords": [
|
||||
"dataview",
|
||||
"arraybuffer",
|
||||
"bit",
|
||||
"bits"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "bit-buffer.js",
|
||||
"name": "bit-buffer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/inolen/bit-buffer.git"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "jshint bit-buffer.js",
|
||||
"test": "mocha --ui tdd"
|
||||
},
|
||||
"types": "./bit-buffer.d.ts",
|
||||
"version": "0.2.5"
|
||||
}
|
628
node_modules/lv_font_conv/node_modules/bit-buffer/test.js
generated
vendored
Normal file
628
node_modules/lv_font_conv/node_modules/bit-buffer/test.js
generated
vendored
Normal file
@ -0,0 +1,628 @@
|
||||
var assert = require('assert'),
|
||||
BitView = require('./bit-buffer').BitView,
|
||||
BitStream = require('./bit-buffer').BitStream;
|
||||
|
||||
suite('BitBuffer', function () {
|
||||
var array, bv, bsw, bsr;
|
||||
|
||||
setup(function () {
|
||||
array = new ArrayBuffer(64);
|
||||
bv = new BitView(array);
|
||||
bsw = new BitStream(bv);
|
||||
// Test initializing straight from the array.
|
||||
bsr = new BitStream(array);
|
||||
});
|
||||
|
||||
test('Min / max signed 5 bits', function () {
|
||||
var signed_max = (1 << 4) - 1;
|
||||
|
||||
bsw.writeBits(signed_max, 5);
|
||||
bsw.writeBits(-signed_max - 1, 5);
|
||||
assert(bsr.readBits(5, true) === signed_max);
|
||||
assert(bsr.readBits(5, true) === -signed_max - 1);
|
||||
});
|
||||
|
||||
test('Min / max unsigned 5 bits', function () {
|
||||
var unsigned_max = (1 << 5) - 1;
|
||||
|
||||
bsw.writeBits(unsigned_max, 5);
|
||||
bsw.writeBits(-unsigned_max, 5);
|
||||
assert.equal(bsr.readBits(5), unsigned_max);
|
||||
assert.equal(bsr.readBits(5), 1);
|
||||
});
|
||||
|
||||
test('Min / max int8', function () {
|
||||
var signed_max = 0x7F;
|
||||
|
||||
bsw.writeInt8(signed_max);
|
||||
bsw.writeInt8(-signed_max - 1);
|
||||
assert.equal(bsr.readInt8(), signed_max);
|
||||
assert.equal(bsr.readInt8(), -signed_max - 1);
|
||||
});
|
||||
|
||||
test('Min / max uint8', function () {
|
||||
var unsigned_max = 0xFF;
|
||||
|
||||
bsw.writeUint8(unsigned_max);
|
||||
bsw.writeUint8(-unsigned_max);
|
||||
assert.equal(bsr.readUint8(), unsigned_max);
|
||||
assert.equal(bsr.readUint8(), 1);
|
||||
});
|
||||
|
||||
test('Min / max int16', function () {
|
||||
var signed_max = 0x7FFF;
|
||||
|
||||
bsw.writeInt16(signed_max);
|
||||
bsw.writeInt16(-signed_max - 1);
|
||||
assert.equal(bsr.readInt16(), signed_max);
|
||||
assert.equal(bsr.readInt16(), -signed_max - 1);
|
||||
});
|
||||
|
||||
test('Min / max uint16', function () {
|
||||
var unsigned_max = 0xFFFF;
|
||||
|
||||
bsw.writeUint16(unsigned_max);
|
||||
bsw.writeUint16(-unsigned_max);
|
||||
assert.equal(bsr.readUint16(), unsigned_max);
|
||||
assert.equal(bsr.readUint16(), 1);
|
||||
});
|
||||
|
||||
test('Min / max int32', function () {
|
||||
var signed_max = 0x7FFFFFFF;
|
||||
|
||||
bsw.writeInt32(signed_max);
|
||||
bsw.writeInt32(-signed_max - 1);
|
||||
assert.equal(bsr.readInt32(), signed_max);
|
||||
assert.equal(bsr.readInt32(), -signed_max - 1);
|
||||
});
|
||||
|
||||
test('Min / max uint32', function () {
|
||||
var unsigned_max = 0xFFFFFFFF;
|
||||
|
||||
bsw.writeUint32(unsigned_max);
|
||||
bsw.writeUint32(-unsigned_max);
|
||||
assert.equal(bsr.readUint32(), unsigned_max);
|
||||
assert.equal(bsr.readUint32(), 1);
|
||||
});
|
||||
|
||||
test('Unaligned reads', function () {
|
||||
bsw.writeBits(13, 5);
|
||||
bsw.writeUint8(0xFF);
|
||||
bsw.writeBits(14, 5);
|
||||
|
||||
assert.equal(bsr.readBits(5), 13);
|
||||
assert.equal(bsr.readUint8(), 0xFF);
|
||||
assert.equal(bsr.readBits(5), 14);
|
||||
});
|
||||
|
||||
test('Min / max float32 (normal values)', function () {
|
||||
var scratch = new DataView(new ArrayBuffer(8));
|
||||
|
||||
scratch.setUint32(0, 0x00800000);
|
||||
scratch.setUint32(4, 0x7f7fffff);
|
||||
|
||||
var min = scratch.getFloat32(0);
|
||||
var max = scratch.getFloat32(4);
|
||||
|
||||
bsw.writeFloat32(min);
|
||||
bsw.writeFloat32(max);
|
||||
|
||||
assert.equal(bsr.readFloat32(), min);
|
||||
assert.equal(bsr.readFloat32(), max);
|
||||
});
|
||||
|
||||
test('Min / max float64 (normal values)', function () {
|
||||
var scratch = new DataView(new ArrayBuffer(16));
|
||||
|
||||
scratch.setUint32(0, 0x00100000);
|
||||
scratch.setUint32(4, 0x00000000);
|
||||
scratch.setUint32(8, 0x7fefffff);
|
||||
scratch.setUint32(12, 0xffffffff);
|
||||
|
||||
var min = scratch.getFloat64(0);
|
||||
var max = scratch.getFloat64(8);
|
||||
|
||||
bsw.writeFloat64(min);
|
||||
bsw.writeFloat64(max);
|
||||
|
||||
assert.equal(bsr.readFloat64(), min);
|
||||
assert.equal(bsr.readFloat64(), max);
|
||||
});
|
||||
|
||||
test('Overwrite previous value with 0', function () {
|
||||
bv.setUint8(0, 13);
|
||||
bv.setUint8(0, 0);
|
||||
|
||||
assert.equal(bv.getUint8(0), 0);
|
||||
});
|
||||
|
||||
test('Read / write ASCII string, fixed length', function () {
|
||||
var str = 'foobar';
|
||||
var len = 16;
|
||||
|
||||
bsw.writeASCIIString(str, len);
|
||||
assert.equal(bsw.byteIndex, len);
|
||||
|
||||
assert.equal(bsr.readASCIIString(len), str);
|
||||
assert.equal(bsr.byteIndex, len);
|
||||
});
|
||||
|
||||
test('Read / write ASCII string, unknown length', function () {
|
||||
var str = 'foobar';
|
||||
|
||||
bsw.writeASCIIString(str);
|
||||
assert.equal(bsw.byteIndex, str.length + 1); // +1 for 0x00
|
||||
|
||||
assert.equal(bsr.readASCIIString(), str);
|
||||
assert.equal(bsr.byteIndex, str.length + 1);
|
||||
});
|
||||
|
||||
test('Read ASCII string, 0 length', function () {
|
||||
var str = 'foobar';
|
||||
|
||||
bsw.writeASCIIString(str);
|
||||
assert.equal(bsw.byteIndex, str.length + 1); // +1 for 0x00
|
||||
|
||||
assert.equal(bsr.readASCIIString(0), '');
|
||||
assert.equal(bsr.byteIndex, 0);
|
||||
});
|
||||
|
||||
test('Read overflow', function () {
|
||||
var exception = false;
|
||||
|
||||
try {
|
||||
bsr.readASCIIString(128);
|
||||
} catch (e) {
|
||||
exception = true;
|
||||
}
|
||||
|
||||
assert(exception);
|
||||
});
|
||||
|
||||
test('Write overflow', function () {
|
||||
var exception = false;
|
||||
|
||||
try {
|
||||
bsw.writeASCIIString('foobar', 128);
|
||||
} catch (e) {
|
||||
exception = true;
|
||||
}
|
||||
|
||||
assert(exception);
|
||||
});
|
||||
|
||||
test('Get boolean', function () {
|
||||
bv.setUint8(0, 1);
|
||||
|
||||
assert(bv.getBoolean(0));
|
||||
|
||||
bv.setUint8(0, 0);
|
||||
assert(!bv.getBoolean(0));
|
||||
});
|
||||
|
||||
test('Set boolean', function () {
|
||||
bv.setBoolean(0, true);
|
||||
|
||||
assert(bv.getBoolean(0));
|
||||
|
||||
bv.setBoolean(0, false);
|
||||
|
||||
assert(!bv.getBoolean(0));
|
||||
});
|
||||
|
||||
test('Read boolean', function () {
|
||||
bv.setBits(0, 1, 1);
|
||||
bv.setBits(1, 0, 1);
|
||||
|
||||
assert(bsr.readBoolean());
|
||||
assert(!bsr.readBoolean());
|
||||
});
|
||||
|
||||
test('Write boolean', function () {
|
||||
bsr.writeBoolean(true);
|
||||
assert.equal(bv.getBits(0, 1, false), 1);
|
||||
bsr.writeBoolean(false);
|
||||
assert.equal(bv.getBits(1, 1, false), 0);
|
||||
});
|
||||
|
||||
test('Read / write UTF8 string, only ASCII characters', function () {
|
||||
var str = 'foobar';
|
||||
|
||||
bsw.writeUTF8String(str);
|
||||
assert(bsw.byteIndex === str.length + 1); // +1 for 0x00
|
||||
|
||||
assert.equal(bsr.readUTF8String(), str);
|
||||
assert.equal(bsr.byteIndex, str.length + 1);
|
||||
});
|
||||
|
||||
test('Read / write UTF8 string, non ASCII characters', function () {
|
||||
var str = '日本語';
|
||||
|
||||
var bytes = [
|
||||
0xE6,
|
||||
0x97,
|
||||
0xA5,
|
||||
0xE6,
|
||||
0x9C,
|
||||
0xAC,
|
||||
0xE8,
|
||||
0xAA,
|
||||
0x9E
|
||||
];
|
||||
|
||||
bsw.writeUTF8String(str);
|
||||
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
assert.equal(bytes[i], bv.getBits(i * 8, 8));
|
||||
}
|
||||
|
||||
assert.equal(bsw.byteIndex, bytes.length + 1); // +1 for 0x00
|
||||
|
||||
assert.equal(str, bsr.readUTF8String());
|
||||
assert.equal(bsr.byteIndex, bytes.length + 1);
|
||||
});
|
||||
|
||||
test('readBitStream', function () {
|
||||
bsw.writeBits(0xF0, 8); //0b11110000
|
||||
bsw.writeBits(0xF1, 8); //0b11110001
|
||||
bsr.readBits(3); //offset
|
||||
var slice = bsr.readBitStream(8);
|
||||
assert.equal(slice.readBits(6), 0x3E); //0b111110
|
||||
assert.equal(9, slice._index);
|
||||
assert.equal(6, slice.index);
|
||||
assert.equal(8, slice.length);
|
||||
assert.equal(2, slice.bitsLeft);
|
||||
|
||||
assert.equal(bsr._index, 11);
|
||||
assert.equal((64 * 8) - 11, bsr.bitsLeft);
|
||||
});
|
||||
|
||||
test('readBitStream overflow', function () {
|
||||
bsw.writeBits(0xF0, 8); //0b11110000
|
||||
bsw.writeBits(0xF1, 8); //0b11110001
|
||||
bsr.readBits(3); //offset
|
||||
var slice = bsr.readBitStream(4);
|
||||
|
||||
var exception = false;
|
||||
|
||||
try {
|
||||
slice.readUint8();
|
||||
} catch (e) {
|
||||
exception = true;
|
||||
}
|
||||
|
||||
assert(exception);
|
||||
});
|
||||
|
||||
test('writeBitStream', function () {
|
||||
var buf = new ArrayBuffer(64);
|
||||
var sourceStream = new BitStream(buf);
|
||||
|
||||
sourceStream.writeBits(0xF0, 8); //0b11110000
|
||||
sourceStream.writeBits(0xF1, 8); //0b11110001
|
||||
sourceStream.index = 0;
|
||||
sourceStream.readBits(3); //offset
|
||||
bsr.writeBitStream(sourceStream, 8);
|
||||
assert.equal(8, bsr.index);
|
||||
bsr.index = 0;
|
||||
assert.equal(bsr.readBits(6), 0x3E); //0b00111110
|
||||
assert.equal(11, sourceStream.index);
|
||||
|
||||
var bin = new Uint8Array(buf);
|
||||
assert.equal(bin[0], 0xF0);
|
||||
assert.equal(bin[1], 0xF1);
|
||||
});
|
||||
|
||||
test('writeBitStream Buffer', function () {
|
||||
var buf = Buffer.alloc(64);
|
||||
var sourceStream = new BitStream(buf);
|
||||
|
||||
sourceStream.writeBits(0xF0, 8); //0b11110000
|
||||
sourceStream.writeBits(0xF1, 8); //0b11110001
|
||||
sourceStream.index = 0;
|
||||
sourceStream.readBits(3); //offset
|
||||
bsr.writeBitStream(sourceStream, 8);
|
||||
assert.equal(8, bsr.index);
|
||||
bsr.index = 0;
|
||||
assert.equal(bsr.readBits(6), 0x3E); //0b00111110
|
||||
assert.equal(11, sourceStream.index);
|
||||
|
||||
var bin = new Uint8Array(buf.buffer);
|
||||
assert.equal(bin[0], 0xF0);
|
||||
assert.equal(bin[1], 0xF1);
|
||||
});
|
||||
|
||||
test('writeBitStream long', function () {
|
||||
var sourceStream = new BitStream(new ArrayBuffer(64));
|
||||
|
||||
sourceStream.writeBits(0xF0, 8);
|
||||
sourceStream.writeBits(0xF1, 8);
|
||||
sourceStream.writeBits(0xF1, 8);
|
||||
sourceStream.writeBits(0xF1, 8);
|
||||
sourceStream.writeBits(0xF1, 8);
|
||||
sourceStream.index = 0;
|
||||
sourceStream.readBits(3); //offset
|
||||
bsr.index = 3;
|
||||
bsr.writeBitStream(sourceStream, 35);
|
||||
assert.equal(38, bsr.index);
|
||||
bsr.index = 3;
|
||||
assert.equal(bsr.readBits(35), 1044266558);
|
||||
assert.equal(38, sourceStream.index);
|
||||
});
|
||||
|
||||
test('readArrayBuffer', function () {
|
||||
bsw.writeBits(0xF0, 8); //0b11110000
|
||||
bsw.writeBits(0xF1, 8); //0b11110001
|
||||
bsw.writeBits(0xF0, 8); //0b11110000
|
||||
bsr.readBits(3); //offset
|
||||
|
||||
var buffer = bsr.readArrayBuffer(2);
|
||||
|
||||
assert.equal(0x3E, buffer[0]); //0b00111110
|
||||
assert.equal(0x1E, buffer[1]); //0b00011110
|
||||
|
||||
assert.equal(3 + (2 * 8), bsr._index);
|
||||
});
|
||||
|
||||
test('writeArrayBuffer', function () {
|
||||
var source = new Uint8Array(4);
|
||||
source[0] = 0xF0;
|
||||
source[1] = 0xF1;
|
||||
source[2] = 0xF1;
|
||||
bsr.readBits(3); //offset
|
||||
|
||||
bsr.writeArrayBuffer(source.buffer, 2);
|
||||
assert.equal(19, bsr.index);
|
||||
|
||||
bsr.index = 0;
|
||||
|
||||
assert.equal(bsr.readBits(8), 128);
|
||||
});
|
||||
|
||||
test('Get buffer from view', function () {
|
||||
bv.setBits(0, 0xFFFFFFFF, 32);
|
||||
var buffer = bv.buffer;
|
||||
|
||||
assert.equal(64, buffer.length);
|
||||
assert.equal(0xFFFF, buffer.readUInt16LE(0));
|
||||
});
|
||||
|
||||
test('Get buffer from stream', function () {
|
||||
bsw.writeBits(0xFFFFFFFF, 32);
|
||||
var buffer = bsr.buffer;
|
||||
|
||||
assert.equal(64, buffer.length);
|
||||
assert.equal(0xFFFF, buffer.readUInt16LE(0));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Reading big/little endian', function () {
|
||||
var array, u8, bv, bsw, bsr;
|
||||
|
||||
setup(function () {
|
||||
array = new ArrayBuffer(64);
|
||||
u8 = new Uint8Array(array);
|
||||
u8[0] = 0x01;
|
||||
u8[1] = 0x02;
|
||||
// Test initializing straight from the array.
|
||||
bsr = new BitStream(array);
|
||||
});
|
||||
|
||||
test('4b, little-endian', function () {
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(4));
|
||||
result.push(bsr.readBits(4));
|
||||
result.push(bsr.readBits(4));
|
||||
result.push(bsr.readBits(4));
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [#2] [#1] [#4] [#3]
|
||||
assert.deepEqual(result, [1, 0, 2, 0]);
|
||||
});
|
||||
|
||||
test('8b, little-endian', function () {
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(8));
|
||||
result.push(bsr.readBits(8));
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1] [ #2]
|
||||
assert.deepEqual(result, [1, 2]);
|
||||
});
|
||||
|
||||
test('10b, little-endian', function () {
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(10));
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// ... #1] [ #2][#1...
|
||||
assert.deepEqual(result, [513]);
|
||||
});
|
||||
|
||||
test('16b, little-endian', function () {
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(16));
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1]
|
||||
assert.deepEqual(result, [0x201]);
|
||||
});
|
||||
|
||||
test('24b, little-endian', function () {
|
||||
u8[2] = 0x03;
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(24));
|
||||
|
||||
// 0000 0001 0000 0010 0000 0011 [01 02 03]
|
||||
// [ #1]
|
||||
assert.deepEqual(result, [0x30201]);
|
||||
});
|
||||
|
||||
test('4b, big-endian', function () {
|
||||
bsr.bigEndian = true;
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(4));
|
||||
result.push(bsr.readBits(4));
|
||||
result.push(bsr.readBits(4));
|
||||
result.push(bsr.readBits(4));
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [#1] [#2] [#3] [#4]
|
||||
assert.deepEqual(result, [0, 1, 0, 2]);
|
||||
});
|
||||
|
||||
test('8b, big-endian', function () {
|
||||
bsr.bigEndian = true;
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(8));
|
||||
result.push(bsr.readBits(8));
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1] [ #2]
|
||||
assert.deepEqual(result, [1, 2]);
|
||||
});
|
||||
|
||||
test('10b, big-endian', function () {
|
||||
bsr.bigEndian = true;
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(10));
|
||||
result.push(bsr.readBits(6));
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1][ #2]
|
||||
assert.deepEqual(result, [4, 2]);
|
||||
});
|
||||
|
||||
test('16b, big-endian', function () {
|
||||
bsr.bigEndian = true;
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(16));
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1]
|
||||
assert.deepEqual(result, [0x102]);
|
||||
});
|
||||
|
||||
test('24b, big-endian', function () {
|
||||
u8[2] = 0x03;
|
||||
bsr.bigEndian = true;
|
||||
assert.equal(bsr.index, 0, 'BitStream didn\'t init at offset 0');
|
||||
|
||||
var result = [];
|
||||
result.push(bsr.readBits(24));
|
||||
|
||||
// 0000 0001 0000 0010 0000 0011 [01 02 03]
|
||||
// [ #1]
|
||||
assert.deepEqual(result, [0x10203]);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Writing big/little endian', function () {
|
||||
var array, u8, bv, bsw, bsr;
|
||||
|
||||
setup(function () {
|
||||
array = new ArrayBuffer(2);
|
||||
u8 = new Uint8Array(array);
|
||||
bv = new BitView(array);
|
||||
bsw = new BitStream(bv);
|
||||
});
|
||||
|
||||
test('4b, little-endian', function () {
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [#2] [#1] [#4] [#3]
|
||||
bsw.writeBits(1, 4);
|
||||
bsw.writeBits(0, 4);
|
||||
bsw.writeBits(2, 4);
|
||||
bsw.writeBits(0, 4);
|
||||
|
||||
assert.deepEqual(u8, new Uint8Array([0x01, 0x02]));
|
||||
});
|
||||
|
||||
test('8b, little-endian', function () {
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1] [ #2]
|
||||
bsw.writeBits(1, 8);
|
||||
bsw.writeBits(2, 8);
|
||||
|
||||
assert.deepEqual(u8, new Uint8Array([0x01, 0x02]));
|
||||
});
|
||||
|
||||
test('10b, little-endian', function () {
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// ... #1] [ #2][#1...
|
||||
bsw.writeBits(513, 10);
|
||||
|
||||
assert.deepEqual(u8, new Uint8Array([0x01, 0x02]));
|
||||
});
|
||||
|
||||
test('16b, little-endian', function () {
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1]
|
||||
bsw.writeBits(0x201, 16);
|
||||
|
||||
assert.deepEqual(u8, new Uint8Array([0x01, 0x02]));
|
||||
});
|
||||
|
||||
test('4b, big-endian', function () {
|
||||
bsw.bigEndian = true;
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [#1] [#2] [#3] [#4]
|
||||
bsw.writeBits(0, 4);
|
||||
bsw.writeBits(1, 4);
|
||||
bsw.writeBits(0, 4);
|
||||
bsw.writeBits(2, 4);
|
||||
|
||||
assert.deepEqual(u8, new Uint8Array([0x01, 0x02]));
|
||||
});
|
||||
|
||||
test('8b, big-endian', function () {
|
||||
bsw.bigEndian = true;
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1] [ #2]
|
||||
bsw.writeBits(1, 8);
|
||||
bsw.writeBits(2, 8);
|
||||
|
||||
assert.deepEqual(u8, new Uint8Array([0x01, 0x02]));
|
||||
});
|
||||
|
||||
test('10b, big-endian', function () {
|
||||
bsw.bigEndian = true;
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1][ #2]
|
||||
bsw.writeBits(4, 10);
|
||||
bsw.writeBits(2, 6);
|
||||
|
||||
assert.deepEqual(u8, new Uint8Array([0x01, 0x02]));
|
||||
});
|
||||
|
||||
test('16b, big-endian', function () {
|
||||
bsw.bigEndian = true;
|
||||
|
||||
// 0000 0001 0000 0010 [01 02]
|
||||
// [ #1]
|
||||
bsw.writeBits(0x102, 16);
|
||||
|
||||
assert.deepEqual(u8, new Uint8Array([0x01, 0x02]));
|
||||
});
|
||||
});
|
19
node_modules/lv_font_conv/node_modules/debug/LICENSE
generated
vendored
Normal file
19
node_modules/lv_font_conv/node_modules/debug/LICENSE
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
and associated documentation files (the 'Software'), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
455
node_modules/lv_font_conv/node_modules/debug/README.md
generated
vendored
Normal file
455
node_modules/lv_font_conv/node_modules/debug/README.md
generated
vendored
Normal file
@ -0,0 +1,455 @@
|
||||
# debug
|
||||
[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug) [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master) [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers)
|
||||
[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
|
||||
|
||||
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
|
||||
|
||||
A tiny JavaScript debugging utility modelled after Node.js core's debugging
|
||||
technique. Works in Node.js and web browsers.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install debug
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
|
||||
|
||||
Example [_app.js_](./examples/node/app.js):
|
||||
|
||||
```js
|
||||
var debug = require('debug')('http')
|
||||
, http = require('http')
|
||||
, name = 'My App';
|
||||
|
||||
// fake app
|
||||
|
||||
debug('booting %o', name);
|
||||
|
||||
http.createServer(function(req, res){
|
||||
debug(req.method + ' ' + req.url);
|
||||
res.end('hello\n');
|
||||
}).listen(3000, function(){
|
||||
debug('listening');
|
||||
});
|
||||
|
||||
// fake worker of some kind
|
||||
|
||||
require('./worker');
|
||||
```
|
||||
|
||||
Example [_worker.js_](./examples/node/worker.js):
|
||||
|
||||
```js
|
||||
var a = require('debug')('worker:a')
|
||||
, b = require('debug')('worker:b');
|
||||
|
||||
function work() {
|
||||
a('doing lots of uninteresting work');
|
||||
setTimeout(work, Math.random() * 1000);
|
||||
}
|
||||
|
||||
work();
|
||||
|
||||
function workb() {
|
||||
b('doing some work');
|
||||
setTimeout(workb, Math.random() * 2000);
|
||||
}
|
||||
|
||||
workb();
|
||||
```
|
||||
|
||||
The `DEBUG` environment variable is then used to enable these based on space or
|
||||
comma-delimited names.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
<img width="647" alt="screen shot 2017-08-08 at 12 53 04 pm" src="https://user-images.githubusercontent.com/71256/29091703-a6302cdc-7c38-11e7-8304-7c0b3bc600cd.png">
|
||||
<img width="647" alt="screen shot 2017-08-08 at 12 53 38 pm" src="https://user-images.githubusercontent.com/71256/29091700-a62a6888-7c38-11e7-800b-db911291ca2b.png">
|
||||
<img width="647" alt="screen shot 2017-08-08 at 12 53 25 pm" src="https://user-images.githubusercontent.com/71256/29091701-a62ea114-7c38-11e7-826a-2692bedca740.png">
|
||||
|
||||
#### Windows command prompt notes
|
||||
|
||||
##### CMD
|
||||
|
||||
On Windows the environment variable is set using the `set` command.
|
||||
|
||||
```cmd
|
||||
set DEBUG=*,-not_this
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```cmd
|
||||
set DEBUG=* & node app.js
|
||||
```
|
||||
|
||||
##### PowerShell (VS Code default)
|
||||
|
||||
PowerShell uses different syntax to set environment variables.
|
||||
|
||||
```cmd
|
||||
$env:DEBUG = "*,-not_this"
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```cmd
|
||||
$env:DEBUG='app';node app.js
|
||||
```
|
||||
|
||||
Then, run the program to be debugged as usual.
|
||||
|
||||
npm script example:
|
||||
```js
|
||||
"windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js",
|
||||
```
|
||||
|
||||
## Namespace Colors
|
||||
|
||||
Every debug instance has a color generated for it based on its namespace name.
|
||||
This helps when visually parsing the debug output to identify which debug instance
|
||||
a debug line belongs to.
|
||||
|
||||
#### Node.js
|
||||
|
||||
In Node.js, colors are enabled when stderr is a TTY. You also _should_ install
|
||||
the [`supports-color`](https://npmjs.org/supports-color) module alongside debug,
|
||||
otherwise debug will only use a small handful of basic colors.
|
||||
|
||||
<img width="521" src="https://user-images.githubusercontent.com/71256/29092181-47f6a9e6-7c3a-11e7-9a14-1928d8a711cd.png">
|
||||
|
||||
#### Web Browser
|
||||
|
||||
Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
|
||||
option. These are WebKit web inspectors, Firefox ([since version
|
||||
31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
|
||||
and the Firebug plugin for Firefox (any version).
|
||||
|
||||
<img width="524" src="https://user-images.githubusercontent.com/71256/29092033-b65f9f2e-7c39-11e7-8e32-f6f0d8e865c1.png">
|
||||
|
||||
|
||||
## Millisecond diff
|
||||
|
||||
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
|
||||
|
||||
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
|
||||
|
||||
When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below:
|
||||
|
||||
<img width="647" src="https://user-images.githubusercontent.com/71256/29091956-6bd78372-7c39-11e7-8c55-c948396d6edd.png">
|
||||
|
||||
|
||||
## Conventions
|
||||
|
||||
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output.
|
||||
|
||||
## Wildcards
|
||||
|
||||
The `*` character may be used as a wildcard. Suppose for example your library has
|
||||
debuggers named "connect:bodyParser", "connect:compress", "connect:session",
|
||||
instead of listing all three with
|
||||
`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do
|
||||
`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
|
||||
|
||||
You can also exclude specific debuggers by prefixing them with a "-" character.
|
||||
For example, `DEBUG=*,-connect:*` would include all debuggers except those
|
||||
starting with "connect:".
|
||||
|
||||
## Environment Variables
|
||||
|
||||
When running through Node.js, you can set a few environment variables that will
|
||||
change the behavior of the debug logging:
|
||||
|
||||
| Name | Purpose |
|
||||
|-----------|-------------------------------------------------|
|
||||
| `DEBUG` | Enables/disables specific debugging namespaces. |
|
||||
| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). |
|
||||
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
|
||||
| `DEBUG_DEPTH` | Object inspection depth. |
|
||||
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
|
||||
|
||||
|
||||
__Note:__ The environment variables beginning with `DEBUG_` end up being
|
||||
converted into an Options object that gets used with `%o`/`%O` formatters.
|
||||
See the Node.js documentation for
|
||||
[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
|
||||
for the complete list.
|
||||
|
||||
## Formatters
|
||||
|
||||
Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting.
|
||||
Below are the officially supported formatters:
|
||||
|
||||
| Formatter | Representation |
|
||||
|-----------|----------------|
|
||||
| `%O` | Pretty-print an Object on multiple lines. |
|
||||
| `%o` | Pretty-print an Object all on a single line. |
|
||||
| `%s` | String. |
|
||||
| `%d` | Number (both integer and float). |
|
||||
| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
|
||||
| `%%` | Single percent sign ('%'). This does not consume an argument. |
|
||||
|
||||
|
||||
### Custom formatters
|
||||
|
||||
You can add custom formatters by extending the `debug.formatters` object.
|
||||
For example, if you wanted to add support for rendering a Buffer as hex with
|
||||
`%h`, you could do something like:
|
||||
|
||||
```js
|
||||
const createDebug = require('debug')
|
||||
createDebug.formatters.h = (v) => {
|
||||
return v.toString('hex')
|
||||
}
|
||||
|
||||
// …elsewhere
|
||||
const debug = createDebug('foo')
|
||||
debug('this is hex: %h', new Buffer('hello world'))
|
||||
// foo this is hex: 68656c6c6f20776f726c6421 +0ms
|
||||
```
|
||||
|
||||
|
||||
## Browser Support
|
||||
|
||||
You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
|
||||
or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
|
||||
if you don't want to build it yourself.
|
||||
|
||||
Debug's enable state is currently persisted by `localStorage`.
|
||||
Consider the situation shown below where you have `worker:a` and `worker:b`,
|
||||
and wish to debug both. You can enable this using `localStorage.debug`:
|
||||
|
||||
```js
|
||||
localStorage.debug = 'worker:*'
|
||||
```
|
||||
|
||||
And then refresh the page.
|
||||
|
||||
```js
|
||||
a = debug('worker:a');
|
||||
b = debug('worker:b');
|
||||
|
||||
setInterval(function(){
|
||||
a('doing some work');
|
||||
}, 1000);
|
||||
|
||||
setInterval(function(){
|
||||
b('doing some work');
|
||||
}, 1200);
|
||||
```
|
||||
|
||||
|
||||
## Output streams
|
||||
|
||||
By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
|
||||
|
||||
Example [_stdout.js_](./examples/node/stdout.js):
|
||||
|
||||
```js
|
||||
var debug = require('debug');
|
||||
var error = debug('app:error');
|
||||
|
||||
// by default stderr is used
|
||||
error('goes to stderr!');
|
||||
|
||||
var log = debug('app:log');
|
||||
// set this namespace to log via console.log
|
||||
log.log = console.log.bind(console); // don't forget to bind to console!
|
||||
log('goes to stdout');
|
||||
error('still goes to stderr!');
|
||||
|
||||
// set all output to go via console.info
|
||||
// overrides all per-namespace log settings
|
||||
debug.log = console.info.bind(console);
|
||||
error('now goes to stdout via console.info');
|
||||
log('still goes to stdout, but via console.info now');
|
||||
```
|
||||
|
||||
## Extend
|
||||
You can simply extend debugger
|
||||
```js
|
||||
const log = require('debug')('auth');
|
||||
|
||||
//creates new debug instance with extended namespace
|
||||
const logSign = log.extend('sign');
|
||||
const logLogin = log.extend('login');
|
||||
|
||||
log('hello'); // auth hello
|
||||
logSign('hello'); //auth:sign hello
|
||||
logLogin('hello'); //auth:login hello
|
||||
```
|
||||
|
||||
## Set dynamically
|
||||
|
||||
You can also enable debug dynamically by calling the `enable()` method :
|
||||
|
||||
```js
|
||||
let debug = require('debug');
|
||||
|
||||
console.log(1, debug.enabled('test'));
|
||||
|
||||
debug.enable('test');
|
||||
console.log(2, debug.enabled('test'));
|
||||
|
||||
debug.disable();
|
||||
console.log(3, debug.enabled('test'));
|
||||
|
||||
```
|
||||
|
||||
print :
|
||||
```
|
||||
1 false
|
||||
2 true
|
||||
3 false
|
||||
```
|
||||
|
||||
Usage :
|
||||
`enable(namespaces)`
|
||||
`namespaces` can include modes separated by a colon and wildcards.
|
||||
|
||||
Note that calling `enable()` completely overrides previously set DEBUG variable :
|
||||
|
||||
```
|
||||
$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
|
||||
=> false
|
||||
```
|
||||
|
||||
`disable()`
|
||||
|
||||
Will disable all namespaces. The functions returns the namespaces currently
|
||||
enabled (and skipped). This can be useful if you want to disable debugging
|
||||
temporarily without knowing what was enabled to begin with.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
let debug = require('debug');
|
||||
debug.enable('foo:*,-foo:bar');
|
||||
let namespaces = debug.disable();
|
||||
debug.enable(namespaces);
|
||||
```
|
||||
|
||||
Note: There is no guarantee that the string will be identical to the initial
|
||||
enable string, but semantically they will be identical.
|
||||
|
||||
## Checking whether a debug target is enabled
|
||||
|
||||
After you've created a debug instance, you can determine whether or not it is
|
||||
enabled by checking the `enabled` property:
|
||||
|
||||
```javascript
|
||||
const debug = require('debug')('http');
|
||||
|
||||
if (debug.enabled) {
|
||||
// do stuff...
|
||||
}
|
||||
```
|
||||
|
||||
You can also manually toggle this property to force the debug instance to be
|
||||
enabled or disabled.
|
||||
|
||||
|
||||
## Authors
|
||||
|
||||
- TJ Holowaychuk
|
||||
- Nathan Rajlich
|
||||
- Andrew Rhyne
|
||||
|
||||
## Backers
|
||||
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
|
||||
|
||||
<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
|
||||
|
||||
|
||||
## Sponsors
|
||||
|
||||
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
111
node_modules/lv_font_conv/node_modules/debug/package.json
generated
vendored
Normal file
111
node_modules/lv_font_conv/node_modules/debug/package.json
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"debug@4.3.1",
|
||||
"/home/vitaly/Dropbox/Coding/lv_font_conv"
|
||||
]
|
||||
],
|
||||
"_from": "debug@4.3.1",
|
||||
"_id": "debug@4.3.1",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||
"_location": "/debug",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "debug@4.3.1",
|
||||
"name": "debug",
|
||||
"escapedName": "debug",
|
||||
"rawSpec": "4.3.1",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "4.3.1"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/",
|
||||
"/@babel/core",
|
||||
"/@babel/helper-define-polyfill-provider",
|
||||
"/@babel/traverse",
|
||||
"/@eslint/eslintrc",
|
||||
"/eslint",
|
||||
"/istanbul-lib-source-maps",
|
||||
"/mocha"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
"_spec": "4.3.1",
|
||||
"_where": "/home/vitaly/Dropbox/Coding/lv_font_conv",
|
||||
"author": {
|
||||
"name": "TJ Holowaychuk",
|
||||
"email": "tj@vision-media.ca"
|
||||
},
|
||||
"browser": "./src/browser.js",
|
||||
"bugs": {
|
||||
"url": "https://github.com/visionmedia/debug/issues"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Nathan Rajlich",
|
||||
"email": "nathan@tootallnate.net",
|
||||
"url": "http://n8.io"
|
||||
},
|
||||
{
|
||||
"name": "Andrew Rhyne",
|
||||
"email": "rhyneandrew@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Josh Junon",
|
||||
"email": "josh@junon.me"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"description": "small debugging utility",
|
||||
"devDependencies": {
|
||||
"brfs": "^2.0.1",
|
||||
"browserify": "^16.2.3",
|
||||
"coveralls": "^3.0.2",
|
||||
"istanbul": "^0.4.5",
|
||||
"karma": "^3.1.4",
|
||||
"karma-browserify": "^6.0.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"mocha": "^5.2.0",
|
||||
"mocha-lcov-reporter": "^1.2.0",
|
||||
"xo": "^0.23.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
],
|
||||
"homepage": "https://github.com/visionmedia/debug#readme",
|
||||
"keywords": [
|
||||
"debug",
|
||||
"log",
|
||||
"debugger"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "./src/index.js",
|
||||
"name": "debug",
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/visionmedia/debug.git"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "xo",
|
||||
"test": "npm run test:node && npm run test:browser && npm run lint",
|
||||
"test:browser": "karma start --single-run",
|
||||
"test:coverage": "cat ./coverage/lcov.info | coveralls",
|
||||
"test:node": "istanbul cover _mocha -- test.js"
|
||||
},
|
||||
"version": "4.3.1"
|
||||
}
|
269
node_modules/lv_font_conv/node_modules/debug/src/browser.js
generated
vendored
Normal file
269
node_modules/lv_font_conv/node_modules/debug/src/browser.js
generated
vendored
Normal file
@ -0,0 +1,269 @@
|
||||
/* eslint-env browser */
|
||||
|
||||
/**
|
||||
* This is the web browser implementation of `debug()`.
|
||||
*/
|
||||
|
||||
exports.formatArgs = formatArgs;
|
||||
exports.save = save;
|
||||
exports.load = load;
|
||||
exports.useColors = useColors;
|
||||
exports.storage = localstorage();
|
||||
exports.destroy = (() => {
|
||||
let warned = false;
|
||||
|
||||
return () => {
|
||||
if (!warned) {
|
||||
warned = true;
|
||||
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
exports.colors = [
|
||||
'#0000CC',
|
||||
'#0000FF',
|
||||
'#0033CC',
|
||||
'#0033FF',
|
||||
'#0066CC',
|
||||
'#0066FF',
|
||||
'#0099CC',
|
||||
'#0099FF',
|
||||
'#00CC00',
|
||||
'#00CC33',
|
||||
'#00CC66',
|
||||
'#00CC99',
|
||||
'#00CCCC',
|
||||
'#00CCFF',
|
||||
'#3300CC',
|
||||
'#3300FF',
|
||||
'#3333CC',
|
||||
'#3333FF',
|
||||
'#3366CC',
|
||||
'#3366FF',
|
||||
'#3399CC',
|
||||
'#3399FF',
|
||||
'#33CC00',
|
||||
'#33CC33',
|
||||
'#33CC66',
|
||||
'#33CC99',
|
||||
'#33CCCC',
|
||||
'#33CCFF',
|
||||
'#6600CC',
|
||||
'#6600FF',
|
||||
'#6633CC',
|
||||
'#6633FF',
|
||||
'#66CC00',
|
||||
'#66CC33',
|
||||
'#9900CC',
|
||||
'#9900FF',
|
||||
'#9933CC',
|
||||
'#9933FF',
|
||||
'#99CC00',
|
||||
'#99CC33',
|
||||
'#CC0000',
|
||||
'#CC0033',
|
||||
'#CC0066',
|
||||
'#CC0099',
|
||||
'#CC00CC',
|
||||
'#CC00FF',
|
||||
'#CC3300',
|
||||
'#CC3333',
|
||||
'#CC3366',
|
||||
'#CC3399',
|
||||
'#CC33CC',
|
||||
'#CC33FF',
|
||||
'#CC6600',
|
||||
'#CC6633',
|
||||
'#CC9900',
|
||||
'#CC9933',
|
||||
'#CCCC00',
|
||||
'#CCCC33',
|
||||
'#FF0000',
|
||||
'#FF0033',
|
||||
'#FF0066',
|
||||
'#FF0099',
|
||||
'#FF00CC',
|
||||
'#FF00FF',
|
||||
'#FF3300',
|
||||
'#FF3333',
|
||||
'#FF3366',
|
||||
'#FF3399',
|
||||
'#FF33CC',
|
||||
'#FF33FF',
|
||||
'#FF6600',
|
||||
'#FF6633',
|
||||
'#FF9900',
|
||||
'#FF9933',
|
||||
'#FFCC00',
|
||||
'#FFCC33'
|
||||
];
|
||||
|
||||
/**
|
||||
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
|
||||
* and the Firebug extension (any Firefox version) are known
|
||||
* to support "%c" CSS customizations.
|
||||
*
|
||||
* TODO: add a `localStorage` variable to explicitly enable/disable colors
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
function useColors() {
|
||||
// NB: In an Electron preload script, document will be defined but not fully
|
||||
// initialized. Since we know we're in Chrome, we'll just detect this case
|
||||
// explicitly
|
||||
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Internet Explorer and Edge do not support colors.
|
||||
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is webkit? http://stackoverflow.com/a/16459606/376773
|
||||
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||||
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
|
||||
// Is firebug? http://stackoverflow.com/a/398120/376773
|
||||
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
|
||||
// Is firefox >= v31?
|
||||
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
||||
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
||||
// Double check webkit in userAgent just in case we are in a worker
|
||||
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorize log arguments if enabled.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function formatArgs(args) {
|
||||
args[0] = (this.useColors ? '%c' : '') +
|
||||
this.namespace +
|
||||
(this.useColors ? ' %c' : ' ') +
|
||||
args[0] +
|
||||
(this.useColors ? '%c ' : ' ') +
|
||||
'+' + module.exports.humanize(this.diff);
|
||||
|
||||
if (!this.useColors) {
|
||||
return;
|
||||
}
|
||||
|
||||
const c = 'color: ' + this.color;
|
||||
args.splice(1, 0, c, 'color: inherit');
|
||||
|
||||
// The final "%c" is somewhat tricky, because there could be other
|
||||
// arguments passed either before or after the %c, so we need to
|
||||
// figure out the correct index to insert the CSS into
|
||||
let index = 0;
|
||||
let lastC = 0;
|
||||
args[0].replace(/%[a-zA-Z%]/g, match => {
|
||||
if (match === '%%') {
|
||||
return;
|
||||
}
|
||||
index++;
|
||||
if (match === '%c') {
|
||||
// We only are interested in the *last* %c
|
||||
// (the user may have provided their own)
|
||||
lastC = index;
|
||||
}
|
||||
});
|
||||
|
||||
args.splice(lastC, 0, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes `console.debug()` when available.
|
||||
* No-op when `console.debug` is not a "function".
|
||||
* If `console.debug` is not available, falls back
|
||||
* to `console.log`.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
exports.log = console.debug || console.log || (() => {});
|
||||
|
||||
/**
|
||||
* Save `namespaces`.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api private
|
||||
*/
|
||||
function save(namespaces) {
|
||||
try {
|
||||
if (namespaces) {
|
||||
exports.storage.setItem('debug', namespaces);
|
||||
} else {
|
||||
exports.storage.removeItem('debug');
|
||||
}
|
||||
} catch (error) {
|
||||
// Swallow
|
||||
// XXX (@Qix-) should we be logging these?
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load `namespaces`.
|
||||
*
|
||||
* @return {String} returns the previously persisted debug modes
|
||||
* @api private
|
||||
*/
|
||||
function load() {
|
||||
let r;
|
||||
try {
|
||||
r = exports.storage.getItem('debug');
|
||||
} catch (error) {
|
||||
// Swallow
|
||||
// XXX (@Qix-) should we be logging these?
|
||||
}
|
||||
|
||||
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
||||
if (!r && typeof process !== 'undefined' && 'env' in process) {
|
||||
r = process.env.DEBUG;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Localstorage attempts to return the localstorage.
|
||||
*
|
||||
* This is necessary because safari throws
|
||||
* when a user disables cookies/localstorage
|
||||
* and you attempt to access it.
|
||||
*
|
||||
* @return {LocalStorage}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function localstorage() {
|
||||
try {
|
||||
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
|
||||
// The Browser also has localStorage in the global context.
|
||||
return localStorage;
|
||||
} catch (error) {
|
||||
// Swallow
|
||||
// XXX (@Qix-) should we be logging these?
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = require('./common')(exports);
|
||||
|
||||
const {formatters} = module.exports;
|
||||
|
||||
/**
|
||||
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
||||
*/
|
||||
|
||||
formatters.j = function (v) {
|
||||
try {
|
||||
return JSON.stringify(v);
|
||||
} catch (error) {
|
||||
return '[UnexpectedJSONParseError]: ' + error.message;
|
||||
}
|
||||
};
|
261
node_modules/lv_font_conv/node_modules/debug/src/common.js
generated
vendored
Normal file
261
node_modules/lv_font_conv/node_modules/debug/src/common.js
generated
vendored
Normal file
@ -0,0 +1,261 @@
|
||||
|
||||
/**
|
||||
* This is the common logic for both the Node.js and web browser
|
||||
* implementations of `debug()`.
|
||||
*/
|
||||
|
||||
function setup(env) {
|
||||
createDebug.debug = createDebug;
|
||||
createDebug.default = createDebug;
|
||||
createDebug.coerce = coerce;
|
||||
createDebug.disable = disable;
|
||||
createDebug.enable = enable;
|
||||
createDebug.enabled = enabled;
|
||||
createDebug.humanize = require('ms');
|
||||
createDebug.destroy = destroy;
|
||||
|
||||
Object.keys(env).forEach(key => {
|
||||
createDebug[key] = env[key];
|
||||
});
|
||||
|
||||
/**
|
||||
* The currently active debug mode names, and names to skip.
|
||||
*/
|
||||
|
||||
createDebug.names = [];
|
||||
createDebug.skips = [];
|
||||
|
||||
/**
|
||||
* Map of special "%n" handling functions, for the debug "format" argument.
|
||||
*
|
||||
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
|
||||
*/
|
||||
createDebug.formatters = {};
|
||||
|
||||
/**
|
||||
* Selects a color for a debug namespace
|
||||
* @param {String} namespace The namespace string for the for the debug instance to be colored
|
||||
* @return {Number|String} An ANSI color code for the given namespace
|
||||
* @api private
|
||||
*/
|
||||
function selectColor(namespace) {
|
||||
let hash = 0;
|
||||
|
||||
for (let i = 0; i < namespace.length; i++) {
|
||||
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
||||
hash |= 0; // Convert to 32bit integer
|
||||
}
|
||||
|
||||
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
||||
}
|
||||
createDebug.selectColor = selectColor;
|
||||
|
||||
/**
|
||||
* Create a debugger with the given `namespace`.
|
||||
*
|
||||
* @param {String} namespace
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
function createDebug(namespace) {
|
||||
let prevTime;
|
||||
let enableOverride = null;
|
||||
|
||||
function debug(...args) {
|
||||
// Disabled?
|
||||
if (!debug.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const self = debug;
|
||||
|
||||
// Set `diff` timestamp
|
||||
const curr = Number(new Date());
|
||||
const ms = curr - (prevTime || curr);
|
||||
self.diff = ms;
|
||||
self.prev = prevTime;
|
||||
self.curr = curr;
|
||||
prevTime = curr;
|
||||
|
||||
args[0] = createDebug.coerce(args[0]);
|
||||
|
||||
if (typeof args[0] !== 'string') {
|
||||
// Anything else let's inspect with %O
|
||||
args.unshift('%O');
|
||||
}
|
||||
|
||||
// Apply any `formatters` transformations
|
||||
let index = 0;
|
||||
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
||||
// If we encounter an escaped % then don't increase the array index
|
||||
if (match === '%%') {
|
||||
return '%';
|
||||
}
|
||||
index++;
|
||||
const formatter = createDebug.formatters[format];
|
||||
if (typeof formatter === 'function') {
|
||||
const val = args[index];
|
||||
match = formatter.call(self, val);
|
||||
|
||||
// Now we need to remove `args[index]` since it's inlined in the `format`
|
||||
args.splice(index, 1);
|
||||
index--;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
|
||||
// Apply env-specific formatting (colors, etc.)
|
||||
createDebug.formatArgs.call(self, args);
|
||||
|
||||
const logFn = self.log || createDebug.log;
|
||||
logFn.apply(self, args);
|
||||
}
|
||||
|
||||
debug.namespace = namespace;
|
||||
debug.useColors = createDebug.useColors();
|
||||
debug.color = createDebug.selectColor(namespace);
|
||||
debug.extend = extend;
|
||||
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
|
||||
|
||||
Object.defineProperty(debug, 'enabled', {
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
get: () => enableOverride === null ? createDebug.enabled(namespace) : enableOverride,
|
||||
set: v => {
|
||||
enableOverride = v;
|
||||
}
|
||||
});
|
||||
|
||||
// Env-specific initialization logic for debug instances
|
||||
if (typeof createDebug.init === 'function') {
|
||||
createDebug.init(debug);
|
||||
}
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
||||
function extend(namespace, delimiter) {
|
||||
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
|
||||
newDebug.log = this.log;
|
||||
return newDebug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a debug mode by namespaces. This can include modes
|
||||
* separated by a colon and wildcards.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api public
|
||||
*/
|
||||
function enable(namespaces) {
|
||||
createDebug.save(namespaces);
|
||||
|
||||
createDebug.names = [];
|
||||
createDebug.skips = [];
|
||||
|
||||
let i;
|
||||
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
|
||||
const len = split.length;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!split[i]) {
|
||||
// ignore empty strings
|
||||
continue;
|
||||
}
|
||||
|
||||
namespaces = split[i].replace(/\*/g, '.*?');
|
||||
|
||||
if (namespaces[0] === '-') {
|
||||
createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
|
||||
} else {
|
||||
createDebug.names.push(new RegExp('^' + namespaces + '$'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable debug output.
|
||||
*
|
||||
* @return {String} namespaces
|
||||
* @api public
|
||||
*/
|
||||
function disable() {
|
||||
const namespaces = [
|
||||
...createDebug.names.map(toNamespace),
|
||||
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
|
||||
].join(',');
|
||||
createDebug.enable('');
|
||||
return namespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given mode name is enabled, false otherwise.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
function enabled(name) {
|
||||
if (name[name.length - 1] === '*') {
|
||||
return true;
|
||||
}
|
||||
|
||||
let i;
|
||||
let len;
|
||||
|
||||
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
||||
if (createDebug.skips[i].test(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, len = createDebug.names.length; i < len; i++) {
|
||||
if (createDebug.names[i].test(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert regexp to namespace
|
||||
*
|
||||
* @param {RegExp} regxep
|
||||
* @return {String} namespace
|
||||
* @api private
|
||||
*/
|
||||
function toNamespace(regexp) {
|
||||
return regexp.toString()
|
||||
.substring(2, regexp.toString().length - 2)
|
||||
.replace(/\.\*\?$/, '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Coerce `val`.
|
||||
*
|
||||
* @param {Mixed} val
|
||||
* @return {Mixed}
|
||||
* @api private
|
||||
*/
|
||||
function coerce(val) {
|
||||
if (val instanceof Error) {
|
||||
return val.stack || val.message;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX DO NOT USE. This is a temporary stub function.
|
||||
* XXX It WILL be removed in the next major release.
|
||||
*/
|
||||
function destroy() {
|
||||
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
||||
}
|
||||
|
||||
createDebug.enable(createDebug.load());
|
||||
|
||||
return createDebug;
|
||||
}
|
||||
|
||||
module.exports = setup;
|
10
node_modules/lv_font_conv/node_modules/debug/src/index.js
generated
vendored
Normal file
10
node_modules/lv_font_conv/node_modules/debug/src/index.js
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Detect Electron renderer / nwjs process, which is node, but we should
|
||||
* treat as a browser.
|
||||
*/
|
||||
|
||||
if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
|
||||
module.exports = require('./browser.js');
|
||||
} else {
|
||||
module.exports = require('./node.js');
|
||||
}
|
263
node_modules/lv_font_conv/node_modules/debug/src/node.js
generated
vendored
Normal file
263
node_modules/lv_font_conv/node_modules/debug/src/node.js
generated
vendored
Normal file
@ -0,0 +1,263 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
const tty = require('tty');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* This is the Node.js implementation of `debug()`.
|
||||
*/
|
||||
|
||||
exports.init = init;
|
||||
exports.log = log;
|
||||
exports.formatArgs = formatArgs;
|
||||
exports.save = save;
|
||||
exports.load = load;
|
||||
exports.useColors = useColors;
|
||||
exports.destroy = util.deprecate(
|
||||
() => {},
|
||||
'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
|
||||
);
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
exports.colors = [6, 2, 3, 4, 5, 1];
|
||||
|
||||
try {
|
||||
// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const supportsColor = require('supports-color');
|
||||
|
||||
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
||||
exports.colors = [
|
||||
20,
|
||||
21,
|
||||
26,
|
||||
27,
|
||||
32,
|
||||
33,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
56,
|
||||
57,
|
||||
62,
|
||||
63,
|
||||
68,
|
||||
69,
|
||||
74,
|
||||
75,
|
||||
76,
|
||||
77,
|
||||
78,
|
||||
79,
|
||||
80,
|
||||
81,
|
||||
92,
|
||||
93,
|
||||
98,
|
||||
99,
|
||||
112,
|
||||
113,
|
||||
128,
|
||||
129,
|
||||
134,
|
||||
135,
|
||||
148,
|
||||
149,
|
||||
160,
|
||||
161,
|
||||
162,
|
||||
163,
|
||||
164,
|
||||
165,
|
||||
166,
|
||||
167,
|
||||
168,
|
||||
169,
|
||||
170,
|
||||
171,
|
||||
172,
|
||||
173,
|
||||
178,
|
||||
179,
|
||||
184,
|
||||
185,
|
||||
196,
|
||||
197,
|
||||
198,
|
||||
199,
|
||||
200,
|
||||
201,
|
||||
202,
|
||||
203,
|
||||
204,
|
||||
205,
|
||||
206,
|
||||
207,
|
||||
208,
|
||||
209,
|
||||
214,
|
||||
215,
|
||||
220,
|
||||
221
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
// Swallow - we only care if `supports-color` is available; it doesn't have to be.
|
||||
}
|
||||
|
||||
/**
|
||||
* Build up the default `inspectOpts` object from the environment variables.
|
||||
*
|
||||
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
|
||||
*/
|
||||
|
||||
exports.inspectOpts = Object.keys(process.env).filter(key => {
|
||||
return /^debug_/i.test(key);
|
||||
}).reduce((obj, key) => {
|
||||
// Camel-case
|
||||
const prop = key
|
||||
.substring(6)
|
||||
.toLowerCase()
|
||||
.replace(/_([a-z])/g, (_, k) => {
|
||||
return k.toUpperCase();
|
||||
});
|
||||
|
||||
// Coerce string value into JS value
|
||||
let val = process.env[key];
|
||||
if (/^(yes|on|true|enabled)$/i.test(val)) {
|
||||
val = true;
|
||||
} else if (/^(no|off|false|disabled)$/i.test(val)) {
|
||||
val = false;
|
||||
} else if (val === 'null') {
|
||||
val = null;
|
||||
} else {
|
||||
val = Number(val);
|
||||
}
|
||||
|
||||
obj[prop] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
/**
|
||||
* Is stdout a TTY? Colored output is enabled when `true`.
|
||||
*/
|
||||
|
||||
function useColors() {
|
||||
return 'colors' in exports.inspectOpts ?
|
||||
Boolean(exports.inspectOpts.colors) :
|
||||
tty.isatty(process.stderr.fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds ANSI color escape codes if enabled.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function formatArgs(args) {
|
||||
const {namespace: name, useColors} = this;
|
||||
|
||||
if (useColors) {
|
||||
const c = this.color;
|
||||
const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
|
||||
const prefix = ` ${colorCode};1m${name} \u001B[0m`;
|
||||
|
||||
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
|
||||
args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
|
||||
} else {
|
||||
args[0] = getDate() + name + ' ' + args[0];
|
||||
}
|
||||
}
|
||||
|
||||
function getDate() {
|
||||
if (exports.inspectOpts.hideDate) {
|
||||
return '';
|
||||
}
|
||||
return new Date().toISOString() + ' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes `util.format()` with the specified arguments and writes to stderr.
|
||||
*/
|
||||
|
||||
function log(...args) {
|
||||
return process.stderr.write(util.format(...args) + '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save `namespaces`.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api private
|
||||
*/
|
||||
function save(namespaces) {
|
||||
if (namespaces) {
|
||||
process.env.DEBUG = namespaces;
|
||||
} else {
|
||||
// If you set a process.env field to null or undefined, it gets cast to the
|
||||
// string 'null' or 'undefined'. Just delete instead.
|
||||
delete process.env.DEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load `namespaces`.
|
||||
*
|
||||
* @return {String} returns the previously persisted debug modes
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function load() {
|
||||
return process.env.DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init logic for `debug` instances.
|
||||
*
|
||||
* Create a new `inspectOpts` object in case `useColors` is set
|
||||
* differently for a particular `debug` instance.
|
||||
*/
|
||||
|
||||
function init(debug) {
|
||||
debug.inspectOpts = {};
|
||||
|
||||
const keys = Object.keys(exports.inspectOpts);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = require('./common')(exports);
|
||||
|
||||
const {formatters} = module.exports;
|
||||
|
||||
/**
|
||||
* Map %o to `util.inspect()`, all on a single line.
|
||||
*/
|
||||
|
||||
formatters.o = function (v) {
|
||||
this.inspectOpts.colors = this.useColors;
|
||||
return util.inspect(v, this.inspectOpts)
|
||||
.split('\n')
|
||||
.map(str => str.trim())
|
||||
.join(' ');
|
||||
};
|
||||
|
||||
/**
|
||||
* Map %O to `util.inspect()`, allowing multiple lines if needed.
|
||||
*/
|
||||
|
||||
formatters.O = function (v) {
|
||||
this.inspectOpts.colors = this.useColors;
|
||||
return util.inspect(v, this.inspectOpts);
|
||||
};
|
5
node_modules/lv_font_conv/node_modules/make-error/LICENSE
generated
vendored
Normal file
5
node_modules/lv_font_conv/node_modules/make-error/LICENSE
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
Copyright 2014 Julien Fontanet
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
112
node_modules/lv_font_conv/node_modules/make-error/README.md
generated
vendored
Normal file
112
node_modules/lv_font_conv/node_modules/make-error/README.md
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
# make-error
|
||||
|
||||
[![Package Version](https://badgen.net/npm/v/make-error)](https://npmjs.org/package/make-error) [![Build Status](https://travis-ci.org/JsCommunity/make-error.png?branch=master)](https://travis-ci.org/JsCommunity/make-error) [![PackagePhobia](https://badgen.net/packagephobia/install/make-error)](https://packagephobia.now.sh/result?p=make-error) [![Latest Commit](https://badgen.net/github/last-commit/JsCommunity/make-error)](https://github.com/JsCommunity/make-error/commits/master)
|
||||
|
||||
> Make your own error types!
|
||||
|
||||
## Features
|
||||
|
||||
- Compatible Node & browsers
|
||||
- `instanceof` support
|
||||
- `error.name` & `error.stack` support
|
||||
- compatible with [CSP](https://en.wikipedia.org/wiki/Content_Security_Policy) (i.e. no `eval()`)
|
||||
|
||||
## Installation
|
||||
|
||||
### Node & [Browserify](http://browserify.org/)/[Webpack](https://webpack.js.org/)
|
||||
|
||||
Installation of the [npm package](https://npmjs.org/package/make-error):
|
||||
|
||||
```
|
||||
> npm install --save make-error
|
||||
```
|
||||
|
||||
Then require the package:
|
||||
|
||||
```javascript
|
||||
var makeError = require("make-error");
|
||||
```
|
||||
|
||||
### Browser
|
||||
|
||||
You can directly use the build provided at [unpkg.com](https://unpkg.com):
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/make-error@1/dist/make-error.js"></script>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic named error
|
||||
|
||||
```javascript
|
||||
var CustomError = makeError("CustomError");
|
||||
|
||||
// Parameters are forwarded to the super class (here Error).
|
||||
throw new CustomError("a message");
|
||||
```
|
||||
|
||||
### Advanced error class
|
||||
|
||||
```javascript
|
||||
function CustomError(customValue) {
|
||||
CustomError.super.call(this, "custom error message");
|
||||
|
||||
this.customValue = customValue;
|
||||
}
|
||||
makeError(CustomError);
|
||||
|
||||
// Feel free to extend the prototype.
|
||||
CustomError.prototype.myMethod = function CustomError$myMethod() {
|
||||
console.log("CustomError.myMethod (%s, %s)", this.code, this.message);
|
||||
};
|
||||
|
||||
//-----
|
||||
|
||||
try {
|
||||
throw new CustomError(42);
|
||||
} catch (error) {
|
||||
error.myMethod();
|
||||
}
|
||||
```
|
||||
|
||||
### Specialized error
|
||||
|
||||
```javascript
|
||||
var SpecializedError = makeError("SpecializedError", CustomError);
|
||||
|
||||
throw new SpecializedError(42);
|
||||
```
|
||||
|
||||
### Inheritance
|
||||
|
||||
> Best for ES2015+.
|
||||
|
||||
```javascript
|
||||
import { BaseError } from "make-error";
|
||||
|
||||
class CustomError extends BaseError {
|
||||
constructor() {
|
||||
super("custom error message");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [make-error-cause](https://www.npmjs.com/package/make-error-cause): Make your own error types, with a cause!
|
||||
|
||||
## Contributions
|
||||
|
||||
Contributions are _very_ welcomed, either on the documentation or on
|
||||
the code.
|
||||
|
||||
You may:
|
||||
|
||||
- report any [issue](https://github.com/JsCommunity/make-error/issues)
|
||||
you've encountered;
|
||||
- fork and create a pull request.
|
||||
|
||||
## License
|
||||
|
||||
ISC © [Julien Fontanet](http://julien.isonoe.net)
|
1
node_modules/lv_font_conv/node_modules/make-error/dist/make-error.js
generated
vendored
Normal file
1
node_modules/lv_font_conv/node_modules/make-error/dist/make-error.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(f){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=f();else if("function"==typeof define&&define.amd)define([],f);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).makeError=f()}}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(require,module,exports){"use strict";var construct="undefined"!=typeof Reflect?Reflect.construct:void 0,defineProperty=Object.defineProperty,captureStackTrace=Error.captureStackTrace;function BaseError(message){void 0!==message&&defineProperty(this,"message",{configurable:!0,value:message,writable:!0});var cname=this.constructor.name;void 0!==cname&&cname!==this.name&&defineProperty(this,"name",{configurable:!0,value:cname,writable:!0}),captureStackTrace(this,this.constructor)}void 0===captureStackTrace&&(captureStackTrace=function(error){var container=new Error;defineProperty(error,"stack",{configurable:!0,get:function(){var stack=container.stack;return defineProperty(this,"stack",{configurable:!0,value:stack,writable:!0}),stack},set:function(stack){defineProperty(error,"stack",{configurable:!0,value:stack,writable:!0})}})}),BaseError.prototype=Object.create(Error.prototype,{constructor:{configurable:!0,value:BaseError,writable:!0}});var setFunctionName=function(){function setFunctionName(fn,name){return defineProperty(fn,"name",{configurable:!0,value:name})}try{var f=function(){};if(setFunctionName(f,"foo"),"foo"===f.name)return setFunctionName}catch(_){}}();(module.exports=function(constructor,super_){if(null==super_||super_===Error)super_=BaseError;else if("function"!=typeof super_)throw new TypeError("super_ should be a function");var name;if("string"==typeof constructor)name=constructor,constructor=void 0!==construct?function(){return construct(super_,arguments,this.constructor)}:function(){super_.apply(this,arguments)},void 0!==setFunctionName&&(setFunctionName(constructor,name),name=void 0);else if("function"!=typeof constructor)throw new TypeError("constructor should be either a string or a function");constructor.super_=constructor.super=super_;var properties={constructor:{configurable:!0,value:constructor,writable:!0}};return void 0!==name&&(properties.name={configurable:!0,value:name,writable:!0}),constructor.prototype=Object.create(super_.prototype,properties),constructor}).BaseError=BaseError},{}]},{},[1])(1)});
|
47
node_modules/lv_font_conv/node_modules/make-error/index.d.ts
generated
vendored
Normal file
47
node_modules/lv_font_conv/node_modules/make-error/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Create a new error constructor instance.
|
||||
*/
|
||||
declare function makeError(
|
||||
name: string
|
||||
): makeError.Constructor<makeError.BaseError>;
|
||||
|
||||
/**
|
||||
* Set the constructor prototype to `BaseError`.
|
||||
*/
|
||||
declare function makeError<T extends Error>(super_: {
|
||||
new (...args: any[]): T;
|
||||
}): makeError.Constructor<T & makeError.BaseError>;
|
||||
|
||||
/**
|
||||
* Create a specialized error instance.
|
||||
*/
|
||||
declare function makeError<T extends Error, K>(
|
||||
name: string | Function,
|
||||
super_: K
|
||||
): K & makeError.SpecializedConstructor<T>;
|
||||
|
||||
declare namespace makeError {
|
||||
/**
|
||||
* Use with ES2015+ inheritance.
|
||||
*/
|
||||
export class BaseError extends Error {
|
||||
message: string;
|
||||
name: string;
|
||||
stack: string;
|
||||
|
||||
constructor(message?: string);
|
||||
}
|
||||
|
||||
export interface Constructor<T> {
|
||||
new (message?: string): T;
|
||||
super_: any;
|
||||
prototype: T;
|
||||
}
|
||||
|
||||
export interface SpecializedConstructor<T> {
|
||||
super_: any;
|
||||
prototype: T;
|
||||
}
|
||||
}
|
||||
|
||||
export = makeError;
|
151
node_modules/lv_font_conv/node_modules/make-error/index.js
generated
vendored
Normal file
151
node_modules/lv_font_conv/node_modules/make-error/index.js
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
// ISC @ Julien Fontanet
|
||||
|
||||
"use strict";
|
||||
|
||||
// ===================================================================
|
||||
|
||||
var construct = typeof Reflect !== "undefined" ? Reflect.construct : undefined;
|
||||
var defineProperty = Object.defineProperty;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
var captureStackTrace = Error.captureStackTrace;
|
||||
if (captureStackTrace === undefined) {
|
||||
captureStackTrace = function captureStackTrace(error) {
|
||||
var container = new Error();
|
||||
|
||||
defineProperty(error, "stack", {
|
||||
configurable: true,
|
||||
get: function getStack() {
|
||||
var stack = container.stack;
|
||||
|
||||
// Replace property with value for faster future accesses.
|
||||
defineProperty(this, "stack", {
|
||||
configurable: true,
|
||||
value: stack,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
return stack;
|
||||
},
|
||||
set: function setStack(stack) {
|
||||
defineProperty(error, "stack", {
|
||||
configurable: true,
|
||||
value: stack,
|
||||
writable: true,
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function BaseError(message) {
|
||||
if (message !== undefined) {
|
||||
defineProperty(this, "message", {
|
||||
configurable: true,
|
||||
value: message,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
|
||||
var cname = this.constructor.name;
|
||||
if (cname !== undefined && cname !== this.name) {
|
||||
defineProperty(this, "name", {
|
||||
configurable: true,
|
||||
value: cname,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
|
||||
captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
||||
BaseError.prototype = Object.create(Error.prototype, {
|
||||
// See: https://github.com/JsCommunity/make-error/issues/4
|
||||
constructor: {
|
||||
configurable: true,
|
||||
value: BaseError,
|
||||
writable: true,
|
||||
},
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// Sets the name of a function if possible (depends of the JS engine).
|
||||
var setFunctionName = (function() {
|
||||
function setFunctionName(fn, name) {
|
||||
return defineProperty(fn, "name", {
|
||||
configurable: true,
|
||||
value: name,
|
||||
});
|
||||
}
|
||||
try {
|
||||
var f = function() {};
|
||||
setFunctionName(f, "foo");
|
||||
if (f.name === "foo") {
|
||||
return setFunctionName;
|
||||
}
|
||||
} catch (_) {}
|
||||
})();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function makeError(constructor, super_) {
|
||||
if (super_ == null || super_ === Error) {
|
||||
super_ = BaseError;
|
||||
} else if (typeof super_ !== "function") {
|
||||
throw new TypeError("super_ should be a function");
|
||||
}
|
||||
|
||||
var name;
|
||||
if (typeof constructor === "string") {
|
||||
name = constructor;
|
||||
constructor =
|
||||
construct !== undefined
|
||||
? function() {
|
||||
return construct(super_, arguments, this.constructor);
|
||||
}
|
||||
: function() {
|
||||
super_.apply(this, arguments);
|
||||
};
|
||||
|
||||
// If the name can be set, do it once and for all.
|
||||
if (setFunctionName !== undefined) {
|
||||
setFunctionName(constructor, name);
|
||||
name = undefined;
|
||||
}
|
||||
} else if (typeof constructor !== "function") {
|
||||
throw new TypeError("constructor should be either a string or a function");
|
||||
}
|
||||
|
||||
// Also register the super constructor also as `constructor.super_` just
|
||||
// like Node's `util.inherits()`.
|
||||
//
|
||||
// eslint-disable-next-line dot-notation
|
||||
constructor.super_ = constructor["super"] = super_;
|
||||
|
||||
var properties = {
|
||||
constructor: {
|
||||
configurable: true,
|
||||
value: constructor,
|
||||
writable: true,
|
||||
},
|
||||
};
|
||||
|
||||
// If the name could not be set on the constructor, set it on the
|
||||
// prototype.
|
||||
if (name !== undefined) {
|
||||
properties.name = {
|
||||
configurable: true,
|
||||
value: name,
|
||||
writable: true,
|
||||
};
|
||||
}
|
||||
constructor.prototype = Object.create(super_.prototype, properties);
|
||||
|
||||
return constructor;
|
||||
}
|
||||
exports = module.exports = makeError;
|
||||
exports.BaseError = BaseError;
|
95
node_modules/lv_font_conv/node_modules/make-error/package.json
generated
vendored
Normal file
95
node_modules/lv_font_conv/node_modules/make-error/package.json
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"make-error@1.3.6",
|
||||
"/home/vitaly/Dropbox/Coding/lv_font_conv"
|
||||
]
|
||||
],
|
||||
"_from": "make-error@1.3.6",
|
||||
"_id": "make-error@1.3.6",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"_location": "/make-error",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "make-error@1.3.6",
|
||||
"name": "make-error",
|
||||
"escapedName": "make-error",
|
||||
"rawSpec": "1.3.6",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "1.3.6"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"_spec": "1.3.6",
|
||||
"_where": "/home/vitaly/Dropbox/Coding/lv_font_conv",
|
||||
"author": {
|
||||
"name": "Julien Fontanet",
|
||||
"email": "julien.fontanet@isonoe.net"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/JsCommunity/make-error/issues"
|
||||
},
|
||||
"description": "Make your own error types!",
|
||||
"devDependencies": {
|
||||
"browserify": "^16.2.3",
|
||||
"eslint": "^6.5.1",
|
||||
"eslint-config-prettier": "^6.4.0",
|
||||
"eslint-config-standard": "^14.1.0",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-node": "^10.0.0",
|
||||
"eslint-plugin-promise": "^4.0.1",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"husky": "^3.0.9",
|
||||
"jest": "^24",
|
||||
"prettier": "^1.14.3",
|
||||
"uglify-js": "^3.3.2"
|
||||
},
|
||||
"files": [
|
||||
"dist/",
|
||||
"index.js",
|
||||
"index.d.ts"
|
||||
],
|
||||
"homepage": "https://github.com/JsCommunity/make-error",
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"commit-msg": "npm run test"
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "node"
|
||||
},
|
||||
"keywords": [
|
||||
"create",
|
||||
"custom",
|
||||
"derive",
|
||||
"error",
|
||||
"errors",
|
||||
"extend",
|
||||
"extending",
|
||||
"extension",
|
||||
"factory",
|
||||
"inherit",
|
||||
"make",
|
||||
"subclass"
|
||||
],
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"name": "make-error",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/JsCommunity/make-error.git"
|
||||
},
|
||||
"scripts": {
|
||||
"dev-test": "jest --watch",
|
||||
"format": "prettier --write '**'",
|
||||
"prepublishOnly": "mkdir -p dist && browserify -s makeError index.js | uglifyjs -c > dist/make-error.js",
|
||||
"pretest": "eslint --ignore-path .gitignore .",
|
||||
"test": "jest"
|
||||
},
|
||||
"version": "1.3.6"
|
||||
}
|
15
node_modules/lv_font_conv/node_modules/mkdirp/CHANGELOG.md
generated
vendored
Normal file
15
node_modules/lv_font_conv/node_modules/mkdirp/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Changers Lorgs!
|
||||
|
||||
## 1.0
|
||||
|
||||
Full rewrite. Essentially a brand new module.
|
||||
|
||||
- Return a promise instead of taking a callback.
|
||||
- Use native `fs.mkdir(path, { recursive: true })` when available.
|
||||
- Drop support for outdated Node.js versions. (Technically still works on
|
||||
Node.js v8, but only 10 and above are officially supported.)
|
||||
|
||||
## 0.x
|
||||
|
||||
Original and most widely used recursive directory creation implementation
|
||||
in JavaScript, dating back to 2010.
|
21
node_modules/lv_font_conv/node_modules/mkdirp/LICENSE
generated
vendored
Normal file
21
node_modules/lv_font_conv/node_modules/mkdirp/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
Copyright James Halliday (mail@substack.net) and Isaac Z. Schlueter (i@izs.me)
|
||||
|
||||
This project is free software released under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
68
node_modules/lv_font_conv/node_modules/mkdirp/bin/cmd.js
generated
vendored
Executable file
68
node_modules/lv_font_conv/node_modules/mkdirp/bin/cmd.js
generated
vendored
Executable file
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const usage = () => `
|
||||
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
|
||||
|
||||
Create each supplied directory including any necessary parent directories
|
||||
that don't yet exist.
|
||||
|
||||
If the directory already exists, do nothing.
|
||||
|
||||
OPTIONS are:
|
||||
|
||||
-m<mode> If a directory needs to be created, set the mode as an octal
|
||||
--mode=<mode> permission string.
|
||||
|
||||
-v --version Print the mkdirp version number
|
||||
|
||||
-h --help Print this helpful banner
|
||||
|
||||
-p --print Print the first directories created for each path provided
|
||||
|
||||
--manual Use manual implementation, even if native is available
|
||||
`
|
||||
|
||||
const dirs = []
|
||||
const opts = {}
|
||||
let print = false
|
||||
let dashdash = false
|
||||
let manual = false
|
||||
for (const arg of process.argv.slice(2)) {
|
||||
if (dashdash)
|
||||
dirs.push(arg)
|
||||
else if (arg === '--')
|
||||
dashdash = true
|
||||
else if (arg === '--manual')
|
||||
manual = true
|
||||
else if (/^-h/.test(arg) || /^--help/.test(arg)) {
|
||||
console.log(usage())
|
||||
process.exit(0)
|
||||
} else if (arg === '-v' || arg === '--version') {
|
||||
console.log(require('../package.json').version)
|
||||
process.exit(0)
|
||||
} else if (arg === '-p' || arg === '--print') {
|
||||
print = true
|
||||
} else if (/^-m/.test(arg) || /^--mode=/.test(arg)) {
|
||||
const mode = parseInt(arg.replace(/^(-m|--mode=)/, ''), 8)
|
||||
if (isNaN(mode)) {
|
||||
console.error(`invalid mode argument: ${arg}\nMust be an octal number.`)
|
||||
process.exit(1)
|
||||
}
|
||||
opts.mode = mode
|
||||
} else
|
||||
dirs.push(arg)
|
||||
}
|
||||
|
||||
const mkdirp = require('../')
|
||||
const impl = manual ? mkdirp.manual : mkdirp
|
||||
if (dirs.length === 0)
|
||||
console.error(usage())
|
||||
|
||||
Promise.all(dirs.map(dir => impl(dir, opts)))
|
||||
.then(made => print ? made.forEach(m => m && console.log(m)) : null)
|
||||
.catch(er => {
|
||||
console.error(er.message)
|
||||
if (er.code)
|
||||
console.error(' code: ' + er.code)
|
||||
process.exit(1)
|
||||
})
|
31
node_modules/lv_font_conv/node_modules/mkdirp/index.js
generated
vendored
Normal file
31
node_modules/lv_font_conv/node_modules/mkdirp/index.js
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
const optsArg = require('./lib/opts-arg.js')
|
||||
const pathArg = require('./lib/path-arg.js')
|
||||
|
||||
const {mkdirpNative, mkdirpNativeSync} = require('./lib/mkdirp-native.js')
|
||||
const {mkdirpManual, mkdirpManualSync} = require('./lib/mkdirp-manual.js')
|
||||
const {useNative, useNativeSync} = require('./lib/use-native.js')
|
||||
|
||||
|
||||
const mkdirp = (path, opts) => {
|
||||
path = pathArg(path)
|
||||
opts = optsArg(opts)
|
||||
return useNative(opts)
|
||||
? mkdirpNative(path, opts)
|
||||
: mkdirpManual(path, opts)
|
||||
}
|
||||
|
||||
const mkdirpSync = (path, opts) => {
|
||||
path = pathArg(path)
|
||||
opts = optsArg(opts)
|
||||
return useNativeSync(opts)
|
||||
? mkdirpNativeSync(path, opts)
|
||||
: mkdirpManualSync(path, opts)
|
||||
}
|
||||
|
||||
mkdirp.sync = mkdirpSync
|
||||
mkdirp.native = (path, opts) => mkdirpNative(pathArg(path), optsArg(opts))
|
||||
mkdirp.manual = (path, opts) => mkdirpManual(pathArg(path), optsArg(opts))
|
||||
mkdirp.nativeSync = (path, opts) => mkdirpNativeSync(pathArg(path), optsArg(opts))
|
||||
mkdirp.manualSync = (path, opts) => mkdirpManualSync(pathArg(path), optsArg(opts))
|
||||
|
||||
module.exports = mkdirp
|
29
node_modules/lv_font_conv/node_modules/mkdirp/lib/find-made.js
generated
vendored
Normal file
29
node_modules/lv_font_conv/node_modules/mkdirp/lib/find-made.js
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
const {dirname} = require('path')
|
||||
|
||||
const findMade = (opts, parent, path = undefined) => {
|
||||
// we never want the 'made' return value to be a root directory
|
||||
if (path === parent)
|
||||
return Promise.resolve()
|
||||
|
||||
return opts.statAsync(parent).then(
|
||||
st => st.isDirectory() ? path : undefined, // will fail later
|
||||
er => er.code === 'ENOENT'
|
||||
? findMade(opts, dirname(parent), parent)
|
||||
: undefined
|
||||
)
|
||||
}
|
||||
|
||||
const findMadeSync = (opts, parent, path = undefined) => {
|
||||
if (path === parent)
|
||||
return undefined
|
||||
|
||||
try {
|
||||
return opts.statSync(parent).isDirectory() ? path : undefined
|
||||
} catch (er) {
|
||||
return er.code === 'ENOENT'
|
||||
? findMadeSync(opts, dirname(parent), parent)
|
||||
: undefined
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {findMade, findMadeSync}
|
64
node_modules/lv_font_conv/node_modules/mkdirp/lib/mkdirp-manual.js
generated
vendored
Normal file
64
node_modules/lv_font_conv/node_modules/mkdirp/lib/mkdirp-manual.js
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
const {dirname} = require('path')
|
||||
|
||||
const mkdirpManual = (path, opts, made) => {
|
||||
opts.recursive = false
|
||||
const parent = dirname(path)
|
||||
if (parent === path) {
|
||||
return opts.mkdirAsync(path, opts).catch(er => {
|
||||
// swallowed by recursive implementation on posix systems
|
||||
// any other error is a failure
|
||||
if (er.code !== 'EISDIR')
|
||||
throw er
|
||||
})
|
||||
}
|
||||
|
||||
return opts.mkdirAsync(path, opts).then(() => made || path, er => {
|
||||
if (er.code === 'ENOENT')
|
||||
return mkdirpManual(parent, opts)
|
||||
.then(made => mkdirpManual(path, opts, made))
|
||||
if (er.code !== 'EEXIST' && er.code !== 'EROFS')
|
||||
throw er
|
||||
return opts.statAsync(path).then(st => {
|
||||
if (st.isDirectory())
|
||||
return made
|
||||
else
|
||||
throw er
|
||||
}, () => { throw er })
|
||||
})
|
||||
}
|
||||
|
||||
const mkdirpManualSync = (path, opts, made) => {
|
||||
const parent = dirname(path)
|
||||
opts.recursive = false
|
||||
|
||||
if (parent === path) {
|
||||
try {
|
||||
return opts.mkdirSync(path, opts)
|
||||
} catch (er) {
|
||||
// swallowed by recursive implementation on posix systems
|
||||
// any other error is a failure
|
||||
if (er.code !== 'EISDIR')
|
||||
throw er
|
||||
else
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
opts.mkdirSync(path, opts)
|
||||
return made || path
|
||||
} catch (er) {
|
||||
if (er.code === 'ENOENT')
|
||||
return mkdirpManualSync(path, opts, mkdirpManualSync(parent, opts, made))
|
||||
if (er.code !== 'EEXIST' && er.code !== 'EROFS')
|
||||
throw er
|
||||
try {
|
||||
if (!opts.statSync(path).isDirectory())
|
||||
throw er
|
||||
} catch (_) {
|
||||
throw er
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {mkdirpManual, mkdirpManualSync}
|
39
node_modules/lv_font_conv/node_modules/mkdirp/lib/mkdirp-native.js
generated
vendored
Normal file
39
node_modules/lv_font_conv/node_modules/mkdirp/lib/mkdirp-native.js
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
const {dirname} = require('path')
|
||||
const {findMade, findMadeSync} = require('./find-made.js')
|
||||
const {mkdirpManual, mkdirpManualSync} = require('./mkdirp-manual.js')
|
||||
|
||||
const mkdirpNative = (path, opts) => {
|
||||
opts.recursive = true
|
||||
const parent = dirname(path)
|
||||
if (parent === path)
|
||||
return opts.mkdirAsync(path, opts)
|
||||
|
||||
return findMade(opts, path).then(made =>
|
||||
opts.mkdirAsync(path, opts).then(() => made)
|
||||
.catch(er => {
|
||||
if (er.code === 'ENOENT')
|
||||
return mkdirpManual(path, opts)
|
||||
else
|
||||
throw er
|
||||
}))
|
||||
}
|
||||
|
||||
const mkdirpNativeSync = (path, opts) => {
|
||||
opts.recursive = true
|
||||
const parent = dirname(path)
|
||||
if (parent === path)
|
||||
return opts.mkdirSync(path, opts)
|
||||
|
||||
const made = findMadeSync(opts, path)
|
||||
try {
|
||||
opts.mkdirSync(path, opts)
|
||||
return made
|
||||
} catch (er) {
|
||||
if (er.code === 'ENOENT')
|
||||
return mkdirpManualSync(path, opts)
|
||||
else
|
||||
throw er
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {mkdirpNative, mkdirpNativeSync}
|
23
node_modules/lv_font_conv/node_modules/mkdirp/lib/opts-arg.js
generated
vendored
Normal file
23
node_modules/lv_font_conv/node_modules/mkdirp/lib/opts-arg.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
const { promisify } = require('util')
|
||||
const fs = require('fs')
|
||||
const optsArg = opts => {
|
||||
if (!opts)
|
||||
opts = { mode: 0o777, fs }
|
||||
else if (typeof opts === 'object')
|
||||
opts = { mode: 0o777, fs, ...opts }
|
||||
else if (typeof opts === 'number')
|
||||
opts = { mode: opts, fs }
|
||||
else if (typeof opts === 'string')
|
||||
opts = { mode: parseInt(opts, 8), fs }
|
||||
else
|
||||
throw new TypeError('invalid options argument')
|
||||
|
||||
opts.mkdir = opts.mkdir || opts.fs.mkdir || fs.mkdir
|
||||
opts.mkdirAsync = promisify(opts.mkdir)
|
||||
opts.stat = opts.stat || opts.fs.stat || fs.stat
|
||||
opts.statAsync = promisify(opts.stat)
|
||||
opts.statSync = opts.statSync || opts.fs.statSync || fs.statSync
|
||||
opts.mkdirSync = opts.mkdirSync || opts.fs.mkdirSync || fs.mkdirSync
|
||||
return opts
|
||||
}
|
||||
module.exports = optsArg
|
29
node_modules/lv_font_conv/node_modules/mkdirp/lib/path-arg.js
generated
vendored
Normal file
29
node_modules/lv_font_conv/node_modules/mkdirp/lib/path-arg.js
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
const platform = process.env.__TESTING_MKDIRP_PLATFORM__ || process.platform
|
||||
const { resolve, parse } = require('path')
|
||||
const pathArg = path => {
|
||||
if (/\0/.test(path)) {
|
||||
// simulate same failure that node raises
|
||||
throw Object.assign(
|
||||
new TypeError('path must be a string without null bytes'),
|
||||
{
|
||||
path,
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
path = resolve(path)
|
||||
if (platform === 'win32') {
|
||||
const badWinChars = /[*|"<>?:]/
|
||||
const {root} = parse(path)
|
||||
if (badWinChars.test(path.substr(root.length))) {
|
||||
throw Object.assign(new Error('Illegal characters in path.'), {
|
||||
path,
|
||||
code: 'EINVAL',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
module.exports = pathArg
|
10
node_modules/lv_font_conv/node_modules/mkdirp/lib/use-native.js
generated
vendored
Normal file
10
node_modules/lv_font_conv/node_modules/mkdirp/lib/use-native.js
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
const fs = require('fs')
|
||||
|
||||
const version = process.env.__TESTING_MKDIRP_NODE_VERSION__ || process.version
|
||||
const versArr = version.replace(/^v/, '').split('.')
|
||||
const hasNative = +versArr[0] > 10 || +versArr[0] === 10 && +versArr[1] >= 12
|
||||
|
||||
const useNative = !hasNative ? () => false : opts => opts.mkdir === fs.mkdir
|
||||
const useNativeSync = !hasNative ? () => false : opts => opts.mkdirSync === fs.mkdirSync
|
||||
|
||||
module.exports = {useNative, useNativeSync}
|
78
node_modules/lv_font_conv/node_modules/mkdirp/package.json
generated
vendored
Normal file
78
node_modules/lv_font_conv/node_modules/mkdirp/package.json
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"mkdirp@1.0.4",
|
||||
"/home/vitaly/Dropbox/Coding/lv_font_conv"
|
||||
]
|
||||
],
|
||||
"_from": "mkdirp@1.0.4",
|
||||
"_id": "mkdirp@1.0.4",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"_location": "/mkdirp",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "mkdirp@1.0.4",
|
||||
"name": "mkdirp",
|
||||
"escapedName": "mkdirp",
|
||||
"rawSpec": "1.0.4",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "1.0.4"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"_spec": "1.0.4",
|
||||
"_where": "/home/vitaly/Dropbox/Coding/lv_font_conv",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/node-mkdirp/issues"
|
||||
},
|
||||
"description": "Recursively mkdir, like `mkdir -p`",
|
||||
"devDependencies": {
|
||||
"require-inject": "^1.4.4",
|
||||
"tap": "^14.10.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"files": [
|
||||
"bin",
|
||||
"lib",
|
||||
"index.js"
|
||||
],
|
||||
"homepage": "https://github.com/isaacs/node-mkdirp#readme",
|
||||
"keywords": [
|
||||
"mkdir",
|
||||
"directory",
|
||||
"make dir",
|
||||
"make",
|
||||
"dir",
|
||||
"recursive",
|
||||
"native"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"name": "mkdirp",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/isaacs/node-mkdirp.git"
|
||||
},
|
||||
"scripts": {
|
||||
"postpublish": "git push origin --follow-tags",
|
||||
"postversion": "npm publish",
|
||||
"preversion": "npm test",
|
||||
"snap": "tap",
|
||||
"test": "tap"
|
||||
},
|
||||
"tap": {
|
||||
"check-coverage": true,
|
||||
"coverage-map": "map.js"
|
||||
},
|
||||
"version": "1.0.4"
|
||||
}
|
266
node_modules/lv_font_conv/node_modules/mkdirp/readme.markdown
generated
vendored
Normal file
266
node_modules/lv_font_conv/node_modules/mkdirp/readme.markdown
generated
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
# mkdirp
|
||||
|
||||
Like `mkdir -p`, but in Node.js!
|
||||
|
||||
Now with a modern API and no\* bugs!
|
||||
|
||||
<small>\* may contain some bugs</small>
|
||||
|
||||
# example
|
||||
|
||||
## pow.js
|
||||
|
||||
```js
|
||||
const mkdirp = require('mkdirp')
|
||||
|
||||
// return value is a Promise resolving to the first directory created
|
||||
mkdirp('/tmp/foo/bar/baz').then(made =>
|
||||
console.log(`made directories, starting with ${made}`))
|
||||
```
|
||||
|
||||
Output (where `/tmp/foo` already exists)
|
||||
|
||||
```
|
||||
made directories, starting with /tmp/foo/bar
|
||||
```
|
||||
|
||||
Or, if you don't have time to wait around for promises:
|
||||
|
||||
```js
|
||||
const mkdirp = require('mkdirp')
|
||||
|
||||
// return value is the first directory created
|
||||
const made = mkdirp.sync('/tmp/foo/bar/baz')
|
||||
console.log(`made directories, starting with ${made}`)
|
||||
```
|
||||
|
||||
And now /tmp/foo/bar/baz exists, huzzah!
|
||||
|
||||
# methods
|
||||
|
||||
```js
|
||||
const mkdirp = require('mkdirp')
|
||||
```
|
||||
|
||||
## mkdirp(dir, [opts]) -> Promise<String | undefined>
|
||||
|
||||
Create a new directory and any necessary subdirectories at `dir` with octal
|
||||
permission string `opts.mode`. If `opts` is a string or number, it will be
|
||||
treated as the `opts.mode`.
|
||||
|
||||
If `opts.mode` isn't specified, it defaults to `0o777 &
|
||||
(~process.umask())`.
|
||||
|
||||
Promise resolves to first directory `made` that had to be created, or
|
||||
`undefined` if everything already exists. Promise rejects if any errors
|
||||
are encountered. Note that, in the case of promise rejection, some
|
||||
directories _may_ have been created, as recursive directory creation is not
|
||||
an atomic operation.
|
||||
|
||||
You can optionally pass in an alternate `fs` implementation by passing in
|
||||
`opts.fs`. Your implementation should have `opts.fs.mkdir(path, opts, cb)`
|
||||
and `opts.fs.stat(path, cb)`.
|
||||
|
||||
You can also override just one or the other of `mkdir` and `stat` by
|
||||
passing in `opts.stat` or `opts.mkdir`, or providing an `fs` option that
|
||||
only overrides one of these.
|
||||
|
||||
## mkdirp.sync(dir, opts) -> String|null
|
||||
|
||||
Synchronously create a new directory and any necessary subdirectories at
|
||||
`dir` with octal permission string `opts.mode`. If `opts` is a string or
|
||||
number, it will be treated as the `opts.mode`.
|
||||
|
||||
If `opts.mode` isn't specified, it defaults to `0o777 &
|
||||
(~process.umask())`.
|
||||
|
||||
Returns the first directory that had to be created, or undefined if
|
||||
everything already exists.
|
||||
|
||||
You can optionally pass in an alternate `fs` implementation by passing in
|
||||
`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)`
|
||||
and `opts.fs.statSync(path)`.
|
||||
|
||||
You can also override just one or the other of `mkdirSync` and `statSync`
|
||||
by passing in `opts.statSync` or `opts.mkdirSync`, or providing an `fs`
|
||||
option that only overrides one of these.
|
||||
|
||||
## mkdirp.manual, mkdirp.manualSync
|
||||
|
||||
Use the manual implementation (not the native one). This is the default
|
||||
when the native implementation is not available or the stat/mkdir
|
||||
implementation is overridden.
|
||||
|
||||
## mkdirp.native, mkdirp.nativeSync
|
||||
|
||||
Use the native implementation (not the manual one). This is the default
|
||||
when the native implementation is available and stat/mkdir are not
|
||||
overridden.
|
||||
|
||||
# implementation
|
||||
|
||||
On Node.js v10.12.0 and above, use the native `fs.mkdir(p,
|
||||
{recursive:true})` option, unless `fs.mkdir`/`fs.mkdirSync` has been
|
||||
overridden by an option.
|
||||
|
||||
## native implementation
|
||||
|
||||
- If the path is a root directory, then pass it to the underlying
|
||||
implementation and return the result/error. (In this case, it'll either
|
||||
succeed or fail, but we aren't actually creating any dirs.)
|
||||
- Walk up the path statting each directory, to find the first path that
|
||||
will be created, `made`.
|
||||
- Call `fs.mkdir(path, { recursive: true })` (or `fs.mkdirSync`)
|
||||
- If error, raise it to the caller.
|
||||
- Return `made`.
|
||||
|
||||
## manual implementation
|
||||
|
||||
- Call underlying `fs.mkdir` implementation, with `recursive: false`
|
||||
- If error:
|
||||
- If path is a root directory, raise to the caller and do not handle it
|
||||
- If ENOENT, mkdirp parent dir, store result as `made`
|
||||
- stat(path)
|
||||
- If error, raise original `mkdir` error
|
||||
- If directory, return `made`
|
||||
- Else, raise original `mkdir` error
|
||||
- else
|
||||
- return `undefined` if a root dir, or `made` if set, or `path`
|
||||
|
||||
## windows vs unix caveat
|
||||
|
||||
On Windows file systems, attempts to create a root directory (ie, a drive
|
||||
letter or root UNC path) will fail. If the root directory exists, then it
|
||||
will fail with `EPERM`. If the root directory does not exist, then it will
|
||||
fail with `ENOENT`.
|
||||
|
||||
On posix file systems, attempts to create a root directory (in recursive
|
||||
mode) will succeed silently, as it is treated like just another directory
|
||||
that already exists. (In non-recursive mode, of course, it fails with
|
||||
`EEXIST`.)
|
||||
|
||||
In order to preserve this system-specific behavior (and because it's not as
|
||||
if we can create the parent of a root directory anyway), attempts to create
|
||||
a root directory are passed directly to the `fs` implementation, and any
|
||||
errors encountered are not handled.
|
||||
|
||||
## native error caveat
|
||||
|
||||
The native implementation (as of at least Node.js v13.4.0) does not provide
|
||||
appropriate errors in some cases (see
|
||||
[nodejs/node#31481](https://github.com/nodejs/node/issues/31481) and
|
||||
[nodejs/node#28015](https://github.com/nodejs/node/issues/28015)).
|
||||
|
||||
In order to work around this issue, the native implementation will fall
|
||||
back to the manual implementation if an `ENOENT` error is encountered.
|
||||
|
||||
# choosing a recursive mkdir implementation
|
||||
|
||||
There are a few to choose from! Use the one that suits your needs best :D
|
||||
|
||||
## use `fs.mkdir(path, {recursive: true}, cb)` if:
|
||||
|
||||
- You wish to optimize performance even at the expense of other factors.
|
||||
- You don't need to know the first dir created.
|
||||
- You are ok with getting `ENOENT` as the error when some other problem is
|
||||
the actual cause.
|
||||
- You can limit your platforms to Node.js v10.12 and above.
|
||||
- You're ok with using callbacks instead of promises.
|
||||
- You don't need/want a CLI.
|
||||
- You don't need to override the `fs` methods in use.
|
||||
|
||||
## use this module (mkdirp 1.x) if:
|
||||
|
||||
- You need to know the first directory that was created.
|
||||
- You wish to use the native implementation if available, but fall back
|
||||
when it's not.
|
||||
- You prefer promise-returning APIs to callback-taking APIs.
|
||||
- You want more useful error messages than the native recursive mkdir
|
||||
provides (at least as of Node.js v13.4), and are ok with re-trying on
|
||||
`ENOENT` to achieve this.
|
||||
- You need (or at least, are ok with) a CLI.
|
||||
- You need to override the `fs` methods in use.
|
||||
|
||||
## use [`make-dir`](http://npm.im/make-dir) if:
|
||||
|
||||
- You do not need to know the first dir created (and wish to save a few
|
||||
`stat` calls when using the native implementation for this reason).
|
||||
- You wish to use the native implementation if available, but fall back
|
||||
when it's not.
|
||||
- You prefer promise-returning APIs to callback-taking APIs.
|
||||
- You are ok with occasionally getting `ENOENT` errors for failures that
|
||||
are actually related to something other than a missing file system entry.
|
||||
- You don't need/want a CLI.
|
||||
- You need to override the `fs` methods in use.
|
||||
|
||||
## use mkdirp 0.x if:
|
||||
|
||||
- You need to know the first directory that was created.
|
||||
- You need (or at least, are ok with) a CLI.
|
||||
- You need to override the `fs` methods in use.
|
||||
- You're ok with using callbacks instead of promises.
|
||||
- You are not running on Windows, where the root-level ENOENT errors can
|
||||
lead to infinite regress.
|
||||
- You think vinyl just sounds warmer and richer for some weird reason.
|
||||
- You are supporting truly ancient Node.js versions, before even the advent
|
||||
of a `Promise` language primitive. (Please don't. You deserve better.)
|
||||
|
||||
# cli
|
||||
|
||||
This package also ships with a `mkdirp` command.
|
||||
|
||||
```
|
||||
$ mkdirp -h
|
||||
|
||||
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
|
||||
|
||||
Create each supplied directory including any necessary parent directories
|
||||
that don't yet exist.
|
||||
|
||||
If the directory already exists, do nothing.
|
||||
|
||||
OPTIONS are:
|
||||
|
||||
-m<mode> If a directory needs to be created, set the mode as an octal
|
||||
--mode=<mode> permission string.
|
||||
|
||||
-v --version Print the mkdirp version number
|
||||
|
||||
-h --help Print this helpful banner
|
||||
|
||||
-p --print Print the first directories created for each path provided
|
||||
|
||||
--manual Use manual implementation, even if native is available
|
||||
```
|
||||
|
||||
# install
|
||||
|
||||
With [npm](http://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm install mkdirp
|
||||
```
|
||||
|
||||
to get the library locally, or
|
||||
|
||||
```
|
||||
npm install -g mkdirp
|
||||
```
|
||||
|
||||
to get the command everywhere, or
|
||||
|
||||
```
|
||||
npx mkdirp ...
|
||||
```
|
||||
|
||||
to run the command without installing it globally.
|
||||
|
||||
# platform support
|
||||
|
||||
This module works on node v8, but only v10 and above are officially
|
||||
supported, as Node v8 reached its LTS end of life 2020-01-01, which is in
|
||||
the past, as of this writing.
|
||||
|
||||
# license
|
||||
|
||||
MIT
|
162
node_modules/lv_font_conv/node_modules/ms/index.js
generated
vendored
Normal file
162
node_modules/lv_font_conv/node_modules/ms/index.js
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
|
||||
var s = 1000;
|
||||
var m = s * 60;
|
||||
var h = m * 60;
|
||||
var d = h * 24;
|
||||
var w = d * 7;
|
||||
var y = d * 365.25;
|
||||
|
||||
/**
|
||||
* Parse or format the given `val`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `long` verbose formatting [false]
|
||||
*
|
||||
* @param {String|Number} val
|
||||
* @param {Object} [options]
|
||||
* @throws {Error} throw an error if val is not a non-empty string or a number
|
||||
* @return {String|Number}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
module.exports = function(val, options) {
|
||||
options = options || {};
|
||||
var type = typeof val;
|
||||
if (type === 'string' && val.length > 0) {
|
||||
return parse(val);
|
||||
} else if (type === 'number' && isFinite(val)) {
|
||||
return options.long ? fmtLong(val) : fmtShort(val);
|
||||
}
|
||||
throw new Error(
|
||||
'val is not a non-empty string or a valid number. val=' +
|
||||
JSON.stringify(val)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the given `str` and return milliseconds.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function parse(str) {
|
||||
str = String(str);
|
||||
if (str.length > 100) {
|
||||
return;
|
||||
}
|
||||
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
|
||||
str
|
||||
);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
var n = parseFloat(match[1]);
|
||||
var type = (match[2] || 'ms').toLowerCase();
|
||||
switch (type) {
|
||||
case 'years':
|
||||
case 'year':
|
||||
case 'yrs':
|
||||
case 'yr':
|
||||
case 'y':
|
||||
return n * y;
|
||||
case 'weeks':
|
||||
case 'week':
|
||||
case 'w':
|
||||
return n * w;
|
||||
case 'days':
|
||||
case 'day':
|
||||
case 'd':
|
||||
return n * d;
|
||||
case 'hours':
|
||||
case 'hour':
|
||||
case 'hrs':
|
||||
case 'hr':
|
||||
case 'h':
|
||||
return n * h;
|
||||
case 'minutes':
|
||||
case 'minute':
|
||||
case 'mins':
|
||||
case 'min':
|
||||
case 'm':
|
||||
return n * m;
|
||||
case 'seconds':
|
||||
case 'second':
|
||||
case 'secs':
|
||||
case 'sec':
|
||||
case 's':
|
||||
return n * s;
|
||||
case 'milliseconds':
|
||||
case 'millisecond':
|
||||
case 'msecs':
|
||||
case 'msec':
|
||||
case 'ms':
|
||||
return n;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Short format for `ms`.
|
||||
*
|
||||
* @param {Number} ms
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function fmtShort(ms) {
|
||||
var msAbs = Math.abs(ms);
|
||||
if (msAbs >= d) {
|
||||
return Math.round(ms / d) + 'd';
|
||||
}
|
||||
if (msAbs >= h) {
|
||||
return Math.round(ms / h) + 'h';
|
||||
}
|
||||
if (msAbs >= m) {
|
||||
return Math.round(ms / m) + 'm';
|
||||
}
|
||||
if (msAbs >= s) {
|
||||
return Math.round(ms / s) + 's';
|
||||
}
|
||||
return ms + 'ms';
|
||||
}
|
||||
|
||||
/**
|
||||
* Long format for `ms`.
|
||||
*
|
||||
* @param {Number} ms
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function fmtLong(ms) {
|
||||
var msAbs = Math.abs(ms);
|
||||
if (msAbs >= d) {
|
||||
return plural(ms, msAbs, d, 'day');
|
||||
}
|
||||
if (msAbs >= h) {
|
||||
return plural(ms, msAbs, h, 'hour');
|
||||
}
|
||||
if (msAbs >= m) {
|
||||
return plural(ms, msAbs, m, 'minute');
|
||||
}
|
||||
if (msAbs >= s) {
|
||||
return plural(ms, msAbs, s, 'second');
|
||||
}
|
||||
return ms + ' ms';
|
||||
}
|
||||
|
||||
/**
|
||||
* Pluralization helper.
|
||||
*/
|
||||
|
||||
function plural(ms, msAbs, n, name) {
|
||||
var isPlural = msAbs >= n * 1.5;
|
||||
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
|
||||
}
|
21
node_modules/lv_font_conv/node_modules/ms/license.md
generated
vendored
Normal file
21
node_modules/lv_font_conv/node_modules/ms/license.md
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Zeit, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
72
node_modules/lv_font_conv/node_modules/ms/package.json
generated
vendored
Normal file
72
node_modules/lv_font_conv/node_modules/ms/package.json
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"ms@2.1.2",
|
||||
"/home/vitaly/Dropbox/Coding/lv_font_conv"
|
||||
]
|
||||
],
|
||||
"_from": "ms@2.1.2",
|
||||
"_id": "ms@2.1.2",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"_location": "/ms",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "ms@2.1.2",
|
||||
"name": "ms",
|
||||
"escapedName": "ms",
|
||||
"rawSpec": "2.1.2",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "2.1.2"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/debug"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"_spec": "2.1.2",
|
||||
"_where": "/home/vitaly/Dropbox/Coding/lv_font_conv",
|
||||
"bugs": {
|
||||
"url": "https://github.com/zeit/ms/issues"
|
||||
},
|
||||
"description": "Tiny millisecond conversion utility",
|
||||
"devDependencies": {
|
||||
"eslint": "4.12.1",
|
||||
"expect.js": "0.3.1",
|
||||
"husky": "0.14.3",
|
||||
"lint-staged": "5.0.0",
|
||||
"mocha": "4.0.1"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"homepage": "https://github.com/zeit/ms#readme",
|
||||
"license": "MIT",
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"npm run lint",
|
||||
"prettier --single-quote --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"main": "./index",
|
||||
"name": "ms",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/zeit/ms.git"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint lib/* bin/*",
|
||||
"precommit": "lint-staged",
|
||||
"test": "mocha tests.js"
|
||||
},
|
||||
"version": "2.1.2"
|
||||
}
|
60
node_modules/lv_font_conv/node_modules/ms/readme.md
generated
vendored
Normal file
60
node_modules/lv_font_conv/node_modules/ms/readme.md
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
# ms
|
||||
|
||||
[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
|
||||
[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/zeit)
|
||||
|
||||
Use this package to easily convert various time formats to milliseconds.
|
||||
|
||||
## Examples
|
||||
|
||||
```js
|
||||
ms('2 days') // 172800000
|
||||
ms('1d') // 86400000
|
||||
ms('10h') // 36000000
|
||||
ms('2.5 hrs') // 9000000
|
||||
ms('2h') // 7200000
|
||||
ms('1m') // 60000
|
||||
ms('5s') // 5000
|
||||
ms('1y') // 31557600000
|
||||
ms('100') // 100
|
||||
ms('-3 days') // -259200000
|
||||
ms('-1h') // -3600000
|
||||
ms('-200') // -200
|
||||
```
|
||||
|
||||
### Convert from Milliseconds
|
||||
|
||||
```js
|
||||
ms(60000) // "1m"
|
||||
ms(2 * 60000) // "2m"
|
||||
ms(-3 * 60000) // "-3m"
|
||||
ms(ms('10 hours')) // "10h"
|
||||
```
|
||||
|
||||
### Time Format Written-Out
|
||||
|
||||
```js
|
||||
ms(60000, { long: true }) // "1 minute"
|
||||
ms(2 * 60000, { long: true }) // "2 minutes"
|
||||
ms(-3 * 60000, { long: true }) // "-3 minutes"
|
||||
ms(ms('10 hours'), { long: true }) // "10 hours"
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Works both in [Node.js](https://nodejs.org) and in the browser
|
||||
- If a number is supplied to `ms`, a string with a unit is returned
|
||||
- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`)
|
||||
- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned
|
||||
|
||||
## Related Packages
|
||||
|
||||
- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time.
|
||||
|
||||
## Caught a Bug?
|
||||
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
|
||||
2. Link the package to the global module directory: `npm link`
|
||||
3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms!
|
||||
|
||||
As always, you can run the tests using: `npm test`
|
20
node_modules/lv_font_conv/node_modules/opentype.js/LICENSE
generated
vendored
Normal file
20
node_modules/lv_font_conv/node_modules/opentype.js/LICENSE
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Frederik De Bleser
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
313
node_modules/lv_font_conv/node_modules/opentype.js/README.md
generated
vendored
Normal file
313
node_modules/lv_font_conv/node_modules/opentype.js/README.md
generated
vendored
Normal file
@ -0,0 +1,313 @@
|
||||
|
||||
# opentype.js · [![Build Status](https://img.shields.io/travis/opentypejs/opentype.js.svg?style=flat-square)](https://travis-ci.org/opentypejs/opentype.js) [![npm](https://img.shields.io/npm/v/opentype.js.svg?style=flat-square)](https://www.npmjs.com/package/opentype.js) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/opentypejs/opentype.js/blob/master/LICENSE) [![david-dm](https://david-dm.org/opentypejs/opentype.js.svg)](https://david-dm.org/opentypejs/opentype.js) [![Gitter](https://badges.gitter.im/opentypejs/opentype.js.svg)](https://gitter.im/opentypejs/opentype.js)
|
||||
|
||||
opentype.js is a JavaScript parser and writer for TrueType and OpenType fonts.
|
||||
|
||||
It gives you access to the <strong>letterforms</strong> of text from the browser or Node.js.
|
||||
See [https://opentype.js.org/](https://opentype.js.org/) for a live demo.
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
* Create a bézier path out of a piece of text.
|
||||
* Support for composite glyphs (accented letters).
|
||||
* Support for WOFF, OTF, TTF (both with TrueType `glyf` and PostScript `cff` outlines)
|
||||
* Support for kerning (Using GPOS or the kern table).
|
||||
* Support for ligatures.
|
||||
* Support for TrueType font hinting.
|
||||
* Support arabic text rendering (See issue #364 & PR #359 #361)
|
||||
* A low memory mode is available as an option (see #329)
|
||||
* Runs in the browser and Node.js.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
### Using [npm](http://npmjs.org/) package manager
|
||||
|
||||
npm install opentype.js
|
||||
|
||||
const opentype = require('opentype.js');
|
||||
|
||||
import opentype from 'opentype.js'
|
||||
|
||||
import { load } from 'opentype.js'
|
||||
|
||||
Using TypeScript? [See this example](examples/typescript)
|
||||
|
||||
Note: OpenType.js uses ES6-style imports, so if you want to edit it and debug it in Node.js run `npm run build` first and use `npm run watch` to automatically rebuild when files change.
|
||||
|
||||
### Directly
|
||||
|
||||
[Download the latest ZIP](https://github.com/opentypejs/opentype.js/archive/master.zip) and grab the files in the `dist`
|
||||
folder. These are compiled.
|
||||
|
||||
### Using via a CDN
|
||||
|
||||
To use via a CDN, include the following code in your html:
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>
|
||||
|
||||
### Using Bower (Deprecated [see official post](https://bower.io/blog/2017/how-to-migrate-away-from-bower/))
|
||||
|
||||
To install using [Bower](https://bower.io/), enter the following command in your project directory:
|
||||
|
||||
bower install opentype.js
|
||||
|
||||
You can then include them in your scripts using:
|
||||
|
||||
<script src="/bower_components/opentype.js/dist/opentype.js"></script>
|
||||
|
||||
|
||||
API
|
||||
===
|
||||
### Loading a font
|
||||
![OpenType.js example Hello World](https://raw.github.com/opentypejs/opentype.js/master/g/hello-world.png)
|
||||
|
||||
Use `opentype.load(url, callback)` to load a font from a URL. Since this method goes out the network, it is asynchronous.
|
||||
The callback gets `(err, font)` where `font` is a `Font` object. Check if the `err` is null before using the font.
|
||||
```javascript
|
||||
opentype.load('fonts/Roboto-Black.ttf', function(err, font) {
|
||||
if (err) {
|
||||
alert('Font could not be loaded: ' + err);
|
||||
} else {
|
||||
// Now let's display it on a canvas with id "canvas"
|
||||
const ctx = document.getElementById('canvas').getContext('2d');
|
||||
|
||||
// Construct a Path object containing the letter shapes of the given text.
|
||||
// The other parameters are x, y and fontSize.
|
||||
// Note that y is the position of the baseline.
|
||||
const path = font.getPath('Hello, World!', 0, 150, 72);
|
||||
|
||||
// If you just want to draw the text you can also use font.draw(ctx, text, x, y, fontSize).
|
||||
path.draw(ctx);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
You can also use `es6 async/await` syntax to load your fonts
|
||||
|
||||
```javascript
|
||||
async function make(){
|
||||
const font = await opentype.load('fonts/Roboto-Black.ttf');
|
||||
const path = font.getPath('Hello, World!', 0, 150, 72);
|
||||
console.log(path);
|
||||
}
|
||||
```
|
||||
|
||||
If you already have an `ArrayBuffer`, you can use `opentype.parse(buffer)` to parse the buffer. This method always
|
||||
returns a Font, but check `font.supported` to see if the font is in a supported format. (Fonts can be marked unsupported
|
||||
if they have encoding tables we can't read).
|
||||
|
||||
const font = opentype.parse(myBuffer);
|
||||
|
||||
### Loading a font synchronously (Node.js)
|
||||
Use `opentype.loadSync(url)` to load a font from a file and return a `Font` object.
|
||||
Throws an error if the font could not be parsed. This only works in Node.js.
|
||||
|
||||
const font = opentype.loadSync('fonts/Roboto-Black.ttf');
|
||||
|
||||
### Writing a font
|
||||
Once you have a `Font` object (either by using `opentype.load` or by creating a new one from scratch) you can write it
|
||||
back out as a binary file.
|
||||
|
||||
In the browser, you can use `Font.download()` to instruct the browser to download a binary .OTF file. The name is based
|
||||
on the font name.
|
||||
```javascript
|
||||
// Create the bézier paths for each of the glyphs.
|
||||
// Note that the .notdef glyph is required.
|
||||
const notdefGlyph = new opentype.Glyph({
|
||||
name: '.notdef',
|
||||
unicode: 0,
|
||||
advanceWidth: 650,
|
||||
path: new opentype.Path()
|
||||
});
|
||||
|
||||
const aPath = new opentype.Path();
|
||||
aPath.moveTo(100, 0);
|
||||
aPath.lineTo(100, 700);
|
||||
// more drawing instructions...
|
||||
const aGlyph = new opentype.Glyph({
|
||||
name: 'A',
|
||||
unicode: 65,
|
||||
advanceWidth: 650,
|
||||
path: aPath
|
||||
});
|
||||
|
||||
const glyphs = [notdefGlyph, aGlyph];
|
||||
const font = new opentype.Font({
|
||||
familyName: 'OpenTypeSans',
|
||||
styleName: 'Medium',
|
||||
unitsPerEm: 1000,
|
||||
ascender: 800,
|
||||
descender: -200,
|
||||
glyphs: glyphs});
|
||||
font.download();
|
||||
```
|
||||
|
||||
If you want to inspect the font, use `font.toTables()` to generate an object showing the data structures that map
|
||||
directly to binary values. If you want to get an `ArrayBuffer`, use `font.toArrayBuffer()`.
|
||||
|
||||
|
||||
### The Font object
|
||||
A Font represents a loaded OpenType font file. It contains a set of glyphs and methods to draw text on a drawing context, or to get a path representing the text.
|
||||
|
||||
* `glyphs`: an indexed list of Glyph objects.
|
||||
* `unitsPerEm`: X/Y coordinates in fonts are stored as integers. This value determines the size of the grid. Common values are 2048 and 4096.
|
||||
* `ascender`: Distance from baseline of highest ascender. In font units, not pixels.
|
||||
* `descender`: Distance from baseline of lowest descender. In font units, not pixels.
|
||||
|
||||
#### `Font.getPath(text, x, y, fontSize, options)`
|
||||
Create a Path that represents the given text.
|
||||
* `x`: Horizontal position of the beginning of the text. (default: 0)
|
||||
* `y`: Vertical position of the *baseline* of the text. (default: 0)
|
||||
* `fontSize`: Size of the text in pixels (default: 72).
|
||||
|
||||
Options is an optional object containing:
|
||||
* `kerning`: if true takes kerning information into account (default: true)
|
||||
* `features`: an object with [OpenType feature tags](https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags) as keys, and a boolean value to enable each feature.
|
||||
Currently only ligature features "liga" and "rlig" are supported (default: true).
|
||||
* `hinting`: if true uses TrueType font hinting if available (default: false).
|
||||
|
||||
_Note: there is also `Font.getPaths` with the same arguments which returns a list of Paths._
|
||||
|
||||
#### `Font.draw(ctx, text, x, y, fontSize, options)`
|
||||
Create a Path that represents the given text.
|
||||
* `ctx`: A 2D drawing context, like Canvas.
|
||||
* `x`: Horizontal position of the beginning of the text. (default: 0)
|
||||
* `y`: Vertical position of the *baseline* of the text. (default: 0)
|
||||
* `fontSize`: Size of the text in pixels (default: 72).
|
||||
|
||||
Options is an optional object containing:
|
||||
* `kerning`: if true takes kerning information into account (default: true)
|
||||
* `features`: an object with [OpenType feature tags](https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags) as keys, and a boolean value to enable each feature.
|
||||
Currently only ligature features "liga" and "rlig" are supported (default: true).
|
||||
* `hinting`: if true uses TrueType font hinting if available (default: false).
|
||||
|
||||
#### `Font.drawPoints(ctx, text, x, y, fontSize, options)`
|
||||
Draw the points of all glyphs in the text. On-curve points will be drawn in blue, off-curve points will be drawn in red. The arguments are the same as `Font.draw`.
|
||||
|
||||
#### `Font.drawMetrics(ctx, text, x, y, fontSize, options)`
|
||||
Draw lines indicating important font measurements for all glyphs in the text.
|
||||
Black lines indicate the origin of the coordinate system (point 0,0).
|
||||
Blue lines indicate the glyph bounding box.
|
||||
Green line indicates the advance width of the glyph.
|
||||
|
||||
#### `Font.stringToGlyphs(string)`
|
||||
Convert the string to a list of glyph objects.
|
||||
Note that there is no strict 1-to-1 correspondence between the string and glyph list due to
|
||||
possible substitutions such as ligatures. The list of returned glyphs can be larger or smaller than the length of the given string.
|
||||
|
||||
#### `Font.charToGlyph(char)`
|
||||
Convert the character to a `Glyph` object. Returns null if the glyph could not be found. Note that this function assumes that there is a one-to-one mapping between the given character and a glyph; for complex scripts this might not be the case.
|
||||
|
||||
#### `Font.getKerningValue(leftGlyph, rightGlyph)`
|
||||
Retrieve the value of the [kerning pair](https://en.wikipedia.org/wiki/Kerning) between the left glyph (or its index) and the right glyph (or its index). If no kerning pair is found, return 0. The kerning value gets added to the advance width when calculating the spacing between glyphs.
|
||||
|
||||
#### `Font.getAdvanceWidth(text, fontSize, options)`
|
||||
Returns the advance width of a text.
|
||||
|
||||
This is something different than Path.getBoundingBox() as for example a
|
||||
suffixed whitespace increases the advancewidth but not the bounding box
|
||||
or an overhanging letter like a calligraphic 'f' might have a quite larger
|
||||
bounding box than its advance width.
|
||||
|
||||
This corresponds to canvas2dContext.measureText(text).width
|
||||
* `fontSize`: Size of the text in pixels (default: 72).
|
||||
* `options`: See Font.getPath
|
||||
|
||||
#### The Glyph object
|
||||
A Glyph is an individual mark that often corresponds to a character. Some glyphs, such as ligatures, are a combination of many characters. Glyphs are the basic building blocks of a font.
|
||||
|
||||
* `font`: A reference to the `Font` object.
|
||||
* `name`: The glyph name (e.g. "Aring", "five")
|
||||
* `unicode`: The primary unicode value of this glyph (can be `undefined`).
|
||||
* `unicodes`: The list of unicode values for this glyph (most of the time this will be 1, can also be empty).
|
||||
* `index`: The index number of the glyph.
|
||||
* `advanceWidth`: The width to advance the pen when drawing this glyph.
|
||||
* `xMin`, `yMin`, `xMax`, `yMax`: The bounding box of the glyph.
|
||||
* `path`: The raw, unscaled path of the glyph.
|
||||
|
||||
##### `Glyph.getPath(x, y, fontSize)`
|
||||
Get a scaled glyph Path object we can draw on a drawing context.
|
||||
* `x`: Horizontal position of the glyph. (default: 0)
|
||||
* `y`: Vertical position of the *baseline* of the glyph. (default: 0)
|
||||
* `fontSize`: Font size in pixels (default: 72).
|
||||
|
||||
##### `Glyph.getBoundingBox()`
|
||||
Calculate the minimum bounding box for the unscaled path of the given glyph. Returns an `opentype.BoundingBox` object that contains x1/y1/x2/y2.
|
||||
If the glyph has no points (e.g. a space character), all coordinates will be zero.
|
||||
|
||||
##### `Glyph.draw(ctx, x, y, fontSize)`
|
||||
Draw the glyph on the given context.
|
||||
* `ctx`: The drawing context.
|
||||
* `x`: Horizontal position of the glyph. (default: 0)
|
||||
* `y`: Vertical position of the *baseline* of the glyph. (default: 0)
|
||||
* `fontSize`: Font size, in pixels (default: 72).
|
||||
|
||||
##### `Glyph.drawPoints(ctx, x, y, fontSize)`
|
||||
Draw the points of the glyph on the given context.
|
||||
On-curve points will be drawn in blue, off-curve points will be drawn in red.
|
||||
The arguments are the same as `Glyph.draw`.
|
||||
|
||||
##### `Glyph.drawMetrics(ctx, x, y, fontSize)`
|
||||
Draw lines indicating important font measurements for all glyphs in the text.
|
||||
Black lines indicate the origin of the coordinate system (point 0,0).
|
||||
Blue lines indicate the glyph bounding box.
|
||||
Green line indicates the advance width of the glyph.
|
||||
The arguments are the same as `Glyph.draw`.
|
||||
|
||||
### The Path object
|
||||
Once you have a path through `Font.getPath` or `Glyph.getPath`, you can use it.
|
||||
|
||||
* `commands`: The path commands. Each command is a dictionary containing a type and coordinates. See below for examples.
|
||||
* `fill`: The fill color of the `Path`. Color is a string representing a [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). (default: 'black')
|
||||
* `stroke`: The stroke color of the `Path`. Color is a string representing a [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). (default: `null`: the path will not be stroked)
|
||||
* `strokeWidth`: The line thickness of the `Path`. (default: 1, but since the `stroke` is null no stroke will be drawn)
|
||||
|
||||
##### `Path.draw(ctx)`
|
||||
Draw the path on the given 2D context. This uses the `fill`, `stroke` and `strokeWidth` properties of the `Path` object.
|
||||
* `ctx`: The drawing context.
|
||||
|
||||
##### `Path.getBoundingBox()`
|
||||
Calculate the minimum bounding box for the given path. Returns an `opentype.BoundingBox` object that contains x1/y1/x2/y2.
|
||||
If the path is empty (e.g. a space character), all coordinates will be zero.
|
||||
|
||||
##### `Path.toPathData(decimalPlaces)`
|
||||
Convert the Path to a string of path data instructions.
|
||||
See https://www.w3.org/TR/SVG/paths.html#PathData
|
||||
* `decimalPlaces`: The amount of decimal places for floating-point values. (default: 2)
|
||||
|
||||
##### `Path.toSVG(decimalPlaces)`
|
||||
Convert the path to a SVG <path> element, as a string.
|
||||
* `decimalPlaces`: The amount of decimal places for floating-point values. (default: 2)
|
||||
|
||||
#### Path commands
|
||||
* **Move To**: Move to a new position. This creates a new contour. Example: `{type: 'M', x: 100, y: 200}`
|
||||
* **Line To**: Draw a line from the previous position to the given coordinate. Example: `{type: 'L', x: 100, y: 200}`
|
||||
* **Curve To**: Draw a bézier curve from the current position to the given coordinate. Example: `{type: 'C', x1: 0, y1: 50, x2: 100, y2: 200, x: 100, y: 200}`
|
||||
* **Quad To**: Draw a quadratic bézier curve from the current position to the given coordinate. Example: `{type: 'Q', x1: 0, y1: 50, x: 100, y: 200}`
|
||||
* **Close**: Close the path. If stroked, this will draw a line from the first to the last point of the contour. Example: `{type: 'Z'}`
|
||||
|
||||
|
||||
## Versioning
|
||||
|
||||
We use [SemVer](https://semver.org/) for versioning.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
|
||||
Thanks
|
||||
======
|
||||
I would like to acknowledge the work of others without which opentype.js wouldn't be possible:
|
||||
|
||||
* [pdf.js](https://mozilla.github.io/pdf.js/): for an awesome implementation of font parsing in the browser.
|
||||
* [FreeType](https://www.freetype.org/): for the nitty-gritty details and filling in the gaps when the spec was incomplete.
|
||||
* [ttf.js](https://ynakajima.github.io/ttf.js/demo/glyflist/): for hints about the TrueType parsing code.
|
||||
* [CFF-glyphlet-fonts](https://pomax.github.io/CFF-glyphlet-fonts/): for a great explanation/implementation of CFF font writing.
|
||||
* [tiny-inflate](https://github.com/foliojs/tiny-inflate): for WOFF decompression.
|
||||
* [Microsoft Typography](https://docs.microsoft.com/en-us/typography/opentype/spec/otff): the go-to reference for all things OpenType.
|
||||
* [Adobe Compact Font Format spec](http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/cff.pdf) and the [Adobe Type 2 Charstring spec](http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/type2.pdf): explains the data structures and commands for the CFF glyph format.
|
||||
* All contributing authors mentioned in the [AUTHORS](https://github.com/opentypejs/opentype.js/blob/master/AUTHORS.md) file.
|
267
node_modules/lv_font_conv/node_modules/opentype.js/RELEASES.md
generated
vendored
Normal file
267
node_modules/lv_font_conv/node_modules/opentype.js/RELEASES.md
generated
vendored
Normal file
@ -0,0 +1,267 @@
|
||||
1.3.3 (April 20, 2020)
|
||||
=====================
|
||||
* fix GlyphOptions with falsy values (#430)
|
||||
|
||||
1.3.2 (April 20, 2020)
|
||||
=====================
|
||||
* Re-export named exports with a default export and add a TypeScript import example
|
||||
|
||||
* 1.3.1 (April 13, 2020)
|
||||
=====================
|
||||
* Revert Fix Path.toPathData and Path.toSVG - X Axis is flipped (#369)
|
||||
|
||||
1.3.0 (April 13, 2020)
|
||||
=====================
|
||||
* Forward os2 Table attributs during font construction (#422)
|
||||
* Add default export
|
||||
|
||||
1.2.1 (April 13, 2020)
|
||||
=====================
|
||||
* Fix Path.toPathData and Path.toSVG - X Axis is flipped (#369)
|
||||
* Fix use of Promise / async/await in the load function (#427)
|
||||
* Fix a bug for unsupported SUBSTITUTIONS #403
|
||||
|
||||
1.2.0 (April 13, 2020)
|
||||
=====================
|
||||
* Fix issue #385, merge default options with user options (#386)
|
||||
* Adds support for browser Async/Await for .load() (#389)
|
||||
* Introduce ES6 module build (#391)
|
||||
* Fix test in featureQuery
|
||||
* Remove Node 4 from Travis (#392)
|
||||
* Update dependencies & build dist files
|
||||
|
||||
1.1.0 (May 1, 2019)
|
||||
=====================
|
||||
* Support reading GSUB Single substitution format 1 (PR #382) (thanks @solomancode!)
|
||||
|
||||
1.0.1 (April 19, 2019)
|
||||
=====================
|
||||
* Fix error if defaultLangSys is undefined (Issue #378)
|
||||
|
||||
1.0.0 (April 17, 2019)
|
||||
=====================
|
||||
* Render arabic rtl text properly (PR #361, partial fix of #364) (thanks @solomancode!)
|
||||
* #361 introduced a breaking change to `Font.prototype.defaultRenderOptions`
|
||||
Before
|
||||
```js
|
||||
Font.prototype.defaultRenderOptions = {
|
||||
kerning: true,
|
||||
features: {
|
||||
liga: true,
|
||||
rlig: true
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Now
|
||||
```js
|
||||
Font.prototype.defaultRenderOptions = {
|
||||
kerning: true,
|
||||
features: [
|
||||
/**
|
||||
* these 4 features are required to render Arabic text properly
|
||||
* and shouldn't be turned off when rendering arabic text.
|
||||
*/
|
||||
{ script: 'arab', tags: ['init', 'medi', 'fina', 'rlig'] },
|
||||
{ script: 'latn', tags: ['liga', 'rlig'] }
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
Also as this project is now using SemVer, the breaking change required a new major version, 1.0.0!
|
||||
|
||||
0.12.0 (April 17, 2019)
|
||||
=====================
|
||||
* Fix Glyph.getPath() issue (PR #362, fixes #363) (thanks @solomancode!)
|
||||
* Add lowMemory mode (PR #329) (thanks @debussy2k!)
|
||||
* Update README (PR #377) (thanks @jolg42!)
|
||||
|
||||
0.11.0 (October 22, 2018)
|
||||
=====================
|
||||
* Support Arabic text rendering (PR #359, fixes #46) (thanks @solomancode!)
|
||||
|
||||
0.10.0 (August 14, 2018)
|
||||
=====================
|
||||
* font.download(): use window.URL instead of window.requestFileSystem, which works on a larger set of browsers : Chrome (32+), Opera (19+), Firefox (26+), Safari (7.1+), and all of Edge.
|
||||
|
||||
0.9.0 (June 21, 2018)
|
||||
=====================
|
||||
* Update/Migrate rollup, update all dependencies, add package-lock.json and fix circular dependency (thanks @jolg42!)
|
||||
* Parse cmap table with platform id 0 as well (PR #350, fixes #348) (thanks @moyogo!)
|
||||
* Prevent auto-generated postScriptName from containing whitespace (#339) (thanks @mqudsi!)
|
||||
* Support non-Basic-Multilingual-Plane (BMP) characters (#338) (thanks @antonytse!)
|
||||
* GPOS: display correct error message in some cases of malformed data (#336) (thanks @fpirsch!)
|
||||
* Restore simple GPOS kerning in font.getKerningValue (#335) (thanks @fpirsch!)
|
||||
* Fix duplicated lineTo when using `getPath` (#328) (thanks @jolg42!)
|
||||
* Change example generate-font-node.js to be compatible with any Node.js version (thanks @jolg42!)
|
||||
|
||||
0.8.0 (March 6, 2018)
|
||||
=====================
|
||||
* Fix loading font file on Android devices (thanks @maoamid!).
|
||||
* Fix loading fonts from a local source (file://data/... for Android for example (thanks @IntuilabGit!).
|
||||
* Fixing 2 issues when hinting "mutlu.ttf" (thanks @axkibe!).
|
||||
* Add some support for OpenType font variations (thanks @taylorb-monotype!).
|
||||
* Make cmap table format 12 if needed (thanks @Jolg42!).
|
||||
* Enable uglify's mangle and compress optimizations for a ~30% smaller minified file. (thanks @lojjic & @Jolg42!).
|
||||
* Better parsing of NULL pointers (thanks @fpirsch!).
|
||||
* Fix bad path init (empty glyphs) (thanks @fpirsch!).
|
||||
* Rewrite GPOS parsing (thanks @fpirsch!).
|
||||
* Roboto-Black.ttf updated (thanks @Jolg42!).
|
||||
|
||||
0.7.3 (July 18, 2017)
|
||||
=====================
|
||||
* Fix "Object x already has key" error in Safari (thanks @neiltron!).
|
||||
* Fixed a bug where Font.getPaths() didn't pass options (thanks @keeslinp!).
|
||||
|
||||
0.7.2 (June 7, 2017)
|
||||
====================
|
||||
* WOFF fonts with cvt tables now parse correctly.
|
||||
* Migrated to ES6 modules and let/const.
|
||||
* Use Rollup to bundle the JavaScript.
|
||||
|
||||
0.7.1 (Apr 25, 2017)
|
||||
====================
|
||||
* Auto-generated glyph IDs (CID-keyed fonts) are now prefixed with "gid", e.g. "gid42".
|
||||
* Fix ligature substitution for fonts with coverage table format 2.
|
||||
* Better error messages when no valid cmap is found.
|
||||
|
||||
0.7.0 (Apr 25, 2017)
|
||||
====================
|
||||
* Add font hinting (thanks @axkibe!)
|
||||
* Add support for CID-keyed fonts, thanks to @tshinnic.
|
||||
* TrueType fonts with signature 'true' or 'typ1' are also supported.
|
||||
* Fixing rounding issues.
|
||||
* Add GSUB and kern output in font-inspector.
|
||||
* Add font loading error callback.
|
||||
* Dev server turns browser caching off.
|
||||
* Add encoding support for variation adjustment deltas (thanks @brawer!).
|
||||
|
||||
0.6.9 (Jan 17, 2017)
|
||||
====================
|
||||
* Add ligature rendering (thanks @fpirsch!)
|
||||
|
||||
0.6.8 (Jan 9, 2017)
|
||||
=========================
|
||||
* Add a `getBoundingBox` method to the `Path` and `Glyph` objects.
|
||||
|
||||
0.6.7 (Jan 5, 2017)
|
||||
=========================
|
||||
* Add basic support for Mac OS X format kern tables.
|
||||
|
||||
0.6.6 (October 25, 2016)
|
||||
=========================
|
||||
* Add support for letter-spacing and tracking (thanks @lachmanski!).
|
||||
* Fixed a bug in the nameToGlyph function.
|
||||
|
||||
0.6.5 (September 9, 2016)
|
||||
=========================
|
||||
* GSUB reading and writing by @fpirsch. This is still missing a user-friendly API.
|
||||
* Add support for cmap table format 12, which enables support for Unicode characters outside of the 0x0 - 0xFFFF range.
|
||||
* Better API documentation using [JSDoc](http://usejsdoc.org/).
|
||||
* Accessing xMin/... metrics works before path load.
|
||||
|
||||
0.6.4 (June 30, 2016)
|
||||
=========================
|
||||
* Add X/Y scale options to compute a streched path of a glyph.
|
||||
* Correct reading/writing of font timestamps.
|
||||
* examples/generate-font-node.js now generates "full" Latin font.
|
||||
* Add OS/2 value options for weight, width and fsSelection.
|
||||
|
||||
0.6.3 (May 10, 2016)
|
||||
=========================
|
||||
* Wrapped parseBuffer in a try/catch so it doesn't throw exceptions. Thanks @rBurgett!
|
||||
* Fix a leaking global variable. Thanks @cuixiping!
|
||||
|
||||
0.6.2 (March 11, 2016)
|
||||
=========================
|
||||
* Improve table writing to support nested subtables. Thanks @fpirsch!
|
||||
|
||||
0.6.1 (February 20, 2016)
|
||||
=========================
|
||||
* Left side bearing is now correctly reported.
|
||||
* Simplified code for including ascender / descender values.
|
||||
|
||||
0.6.0 (December 1, 2015)
|
||||
========================
|
||||
* Improvements to font writing: generated fonts now work properly on OS X.
|
||||
* When creating a new font, ascender and descender are now required.
|
||||
|
||||
0.5.1 (October 26, 2015)
|
||||
========================
|
||||
* Add `Font.getPaths()` which returns a list of paths.
|
||||
|
||||
0.5.0 (October 6, 2015)
|
||||
=======================
|
||||
* Read support for WOFF.
|
||||
|
||||
0.4.11 (September 27, 2015)
|
||||
===========================
|
||||
* Fix issue with loading of TrueType composite glyphs.
|
||||
* Fix issue with missing hmtx values.
|
||||
* Sensible getMetrics() values for empty glyphs (e.g. space).
|
||||
|
||||
0.4.10 (July 30, 2015)
|
||||
======================
|
||||
* Add loadSync method for Node.js.
|
||||
* Unit tests for basic types and tables.
|
||||
* Implement MACSTRING codec.
|
||||
* Support multilingual names.
|
||||
* Handle names of font variation axes and instances.
|
||||
|
||||
0.4.9 (June 23, 2015)
|
||||
=====================
|
||||
* Improve memory usage by deferring glyph / path loading. Thanks @Pomax!
|
||||
* Put examples in the "examples" directory. Use the local web server to see them.
|
||||
|
||||
0.4.8 (June 3, 2015)
|
||||
====================
|
||||
* Fix an issue with writing out fonts that have an UPM != 1000.
|
||||
|
||||
0.4.6 (March 26, 2015)
|
||||
======================
|
||||
* Fix issues with exporting/subsetting TrueType fonts.
|
||||
* Improve validness of exported fonts.
|
||||
* Empty paths (think: space) no longer contain a single closePath command.
|
||||
* Fix issues with exporting fonts with TrueType half-point values.
|
||||
* Expose the internal byte parsing algorithms as opentype._parse.
|
||||
|
||||
0.4.5 (March 10, 2015)
|
||||
======================
|
||||
* Add support for writing quad curves.
|
||||
* Add support for CFF flex operators.
|
||||
* Close CFF subpaths.
|
||||
|
||||
0.4.4 (Dec 8, 2014)
|
||||
===================
|
||||
* Solve issues with Browserify.
|
||||
|
||||
0.4.3 (Nov 26, 2014)
|
||||
====================
|
||||
* Un-break node.js support.
|
||||
|
||||
0.4.2 (Nov 24, 2014)
|
||||
====================
|
||||
* 2x speedup when writing fonts, thanks @louisremi!
|
||||
|
||||
0.4.1 (Nov 10, 2014)
|
||||
====================
|
||||
* Fix bug that prevented `npm install`.
|
||||
|
||||
0.4.0 (Nov 10, 2014)
|
||||
====================
|
||||
* Add support for font writing.
|
||||
|
||||
0.3.0 (Jun 10, 2014)
|
||||
====================
|
||||
* Support for GPOS kerning, which works in both PostScript and OpenType.
|
||||
* Big performance improvements.
|
||||
* The font and glyph inspector can visually debug a font.
|
||||
|
||||
0.2.0 (Feb 7, 2014)
|
||||
===================
|
||||
* Support for reading PostScript fonts.
|
||||
|
||||
0.1.0 (Sep 27, 2013)
|
||||
====================
|
||||
* Initial release.
|
||||
* Supports reading TrueType CFF fonts.
|
84
node_modules/lv_font_conv/node_modules/opentype.js/bin/ot
generated
vendored
Executable file
84
node_modules/lv_font_conv/node_modules/opentype.js/bin/ot
generated
vendored
Executable file
@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env node
|
||||
/* eslint no-console: off */
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { load } from '../src/opentype';
|
||||
|
||||
// Print out information about the font on the console.
|
||||
function printFontInfo(font) {
|
||||
console.log(' glyphs:', font.glyphs.length);
|
||||
console.log(' kerning pairs (kern table):', Object.keys(font.kerningPairs).length);
|
||||
console.log(' kerning pairs (GPOS table):', (font.getGposKerningValue) ? 'yes' : 'no');
|
||||
}
|
||||
|
||||
// Recursively walk a directory and execute the function for every file.
|
||||
function walk(dir, fn) {
|
||||
var files, i, file;
|
||||
files = fs.readdirSync(dir);
|
||||
for (i = 0; i < files.length; i += 1) {
|
||||
file = files[i];
|
||||
var fullName = path.join(dir, file);
|
||||
var stat = fs.statSync(fullName);
|
||||
if (stat.isFile()) {
|
||||
fn(fullName);
|
||||
} else if (stat.isDirectory()) {
|
||||
walk(fullName, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print out usage information.
|
||||
function printUsage() {
|
||||
console.log('Usage: ot command [dir|file]');
|
||||
console.log();
|
||||
console.log('Commands:');
|
||||
console.log();
|
||||
console.log(' info Get information of specified font or fonts in the specified directory.');
|
||||
console.log();
|
||||
}
|
||||
|
||||
function fileInfo(file) {
|
||||
load(file, function(err, font) {
|
||||
console.log(path.basename(file));
|
||||
if (err) {
|
||||
console.log(' (Error: ' + err + ')');
|
||||
} else if (!font.supported) {
|
||||
console.log(' (Unsupported)');
|
||||
} else {
|
||||
printFontInfo(font);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function recursiveInfo(fontDirectory) {
|
||||
walk(fontDirectory, function(file) {
|
||||
var ext = path.extname(file).toLowerCase();
|
||||
if (ext === '.ttf' || ext === '.otf') {
|
||||
fileInfo(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
printUsage();
|
||||
} else {
|
||||
var command = process.argv[2];
|
||||
if (command === 'info') {
|
||||
var fontpath = process.argv.length === 3 ? '.' : process.argv[3];
|
||||
if (fs.existsSync(fontpath)) {
|
||||
var ext = path.extname(fontpath).toLowerCase();
|
||||
if (fs.statSync(fontpath).isDirectory()) {
|
||||
recursiveInfo(fontpath);
|
||||
} else if (ext === '.ttf' || ext === '.otf') {
|
||||
fileInfo(fontpath);
|
||||
} else {
|
||||
printUsage();
|
||||
}
|
||||
} else {
|
||||
console.log('Path not found');
|
||||
}
|
||||
} else {
|
||||
printUsage();
|
||||
}
|
||||
}
|
64
node_modules/lv_font_conv/node_modules/opentype.js/bin/server.js
generated
vendored
Executable file
64
node_modules/lv_font_conv/node_modules/opentype.js/bin/server.js
generated
vendored
Executable file
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
var http = require('http');
|
||||
var path = require('path');
|
||||
var rollup = require('rollup');
|
||||
var rollupConfig = require('../rollup.config');
|
||||
|
||||
var CONTENT_TYPES = {
|
||||
'.html': 'text/html',
|
||||
'.css': 'text/css',
|
||||
'.png': 'image/png',
|
||||
'.js': 'text/javascript',
|
||||
'.ttf': 'font/otf',
|
||||
'.otf': 'font/otf',
|
||||
'.woff': 'font/woff',
|
||||
'.woff2': 'font/woff2',
|
||||
};
|
||||
|
||||
http.createServer(function(req, res) {
|
||||
var rewrite = '';
|
||||
var url = req.url.substring(1);
|
||||
if (url.length === 0) {
|
||||
url = 'index.html';
|
||||
rewrite = ' -> ' + url;
|
||||
}
|
||||
|
||||
console.log('HTTP', req.url, rewrite);
|
||||
var filePath = './' + url;
|
||||
fs.readFile(filePath, function(err, data) {
|
||||
if (err) {
|
||||
res.writeHead(404, {'Content-Type': 'text/plain'});
|
||||
res.end('Error: ' + err);
|
||||
} else {
|
||||
var contentType = CONTENT_TYPES[path.extname(filePath)] || 'text/plain';
|
||||
res.writeHead(200, {
|
||||
'Content-Type': contentType,
|
||||
'Cache-Control': 'max-age=0'
|
||||
});
|
||||
res.end(data);
|
||||
}
|
||||
});
|
||||
}).listen(8080);
|
||||
console.log('Server running at http://localhost:8080/');
|
||||
|
||||
// Watch changes and rebundle
|
||||
var watcher = rollup.watch(rollupConfig);
|
||||
watcher.on('event', e => {
|
||||
// event.code can be one of:
|
||||
// START — the watcher is (re)starting
|
||||
// BUNDLE_START — building an individual bundle
|
||||
// BUNDLE_END — finished building a bundle
|
||||
// END — finished building all bundles
|
||||
// ERROR — encountered an error while bundling
|
||||
// FATAL — encountered an unrecoverable error
|
||||
|
||||
if (e.code === 'BUNDLE_START') {
|
||||
console.log('Bundling...');
|
||||
} else if (e.code === 'BUNDLE_END') {
|
||||
console.log('Bundled in ' + e.duration + 'ms.');
|
||||
} else if (e.code === 'ERROR' || e.code === 'FATAL') {
|
||||
console.error(e.error);
|
||||
}
|
||||
});
|
96
node_modules/lv_font_conv/node_modules/opentype.js/bin/test-render
generated
vendored
Executable file
96
node_modules/lv_font_conv/node_modules/opentype.js/bin/test-render
generated
vendored
Executable file
@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env node
|
||||
// This is a command to test the text rendering compliance of OpenType.js.
|
||||
// It is designed to operate with https://github.com/unicode-org/text-rendering-tests.
|
||||
//
|
||||
// Call it like this:
|
||||
//
|
||||
// ./bin/test-render --font=fonts/FiraSansOT-Medium.otf --testcase=TEST-1 --render=BALL
|
||||
//
|
||||
// The output will look like this:
|
||||
//
|
||||
// <?xml version="1.0" encoding="UTF-8"?>
|
||||
// <svg version="1.1"
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
// viewBox="0 -500 2230 1550">
|
||||
// <symbol id="TEST-1.B" overflow="visible"><path d="M443 203C443 117 375 99 309 99L217 99L217 315L315 315C389 315 443 289 443 203ZM417 504C417 436 380 407 305 407L217 407L217 594L299 594C375 594 417 568 417 504ZM581 200C581 312 500 352 432 365L432 369C489 382 552 430 552 515C552 651 429 691 295 691L84 691L84 0L307 0C448 0 581 44 581 200Z"/></symbol>
|
||||
// <symbol id="TEST-1.A" overflow="visible"><path d="M452 0L594 0L377 691L214 691L-5 0L133 0L177 160L408 160ZM291 581L295 581L383 260L202 260Z"/></symbol>
|
||||
// <symbol id="TEST-1.L" overflow="visible"><path d="M478 0L493 108L217 108L217 691L84 691L84 0Z"/></symbol>
|
||||
// <use xlink:href="#TEST-1.B" x="0" y="0"/>
|
||||
// <use xlink:href="#TEST-1.A" x="625" y="0"/>
|
||||
// <use xlink:href="#TEST-1.L" x="1214" y="0"/>
|
||||
// <use xlink:href="#TEST-1.L" x="1722" y="0"/>
|
||||
// </svg>
|
||||
//
|
||||
// When viewing the SVG, it will be upside-down (since glyphs are designed Y-up).
|
||||
|
||||
var opentype = require('../dist/opentype.js');
|
||||
|
||||
const SVG_FOOTER = `</svg>`;
|
||||
|
||||
function printUsage() {
|
||||
console.log('Usage: test-render --font=filename.otf --testcase=TEST_NAME --render=TEXT_TO_RENDER');
|
||||
console.log('This commands output the text to render as an SVG file.');
|
||||
console.log();
|
||||
}
|
||||
|
||||
let filename;
|
||||
let testcase;
|
||||
let textToRender;
|
||||
for (let i = 0; i < process.argv.length; i++) {
|
||||
const arg = process.argv[i];
|
||||
if (arg.startsWith('--font=')) {
|
||||
filename = arg.substring('--font='.length);
|
||||
} else if (arg.startsWith('--testcase=')) {
|
||||
testcase = arg.substring('--testcase='.length);
|
||||
} else if (arg.startsWith('--render=')) {
|
||||
textToRender = arg.substring('--render='.length);
|
||||
}
|
||||
}
|
||||
|
||||
if (filename === undefined || testcase === undefined || textToRender === undefined) {
|
||||
printUsage();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function renderSVG() {
|
||||
var font = opentype.loadSync(filename);
|
||||
|
||||
let svgSymbols = [];
|
||||
let svgBody = [];
|
||||
|
||||
var glyphSet = new Set();
|
||||
let x = 0;
|
||||
const glyphs = font.stringToGlyphs(textToRender);
|
||||
for (let i = 0; i < glyphs.length; i++) {
|
||||
const glyph = glyphs[i];
|
||||
const symbolId = testcase + '.' + glyph.name;
|
||||
if (!glyphSet.has(glyph)) {
|
||||
glyphSet.add(glyph);
|
||||
const svgPath = glyph.path.toSVG();
|
||||
svgSymbols.push(` <symbol id="${symbolId}" overflow="visible">${svgPath}</symbol>`);
|
||||
}
|
||||
svgBody.push(` <use xlink:href="#${symbolId}" x="${x}" y="0"/>`);
|
||||
x += glyph.advanceWidth;
|
||||
}
|
||||
|
||||
let minX = 0;
|
||||
let minY = Math.round(font.descender);
|
||||
let width = Math.round(x);
|
||||
let height = Math.round(font.ascender - font.descender);
|
||||
let svgHeader = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="${minX} ${minY} ${width} ${height}">`;
|
||||
|
||||
return svgHeader + svgSymbols.join('\n') + svgBody.join('\n') + SVG_FOOTER;
|
||||
}
|
||||
|
||||
try {
|
||||
var svg = renderSVG();
|
||||
console.log(svg);
|
||||
} catch(e) {
|
||||
console.error(e.stack);
|
||||
process.exit(1);
|
||||
}
|
14254
node_modules/lv_font_conv/node_modules/opentype.js/dist/opentype.js
generated
vendored
Normal file
14254
node_modules/lv_font_conv/node_modules/opentype.js/dist/opentype.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
102
node_modules/lv_font_conv/node_modules/opentype.js/package.json
generated
vendored
Normal file
102
node_modules/lv_font_conv/node_modules/opentype.js/package.json
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"opentype.js@1.3.3",
|
||||
"/home/vitaly/Dropbox/Coding/lv_font_conv"
|
||||
]
|
||||
],
|
||||
"_from": "opentype.js@1.3.3",
|
||||
"_id": "opentype.js@1.3.3",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-/qIY/+WnKGlPIIPhbeNjynfD2PO15G9lA/xqlX2bDH+4lc3Xz5GCQ68mqxj3DdUv6AJqCeaPvuAoH8mVL0zcuA==",
|
||||
"_location": "/opentype.js",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "opentype.js@1.3.3",
|
||||
"name": "opentype.js",
|
||||
"escapedName": "opentype.js",
|
||||
"rawSpec": "1.3.3",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "1.3.3"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.3.tgz",
|
||||
"_spec": "1.3.3",
|
||||
"_where": "/home/vitaly/Dropbox/Coding/lv_font_conv",
|
||||
"author": {
|
||||
"name": "Frederik De Bleser",
|
||||
"email": "frederik@debleser.be"
|
||||
},
|
||||
"bin": {
|
||||
"ot": "bin/ot"
|
||||
},
|
||||
"browser": {
|
||||
"fs": false
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/opentypejs/opentype.js/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"string.prototype.codepointat": "^0.2.1",
|
||||
"tiny-inflate": "^1.0.3"
|
||||
},
|
||||
"description": "OpenType font parser",
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.9.5",
|
||||
"buble": "^0.20.0",
|
||||
"cross-env": "^7.0.2",
|
||||
"jscs": "^3.0.7",
|
||||
"jshint": "^2.11.0",
|
||||
"mocha": "^7.1.1",
|
||||
"reify": "^0.20.12",
|
||||
"rollup": "^1.32.1",
|
||||
"rollup-plugin-buble": "^0.19.8",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-license": "^0.9.0",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
"uglify-js": "^3.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"RELEASES.md",
|
||||
"README.md",
|
||||
"bin",
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"homepage": "https://github.com/opentypejs/opentype.js#readme",
|
||||
"keywords": [
|
||||
"graphics",
|
||||
"fonts",
|
||||
"font",
|
||||
"opentype",
|
||||
"otf",
|
||||
"ttf",
|
||||
"woff",
|
||||
"type"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "dist/opentype.js",
|
||||
"module": "dist/opentype.module.js",
|
||||
"name": "opentype.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/opentypejs/opentype.js.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"dist": "npm run test && npm run build && npm run minify",
|
||||
"minify": "uglifyjs --source-map \"url='opentype.min.js.map'\" --compress --mangle --output ./dist/opentype.min.js -- ./dist/opentype.js",
|
||||
"start": "node ./bin/server.js",
|
||||
"test": "mocha --require reify --recursive && jshint . && jscs .",
|
||||
"watch": "rollup -c -w"
|
||||
},
|
||||
"version": "1.3.3"
|
||||
}
|
20
node_modules/lv_font_conv/node_modules/pngjs/LICENSE
generated
vendored
Normal file
20
node_modules/lv_font_conv/node_modules/pngjs/LICENSE
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
pngjs2 original work Copyright (c) 2015 Luke Page & Original Contributors
|
||||
pngjs derived work Copyright (c) 2012 Kuba Niegowski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
433
node_modules/lv_font_conv/node_modules/pngjs/README.md
generated
vendored
Normal file
433
node_modules/lv_font_conv/node_modules/pngjs/README.md
generated
vendored
Normal file
@ -0,0 +1,433 @@
|
||||
[![Build Status](https://travis-ci.com/lukeapage/pngjs.svg?branch=master)](https://travis-ci.com/lukeapage/pngjs) [![Build status](https://ci.appveyor.com/api/projects/status/qo5x8ayutr028108/branch/master?svg=true)](https://ci.appveyor.com/project/lukeapage/pngjs/branch/master) [![codecov](https://codecov.io/gh/lukeapage/pngjs/branch/master/graph/badge.svg)](https://codecov.io/gh/lukeapage/pngjs) [![npm version](https://badge.fury.io/js/pngjs.svg)](http://badge.fury.io/js/pngjs)
|
||||
|
||||
# pngjs
|
||||
|
||||
Simple PNG encoder/decoder for Node.js with no dependencies.
|
||||
|
||||
Based on the original [pngjs](https://github.com/niegowski/node-pngjs) with the follow enhancements.
|
||||
|
||||
- Support for reading 1,2,4 & 16 bit files
|
||||
- Support for reading interlace files
|
||||
- Support for reading `tTRNS` transparent colours
|
||||
- Support for writing colortype 0 (grayscale), colortype 2 (RGB), colortype 4 (grayscale alpha) and colortype 6 (RGBA)
|
||||
- Sync interface as well as async
|
||||
- API compatible with pngjs and node-pngjs
|
||||
|
||||
Known lack of support for:
|
||||
|
||||
- Extended PNG e.g. Animation
|
||||
- Writing in colortype 3 (indexed color)
|
||||
|
||||
# Table of Contents
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Comparison Table](#comparison-table)
|
||||
- [Tests](#tests)
|
||||
- [Installation](#installation)
|
||||
- [Browser](#browser)
|
||||
- [Example](#example)
|
||||
- [Async API](#async-api)
|
||||
- [Sync API](#sync-api)
|
||||
- [Changelog](#changelog)
|
||||
|
||||
# Comparison Table
|
||||
|
||||
| Name | Forked From | Sync | Async | 16 Bit | 1/2/4 Bit | Interlace | Gamma | Encodes | Tested |
|
||||
| ------------- | ----------- | ---- | ----- | ------ | --------- | --------- | ------ | ------- | ------ |
|
||||
| pngjs | | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| node-png | pngjs | No | Yes | No | No | No | Hidden | Yes | Manual |
|
||||
| png-coder | pngjs | No | Yes | Yes | No | No | Hidden | Yes | Manual |
|
||||
| pngparse | | No | Yes | No | Yes | No | No | No | Yes |
|
||||
| pngparse-sync | pngparse | Yes | No | No | Yes | No | No | No | Yes |
|
||||
| png-async | | No | Yes | No | No | No | No | Yes | Yes |
|
||||
| png-js | | No | Yes | No | No | No | No | No | No |
|
||||
|
||||
Native C++ node decoders:
|
||||
|
||||
- png
|
||||
- png-sync (sync version of above)
|
||||
- pixel-png
|
||||
- png-img
|
||||
|
||||
# Tests
|
||||
|
||||
Tested using [PNG Suite](http://www.schaik.com/pngsuite/). We read every file into pngjs, output it in standard 8bit colour, synchronously and asynchronously, then compare the original with the newly saved images.
|
||||
|
||||
To run the tests, fetch the repo (tests are not distributed via npm) and install with `npm i`, run `npm test`.
|
||||
|
||||
The only thing not converted is gamma correction - this is because multiple vendors will do gamma correction differently, so the tests will have different results on different browsers.
|
||||
|
||||
# Installation
|
||||
|
||||
```
|
||||
$ npm install pngjs --save
|
||||
```
|
||||
|
||||
# Browser
|
||||
|
||||
The package has been build with a [Browserify](browserify.org) version (`npm run browserify`) and you can use the browser version by including in your code:
|
||||
|
||||
```
|
||||
import { PNG } from 'pngjs/browser';
|
||||
```
|
||||
|
||||
# Example
|
||||
|
||||
```js
|
||||
var fs = require("fs"),
|
||||
PNG = require("pngjs").PNG;
|
||||
|
||||
fs.createReadStream("in.png")
|
||||
.pipe(
|
||||
new PNG({
|
||||
filterType: 4,
|
||||
})
|
||||
)
|
||||
.on("parsed", function () {
|
||||
for (var y = 0; y < this.height; y++) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var idx = (this.width * y + x) << 2;
|
||||
|
||||
// invert color
|
||||
this.data[idx] = 255 - this.data[idx];
|
||||
this.data[idx + 1] = 255 - this.data[idx + 1];
|
||||
this.data[idx + 2] = 255 - this.data[idx + 2];
|
||||
|
||||
// and reduce opacity
|
||||
this.data[idx + 3] = this.data[idx + 3] >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
this.pack().pipe(fs.createWriteStream("out.png"));
|
||||
});
|
||||
```
|
||||
|
||||
For more examples see `examples` folder.
|
||||
|
||||
# Async API
|
||||
|
||||
As input any color type is accepted (grayscale, rgb, palette, grayscale with alpha, rgb with alpha) but 8 bit per sample (channel) is the only supported bit depth. Interlaced mode is not supported.
|
||||
|
||||
## Class: PNG
|
||||
|
||||
`PNG` is readable and writable `Stream`.
|
||||
|
||||
### Options
|
||||
|
||||
- `width` - use this with `height` if you want to create png from scratch
|
||||
- `height` - as above
|
||||
- `checkCRC` - whether parser should be strict about checksums in source stream (default: `true`)
|
||||
- `deflateChunkSize` - chunk size used for deflating data chunks, this should be power of 2 and must not be less than 256 and more than 32\*1024 (default: 32 kB)
|
||||
- `deflateLevel` - compression level for deflate (default: 9)
|
||||
- `deflateStrategy` - compression strategy for deflate (default: 3)
|
||||
- `deflateFactory` - deflate stream factory (default: `zlib.createDeflate`)
|
||||
- `filterType` - png filtering method for scanlines (default: -1 => auto, accepts array of numbers 0-4)
|
||||
- `colorType` - the output colorType - see constants. 0 = grayscale, no alpha, 2 = color, no alpha, 4 = grayscale & alpha, 6 = color & alpha. Default currently 6, but in the future may calculate best mode.
|
||||
- `inputColorType` - the input colorType - see constants. Default is 6 (RGBA)
|
||||
- `bitDepth` - the bitDepth of the output, 8 or 16 bits. Input data is expected to have this bit depth.
|
||||
16 bit data is expected in the system endianness (Default: 8)
|
||||
- `inputHasAlpha` - whether the input bitmap has 4 bytes per pixel (rgb and alpha) or 3 (rgb - no alpha).
|
||||
- `bgColor` - an object containing red, green, and blue values between 0 and 255
|
||||
that is used when packing a PNG if alpha is not to be included (default: 255,255,255)
|
||||
|
||||
### Event "metadata"
|
||||
|
||||
`function(metadata) { }`
|
||||
Image's header has been parsed, metadata contains this information:
|
||||
|
||||
- `width` image size in pixels
|
||||
- `height` image size in pixels
|
||||
- `palette` image is paletted
|
||||
- `color` image is not grayscale
|
||||
- `alpha` image contains alpha channel
|
||||
- `interlace` image is interlaced
|
||||
|
||||
### Event: "parsed"
|
||||
|
||||
`function(data) { }`
|
||||
Input image has been completely parsed, `data` is complete and ready for modification.
|
||||
|
||||
### Event: "error"
|
||||
|
||||
`function(error) { }`
|
||||
|
||||
### png.parse(data, [callback])
|
||||
|
||||
Parses PNG file data. Can be `String` or `Buffer`. Alternatively you can stream data to instance of PNG.
|
||||
|
||||
Optional `callback` is once called on `error` or `parsed`. The callback gets
|
||||
two arguments `(err, data)`.
|
||||
|
||||
Returns `this` for method chaining.
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
new PNG({ filterType: 4 }).parse(imageData, function (error, data) {
|
||||
console.log(error, data);
|
||||
});
|
||||
```
|
||||
|
||||
### png.pack()
|
||||
|
||||
Starts converting data to PNG file Stream.
|
||||
|
||||
Returns `this` for method chaining.
|
||||
|
||||
### png.bitblt(dst, sx, sy, w, h, dx, dy)
|
||||
|
||||
Helper for image manipulation, copies a rectangle of pixels from current (i.e. the source) image (`sx`, `sy`, `w`, `h`) to `dst` image (at `dx`, `dy`).
|
||||
|
||||
Returns `this` for method chaining.
|
||||
|
||||
For example, the following code copies the top-left 100x50 px of `in.png` into dst and writes it to `out.png`:
|
||||
|
||||
```js
|
||||
var dst = new PNG({ width: 100, height: 50 });
|
||||
fs.createReadStream("in.png")
|
||||
.pipe(new PNG())
|
||||
.on("parsed", function () {
|
||||
this.bitblt(dst, 0, 0, 100, 50, 0, 0);
|
||||
dst.pack().pipe(fs.createWriteStream("out.png"));
|
||||
});
|
||||
```
|
||||
|
||||
### Property: adjustGamma()
|
||||
|
||||
Helper that takes data and adjusts it to be gamma corrected. Note that it is not 100% reliable with transparent colours because that requires knowing the background colour the bitmap is rendered on to.
|
||||
|
||||
In tests against PNG suite it compared 100% with chrome on all 8 bit and below images. On IE there were some differences.
|
||||
|
||||
The following example reads a file, adjusts the gamma (which sets the gamma to 0) and writes it out again, effectively removing any gamma correction from the image.
|
||||
|
||||
```js
|
||||
fs.createReadStream("in.png")
|
||||
.pipe(new PNG())
|
||||
.on("parsed", function () {
|
||||
this.adjustGamma();
|
||||
this.pack().pipe(fs.createWriteStream("out.png"));
|
||||
});
|
||||
```
|
||||
|
||||
### Property: width
|
||||
|
||||
Width of image in pixels
|
||||
|
||||
### Property: height
|
||||
|
||||
Height of image in pixels
|
||||
|
||||
### Property: data
|
||||
|
||||
Buffer of image pixel data. Every pixel consists 4 bytes: R, G, B, A (opacity).
|
||||
|
||||
### Property: gamma
|
||||
|
||||
Gamma of image (0 if not specified)
|
||||
|
||||
## Packing a PNG and removing alpha (RGBA to RGB)
|
||||
|
||||
When removing the alpha channel from an image, there needs to be a background color to correctly
|
||||
convert each pixel's transparency to the appropriate RGB value. By default, pngjs will flatten
|
||||
the image against a white background. You can override this in the options:
|
||||
|
||||
```js
|
||||
var fs = require("fs"),
|
||||
PNG = require("pngjs").PNG;
|
||||
|
||||
fs.createReadStream("in.png")
|
||||
.pipe(
|
||||
new PNG({
|
||||
colorType: 2,
|
||||
bgColor: {
|
||||
red: 0,
|
||||
green: 255,
|
||||
blue: 0,
|
||||
},
|
||||
})
|
||||
)
|
||||
.on("parsed", function () {
|
||||
this.pack().pipe(fs.createWriteStream("out.png"));
|
||||
});
|
||||
```
|
||||
|
||||
# Sync API
|
||||
|
||||
## PNG.sync
|
||||
|
||||
### PNG.sync.read(buffer)
|
||||
|
||||
Take a buffer and returns a PNG image. The properties on the image include the meta data and `data` as per the async API above.
|
||||
|
||||
```
|
||||
var data = fs.readFileSync('in.png');
|
||||
var png = PNG.sync.read(data);
|
||||
```
|
||||
|
||||
### PNG.sync.write(png)
|
||||
|
||||
Take a PNG image and returns a buffer. The properties on the image include the meta data and `data` as per the async API above.
|
||||
|
||||
```
|
||||
var data = fs.readFileSync('in.png');
|
||||
var png = PNG.sync.read(data);
|
||||
var options = { colorType: 6 };
|
||||
var buffer = PNG.sync.write(png, options);
|
||||
fs.writeFileSync('out.png', buffer);
|
||||
```
|
||||
|
||||
### PNG.adjustGamma(src)
|
||||
|
||||
Adjusts the gamma of a sync image. See the async adjustGamma.
|
||||
|
||||
```
|
||||
var data = fs.readFileSync('in.png');
|
||||
var png = PNG.sync.read(data);
|
||||
PNG.adjustGamma(png);
|
||||
```
|
||||
|
||||
# Changelog
|
||||
|
||||
### 6.0.0 - 24/10/2020
|
||||
|
||||
- BREAKING - Sync version now throws if there is unexpected content at the end of the stream.
|
||||
- BREAKING - Drop support for node 10 (Though nothing incompatible in this release yet)
|
||||
- Reduce the number of files included in the package
|
||||
|
||||
### 5.1.0 - 13/09/2020
|
||||
|
||||
- Add option to skip rescaling
|
||||
|
||||
### 5.0.0 - 15/04/2020
|
||||
|
||||
- Drop support for Node 8
|
||||
- Browserified bundle may now contain ES20(15-20) code if the supported node version supports it. Please run the browserified version through babel if you need to support older browsers.
|
||||
|
||||
### 4.0.1 - 15/04/2020
|
||||
|
||||
- Fix to possible null reference in nextTick of async method
|
||||
|
||||
### 4.0.0 - 09/04/2020
|
||||
|
||||
- Fix issue in newer nodes with using Buffer
|
||||
- Fix async issue with some png files
|
||||
- Drop support for Node 4 & 6
|
||||
|
||||
### 3.4.0 - 09/03/2019
|
||||
|
||||
- Include whether the png has alpha in the meta data
|
||||
- emit an error if the image is truncated instead of hanging
|
||||
- Add a browserified version
|
||||
- speed up some mapping functions
|
||||
|
||||
### 3.3.3 - 19/04/2018
|
||||
|
||||
- Real fix for node 9
|
||||
|
||||
### 3.3.2 - 16/02/2018
|
||||
|
||||
- Fix for node 9
|
||||
|
||||
### 3.3.1 - 15/11/2017
|
||||
|
||||
- Bugfixes and removal of es6
|
||||
|
||||
### 3.3.0
|
||||
|
||||
- Add writing 16 bit channels and support for grayscale input
|
||||
|
||||
### 3.2.0 - 30/04/2017
|
||||
|
||||
- Support for encoding 8-bit grayscale images
|
||||
|
||||
### 3.1.0 - 30/04/2017
|
||||
|
||||
- Support for pngs with zlib chunks that are malformed after valid data
|
||||
|
||||
### 3.0.1 - 16/02/2017
|
||||
|
||||
- Fix single pixel pngs
|
||||
|
||||
### 3.0.0 - 03/08/2016
|
||||
|
||||
- Drop support for node below v4 and iojs. Pin to 2.3.0 to use with old, unsupported or patched node versions.
|
||||
|
||||
### 2.3.0 - 22/04/2016
|
||||
|
||||
- Support for sync in node 0.10
|
||||
|
||||
### 2.2.0 - 04/12/2015
|
||||
|
||||
- Add sync write api
|
||||
- Fix newfile example
|
||||
- Correct comparison table
|
||||
|
||||
### 2.1.0 - 28/10/2015
|
||||
|
||||
- rename package to pngjs
|
||||
- added 'bgColor' option
|
||||
|
||||
### 2.0.0 - 08/10/2015
|
||||
|
||||
- fixes to readme
|
||||
- _breaking change_ - bitblt on the png prototype now doesn't take a unused, unnecessary src first argument
|
||||
|
||||
### 1.2.0 - 13/09/2015
|
||||
|
||||
- support passing colorType to write PNG's and writing bitmaps without alpha information
|
||||
|
||||
### 1.1.0 - 07/09/2015
|
||||
|
||||
- support passing a deflate factory for controlled compression
|
||||
|
||||
### 1.0.2 - 22/08/2015
|
||||
|
||||
- Expose all PNG creation info
|
||||
|
||||
### 1.0.1 - 21/08/2015
|
||||
|
||||
- Fix non square interlaced files
|
||||
|
||||
### 1.0.0 - 08/08/2015
|
||||
|
||||
- More tests
|
||||
- source linted
|
||||
- maintainability refactorings
|
||||
- async API - exceptions in reading now emit warnings
|
||||
- documentation improvement - sync api now documented, adjustGamma documented
|
||||
- breaking change - gamma chunk is now written. previously a read then write would destroy gamma information, now it is persisted.
|
||||
|
||||
### 0.0.3 - 03/08/2015
|
||||
|
||||
- Error handling fixes
|
||||
- ignore files for smaller npm footprint
|
||||
|
||||
### 0.0.2 - 02/08/2015
|
||||
|
||||
- Bugfixes to interlacing, support for transparent colours
|
||||
|
||||
### 0.0.1 - 02/08/2015
|
||||
|
||||
- Initial release, see pngjs for older changelog.
|
||||
|
||||
# License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
267
node_modules/lv_font_conv/node_modules/pngjs/lib/bitmapper.js
generated
vendored
Normal file
267
node_modules/lv_font_conv/node_modules/pngjs/lib/bitmapper.js
generated
vendored
Normal file
@ -0,0 +1,267 @@
|
||||
"use strict";
|
||||
|
||||
let interlaceUtils = require("./interlace");
|
||||
|
||||
let pixelBppMapper = [
|
||||
// 0 - dummy entry
|
||||
function () {},
|
||||
|
||||
// 1 - L
|
||||
// 0: 0, 1: 0, 2: 0, 3: 0xff
|
||||
function (pxData, data, pxPos, rawPos) {
|
||||
if (rawPos === data.length) {
|
||||
throw new Error("Ran out of data");
|
||||
}
|
||||
|
||||
let pixel = data[rawPos];
|
||||
pxData[pxPos] = pixel;
|
||||
pxData[pxPos + 1] = pixel;
|
||||
pxData[pxPos + 2] = pixel;
|
||||
pxData[pxPos + 3] = 0xff;
|
||||
},
|
||||
|
||||
// 2 - LA
|
||||
// 0: 0, 1: 0, 2: 0, 3: 1
|
||||
function (pxData, data, pxPos, rawPos) {
|
||||
if (rawPos + 1 >= data.length) {
|
||||
throw new Error("Ran out of data");
|
||||
}
|
||||
|
||||
let pixel = data[rawPos];
|
||||
pxData[pxPos] = pixel;
|
||||
pxData[pxPos + 1] = pixel;
|
||||
pxData[pxPos + 2] = pixel;
|
||||
pxData[pxPos + 3] = data[rawPos + 1];
|
||||
},
|
||||
|
||||
// 3 - RGB
|
||||
// 0: 0, 1: 1, 2: 2, 3: 0xff
|
||||
function (pxData, data, pxPos, rawPos) {
|
||||
if (rawPos + 2 >= data.length) {
|
||||
throw new Error("Ran out of data");
|
||||
}
|
||||
|
||||
pxData[pxPos] = data[rawPos];
|
||||
pxData[pxPos + 1] = data[rawPos + 1];
|
||||
pxData[pxPos + 2] = data[rawPos + 2];
|
||||
pxData[pxPos + 3] = 0xff;
|
||||
},
|
||||
|
||||
// 4 - RGBA
|
||||
// 0: 0, 1: 1, 2: 2, 3: 3
|
||||
function (pxData, data, pxPos, rawPos) {
|
||||
if (rawPos + 3 >= data.length) {
|
||||
throw new Error("Ran out of data");
|
||||
}
|
||||
|
||||
pxData[pxPos] = data[rawPos];
|
||||
pxData[pxPos + 1] = data[rawPos + 1];
|
||||
pxData[pxPos + 2] = data[rawPos + 2];
|
||||
pxData[pxPos + 3] = data[rawPos + 3];
|
||||
},
|
||||
];
|
||||
|
||||
let pixelBppCustomMapper = [
|
||||
// 0 - dummy entry
|
||||
function () {},
|
||||
|
||||
// 1 - L
|
||||
// 0: 0, 1: 0, 2: 0, 3: 0xff
|
||||
function (pxData, pixelData, pxPos, maxBit) {
|
||||
let pixel = pixelData[0];
|
||||
pxData[pxPos] = pixel;
|
||||
pxData[pxPos + 1] = pixel;
|
||||
pxData[pxPos + 2] = pixel;
|
||||
pxData[pxPos + 3] = maxBit;
|
||||
},
|
||||
|
||||
// 2 - LA
|
||||
// 0: 0, 1: 0, 2: 0, 3: 1
|
||||
function (pxData, pixelData, pxPos) {
|
||||
let pixel = pixelData[0];
|
||||
pxData[pxPos] = pixel;
|
||||
pxData[pxPos + 1] = pixel;
|
||||
pxData[pxPos + 2] = pixel;
|
||||
pxData[pxPos + 3] = pixelData[1];
|
||||
},
|
||||
|
||||
// 3 - RGB
|
||||
// 0: 0, 1: 1, 2: 2, 3: 0xff
|
||||
function (pxData, pixelData, pxPos, maxBit) {
|
||||
pxData[pxPos] = pixelData[0];
|
||||
pxData[pxPos + 1] = pixelData[1];
|
||||
pxData[pxPos + 2] = pixelData[2];
|
||||
pxData[pxPos + 3] = maxBit;
|
||||
},
|
||||
|
||||
// 4 - RGBA
|
||||
// 0: 0, 1: 1, 2: 2, 3: 3
|
||||
function (pxData, pixelData, pxPos) {
|
||||
pxData[pxPos] = pixelData[0];
|
||||
pxData[pxPos + 1] = pixelData[1];
|
||||
pxData[pxPos + 2] = pixelData[2];
|
||||
pxData[pxPos + 3] = pixelData[3];
|
||||
},
|
||||
];
|
||||
|
||||
function bitRetriever(data, depth) {
|
||||
let leftOver = [];
|
||||
let i = 0;
|
||||
|
||||
function split() {
|
||||
if (i === data.length) {
|
||||
throw new Error("Ran out of data");
|
||||
}
|
||||
let byte = data[i];
|
||||
i++;
|
||||
let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
|
||||
switch (depth) {
|
||||
default:
|
||||
throw new Error("unrecognised depth");
|
||||
case 16:
|
||||
byte2 = data[i];
|
||||
i++;
|
||||
leftOver.push((byte << 8) + byte2);
|
||||
break;
|
||||
case 4:
|
||||
byte2 = byte & 0x0f;
|
||||
byte1 = byte >> 4;
|
||||
leftOver.push(byte1, byte2);
|
||||
break;
|
||||
case 2:
|
||||
byte4 = byte & 3;
|
||||
byte3 = (byte >> 2) & 3;
|
||||
byte2 = (byte >> 4) & 3;
|
||||
byte1 = (byte >> 6) & 3;
|
||||
leftOver.push(byte1, byte2, byte3, byte4);
|
||||
break;
|
||||
case 1:
|
||||
byte8 = byte & 1;
|
||||
byte7 = (byte >> 1) & 1;
|
||||
byte6 = (byte >> 2) & 1;
|
||||
byte5 = (byte >> 3) & 1;
|
||||
byte4 = (byte >> 4) & 1;
|
||||
byte3 = (byte >> 5) & 1;
|
||||
byte2 = (byte >> 6) & 1;
|
||||
byte1 = (byte >> 7) & 1;
|
||||
leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
get: function (count) {
|
||||
while (leftOver.length < count) {
|
||||
split();
|
||||
}
|
||||
let returner = leftOver.slice(0, count);
|
||||
leftOver = leftOver.slice(count);
|
||||
return returner;
|
||||
},
|
||||
resetAfterLine: function () {
|
||||
leftOver.length = 0;
|
||||
},
|
||||
end: function () {
|
||||
if (i !== data.length) {
|
||||
throw new Error("extra data found");
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) {
|
||||
// eslint-disable-line max-params
|
||||
let imageWidth = image.width;
|
||||
let imageHeight = image.height;
|
||||
let imagePass = image.index;
|
||||
for (let y = 0; y < imageHeight; y++) {
|
||||
for (let x = 0; x < imageWidth; x++) {
|
||||
let pxPos = getPxPos(x, y, imagePass);
|
||||
pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
|
||||
rawPos += bpp; //eslint-disable-line no-param-reassign
|
||||
}
|
||||
}
|
||||
return rawPos;
|
||||
}
|
||||
|
||||
function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) {
|
||||
// eslint-disable-line max-params
|
||||
let imageWidth = image.width;
|
||||
let imageHeight = image.height;
|
||||
let imagePass = image.index;
|
||||
for (let y = 0; y < imageHeight; y++) {
|
||||
for (let x = 0; x < imageWidth; x++) {
|
||||
let pixelData = bits.get(bpp);
|
||||
let pxPos = getPxPos(x, y, imagePass);
|
||||
pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
|
||||
}
|
||||
bits.resetAfterLine();
|
||||
}
|
||||
}
|
||||
|
||||
exports.dataToBitMap = function (data, bitmapInfo) {
|
||||
let width = bitmapInfo.width;
|
||||
let height = bitmapInfo.height;
|
||||
let depth = bitmapInfo.depth;
|
||||
let bpp = bitmapInfo.bpp;
|
||||
let interlace = bitmapInfo.interlace;
|
||||
let bits;
|
||||
|
||||
if (depth !== 8) {
|
||||
bits = bitRetriever(data, depth);
|
||||
}
|
||||
let pxData;
|
||||
if (depth <= 8) {
|
||||
pxData = Buffer.alloc(width * height * 4);
|
||||
} else {
|
||||
pxData = new Uint16Array(width * height * 4);
|
||||
}
|
||||
let maxBit = Math.pow(2, depth) - 1;
|
||||
let rawPos = 0;
|
||||
let images;
|
||||
let getPxPos;
|
||||
|
||||
if (interlace) {
|
||||
images = interlaceUtils.getImagePasses(width, height);
|
||||
getPxPos = interlaceUtils.getInterlaceIterator(width, height);
|
||||
} else {
|
||||
let nonInterlacedPxPos = 0;
|
||||
getPxPos = function () {
|
||||
let returner = nonInterlacedPxPos;
|
||||
nonInterlacedPxPos += 4;
|
||||
return returner;
|
||||
};
|
||||
images = [{ width: width, height: height }];
|
||||
}
|
||||
|
||||
for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
|
||||
if (depth === 8) {
|
||||
rawPos = mapImage8Bit(
|
||||
images[imageIndex],
|
||||
pxData,
|
||||
getPxPos,
|
||||
bpp,
|
||||
data,
|
||||
rawPos
|
||||
);
|
||||
} else {
|
||||
mapImageCustomBit(
|
||||
images[imageIndex],
|
||||
pxData,
|
||||
getPxPos,
|
||||
bpp,
|
||||
bits,
|
||||
maxBit
|
||||
);
|
||||
}
|
||||
}
|
||||
if (depth === 8) {
|
||||
if (rawPos !== data.length) {
|
||||
throw new Error("extra data found");
|
||||
}
|
||||
} else {
|
||||
bits.end();
|
||||
}
|
||||
|
||||
return pxData;
|
||||
};
|
158
node_modules/lv_font_conv/node_modules/pngjs/lib/bitpacker.js
generated
vendored
Normal file
158
node_modules/lv_font_conv/node_modules/pngjs/lib/bitpacker.js
generated
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
"use strict";
|
||||
|
||||
let constants = require("./constants");
|
||||
|
||||
module.exports = function (dataIn, width, height, options) {
|
||||
let outHasAlpha =
|
||||
[constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(
|
||||
options.colorType
|
||||
) !== -1;
|
||||
if (options.colorType === options.inputColorType) {
|
||||
let bigEndian = (function () {
|
||||
let buffer = new ArrayBuffer(2);
|
||||
new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
|
||||
// Int16Array uses the platform's endianness.
|
||||
return new Int16Array(buffer)[0] !== 256;
|
||||
})();
|
||||
// If no need to convert to grayscale and alpha is present/absent in both, take a fast route
|
||||
if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
|
||||
return dataIn;
|
||||
}
|
||||
}
|
||||
|
||||
// map to a UInt16 array if data is 16bit, fix endianness below
|
||||
let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
|
||||
|
||||
let maxValue = 255;
|
||||
let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
|
||||
if (inBpp === 4 && !options.inputHasAlpha) {
|
||||
inBpp = 3;
|
||||
}
|
||||
let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
|
||||
if (options.bitDepth === 16) {
|
||||
maxValue = 65535;
|
||||
outBpp *= 2;
|
||||
}
|
||||
let outData = Buffer.alloc(width * height * outBpp);
|
||||
|
||||
let inIndex = 0;
|
||||
let outIndex = 0;
|
||||
|
||||
let bgColor = options.bgColor || {};
|
||||
if (bgColor.red === undefined) {
|
||||
bgColor.red = maxValue;
|
||||
}
|
||||
if (bgColor.green === undefined) {
|
||||
bgColor.green = maxValue;
|
||||
}
|
||||
if (bgColor.blue === undefined) {
|
||||
bgColor.blue = maxValue;
|
||||
}
|
||||
|
||||
function getRGBA() {
|
||||
let red;
|
||||
let green;
|
||||
let blue;
|
||||
let alpha = maxValue;
|
||||
switch (options.inputColorType) {
|
||||
case constants.COLORTYPE_COLOR_ALPHA:
|
||||
alpha = data[inIndex + 3];
|
||||
red = data[inIndex];
|
||||
green = data[inIndex + 1];
|
||||
blue = data[inIndex + 2];
|
||||
break;
|
||||
case constants.COLORTYPE_COLOR:
|
||||
red = data[inIndex];
|
||||
green = data[inIndex + 1];
|
||||
blue = data[inIndex + 2];
|
||||
break;
|
||||
case constants.COLORTYPE_ALPHA:
|
||||
alpha = data[inIndex + 1];
|
||||
red = data[inIndex];
|
||||
green = red;
|
||||
blue = red;
|
||||
break;
|
||||
case constants.COLORTYPE_GRAYSCALE:
|
||||
red = data[inIndex];
|
||||
green = red;
|
||||
blue = red;
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
"input color type:" +
|
||||
options.inputColorType +
|
||||
" is not supported at present"
|
||||
);
|
||||
}
|
||||
|
||||
if (options.inputHasAlpha) {
|
||||
if (!outHasAlpha) {
|
||||
alpha /= maxValue;
|
||||
red = Math.min(
|
||||
Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0),
|
||||
maxValue
|
||||
);
|
||||
green = Math.min(
|
||||
Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0),
|
||||
maxValue
|
||||
);
|
||||
blue = Math.min(
|
||||
Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0),
|
||||
maxValue
|
||||
);
|
||||
}
|
||||
}
|
||||
return { red: red, green: green, blue: blue, alpha: alpha };
|
||||
}
|
||||
|
||||
for (let y = 0; y < height; y++) {
|
||||
for (let x = 0; x < width; x++) {
|
||||
let rgba = getRGBA(data, inIndex);
|
||||
|
||||
switch (options.colorType) {
|
||||
case constants.COLORTYPE_COLOR_ALPHA:
|
||||
case constants.COLORTYPE_COLOR:
|
||||
if (options.bitDepth === 8) {
|
||||
outData[outIndex] = rgba.red;
|
||||
outData[outIndex + 1] = rgba.green;
|
||||
outData[outIndex + 2] = rgba.blue;
|
||||
if (outHasAlpha) {
|
||||
outData[outIndex + 3] = rgba.alpha;
|
||||
}
|
||||
} else {
|
||||
outData.writeUInt16BE(rgba.red, outIndex);
|
||||
outData.writeUInt16BE(rgba.green, outIndex + 2);
|
||||
outData.writeUInt16BE(rgba.blue, outIndex + 4);
|
||||
if (outHasAlpha) {
|
||||
outData.writeUInt16BE(rgba.alpha, outIndex + 6);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case constants.COLORTYPE_ALPHA:
|
||||
case constants.COLORTYPE_GRAYSCALE: {
|
||||
// Convert to grayscale and alpha
|
||||
let grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
|
||||
if (options.bitDepth === 8) {
|
||||
outData[outIndex] = grayscale;
|
||||
if (outHasAlpha) {
|
||||
outData[outIndex + 1] = rgba.alpha;
|
||||
}
|
||||
} else {
|
||||
outData.writeUInt16BE(grayscale, outIndex);
|
||||
if (outHasAlpha) {
|
||||
outData.writeUInt16BE(rgba.alpha, outIndex + 2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error("unrecognised color Type " + options.colorType);
|
||||
}
|
||||
|
||||
inIndex += inBpp;
|
||||
outIndex += outBpp;
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
};
|
189
node_modules/lv_font_conv/node_modules/pngjs/lib/chunkstream.js
generated
vendored
Normal file
189
node_modules/lv_font_conv/node_modules/pngjs/lib/chunkstream.js
generated
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
"use strict";
|
||||
|
||||
let util = require("util");
|
||||
let Stream = require("stream");
|
||||
|
||||
let ChunkStream = (module.exports = function () {
|
||||
Stream.call(this);
|
||||
|
||||
this._buffers = [];
|
||||
this._buffered = 0;
|
||||
|
||||
this._reads = [];
|
||||
this._paused = false;
|
||||
|
||||
this._encoding = "utf8";
|
||||
this.writable = true;
|
||||
});
|
||||
util.inherits(ChunkStream, Stream);
|
||||
|
||||
ChunkStream.prototype.read = function (length, callback) {
|
||||
this._reads.push({
|
||||
length: Math.abs(length), // if length < 0 then at most this length
|
||||
allowLess: length < 0,
|
||||
func: callback,
|
||||
});
|
||||
|
||||
process.nextTick(
|
||||
function () {
|
||||
this._process();
|
||||
|
||||
// its paused and there is not enought data then ask for more
|
||||
if (this._paused && this._reads && this._reads.length > 0) {
|
||||
this._paused = false;
|
||||
|
||||
this.emit("drain");
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
};
|
||||
|
||||
ChunkStream.prototype.write = function (data, encoding) {
|
||||
if (!this.writable) {
|
||||
this.emit("error", new Error("Stream not writable"));
|
||||
return false;
|
||||
}
|
||||
|
||||
let dataBuffer;
|
||||
if (Buffer.isBuffer(data)) {
|
||||
dataBuffer = data;
|
||||
} else {
|
||||
dataBuffer = Buffer.from(data, encoding || this._encoding);
|
||||
}
|
||||
|
||||
this._buffers.push(dataBuffer);
|
||||
this._buffered += dataBuffer.length;
|
||||
|
||||
this._process();
|
||||
|
||||
// ok if there are no more read requests
|
||||
if (this._reads && this._reads.length === 0) {
|
||||
this._paused = true;
|
||||
}
|
||||
|
||||
return this.writable && !this._paused;
|
||||
};
|
||||
|
||||
ChunkStream.prototype.end = function (data, encoding) {
|
||||
if (data) {
|
||||
this.write(data, encoding);
|
||||
}
|
||||
|
||||
this.writable = false;
|
||||
|
||||
// already destroyed
|
||||
if (!this._buffers) {
|
||||
return;
|
||||
}
|
||||
|
||||
// enqueue or handle end
|
||||
if (this._buffers.length === 0) {
|
||||
this._end();
|
||||
} else {
|
||||
this._buffers.push(null);
|
||||
this._process();
|
||||
}
|
||||
};
|
||||
|
||||
ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
|
||||
|
||||
ChunkStream.prototype._end = function () {
|
||||
if (this._reads.length > 0) {
|
||||
this.emit("error", new Error("Unexpected end of input"));
|
||||
}
|
||||
|
||||
this.destroy();
|
||||
};
|
||||
|
||||
ChunkStream.prototype.destroy = function () {
|
||||
if (!this._buffers) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.writable = false;
|
||||
this._reads = null;
|
||||
this._buffers = null;
|
||||
|
||||
this.emit("close");
|
||||
};
|
||||
|
||||
ChunkStream.prototype._processReadAllowingLess = function (read) {
|
||||
// ok there is any data so that we can satisfy this request
|
||||
this._reads.shift(); // == read
|
||||
|
||||
// first we need to peek into first buffer
|
||||
let smallerBuf = this._buffers[0];
|
||||
|
||||
// ok there is more data than we need
|
||||
if (smallerBuf.length > read.length) {
|
||||
this._buffered -= read.length;
|
||||
this._buffers[0] = smallerBuf.slice(read.length);
|
||||
|
||||
read.func.call(this, smallerBuf.slice(0, read.length));
|
||||
} else {
|
||||
// ok this is less than maximum length so use it all
|
||||
this._buffered -= smallerBuf.length;
|
||||
this._buffers.shift(); // == smallerBuf
|
||||
|
||||
read.func.call(this, smallerBuf);
|
||||
}
|
||||
};
|
||||
|
||||
ChunkStream.prototype._processRead = function (read) {
|
||||
this._reads.shift(); // == read
|
||||
|
||||
let pos = 0;
|
||||
let count = 0;
|
||||
let data = Buffer.alloc(read.length);
|
||||
|
||||
// create buffer for all data
|
||||
while (pos < read.length) {
|
||||
let buf = this._buffers[count++];
|
||||
let len = Math.min(buf.length, read.length - pos);
|
||||
|
||||
buf.copy(data, pos, 0, len);
|
||||
pos += len;
|
||||
|
||||
// last buffer wasn't used all so just slice it and leave
|
||||
if (len !== buf.length) {
|
||||
this._buffers[--count] = buf.slice(len);
|
||||
}
|
||||
}
|
||||
|
||||
// remove all used buffers
|
||||
if (count > 0) {
|
||||
this._buffers.splice(0, count);
|
||||
}
|
||||
|
||||
this._buffered -= read.length;
|
||||
|
||||
read.func.call(this, data);
|
||||
};
|
||||
|
||||
ChunkStream.prototype._process = function () {
|
||||
try {
|
||||
// as long as there is any data and read requests
|
||||
while (this._buffered > 0 && this._reads && this._reads.length > 0) {
|
||||
let read = this._reads[0];
|
||||
|
||||
// read any data (but no more than length)
|
||||
if (read.allowLess) {
|
||||
this._processReadAllowingLess(read);
|
||||
} else if (this._buffered >= read.length) {
|
||||
// ok we can meet some expectations
|
||||
|
||||
this._processRead(read);
|
||||
} else {
|
||||
// not enought data to satisfy first request in queue
|
||||
// so we need to wait for more
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._buffers && !this.writable) {
|
||||
this._end();
|
||||
}
|
||||
} catch (ex) {
|
||||
this.emit("error", ex);
|
||||
}
|
||||
};
|
32
node_modules/lv_font_conv/node_modules/pngjs/lib/constants.js
generated
vendored
Normal file
32
node_modules/lv_font_conv/node_modules/pngjs/lib/constants.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
|
||||
|
||||
TYPE_IHDR: 0x49484452,
|
||||
TYPE_IEND: 0x49454e44,
|
||||
TYPE_IDAT: 0x49444154,
|
||||
TYPE_PLTE: 0x504c5445,
|
||||
TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase
|
||||
TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase
|
||||
|
||||
// color-type bits
|
||||
COLORTYPE_GRAYSCALE: 0,
|
||||
COLORTYPE_PALETTE: 1,
|
||||
COLORTYPE_COLOR: 2,
|
||||
COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha
|
||||
|
||||
// color-type combinations
|
||||
COLORTYPE_PALETTE_COLOR: 3,
|
||||
COLORTYPE_COLOR_ALPHA: 6,
|
||||
|
||||
COLORTYPE_TO_BPP_MAP: {
|
||||
0: 1,
|
||||
2: 3,
|
||||
3: 1,
|
||||
4: 2,
|
||||
6: 4,
|
||||
},
|
||||
|
||||
GAMMA_DIVISION: 100000,
|
||||
};
|
40
node_modules/lv_font_conv/node_modules/pngjs/lib/crc.js
generated
vendored
Normal file
40
node_modules/lv_font_conv/node_modules/pngjs/lib/crc.js
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
|
||||
let crcTable = [];
|
||||
|
||||
(function () {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
let currentCrc = i;
|
||||
for (let j = 0; j < 8; j++) {
|
||||
if (currentCrc & 1) {
|
||||
currentCrc = 0xedb88320 ^ (currentCrc >>> 1);
|
||||
} else {
|
||||
currentCrc = currentCrc >>> 1;
|
||||
}
|
||||
}
|
||||
crcTable[i] = currentCrc;
|
||||
}
|
||||
})();
|
||||
|
||||
let CrcCalculator = (module.exports = function () {
|
||||
this._crc = -1;
|
||||
});
|
||||
|
||||
CrcCalculator.prototype.write = function (data) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
CrcCalculator.prototype.crc32 = function () {
|
||||
return this._crc ^ -1;
|
||||
};
|
||||
|
||||
CrcCalculator.crc32 = function (buf) {
|
||||
let crc = -1;
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
|
||||
}
|
||||
return crc ^ -1;
|
||||
};
|
171
node_modules/lv_font_conv/node_modules/pngjs/lib/filter-pack.js
generated
vendored
Normal file
171
node_modules/lv_font_conv/node_modules/pngjs/lib/filter-pack.js
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
"use strict";
|
||||
|
||||
let paethPredictor = require("./paeth-predictor");
|
||||
|
||||
function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) {
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
rawData[rawPos + x] = pxData[pxPos + x];
|
||||
}
|
||||
}
|
||||
|
||||
function filterSumNone(pxData, pxPos, byteWidth) {
|
||||
let sum = 0;
|
||||
let length = pxPos + byteWidth;
|
||||
|
||||
for (let i = pxPos; i < length; i++) {
|
||||
sum += Math.abs(pxData[i]);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
|
||||
let val = pxData[pxPos + x] - left;
|
||||
|
||||
rawData[rawPos + x] = val;
|
||||
}
|
||||
}
|
||||
|
||||
function filterSumSub(pxData, pxPos, byteWidth, bpp) {
|
||||
let sum = 0;
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
|
||||
let val = pxData[pxPos + x] - left;
|
||||
|
||||
sum += Math.abs(val);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) {
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
|
||||
let val = pxData[pxPos + x] - up;
|
||||
|
||||
rawData[rawPos + x] = val;
|
||||
}
|
||||
}
|
||||
|
||||
function filterSumUp(pxData, pxPos, byteWidth) {
|
||||
let sum = 0;
|
||||
let length = pxPos + byteWidth;
|
||||
for (let x = pxPos; x < length; x++) {
|
||||
let up = pxPos > 0 ? pxData[x - byteWidth] : 0;
|
||||
let val = pxData[x] - up;
|
||||
|
||||
sum += Math.abs(val);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
|
||||
let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
|
||||
let val = pxData[pxPos + x] - ((left + up) >> 1);
|
||||
|
||||
rawData[rawPos + x] = val;
|
||||
}
|
||||
}
|
||||
|
||||
function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
|
||||
let sum = 0;
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
|
||||
let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
|
||||
let val = pxData[pxPos + x] - ((left + up) >> 1);
|
||||
|
||||
sum += Math.abs(val);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
|
||||
let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
|
||||
let upleft =
|
||||
pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
|
||||
let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
|
||||
|
||||
rawData[rawPos + x] = val;
|
||||
}
|
||||
}
|
||||
|
||||
function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
|
||||
let sum = 0;
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
|
||||
let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
|
||||
let upleft =
|
||||
pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
|
||||
let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
|
||||
|
||||
sum += Math.abs(val);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
let filters = {
|
||||
0: filterNone,
|
||||
1: filterSub,
|
||||
2: filterUp,
|
||||
3: filterAvg,
|
||||
4: filterPaeth,
|
||||
};
|
||||
|
||||
let filterSums = {
|
||||
0: filterSumNone,
|
||||
1: filterSumSub,
|
||||
2: filterSumUp,
|
||||
3: filterSumAvg,
|
||||
4: filterSumPaeth,
|
||||
};
|
||||
|
||||
module.exports = function (pxData, width, height, options, bpp) {
|
||||
let filterTypes;
|
||||
if (!("filterType" in options) || options.filterType === -1) {
|
||||
filterTypes = [0, 1, 2, 3, 4];
|
||||
} else if (typeof options.filterType === "number") {
|
||||
filterTypes = [options.filterType];
|
||||
} else {
|
||||
throw new Error("unrecognised filter types");
|
||||
}
|
||||
|
||||
if (options.bitDepth === 16) {
|
||||
bpp *= 2;
|
||||
}
|
||||
let byteWidth = width * bpp;
|
||||
let rawPos = 0;
|
||||
let pxPos = 0;
|
||||
let rawData = Buffer.alloc((byteWidth + 1) * height);
|
||||
|
||||
let sel = filterTypes[0];
|
||||
|
||||
for (let y = 0; y < height; y++) {
|
||||
if (filterTypes.length > 1) {
|
||||
// find best filter for this line (with lowest sum of values)
|
||||
let min = Infinity;
|
||||
|
||||
for (let i = 0; i < filterTypes.length; i++) {
|
||||
let sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp);
|
||||
if (sum < min) {
|
||||
sel = filterTypes[i];
|
||||
min = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rawData[rawPos] = sel;
|
||||
rawPos++;
|
||||
filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp);
|
||||
rawPos += byteWidth;
|
||||
pxPos += byteWidth;
|
||||
}
|
||||
return rawData;
|
||||
};
|
24
node_modules/lv_font_conv/node_modules/pngjs/lib/filter-parse-async.js
generated
vendored
Normal file
24
node_modules/lv_font_conv/node_modules/pngjs/lib/filter-parse-async.js
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
|
||||
let util = require("util");
|
||||
let ChunkStream = require("./chunkstream");
|
||||
let Filter = require("./filter-parse");
|
||||
|
||||
let FilterAsync = (module.exports = function (bitmapInfo) {
|
||||
ChunkStream.call(this);
|
||||
|
||||
let buffers = [];
|
||||
let that = this;
|
||||
this._filter = new Filter(bitmapInfo, {
|
||||
read: this.read.bind(this),
|
||||
write: function (buffer) {
|
||||
buffers.push(buffer);
|
||||
},
|
||||
complete: function () {
|
||||
that.emit("complete", Buffer.concat(buffers));
|
||||
},
|
||||
});
|
||||
|
||||
this._filter.start();
|
||||
});
|
||||
util.inherits(FilterAsync, ChunkStream);
|
21
node_modules/lv_font_conv/node_modules/pngjs/lib/filter-parse-sync.js
generated
vendored
Normal file
21
node_modules/lv_font_conv/node_modules/pngjs/lib/filter-parse-sync.js
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
|
||||
let SyncReader = require("./sync-reader");
|
||||
let Filter = require("./filter-parse");
|
||||
|
||||
exports.process = function (inBuffer, bitmapInfo) {
|
||||
let outBuffers = [];
|
||||
let reader = new SyncReader(inBuffer);
|
||||
let filter = new Filter(bitmapInfo, {
|
||||
read: reader.read.bind(reader),
|
||||
write: function (bufferPart) {
|
||||
outBuffers.push(bufferPart);
|
||||
},
|
||||
complete: function () {},
|
||||
});
|
||||
|
||||
filter.start();
|
||||
reader.process();
|
||||
|
||||
return Buffer.concat(outBuffers);
|
||||
};
|
177
node_modules/lv_font_conv/node_modules/pngjs/lib/filter-parse.js
generated
vendored
Normal file
177
node_modules/lv_font_conv/node_modules/pngjs/lib/filter-parse.js
generated
vendored
Normal file
@ -0,0 +1,177 @@
|
||||
"use strict";
|
||||
|
||||
let interlaceUtils = require("./interlace");
|
||||
let paethPredictor = require("./paeth-predictor");
|
||||
|
||||
function getByteWidth(width, bpp, depth) {
|
||||
let byteWidth = width * bpp;
|
||||
if (depth !== 8) {
|
||||
byteWidth = Math.ceil(byteWidth / (8 / depth));
|
||||
}
|
||||
return byteWidth;
|
||||
}
|
||||
|
||||
let Filter = (module.exports = function (bitmapInfo, dependencies) {
|
||||
let width = bitmapInfo.width;
|
||||
let height = bitmapInfo.height;
|
||||
let interlace = bitmapInfo.interlace;
|
||||
let bpp = bitmapInfo.bpp;
|
||||
let depth = bitmapInfo.depth;
|
||||
|
||||
this.read = dependencies.read;
|
||||
this.write = dependencies.write;
|
||||
this.complete = dependencies.complete;
|
||||
|
||||
this._imageIndex = 0;
|
||||
this._images = [];
|
||||
if (interlace) {
|
||||
let passes = interlaceUtils.getImagePasses(width, height);
|
||||
for (let i = 0; i < passes.length; i++) {
|
||||
this._images.push({
|
||||
byteWidth: getByteWidth(passes[i].width, bpp, depth),
|
||||
height: passes[i].height,
|
||||
lineIndex: 0,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this._images.push({
|
||||
byteWidth: getByteWidth(width, bpp, depth),
|
||||
height: height,
|
||||
lineIndex: 0,
|
||||
});
|
||||
}
|
||||
|
||||
// when filtering the line we look at the pixel to the left
|
||||
// the spec also says it is done on a byte level regardless of the number of pixels
|
||||
// so if the depth is byte compatible (8 or 16) we subtract the bpp in order to compare back
|
||||
// a pixel rather than just a different byte part. However if we are sub byte, we ignore.
|
||||
if (depth === 8) {
|
||||
this._xComparison = bpp;
|
||||
} else if (depth === 16) {
|
||||
this._xComparison = bpp * 2;
|
||||
} else {
|
||||
this._xComparison = 1;
|
||||
}
|
||||
});
|
||||
|
||||
Filter.prototype.start = function () {
|
||||
this.read(
|
||||
this._images[this._imageIndex].byteWidth + 1,
|
||||
this._reverseFilterLine.bind(this)
|
||||
);
|
||||
};
|
||||
|
||||
Filter.prototype._unFilterType1 = function (
|
||||
rawData,
|
||||
unfilteredLine,
|
||||
byteWidth
|
||||
) {
|
||||
let xComparison = this._xComparison;
|
||||
let xBiggerThan = xComparison - 1;
|
||||
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let rawByte = rawData[1 + x];
|
||||
let f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
|
||||
unfilteredLine[x] = rawByte + f1Left;
|
||||
}
|
||||
};
|
||||
|
||||
Filter.prototype._unFilterType2 = function (
|
||||
rawData,
|
||||
unfilteredLine,
|
||||
byteWidth
|
||||
) {
|
||||
let lastLine = this._lastLine;
|
||||
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let rawByte = rawData[1 + x];
|
||||
let f2Up = lastLine ? lastLine[x] : 0;
|
||||
unfilteredLine[x] = rawByte + f2Up;
|
||||
}
|
||||
};
|
||||
|
||||
Filter.prototype._unFilterType3 = function (
|
||||
rawData,
|
||||
unfilteredLine,
|
||||
byteWidth
|
||||
) {
|
||||
let xComparison = this._xComparison;
|
||||
let xBiggerThan = xComparison - 1;
|
||||
let lastLine = this._lastLine;
|
||||
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let rawByte = rawData[1 + x];
|
||||
let f3Up = lastLine ? lastLine[x] : 0;
|
||||
let f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
|
||||
let f3Add = Math.floor((f3Left + f3Up) / 2);
|
||||
unfilteredLine[x] = rawByte + f3Add;
|
||||
}
|
||||
};
|
||||
|
||||
Filter.prototype._unFilterType4 = function (
|
||||
rawData,
|
||||
unfilteredLine,
|
||||
byteWidth
|
||||
) {
|
||||
let xComparison = this._xComparison;
|
||||
let xBiggerThan = xComparison - 1;
|
||||
let lastLine = this._lastLine;
|
||||
|
||||
for (let x = 0; x < byteWidth; x++) {
|
||||
let rawByte = rawData[1 + x];
|
||||
let f4Up = lastLine ? lastLine[x] : 0;
|
||||
let f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
|
||||
let f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
|
||||
let f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
|
||||
unfilteredLine[x] = rawByte + f4Add;
|
||||
}
|
||||
};
|
||||
|
||||
Filter.prototype._reverseFilterLine = function (rawData) {
|
||||
let filter = rawData[0];
|
||||
let unfilteredLine;
|
||||
let currentImage = this._images[this._imageIndex];
|
||||
let byteWidth = currentImage.byteWidth;
|
||||
|
||||
if (filter === 0) {
|
||||
unfilteredLine = rawData.slice(1, byteWidth + 1);
|
||||
} else {
|
||||
unfilteredLine = Buffer.alloc(byteWidth);
|
||||
|
||||
switch (filter) {
|
||||
case 1:
|
||||
this._unFilterType1(rawData, unfilteredLine, byteWidth);
|
||||
break;
|
||||
case 2:
|
||||
this._unFilterType2(rawData, unfilteredLine, byteWidth);
|
||||
break;
|
||||
case 3:
|
||||
this._unFilterType3(rawData, unfilteredLine, byteWidth);
|
||||
break;
|
||||
case 4:
|
||||
this._unFilterType4(rawData, unfilteredLine, byteWidth);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unrecognised filter type - " + filter);
|
||||
}
|
||||
}
|
||||
|
||||
this.write(unfilteredLine);
|
||||
|
||||
currentImage.lineIndex++;
|
||||
if (currentImage.lineIndex >= currentImage.height) {
|
||||
this._lastLine = null;
|
||||
this._imageIndex++;
|
||||
currentImage = this._images[this._imageIndex];
|
||||
} else {
|
||||
this._lastLine = unfilteredLine;
|
||||
}
|
||||
|
||||
if (currentImage) {
|
||||
// read, using the byte width that may be from the new current image
|
||||
this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
|
||||
} else {
|
||||
this._lastLine = null;
|
||||
this.complete();
|
||||
}
|
||||
};
|
93
node_modules/lv_font_conv/node_modules/pngjs/lib/format-normaliser.js
generated
vendored
Normal file
93
node_modules/lv_font_conv/node_modules/pngjs/lib/format-normaliser.js
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
|
||||
function dePalette(indata, outdata, width, height, palette) {
|
||||
let pxPos = 0;
|
||||
// use values from palette
|
||||
for (let y = 0; y < height; y++) {
|
||||
for (let x = 0; x < width; x++) {
|
||||
let color = palette[indata[pxPos]];
|
||||
|
||||
if (!color) {
|
||||
throw new Error("index " + indata[pxPos] + " not in palette");
|
||||
}
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
outdata[pxPos + i] = color[i];
|
||||
}
|
||||
pxPos += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceTransparentColor(indata, outdata, width, height, transColor) {
|
||||
let pxPos = 0;
|
||||
for (let y = 0; y < height; y++) {
|
||||
for (let x = 0; x < width; x++) {
|
||||
let makeTrans = false;
|
||||
|
||||
if (transColor.length === 1) {
|
||||
if (transColor[0] === indata[pxPos]) {
|
||||
makeTrans = true;
|
||||
}
|
||||
} else if (
|
||||
transColor[0] === indata[pxPos] &&
|
||||
transColor[1] === indata[pxPos + 1] &&
|
||||
transColor[2] === indata[pxPos + 2]
|
||||
) {
|
||||
makeTrans = true;
|
||||
}
|
||||
if (makeTrans) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
outdata[pxPos + i] = 0;
|
||||
}
|
||||
}
|
||||
pxPos += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scaleDepth(indata, outdata, width, height, depth) {
|
||||
let maxOutSample = 255;
|
||||
let maxInSample = Math.pow(2, depth) - 1;
|
||||
let pxPos = 0;
|
||||
|
||||
for (let y = 0; y < height; y++) {
|
||||
for (let x = 0; x < width; x++) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
outdata[pxPos + i] = Math.floor(
|
||||
(indata[pxPos + i] * maxOutSample) / maxInSample + 0.5
|
||||
);
|
||||
}
|
||||
pxPos += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function (indata, imageData, skipRescale = false) {
|
||||
let depth = imageData.depth;
|
||||
let width = imageData.width;
|
||||
let height = imageData.height;
|
||||
let colorType = imageData.colorType;
|
||||
let transColor = imageData.transColor;
|
||||
let palette = imageData.palette;
|
||||
|
||||
let outdata = indata; // only different for 16 bits
|
||||
|
||||
if (colorType === 3) {
|
||||
// paletted
|
||||
dePalette(indata, outdata, width, height, palette);
|
||||
} else {
|
||||
if (transColor) {
|
||||
replaceTransparentColor(indata, outdata, width, height, transColor);
|
||||
}
|
||||
// if it needs scaling
|
||||
if (depth !== 8 && !skipRescale) {
|
||||
// if we need to change the buffer size
|
||||
if (depth === 16) {
|
||||
outdata = Buffer.alloc(width * height * 4);
|
||||
}
|
||||
scaleDepth(indata, outdata, width, height, depth);
|
||||
}
|
||||
}
|
||||
return outdata;
|
||||
};
|
95
node_modules/lv_font_conv/node_modules/pngjs/lib/interlace.js
generated
vendored
Normal file
95
node_modules/lv_font_conv/node_modules/pngjs/lib/interlace.js
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
"use strict";
|
||||
|
||||
// Adam 7
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 0 x 6 4 6 x 6 4 6
|
||||
// 1 7 7 7 7 7 7 7 7
|
||||
// 2 5 6 5 6 5 6 5 6
|
||||
// 3 7 7 7 7 7 7 7 7
|
||||
// 4 3 6 4 6 3 6 4 6
|
||||
// 5 7 7 7 7 7 7 7 7
|
||||
// 6 5 6 5 6 5 6 5 6
|
||||
// 7 7 7 7 7 7 7 7 7
|
||||
|
||||
let imagePasses = [
|
||||
{
|
||||
// pass 1 - 1px
|
||||
x: [0],
|
||||
y: [0],
|
||||
},
|
||||
{
|
||||
// pass 2 - 1px
|
||||
x: [4],
|
||||
y: [0],
|
||||
},
|
||||
{
|
||||
// pass 3 - 2px
|
||||
x: [0, 4],
|
||||
y: [4],
|
||||
},
|
||||
{
|
||||
// pass 4 - 4px
|
||||
x: [2, 6],
|
||||
y: [0, 4],
|
||||
},
|
||||
{
|
||||
// pass 5 - 8px
|
||||
x: [0, 2, 4, 6],
|
||||
y: [2, 6],
|
||||
},
|
||||
{
|
||||
// pass 6 - 16px
|
||||
x: [1, 3, 5, 7],
|
||||
y: [0, 2, 4, 6],
|
||||
},
|
||||
{
|
||||
// pass 7 - 32px
|
||||
x: [0, 1, 2, 3, 4, 5, 6, 7],
|
||||
y: [1, 3, 5, 7],
|
||||
},
|
||||
];
|
||||
|
||||
exports.getImagePasses = function (width, height) {
|
||||
let images = [];
|
||||
let xLeftOver = width % 8;
|
||||
let yLeftOver = height % 8;
|
||||
let xRepeats = (width - xLeftOver) / 8;
|
||||
let yRepeats = (height - yLeftOver) / 8;
|
||||
for (let i = 0; i < imagePasses.length; i++) {
|
||||
let pass = imagePasses[i];
|
||||
let passWidth = xRepeats * pass.x.length;
|
||||
let passHeight = yRepeats * pass.y.length;
|
||||
for (let j = 0; j < pass.x.length; j++) {
|
||||
if (pass.x[j] < xLeftOver) {
|
||||
passWidth++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (let j = 0; j < pass.y.length; j++) {
|
||||
if (pass.y[j] < yLeftOver) {
|
||||
passHeight++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (passWidth > 0 && passHeight > 0) {
|
||||
images.push({ width: passWidth, height: passHeight, index: i });
|
||||
}
|
||||
}
|
||||
return images;
|
||||
};
|
||||
|
||||
exports.getInterlaceIterator = function (width) {
|
||||
return function (x, y, pass) {
|
||||
let outerXLeftOver = x % imagePasses[pass].x.length;
|
||||
let outerX =
|
||||
((x - outerXLeftOver) / imagePasses[pass].x.length) * 8 +
|
||||
imagePasses[pass].x[outerXLeftOver];
|
||||
let outerYLeftOver = y % imagePasses[pass].y.length;
|
||||
let outerY =
|
||||
((y - outerYLeftOver) / imagePasses[pass].y.length) * 8 +
|
||||
imagePasses[pass].y[outerYLeftOver];
|
||||
return outerX * 4 + outerY * width * 4;
|
||||
};
|
||||
};
|
50
node_modules/lv_font_conv/node_modules/pngjs/lib/packer-async.js
generated
vendored
Normal file
50
node_modules/lv_font_conv/node_modules/pngjs/lib/packer-async.js
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
"use strict";
|
||||
|
||||
let util = require("util");
|
||||
let Stream = require("stream");
|
||||
let constants = require("./constants");
|
||||
let Packer = require("./packer");
|
||||
|
||||
let PackerAsync = (module.exports = function (opt) {
|
||||
Stream.call(this);
|
||||
|
||||
let options = opt || {};
|
||||
|
||||
this._packer = new Packer(options);
|
||||
this._deflate = this._packer.createDeflate();
|
||||
|
||||
this.readable = true;
|
||||
});
|
||||
util.inherits(PackerAsync, Stream);
|
||||
|
||||
PackerAsync.prototype.pack = function (data, width, height, gamma) {
|
||||
// Signature
|
||||
this.emit("data", Buffer.from(constants.PNG_SIGNATURE));
|
||||
this.emit("data", this._packer.packIHDR(width, height));
|
||||
|
||||
if (gamma) {
|
||||
this.emit("data", this._packer.packGAMA(gamma));
|
||||
}
|
||||
|
||||
let filteredData = this._packer.filterData(data, width, height);
|
||||
|
||||
// compress it
|
||||
this._deflate.on("error", this.emit.bind(this, "error"));
|
||||
|
||||
this._deflate.on(
|
||||
"data",
|
||||
function (compressedData) {
|
||||
this.emit("data", this._packer.packIDAT(compressedData));
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
this._deflate.on(
|
||||
"end",
|
||||
function () {
|
||||
this.emit("data", this._packer.packIEND());
|
||||
this.emit("end");
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
this._deflate.end(filteredData);
|
||||
};
|
56
node_modules/lv_font_conv/node_modules/pngjs/lib/packer-sync.js
generated
vendored
Normal file
56
node_modules/lv_font_conv/node_modules/pngjs/lib/packer-sync.js
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
|
||||
let hasSyncZlib = true;
|
||||
let zlib = require("zlib");
|
||||
if (!zlib.deflateSync) {
|
||||
hasSyncZlib = false;
|
||||
}
|
||||
let constants = require("./constants");
|
||||
let Packer = require("./packer");
|
||||
|
||||
module.exports = function (metaData, opt) {
|
||||
if (!hasSyncZlib) {
|
||||
throw new Error(
|
||||
"To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
|
||||
);
|
||||
}
|
||||
|
||||
let options = opt || {};
|
||||
|
||||
let packer = new Packer(options);
|
||||
|
||||
let chunks = [];
|
||||
|
||||
// Signature
|
||||
chunks.push(Buffer.from(constants.PNG_SIGNATURE));
|
||||
|
||||
// Header
|
||||
chunks.push(packer.packIHDR(metaData.width, metaData.height));
|
||||
|
||||
if (metaData.gamma) {
|
||||
chunks.push(packer.packGAMA(metaData.gamma));
|
||||
}
|
||||
|
||||
let filteredData = packer.filterData(
|
||||
metaData.data,
|
||||
metaData.width,
|
||||
metaData.height
|
||||
);
|
||||
|
||||
// compress it
|
||||
let compressedData = zlib.deflateSync(
|
||||
filteredData,
|
||||
packer.getDeflateOptions()
|
||||
);
|
||||
filteredData = null;
|
||||
|
||||
if (!compressedData || !compressedData.length) {
|
||||
throw new Error("bad png - invalid compressed data response");
|
||||
}
|
||||
chunks.push(packer.packIDAT(compressedData));
|
||||
|
||||
// End
|
||||
chunks.push(packer.packIEND());
|
||||
|
||||
return Buffer.concat(chunks);
|
||||
};
|
129
node_modules/lv_font_conv/node_modules/pngjs/lib/packer.js
generated
vendored
Normal file
129
node_modules/lv_font_conv/node_modules/pngjs/lib/packer.js
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
"use strict";
|
||||
|
||||
let constants = require("./constants");
|
||||
let CrcStream = require("./crc");
|
||||
let bitPacker = require("./bitpacker");
|
||||
let filter = require("./filter-pack");
|
||||
let zlib = require("zlib");
|
||||
|
||||
let Packer = (module.exports = function (options) {
|
||||
this._options = options;
|
||||
|
||||
options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
|
||||
options.deflateLevel =
|
||||
options.deflateLevel != null ? options.deflateLevel : 9;
|
||||
options.deflateStrategy =
|
||||
options.deflateStrategy != null ? options.deflateStrategy : 3;
|
||||
options.inputHasAlpha =
|
||||
options.inputHasAlpha != null ? options.inputHasAlpha : true;
|
||||
options.deflateFactory = options.deflateFactory || zlib.createDeflate;
|
||||
options.bitDepth = options.bitDepth || 8;
|
||||
// This is outputColorType
|
||||
options.colorType =
|
||||
typeof options.colorType === "number"
|
||||
? options.colorType
|
||||
: constants.COLORTYPE_COLOR_ALPHA;
|
||||
options.inputColorType =
|
||||
typeof options.inputColorType === "number"
|
||||
? options.inputColorType
|
||||
: constants.COLORTYPE_COLOR_ALPHA;
|
||||
|
||||
if (
|
||||
[
|
||||
constants.COLORTYPE_GRAYSCALE,
|
||||
constants.COLORTYPE_COLOR,
|
||||
constants.COLORTYPE_COLOR_ALPHA,
|
||||
constants.COLORTYPE_ALPHA,
|
||||
].indexOf(options.colorType) === -1
|
||||
) {
|
||||
throw new Error(
|
||||
"option color type:" + options.colorType + " is not supported at present"
|
||||
);
|
||||
}
|
||||
if (
|
||||
[
|
||||
constants.COLORTYPE_GRAYSCALE,
|
||||
constants.COLORTYPE_COLOR,
|
||||
constants.COLORTYPE_COLOR_ALPHA,
|
||||
constants.COLORTYPE_ALPHA,
|
||||
].indexOf(options.inputColorType) === -1
|
||||
) {
|
||||
throw new Error(
|
||||
"option input color type:" +
|
||||
options.inputColorType +
|
||||
" is not supported at present"
|
||||
);
|
||||
}
|
||||
if (options.bitDepth !== 8 && options.bitDepth !== 16) {
|
||||
throw new Error(
|
||||
"option bit depth:" + options.bitDepth + " is not supported at present"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Packer.prototype.getDeflateOptions = function () {
|
||||
return {
|
||||
chunkSize: this._options.deflateChunkSize,
|
||||
level: this._options.deflateLevel,
|
||||
strategy: this._options.deflateStrategy,
|
||||
};
|
||||
};
|
||||
|
||||
Packer.prototype.createDeflate = function () {
|
||||
return this._options.deflateFactory(this.getDeflateOptions());
|
||||
};
|
||||
|
||||
Packer.prototype.filterData = function (data, width, height) {
|
||||
// convert to correct format for filtering (e.g. right bpp and bit depth)
|
||||
let packedData = bitPacker(data, width, height, this._options);
|
||||
|
||||
// filter pixel data
|
||||
let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
|
||||
let filteredData = filter(packedData, width, height, this._options, bpp);
|
||||
return filteredData;
|
||||
};
|
||||
|
||||
Packer.prototype._packChunk = function (type, data) {
|
||||
let len = data ? data.length : 0;
|
||||
let buf = Buffer.alloc(len + 12);
|
||||
|
||||
buf.writeUInt32BE(len, 0);
|
||||
buf.writeUInt32BE(type, 4);
|
||||
|
||||
if (data) {
|
||||
data.copy(buf, 8);
|
||||
}
|
||||
|
||||
buf.writeInt32BE(
|
||||
CrcStream.crc32(buf.slice(4, buf.length - 4)),
|
||||
buf.length - 4
|
||||
);
|
||||
return buf;
|
||||
};
|
||||
|
||||
Packer.prototype.packGAMA = function (gamma) {
|
||||
let buf = Buffer.alloc(4);
|
||||
buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
|
||||
return this._packChunk(constants.TYPE_gAMA, buf);
|
||||
};
|
||||
|
||||
Packer.prototype.packIHDR = function (width, height) {
|
||||
let buf = Buffer.alloc(13);
|
||||
buf.writeUInt32BE(width, 0);
|
||||
buf.writeUInt32BE(height, 4);
|
||||
buf[8] = this._options.bitDepth; // Bit depth
|
||||
buf[9] = this._options.colorType; // colorType
|
||||
buf[10] = 0; // compression
|
||||
buf[11] = 0; // filter
|
||||
buf[12] = 0; // interlace
|
||||
|
||||
return this._packChunk(constants.TYPE_IHDR, buf);
|
||||
};
|
||||
|
||||
Packer.prototype.packIDAT = function (data) {
|
||||
return this._packChunk(constants.TYPE_IDAT, data);
|
||||
};
|
||||
|
||||
Packer.prototype.packIEND = function () {
|
||||
return this._packChunk(constants.TYPE_IEND, null);
|
||||
};
|
16
node_modules/lv_font_conv/node_modules/pngjs/lib/paeth-predictor.js
generated
vendored
Normal file
16
node_modules/lv_font_conv/node_modules/pngjs/lib/paeth-predictor.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function paethPredictor(left, above, upLeft) {
|
||||
let paeth = left + above - upLeft;
|
||||
let pLeft = Math.abs(paeth - left);
|
||||
let pAbove = Math.abs(paeth - above);
|
||||
let pUpLeft = Math.abs(paeth - upLeft);
|
||||
|
||||
if (pLeft <= pAbove && pLeft <= pUpLeft) {
|
||||
return left;
|
||||
}
|
||||
if (pAbove <= pUpLeft) {
|
||||
return above;
|
||||
}
|
||||
return upLeft;
|
||||
};
|
169
node_modules/lv_font_conv/node_modules/pngjs/lib/parser-async.js
generated
vendored
Normal file
169
node_modules/lv_font_conv/node_modules/pngjs/lib/parser-async.js
generated
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
"use strict";
|
||||
|
||||
let util = require("util");
|
||||
let zlib = require("zlib");
|
||||
let ChunkStream = require("./chunkstream");
|
||||
let FilterAsync = require("./filter-parse-async");
|
||||
let Parser = require("./parser");
|
||||
let bitmapper = require("./bitmapper");
|
||||
let formatNormaliser = require("./format-normaliser");
|
||||
|
||||
let ParserAsync = (module.exports = function (options) {
|
||||
ChunkStream.call(this);
|
||||
|
||||
this._parser = new Parser(options, {
|
||||
read: this.read.bind(this),
|
||||
error: this._handleError.bind(this),
|
||||
metadata: this._handleMetaData.bind(this),
|
||||
gamma: this.emit.bind(this, "gamma"),
|
||||
palette: this._handlePalette.bind(this),
|
||||
transColor: this._handleTransColor.bind(this),
|
||||
finished: this._finished.bind(this),
|
||||
inflateData: this._inflateData.bind(this),
|
||||
simpleTransparency: this._simpleTransparency.bind(this),
|
||||
headersFinished: this._headersFinished.bind(this),
|
||||
});
|
||||
this._options = options;
|
||||
this.writable = true;
|
||||
|
||||
this._parser.start();
|
||||
});
|
||||
util.inherits(ParserAsync, ChunkStream);
|
||||
|
||||
ParserAsync.prototype._handleError = function (err) {
|
||||
this.emit("error", err);
|
||||
|
||||
this.writable = false;
|
||||
|
||||
this.destroy();
|
||||
|
||||
if (this._inflate && this._inflate.destroy) {
|
||||
this._inflate.destroy();
|
||||
}
|
||||
|
||||
if (this._filter) {
|
||||
this._filter.destroy();
|
||||
// For backward compatibility with Node 7 and below.
|
||||
// Suppress errors due to _inflate calling write() even after
|
||||
// it's destroy()'ed.
|
||||
this._filter.on("error", function () {});
|
||||
}
|
||||
|
||||
this.errord = true;
|
||||
};
|
||||
|
||||
ParserAsync.prototype._inflateData = function (data) {
|
||||
if (!this._inflate) {
|
||||
if (this._bitmapInfo.interlace) {
|
||||
this._inflate = zlib.createInflate();
|
||||
|
||||
this._inflate.on("error", this.emit.bind(this, "error"));
|
||||
this._filter.on("complete", this._complete.bind(this));
|
||||
|
||||
this._inflate.pipe(this._filter);
|
||||
} else {
|
||||
let rowSize =
|
||||
((this._bitmapInfo.width *
|
||||
this._bitmapInfo.bpp *
|
||||
this._bitmapInfo.depth +
|
||||
7) >>
|
||||
3) +
|
||||
1;
|
||||
let imageSize = rowSize * this._bitmapInfo.height;
|
||||
let chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK);
|
||||
|
||||
this._inflate = zlib.createInflate({ chunkSize: chunkSize });
|
||||
let leftToInflate = imageSize;
|
||||
|
||||
let emitError = this.emit.bind(this, "error");
|
||||
this._inflate.on("error", function (err) {
|
||||
if (!leftToInflate) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitError(err);
|
||||
});
|
||||
this._filter.on("complete", this._complete.bind(this));
|
||||
|
||||
let filterWrite = this._filter.write.bind(this._filter);
|
||||
this._inflate.on("data", function (chunk) {
|
||||
if (!leftToInflate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (chunk.length > leftToInflate) {
|
||||
chunk = chunk.slice(0, leftToInflate);
|
||||
}
|
||||
|
||||
leftToInflate -= chunk.length;
|
||||
|
||||
filterWrite(chunk);
|
||||
});
|
||||
|
||||
this._inflate.on("end", this._filter.end.bind(this._filter));
|
||||
}
|
||||
}
|
||||
this._inflate.write(data);
|
||||
};
|
||||
|
||||
ParserAsync.prototype._handleMetaData = function (metaData) {
|
||||
this._metaData = metaData;
|
||||
this._bitmapInfo = Object.create(metaData);
|
||||
|
||||
this._filter = new FilterAsync(this._bitmapInfo);
|
||||
};
|
||||
|
||||
ParserAsync.prototype._handleTransColor = function (transColor) {
|
||||
this._bitmapInfo.transColor = transColor;
|
||||
};
|
||||
|
||||
ParserAsync.prototype._handlePalette = function (palette) {
|
||||
this._bitmapInfo.palette = palette;
|
||||
};
|
||||
|
||||
ParserAsync.prototype._simpleTransparency = function () {
|
||||
this._metaData.alpha = true;
|
||||
};
|
||||
|
||||
ParserAsync.prototype._headersFinished = function () {
|
||||
// Up until this point, we don't know if we have a tRNS chunk (alpha)
|
||||
// so we can't emit metadata any earlier
|
||||
this.emit("metadata", this._metaData);
|
||||
};
|
||||
|
||||
ParserAsync.prototype._finished = function () {
|
||||
if (this.errord) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._inflate) {
|
||||
this.emit("error", "No Inflate block");
|
||||
} else {
|
||||
// no more data to inflate
|
||||
this._inflate.end();
|
||||
}
|
||||
};
|
||||
|
||||
ParserAsync.prototype._complete = function (filteredData) {
|
||||
if (this.errord) {
|
||||
return;
|
||||
}
|
||||
|
||||
let normalisedBitmapData;
|
||||
|
||||
try {
|
||||
let bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
|
||||
|
||||
normalisedBitmapData = formatNormaliser(
|
||||
bitmapData,
|
||||
this._bitmapInfo,
|
||||
this._options.skipRescale
|
||||
);
|
||||
bitmapData = null;
|
||||
} catch (ex) {
|
||||
this._handleError(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit("parsed", normalisedBitmapData);
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user