Changed filesystem for static site
@@ -1,24 +1,11 @@
|
|||||||
Webroot for James' blog!
|
# JEKYLL MODE ENABLED
|
||||||
|
Webroot for James' blog, in Jekyll-based static site mode!
|
||||||
|
|
||||||
Goals for this page:
|
Goals for this page:
|
||||||
- Repo for projects and
|
- Repo for projects and
|
||||||
thoughts
|
thoughts
|
||||||
Hosting music! important function
|
- Hosting music! important function
|
||||||
- Should look flashy for employers
|
- Learning Jekyll-based static site generation.
|
||||||
- Place to fuck around with programming
|
|
||||||
|
|
||||||
The plan for the PHP layout is as such:
|
|
||||||
1. index.php loads in header.php
|
|
||||||
2. index.php loads in some content
|
|
||||||
3. index.php loads in footer.php
|
|
||||||
|
|
||||||
Based on the URI, the PHP scripts will serve
|
|
||||||
text content. My fun little goal here is to
|
|
||||||
have PHP interpret the content as HTML, Markdown,
|
|
||||||
and raw text AT THE SAME TIME. This may not work.
|
|
||||||
|
|
||||||
# FOLDERS
|
# FOLDERS
|
||||||
- css: holds the main stylesheets.
|
- css: holds the main stylesheets.
|
||||||
- javascript: holds the main javascript.
|
|
||||||
- php: holds main php.
|
|
||||||
- content: holds main text content for the site.
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# JEKYLL MODE ENABLED
|
||||||
|
Webroot for James' blog, in Jekyll-based static site mode!
|
||||||
|
|
||||||
|
Goals for this page:
|
||||||
|
- Repo for projects and
|
||||||
|
thoughts
|
||||||
|
- Hosting music! important function
|
||||||
|
- Learning Jekyll-based static site generation.
|
||||||
|
|
||||||
|
# FOLDERS
|
||||||
|
- css: holds the main stylesheets.
|
||||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,167 @@
|
|||||||
|
|
||||||
|
/* Common CSS */
|
||||||
|
html {
|
||||||
|
background-color: var(--bg-primary);
|
||||||
|
color: var(--grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: "Liberation Mono", monospace;
|
||||||
|
}
|
||||||
|
#titlebar {
|
||||||
|
font-family: unifont;
|
||||||
|
}
|
||||||
|
#titlebar h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
#subhead {
|
||||||
|
color: var(--cyan);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#subhead a {
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 0 0.5em 0 0.5em;
|
||||||
|
margin: 0 0.5em 0 0.5em;
|
||||||
|
color: var(--cyan);
|
||||||
|
}
|
||||||
|
#subhead a:hover {
|
||||||
|
/*text-decoration: underline;*/
|
||||||
|
background-color: var(--bg-secondary);
|
||||||
|
color: var(--orange);
|
||||||
|
}
|
||||||
|
#subhead ul {
|
||||||
|
border-bottom: 2px dashed var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content p {
|
||||||
|
text-indent: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#foot {
|
||||||
|
border-top: 4px double var(--yellow);
|
||||||
|
padding-top: 2em;
|
||||||
|
padding-bottom: 1em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--cyan);
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: var(--orange);
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Desktop CSS */
|
||||||
|
@media only screen and (min-aspect-ratio: 0.72) {
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
#head {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
#titlebar {
|
||||||
|
align-self: stretch;
|
||||||
|
border-bottom: 4px double var(--yellow);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
#titlebar h1{
|
||||||
|
margin: 0 0 0 0.3em;
|
||||||
|
}
|
||||||
|
#titlebar .item1 {
|
||||||
|
}
|
||||||
|
#titlebar .item2 {
|
||||||
|
}
|
||||||
|
#subhead {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
#subhead ul {
|
||||||
|
list-style-type: none;
|
||||||
|
display: flex;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
}
|
||||||
|
#subhead ul li {
|
||||||
|
}
|
||||||
|
#motd {
|
||||||
|
margin-left: 10px;
|
||||||
|
tab-size: 4;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
width: 90vw;
|
||||||
|
max-width: 65em;
|
||||||
|
margin-top: 1em;
|
||||||
|
padding-left: 1em;
|
||||||
|
/*align-self: center;*/
|
||||||
|
margin-left: 2em;
|
||||||
|
min-height: 85vh;
|
||||||
|
border-left: 2px solid var(--bg-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile CSS */
|
||||||
|
@media screen and (max-aspect-ratio: 0.71) {
|
||||||
|
html {
|
||||||
|
font-size: 2vh;
|
||||||
|
}
|
||||||
|
#titlebar {
|
||||||
|
border-bottom: 4px double var(--yellow);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
#titlebar h1{
|
||||||
|
margin: 0;
|
||||||
|
padding-bottom: 0.3em;
|
||||||
|
}
|
||||||
|
#titlebar .item1 {
|
||||||
|
}
|
||||||
|
#titlebar .item2 {
|
||||||
|
}
|
||||||
|
#subhead {
|
||||||
|
color: var(--cyan);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: stretch;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#subhead ul {
|
||||||
|
list-style-type: none;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
}
|
||||||
|
#motd {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
display: flex;
|
||||||
|
justify-content: left;
|
||||||
|
align-items: center;
|
||||||
|
tab-size: 4;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
margin-left: 15px;
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/* Color variables */
|
||||||
|
:root {
|
||||||
|
/* Ayu Dark */
|
||||||
|
/* --bg-primary: #0A0E14;
|
||||||
|
--red: #FF3333;
|
||||||
|
--red2: #FF3333;
|
||||||
|
--green: #C2D94C;
|
||||||
|
--green2: #C2D94C;
|
||||||
|
--orange: #FF8F40;
|
||||||
|
--orange2: #FF8F40;
|
||||||
|
--blue: #59C2FF;
|
||||||
|
--blue2: #59C2FF;
|
||||||
|
--yellow: #FFEE99;
|
||||||
|
--yellow2: #FFEE99;
|
||||||
|
--cyan: #95E6CB;
|
||||||
|
--cyan2: #95E6CB;
|
||||||
|
--grey: #B3B1AD;
|
||||||
|
--grey2: #B3B1AD;
|
||||||
|
--bg-secondary: #4D5566;
|
||||||
|
*/
|
||||||
|
/* Elementary */
|
||||||
|
--bg-primary: #303030;
|
||||||
|
--red: #E1321A;
|
||||||
|
--red2: #FF361E;
|
||||||
|
--green: #6AB017;
|
||||||
|
--green2: #7BC91F;
|
||||||
|
--orange: #FFC005;
|
||||||
|
--orange2: #FFD00A;
|
||||||
|
--blue: #004F9E;
|
||||||
|
--blue2: #0071FF;
|
||||||
|
--yellow: #EC0048;
|
||||||
|
--yellow2: #FF1D62;
|
||||||
|
--cyan: #2AA7E7;
|
||||||
|
--cyan2: #4BB8FD;
|
||||||
|
--grey: #F2F2F2;
|
||||||
|
--grey2: #A020f0;
|
||||||
|
--bg-secondary: #4D5566;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/* Fonts */
|
||||||
|
@font-face {
|
||||||
|
font-family: hackmono;
|
||||||
|
src: url(fonts/Hack-Regular.ttf);
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Code New Roman";
|
||||||
|
src: url("fonts/Code New Roman.woff");
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: unifont;
|
||||||
|
src: url(fonts/unifont-17.0.04.otf);
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Liberation Mono";
|
||||||
|
src: url(/fonts/liberation-mono.regular.ttf);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/* Desktop CSS */
|
||||||
|
@media only screen and (min-aspect-ratio: 0.72) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile CSS */
|
||||||
|
@media screen and (max-aspect-ratio: 0.71) {
|
||||||
|
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.4 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||||
|
<fontconfig>
|
||||||
|
<!-- Accept terminus font -->
|
||||||
|
<selectfont>
|
||||||
|
<acceptfont>
|
||||||
|
<pattern>
|
||||||
|
<patelt name="family"><string>Terminus</string></patelt>
|
||||||
|
</pattern>
|
||||||
|
</acceptfont>
|
||||||
|
</selectfont>
|
||||||
|
</fontconfig>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Dimitar Zhekov <dimitar.zhekov@gmail.com>
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
Version 4.49.1:
|
||||||
|
* Fixed install-otb and uninstall-otb to use otbdir instead of x11dir.
|
||||||
|
|
||||||
|
Version 4.49:
|
||||||
|
* Added Open Type Bitmap support.
|
||||||
|
* Altered ascii grave in some sizes to be more useful as a back quote.
|
||||||
|
* Fixed 21B5, added 21B2 and 21B3.
|
||||||
|
|
||||||
|
Version 4.48:
|
||||||
|
|
||||||
|
* Added the basic 27 hebrew letters and sheqel, with uppercase height.
|
||||||
|
* Some improvements in the font build scripts.
|
||||||
|
|
||||||
|
Version 4.47:
|
||||||
|
|
||||||
|
* Added 35 new characters (33 glyphs).
|
||||||
|
* Replaced ao2-variant "ae" with ao1 "ae", it was too similar to "oe".
|
||||||
|
* Some fixes and improvements (17 characters in various sizes/styles).
|
||||||
|
* Significantly improved the font conversion tools. Python 3.5.0 or
|
||||||
|
Node 6.9.0 are now required to build the font.
|
||||||
|
|
||||||
|
Version 4.46:
|
||||||
|
|
||||||
|
* The X11 8-bit code pages are not installed by default.
|
||||||
|
* Added IBM-437 8-bit code page for X11.
|
||||||
|
* The CRT VGA weight for Linux console is not installed by default.
|
||||||
|
* Removed the Linux console mapping files.
|
||||||
|
They should be provided by the console packages.
|
||||||
|
* Removed the BSD console installation.
|
||||||
|
The recent BSD-s have a new console subsystem.
|
||||||
|
* Added 50 new characters. Mostly math, but also Buglarian yat and yus.
|
||||||
|
* Rewritten the font conversion tools in python and javascript.
|
||||||
|
The full unicode range (17x64K) is now supported.
|
||||||
|
* The Windows installer can be built from sources.
|
||||||
|
* Small fixes and improvements (7 characters in various sizes).
|
||||||
|
* Renamed (un)install-ref to (un)install-psf-ref.
|
||||||
|
|
||||||
|
Version 4.40:
|
||||||
|
|
||||||
|
* Added 6 combining accents as separate characters.
|
||||||
|
* Added 14 letters with dot above / dot below.
|
||||||
|
* Added partial subscript and superscript: all digits and 11 letters.
|
||||||
|
* Added 30+ math characters, notably large braces, brackets and parens.
|
||||||
|
* Added unicode range 2800-28FF in two variants (br1 and br2).
|
||||||
|
* A few small character fixes.
|
||||||
|
* Altered configure to be a bit more POSIX compliant.
|
||||||
|
* Replaced some obscure (un)install Makefile targets with variables.
|
||||||
|
|
||||||
|
Version 4.39:
|
||||||
|
|
||||||
|
* Added ballot, checkmark, heavy ballot and heavy checkmark.
|
||||||
|
* Changed HT, LF etc. in sizes 14 and 18-hi2 to be proportional to the
|
||||||
|
letter height, not the matrix height.
|
||||||
|
* Added the powerline characters E0A0..E0A2 and E0B0..E0B3.
|
||||||
|
* Added diameter (2300) - same gluph as empty set (2205).
|
||||||
|
* Small improvements in size 32.
|
||||||
|
|
||||||
|
Version 4.38:
|
||||||
|
|
||||||
|
* Added 23 pseudographic characters, most notably rounded frames.
|
||||||
|
* Added new td1 variant with centered ascii tidle.
|
||||||
|
* Fixed Y acute in sizes 22 and 28, internal optimizations (invisible).
|
||||||
|
|
||||||
|
Version 4.36:
|
||||||
|
|
||||||
|
* Removed the rarely used cm2 variant.
|
||||||
|
* Added new ll2 variant with more distinctive l.
|
||||||
|
* Added quotereversed (201B), quotedblreversed (201F), I/i/U/u dotbelow
|
||||||
|
(1ECA, 1ECB, 1EE4, 1EE5).
|
||||||
|
* Moved all quotes and alike in size 32 one line down.
|
||||||
|
* Small fixes and improvements (t commaaccent, quotes alignment etc. in
|
||||||
|
some sizes).
|
||||||
|
* Windows installation: creates the relevant registry key.
|
||||||
|
|
||||||
|
Version 4.35:
|
||||||
|
|
||||||
|
* Added hi2 variant for size 18.
|
||||||
|
* Fixes in size 18: normal V, normal W, bold X, H stroke, some
|
||||||
|
pseudographic characters and the *NIX installation.
|
||||||
|
|
||||||
|
Version 4.34:
|
||||||
|
|
||||||
|
* Added size 10x18.
|
||||||
|
* Small fixes and improvements in section, multiply, Eng/eng, Dje,
|
||||||
|
dje, house, male, zeta and various characters in the different sizes.
|
||||||
|
* The default cyrillic ghe is now ge1, with ge2 available as an option.
|
||||||
|
|
||||||
|
Version 4.32:
|
||||||
|
|
||||||
|
* Slightly more distintive normal M and W.
|
||||||
|
* Rounded 28-bold, 32-normal, 32-bold.
|
||||||
|
Also removed the 32-normal kx2 style.
|
||||||
|
* Small changes: Che/che stroke, phi, Zhe/zhe etc.
|
||||||
|
* Linux console: the default bold is now framebuffer.
|
||||||
|
* Smaller Makefile, GNU make required.
|
||||||
|
* Changed the font license to SIL OFL 1.1.
|
||||||
|
It's FSF approved, no need to worry.
|
||||||
|
* And, as you can see, Terminus Font is now on sourceforge.
|
||||||
|
|
||||||
|
Version 4.30:
|
||||||
|
|
||||||
|
* Added size 22 (not very good).
|
||||||
|
* Added another 25 characters.
|
||||||
|
* Various small fixes and improvements.
|
||||||
|
* Changed the default prefix and x11dir.
|
||||||
|
|
||||||
|
Version 4.28:
|
||||||
|
|
||||||
|
* Heavy frames (written mostly by Tim Allen) and a few more letters.
|
||||||
|
* Altered trianges and arrows, small bugfixes.
|
||||||
|
* Reorganized the 512-character console font to include more letters
|
||||||
|
instead of the IBM-437 specific pseudographics.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
See OFL.TXT
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
See README
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
INT = python3
|
||||||
|
EXT = py
|
||||||
|
BIN = ./bin
|
||||||
|
|
||||||
|
UCS2ANY = $(INT) $(BIN)/ucstoany.$(EXT)
|
||||||
|
BDF2PSF = $(INT) $(BIN)/bdftopsf.$(EXT)
|
||||||
|
UCS2X11 = $(INT) $(BIN)/ucstoany.$(EXT) -f
|
||||||
|
BDF2PCF = bdftopcf
|
||||||
|
#BDF2OTB = fontforge -lang=ff -c 'Open($$3); ScaleToEm(1024); Generate($$2)'
|
||||||
|
BDF2OTB = $(INT) $(BIN)/otb1cli.$(EXT)
|
||||||
|
|
||||||
|
REG_8859_1 = ISO8859 1
|
||||||
|
REG_8859_2 = ISO8859 2
|
||||||
|
REG_8859_5 = ISO8859 5
|
||||||
|
REG_8859_7 = ISO8859 7
|
||||||
|
REG_8859_9 = ISO8859 9
|
||||||
|
REG_MS_1251 = Microsoft CP1251
|
||||||
|
REG_8859_13 = ISO8859 13
|
||||||
|
REG_8859_15 = ISO8859 15
|
||||||
|
REG_8859_16 = ISO8859 16
|
||||||
|
REG_MS_1255 = Microsoft CP1255
|
||||||
|
REG_IBM_437 = IBM CP437
|
||||||
|
REG_KOI8_R = KOI8 R
|
||||||
|
REG_KOI8_U = KOI8 U
|
||||||
|
REG_BG_MIK = Bulgarian MIK
|
||||||
|
REG_PT_154 = Paratype PT154
|
||||||
|
REG_XOS4_2 = XOS4 2
|
||||||
|
REG_10646_1 = ISO10646 1
|
||||||
|
|
||||||
|
PSF_8859_1 = ter-112n.psf ter-114n.psf ter-114b.psf ter-116n.psf ter-116b.psf ter-118n.psf ter-118b.psf ter-120n.psf ter-120b.psf ter-122n.psf ter-122b.psf ter-124n.psf ter-124b.psf ter-128n.psf ter-128b.psf ter-132n.psf ter-132b.psf
|
||||||
|
PSF_8859_2 = ter-212n.psf ter-214n.psf ter-214b.psf ter-216n.psf ter-216b.psf ter-218n.psf ter-218b.psf ter-220n.psf ter-220b.psf ter-222n.psf ter-222b.psf ter-224n.psf ter-224b.psf ter-228n.psf ter-228b.psf ter-232n.psf ter-232b.psf
|
||||||
|
PSF_8859_7 = ter-712n.psf ter-714n.psf ter-714b.psf ter-716n.psf ter-716b.psf ter-718n.psf ter-718b.psf ter-720n.psf ter-720b.psf ter-722n.psf ter-722b.psf ter-724n.psf ter-724b.psf ter-728n.psf ter-728b.psf ter-732n.psf ter-732b.psf
|
||||||
|
PSF_8859_9 = ter-912n.psf ter-914n.psf ter-914b.psf ter-916n.psf ter-916b.psf ter-918n.psf ter-918b.psf ter-920n.psf ter-920b.psf ter-922n.psf ter-922b.psf ter-924n.psf ter-924b.psf ter-928n.psf ter-928b.psf ter-932n.psf ter-932b.psf
|
||||||
|
PSF_MS_1251 = ter-c12n.psf ter-c14n.psf ter-c14b.psf ter-c16n.psf ter-c16b.psf ter-c18n.psf ter-c18b.psf ter-c20n.psf ter-c20b.psf ter-c22n.psf ter-c22b.psf ter-c24n.psf ter-c24b.psf ter-c28n.psf ter-c28b.psf ter-c32n.psf ter-c32b.psf
|
||||||
|
PSF_8859_13 = ter-d12n.psf ter-d14n.psf ter-d14b.psf ter-d16n.psf ter-d16b.psf ter-d18n.psf ter-d18b.psf ter-d20n.psf ter-d20b.psf ter-d22n.psf ter-d22b.psf ter-d24n.psf ter-d24b.psf ter-d28n.psf ter-d28b.psf ter-d32n.psf ter-d32b.psf
|
||||||
|
PSF_8859_16 = ter-g12n.psf ter-g14n.psf ter-g14b.psf ter-g16n.psf ter-g16b.psf ter-g18n.psf ter-g18b.psf ter-g20n.psf ter-g20b.psf ter-g22n.psf ter-g22b.psf ter-g24n.psf ter-g24b.psf ter-g28n.psf ter-g28b.psf ter-g32n.psf ter-g32b.psf
|
||||||
|
PSF_MS_1255 = ter-h12n.psf ter-h14n.psf ter-h14b.psf ter-h16n.psf ter-h16b.psf ter-h18n.psf ter-h18b.psf ter-h20n.psf ter-h20b.psf ter-h22n.psf ter-h22b.psf ter-h24n.psf ter-h24b.psf ter-h28n.psf ter-h28b.psf ter-h32n.psf ter-h32b.psf
|
||||||
|
PSF_IBM_437 = ter-i12n.psf ter-i14n.psf ter-i14b.psf ter-i16n.psf ter-i16b.psf ter-i18n.psf ter-i18b.psf ter-i20n.psf ter-i20b.psf ter-i22n.psf ter-i22b.psf ter-i24n.psf ter-i24b.psf ter-i28n.psf ter-i28b.psf ter-i32n.psf ter-i32b.psf
|
||||||
|
PSF_KOI8_RV = ter-k14n.psf ter-k14b.psf ter-k16n.psf ter-k16b.psf
|
||||||
|
PSF_KOI8_R = ter-k12n.psf ter-k18n.psf ter-k18b.psf ter-k20n.psf ter-k20b.psf ter-k22n.psf ter-k22b.psf ter-k24n.psf ter-k24b.psf ter-k28n.psf ter-k28b.psf ter-k32n.psf ter-k32b.psf
|
||||||
|
PSF_BG_MIK = ter-m12n.psf ter-m14n.psf ter-m14b.psf ter-m16n.psf ter-m16b.psf ter-m18n.psf ter-m18b.psf ter-m20n.psf ter-m20b.psf ter-m22n.psf ter-m22b.psf ter-m24n.psf ter-m24b.psf ter-m28n.psf ter-m28b.psf ter-m32n.psf ter-m32b.psf
|
||||||
|
PSF_PT_154 = ter-p12n.psf ter-p14n.psf ter-p14b.psf ter-p16n.psf ter-p16b.psf ter-p18n.psf ter-p18b.psf ter-p20n.psf ter-p20b.psf ter-p22n.psf ter-p22b.psf ter-p24n.psf ter-p24b.psf ter-p28n.psf ter-p28b.psf ter-p32n.psf ter-p32b.psf
|
||||||
|
PSF_KOI8_UV = ter-u14n.psf ter-u14b.psf ter-u16n.psf ter-u16b.psf
|
||||||
|
PSF_KOI8_U = ter-u12n.psf ter-u18n.psf ter-u18b.psf ter-u20n.psf ter-u20b.psf ter-u22n.psf ter-u22b.psf ter-u24n.psf ter-u24b.psf ter-u28n.psf ter-u28b.psf ter-u32n.psf ter-u32b.psf
|
||||||
|
PSF_XOS4_2 = ter-v12n.psf ter-v14n.psf ter-v14b.psf ter-v16n.psf ter-v16b.psf ter-v18n.psf ter-v18b.psf ter-v20n.psf ter-v20b.psf ter-v22n.psf ter-v22b.psf ter-v24n.psf ter-v24b.psf ter-v28n.psf ter-v28b.psf ter-v32n.psf ter-v32b.psf
|
||||||
|
PSF = $(PSF_8859_1) $(PSF_8859_2) $(PSF_8859_7) $(PSF_8859_9) $(PSF_MS_1251) $(PSF_8859_13) $(PSF_8859_16) $(PSF_MS_1255) $(PSF_IBM_437) $(PSF_KOI8_RV) $(PSF_KOI8_R) $(PSF_BG_MIK) $(PSF_PT_154) $(PSF_KOI8_UV) $(PSF_KOI8_U) $(PSF_XOS4_2)
|
||||||
|
|
||||||
|
PSF_VGAW_8859_1 = ter-114v.psf ter-116v.psf
|
||||||
|
PSF_VGAW_8859_2 = ter-214v.psf ter-216v.psf
|
||||||
|
PSF_VGAW_8859_7 = ter-714v.psf ter-716v.psf
|
||||||
|
PSF_VGAW_8859_9 = ter-914v.psf ter-916v.psf
|
||||||
|
PSF_VGAW_MS_1251 = ter-c14v.psf ter-c16v.psf
|
||||||
|
PSF_VGAW_8859_13 = ter-d14v.psf ter-d16v.psf
|
||||||
|
PSF_VGAW_8859_16 = ter-g14v.psf ter-g16v.psf
|
||||||
|
PSF_VGAW_MS_1255 = ter-h14v.psf ter-h16v.psf
|
||||||
|
PSF_VGAW_IBM_437 = ter-i14v.psf ter-i16v.psf
|
||||||
|
PSF_VGAW_KOI8_RV = ter-k14v.psf ter-k16v.psf
|
||||||
|
PSF_VGAW_BG_MIK = ter-m14v.psf ter-m16v.psf
|
||||||
|
PSF_VGAW_PT_154 = ter-p14v.psf ter-p16v.psf
|
||||||
|
PSF_VGAW_KOI8_UV = ter-u14v.psf ter-u16v.psf
|
||||||
|
PSF_VGAW_XOS4_2 = ter-v14v.psf ter-v16v.psf
|
||||||
|
PSF_VGAW = $(PSF_VGAW_8859_1) $(PSF_VGAW_8859_2) $(PSF_VGAW_8859_7) $(PSF_VGAW_8859_9) $(PSF_VGAW_MS_1251) $(PSF_VGAW_8859_13) $(PSF_VGAW_8859_16) $(PSF_VGAW_MS_1255) $(PSF_VGAW_IBM_437) $(PSF_VGAW_KOI8_RV) $(PSF_VGAW_BG_MIK) $(PSF_VGAW_PT_154) $(PSF_VGAW_KOI8_UV) $(PSF_VGAW_XOS4_2)
|
||||||
|
|
||||||
|
PCF_8859_1 = ter-112n.pcf ter-112b.pcf ter-114n.pcf ter-114b.pcf ter-116n.pcf ter-116b.pcf ter-118n.pcf ter-118b.pcf ter-120n.pcf ter-120b.pcf ter-122n.pcf ter-122b.pcf ter-124n.pcf ter-124b.pcf ter-128n.pcf ter-128b.pcf ter-132n.pcf ter-132b.pcf
|
||||||
|
PCF_8859_2 = ter-212n.pcf ter-212b.pcf ter-214n.pcf ter-214b.pcf ter-216n.pcf ter-216b.pcf ter-218n.pcf ter-218b.pcf ter-220n.pcf ter-220b.pcf ter-222n.pcf ter-222b.pcf ter-224n.pcf ter-224b.pcf ter-228n.pcf ter-228b.pcf ter-232n.pcf ter-232b.pcf
|
||||||
|
PCF_8859_5 = ter-512n.pcf ter-512b.pcf ter-514n.pcf ter-514b.pcf ter-516n.pcf ter-516b.pcf ter-518n.pcf ter-518b.pcf ter-520n.pcf ter-520b.pcf ter-522n.pcf ter-522b.pcf ter-524n.pcf ter-524b.pcf ter-528n.pcf ter-528b.pcf ter-532n.pcf ter-532b.pcf
|
||||||
|
PCF_8859_7 = ter-712n.pcf ter-712b.pcf ter-714n.pcf ter-714b.pcf ter-716n.pcf ter-716b.pcf ter-718n.pcf ter-718b.pcf ter-720n.pcf ter-720b.pcf ter-722n.pcf ter-722b.pcf ter-724n.pcf ter-724b.pcf ter-728n.pcf ter-728b.pcf ter-732n.pcf ter-732b.pcf
|
||||||
|
PCF_8859_9 = ter-912n.pcf ter-912b.pcf ter-914n.pcf ter-914b.pcf ter-916n.pcf ter-916b.pcf ter-918n.pcf ter-918b.pcf ter-920n.pcf ter-920b.pcf ter-922n.pcf ter-922b.pcf ter-924n.pcf ter-924b.pcf ter-928n.pcf ter-928b.pcf ter-932n.pcf ter-932b.pcf
|
||||||
|
PCF_MS_1251 = ter-c12n.pcf ter-c12b.pcf ter-c14n.pcf ter-c14b.pcf ter-c16n.pcf ter-c16b.pcf ter-c18n.pcf ter-c18b.pcf ter-c20n.pcf ter-c20b.pcf ter-c22n.pcf ter-c22b.pcf ter-c24n.pcf ter-c24b.pcf ter-c28n.pcf ter-c28b.pcf ter-c32n.pcf ter-c32b.pcf
|
||||||
|
PCF_8859_13 = ter-d12n.pcf ter-d12b.pcf ter-d14n.pcf ter-d14b.pcf ter-d16n.pcf ter-d16b.pcf ter-d18n.pcf ter-d18b.pcf ter-d20n.pcf ter-d20b.pcf ter-d22n.pcf ter-d22b.pcf ter-d24n.pcf ter-d24b.pcf ter-d28n.pcf ter-d28b.pcf ter-d32n.pcf ter-d32b.pcf
|
||||||
|
PCF_8859_15 = ter-f12n.pcf ter-f12b.pcf ter-f14n.pcf ter-f14b.pcf ter-f16n.pcf ter-f16b.pcf ter-f18n.pcf ter-f18b.pcf ter-f20n.pcf ter-f20b.pcf ter-f22n.pcf ter-f22b.pcf ter-f24n.pcf ter-f24b.pcf ter-f28n.pcf ter-f28b.pcf ter-f32n.pcf ter-f32b.pcf
|
||||||
|
PCF_8859_16 = ter-g12n.pcf ter-g12b.pcf ter-g14n.pcf ter-g14b.pcf ter-g16n.pcf ter-g16b.pcf ter-g18n.pcf ter-g18b.pcf ter-g20n.pcf ter-g20b.pcf ter-g22n.pcf ter-g22b.pcf ter-g24n.pcf ter-g24b.pcf ter-g28n.pcf ter-g28b.pcf ter-g32n.pcf ter-g32b.pcf
|
||||||
|
PCF_IBM_437 = ter-i12n.pcf ter-i12b.pcf ter-i14n.pcf ter-i14b.pcf ter-i16n.pcf ter-i16b.pcf ter-i18n.pcf ter-i18b.pcf ter-i20n.pcf ter-i20b.pcf ter-i22n.pcf ter-i22b.pcf ter-i24n.pcf ter-i24b.pcf ter-i28n.pcf ter-i28b.pcf ter-i32n.pcf ter-i32b.pcf
|
||||||
|
PCF_KOI8_R = ter-k12n.pcf ter-k12b.pcf ter-k14n.pcf ter-k14b.pcf ter-k16n.pcf ter-k16b.pcf ter-k18n.pcf ter-k18b.pcf ter-k20n.pcf ter-k20b.pcf ter-k22n.pcf ter-k22b.pcf ter-k24n.pcf ter-k24b.pcf ter-k28n.pcf ter-k28b.pcf ter-k32n.pcf ter-k32b.pcf
|
||||||
|
PCF_PT_154 = ter-p12n.pcf ter-p12b.pcf ter-p14n.pcf ter-p14b.pcf ter-p16n.pcf ter-p16b.pcf ter-p18n.pcf ter-p18b.pcf ter-p20n.pcf ter-p20b.pcf ter-p22n.pcf ter-p22b.pcf ter-p24n.pcf ter-p24b.pcf ter-p28n.pcf ter-p28b.pcf ter-p32n.pcf ter-p32b.pcf
|
||||||
|
PCF_KOI8_U = ter-u12n.pcf ter-u12b.pcf ter-u14n.pcf ter-u14b.pcf ter-u16n.pcf ter-u16b.pcf ter-u18n.pcf ter-u18b.pcf ter-u20n.pcf ter-u20b.pcf ter-u22n.pcf ter-u22b.pcf ter-u24n.pcf ter-u24b.pcf ter-u28n.pcf ter-u28b.pcf ter-u32n.pcf ter-u32b.pcf
|
||||||
|
PCF_10646_1 = ter-x12n.pcf ter-x12b.pcf ter-x14n.pcf ter-x14b.pcf ter-x16n.pcf ter-x16b.pcf ter-x18n.pcf ter-x18b.pcf ter-x20n.pcf ter-x20b.pcf ter-x22n.pcf ter-x22b.pcf ter-x24n.pcf ter-x24b.pcf ter-x28n.pcf ter-x28b.pcf ter-x32n.pcf ter-x32b.pcf
|
||||||
|
PCF_8BIT = $(PCF_8859_1) $(PCF_8859_2) $(PCF_8859_5) $(PCF_8859_7) $(PCF_8859_9) $(PCF_MS_1251) $(PCF_8859_13) $(PCF_8859_15) $(PCF_8859_16) $(PCF_IBM_437) $(PCF_KOI8_R) $(PCF_PT_154) $(PCF_KOI8_U)
|
||||||
|
PCF = $(PCF_10646_1)
|
||||||
|
|
||||||
|
OTB = ter-u12n.otb ter-u12b.otb ter-u14n.otb ter-u14b.otb ter-u16n.otb ter-u16b.otb ter-u18n.otb ter-u18b.otb ter-u20n.otb ter-u20b.otb ter-u22n.otb ter-u22b.otb ter-u24n.otb ter-u24b.otb ter-u28n.otb ter-u28b.otb ter-u32n.otb ter-u32b.otb
|
||||||
|
|
||||||
|
# Default
|
||||||
|
|
||||||
|
all: $(PSF) $(PCF)
|
||||||
|
|
||||||
|
DESTDIR =
|
||||||
|
prefix = /usr/local
|
||||||
|
psfdir = $(prefix)/share/consolefonts
|
||||||
|
x11dir = $(prefix)/share/fonts/terminus
|
||||||
|
otbdir = $(prefix)/share/fonts/terminus
|
||||||
|
|
||||||
|
install: $(PSF) $(PCF)
|
||||||
|
mkdir -p $(DESTDIR)$(psfdir)
|
||||||
|
for i in $(PSF) ; do gzip -c $$i > $(DESTDIR)$(psfdir)/$$i.gz ; done
|
||||||
|
mkdir -p $(DESTDIR)$(x11dir)
|
||||||
|
for i in $(PCF) ; do gzip -c $$i > $(DESTDIR)$(x11dir)/$$i.gz ; done
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
for i in $(PSF) ; do rm -f $(DESTDIR)$(psfdir)/$$i.gz ; done
|
||||||
|
for i in $(PCF) ; do rm -f $(DESTDIR)$(x11dir)/$$i.gz ; done
|
||||||
|
|
||||||
|
fontdir:
|
||||||
|
mkfontscale $(DESTDIR)$(x11dir)
|
||||||
|
mkfontdir $(DESTDIR)$(x11dir)
|
||||||
|
fc-cache -f $(DESTDIR)$(x11dir)
|
||||||
|
|
||||||
|
# Linux Console
|
||||||
|
|
||||||
|
VGA_8859_1 = uni/vgagr.uni uni/ascii-h.uni uni/win-1252.uni
|
||||||
|
VGA_8859_2 = uni/vgagr.uni uni/ascii-h.uni uni/vga-1250.uni uni/8859-2.uni
|
||||||
|
VGA_8859_7 = uni/vgagr.uni uni/ascii-h.uni uni/vga-1253.uni uni/8859-7.uni
|
||||||
|
VGA_8859_9 = uni/vgagr.uni uni/ascii-h.uni uni/win-1254.uni
|
||||||
|
VGA_MS_1251 = uni/vgagr.uni uni/ascii-h.uni uni/vga-1251.uni uni/win-1251.uni
|
||||||
|
VGA_8859_13 = uni/vgagr.uni uni/ascii-h.uni uni/vga-1257.uni uni/8859-13.uni
|
||||||
|
VGA_8859_16 = uni/vgagr.uni uni/ascii-h.uni uni/nls-1250.uni uni/8859-16.uni
|
||||||
|
VGA_MS_1255 = uni/vgagr.uni uni/ascii-h.uni uni/win-1255.uni
|
||||||
|
VGA_IBM_437 = uni/cntrl.uni uni/ascii-h.uni uni/ibm-437.uni
|
||||||
|
VGA_KOI8_RV = uni/cntrl.uni uni/ascii-h.uni uni/koibm8-r.uni
|
||||||
|
VGA_KOI8_R = uni/cntrl.uni uni/ascii-h.uni uni/koi8-r.uni
|
||||||
|
VGA_BG_MIK = uni/cntrl.uni uni/ascii-h.uni uni/bg-mik.uni
|
||||||
|
VGA_PT_154 = uni/vgagr.uni uni/ascii-h.uni uni/pt-154.uni
|
||||||
|
VGA_KOI8_UV = uni/cntrl.uni uni/ascii-h.uni uni/koibm8-u.uni
|
||||||
|
VGA_KOI8_U = uni/cntrl.uni uni/ascii-h.uni uni/koi8-u.uni
|
||||||
|
VGA_XOS4_2 = uni/xos4-2.uni
|
||||||
|
|
||||||
|
DUP_8859_1 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_8859_2 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_8859_7 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_8859_9 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_MS_1251 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_8859_13 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_8859_16 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_MS_1255 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_IBM_437 = dup/cntrl.dup dup/ascii-h.dup dup/ibm-437.dup
|
||||||
|
DUP_KOI8_RV = dup/cntrl.dup dup/ascii-h.dup dup/koi8.dup
|
||||||
|
DUP_KOI8_R = dup/cntrl.dup dup/ascii-h.dup dup/koi8.dup
|
||||||
|
DUP_BG_MIK = dup/cntrl.dup dup/ascii-h.dup dup/ibm-437.dup
|
||||||
|
DUP_PT_154 = dup/vgagr.dup dup/ascii-h.dup
|
||||||
|
DUP_KOI8_UV = dup/cntrl.dup dup/ascii-h.dup dup/koi8.dup
|
||||||
|
DUP_KOI8_U = dup/cntrl.dup dup/ascii-h.dup dup/koi8.dup
|
||||||
|
DUP_XOS4_2 = dup/vgagr.dup dup/xos4-2.dup
|
||||||
|
|
||||||
|
$(PSF_8859_1) $(PSF_VGAW_8859_1): ter-1%.psf : ter-u%.bdf $(VGA_8859_1) $(DUP_8859_1)
|
||||||
|
$(UCS2ANY) $< $(REG_8859_1) $(VGA_8859_1) | $(BDF2PSF) -o $@ $(DUP_8859_1)
|
||||||
|
|
||||||
|
$(PSF_8859_2) $(PSF_VGAW_8859_2): ter-2%.psf : ter-u%.bdf $(VGA_8859_2) $(DUP_8859_2)
|
||||||
|
$(UCS2ANY) $< $(REG_8859_2) $(VGA_8859_2) | $(BDF2PSF) -o $@ $(DUP_8859_2)
|
||||||
|
|
||||||
|
$(PSF_8859_7) $(PSF_VGAW_8859_7): ter-7%.psf : ter-u%.bdf $(VGA_8859_7) $(DUP_8859_7)
|
||||||
|
$(UCS2ANY) $< $(REG_8859_7) $(VGA_8859_7) | $(BDF2PSF) -o $@ $(DUP_8859_7)
|
||||||
|
|
||||||
|
$(PSF_8859_9) $(PSF_VGAW_8859_9): ter-9%.psf : ter-u%.bdf $(VGA_8859_9) $(DUP_8859_9)
|
||||||
|
$(UCS2ANY) $< $(REG_8859_9) $(VGA_8859_9) | $(BDF2PSF) -o $@ $(DUP_8859_9)
|
||||||
|
|
||||||
|
$(PSF_MS_1251) $(PSF_VGAW_MS_1251): ter-c%.psf : ter-u%.bdf $(VGA_MS_1251) $(DUP_MS_1251)
|
||||||
|
$(UCS2ANY) $< $(REG_MS_1251) $(VGA_MS_1251) | $(BDF2PSF) -o $@ $(DUP_MS_1251)
|
||||||
|
|
||||||
|
$(PSF_8859_13) $(PSF_VGAW_8859_13): ter-d%.psf : ter-u%.bdf $(VGA_8859_13) $(DUP_8859_13)
|
||||||
|
$(UCS2ANY) $< $(REG_8859_13) $(VGA_8859_13) | $(BDF2PSF) -o $@ $(DUP_8859_13)
|
||||||
|
|
||||||
|
$(PSF_8859_16) $(PSF_VGAW_8859_16): ter-g%.psf : ter-u%.bdf $(VGA_8859_16) $(DUP_8859_16)
|
||||||
|
$(UCS2ANY) $< $(REG_8859_16) $(VGA_8859_16) | $(BDF2PSF) -o $@ $(DUP_8859_16)
|
||||||
|
|
||||||
|
$(PSF_MS_1255) $(PSF_VGAW_MS_1255): ter-h%.psf : ter-u%.bdf $(VGA_MS_1255) $(DUP_MS_1255)
|
||||||
|
$(UCS2ANY) $< $(REG_MS_1255) $(VGA_MS_1255) | $(BDF2PSF) -o $@ $(DUP_MS_1255)
|
||||||
|
|
||||||
|
$(PSF_IBM_437) $(PSF_VGAW_IBM_437): ter-i%.psf : ter-u%.bdf $(VGA_IBM_437) $(DUP_IBM_437)
|
||||||
|
$(UCS2ANY) $< $(REG_IBM_437) $(VGA_IBM_437) | $(BDF2PSF) -o $@ $(DUP_IBM_437)
|
||||||
|
|
||||||
|
$(PSF_KOI8_RV) $(PSF_VGAW_KOI8_RV): ter-k%.psf : ter-u%.bdf $(VGA_KOI8_RV) $(DUP_KOI8_RV)
|
||||||
|
$(UCS2ANY) $< $(REG_KOI8_R) $(VGA_KOI8_RV) | $(BDF2PSF) -o $@ $(DUP_KOI8_RV)
|
||||||
|
|
||||||
|
$(PSF_KOI8_R): ter-k%.psf : ter-u%.bdf $(VGA_KOI8_R) $(DUP_KOI8_R)
|
||||||
|
$(UCS2ANY) $< $(REG_KOI8_R) $(VGA_KOI8_R) | $(BDF2PSF) -o $@ $(DUP_KOI8_R)
|
||||||
|
|
||||||
|
$(PSF_BG_MIK) $(PSF_VGAW_BG_MIK): ter-m%.psf : ter-u%.bdf $(VGA_BG_MIK) $(DUP_BG_MIK)
|
||||||
|
$(UCS2ANY) $< $(REG_BG_MIK) $(VGA_BG_MIK) | $(BDF2PSF) -o $@ $(DUP_BG_MIK)
|
||||||
|
|
||||||
|
$(PSF_PT_154) $(PSF_VGAW_PT_154): ter-p%.psf : ter-u%.bdf $(VGA_PT_154) $(DUP_PT_154)
|
||||||
|
$(UCS2ANY) $< $(REG_PT_154) $(VGA_PT_154) | $(BDF2PSF) -o $@ $(DUP_PT_154)
|
||||||
|
|
||||||
|
$(PSF_KOI8_UV) $(PSF_VGAW_KOI8_UV): ter-u%.psf : ter-u%.bdf $(VGA_KOI8_UV) $(DUP_KOI8_UV)
|
||||||
|
$(UCS2ANY) $< $(REG_KOI8_R) $(VGA_KOI8_UV) | $(BDF2PSF) -o $@ $(DUP_KOI8_UV)
|
||||||
|
|
||||||
|
$(PSF_KOI8_U): ter-u%.psf : ter-u%.bdf $(VGA_KOI8_U) $(DUP_KOI8_U)
|
||||||
|
$(UCS2ANY) $< $(REG_KOI8_U) $(VGA_KOI8_U) | $(BDF2PSF) -o $@ $(DUP_KOI8_U)
|
||||||
|
|
||||||
|
$(PSF_XOS4_2) $(PSF_VGAW_XOS4_2): ter-v%.psf : ter-u%.bdf $(VGA_XOS4_2) $(DUP_XOS4_2)
|
||||||
|
$(UCS2ANY) $< $(REG_XOS4_2) $(VGA_XOS4_2) | $(BDF2PSF) -o $@ $(DUP_XOS4_2)
|
||||||
|
|
||||||
|
psf: $(PSF)
|
||||||
|
|
||||||
|
install-psf: $(PSF)
|
||||||
|
mkdir -p $(DESTDIR)$(psfdir)
|
||||||
|
for i in $(PSF) ; do gzip -c $$i > $(DESTDIR)$(psfdir)/$$i.gz ; done
|
||||||
|
|
||||||
|
uninstall-psf:
|
||||||
|
for i in $(PSF) ; do rm -f $(DESTDIR)$(psfdir)/$$i.gz ; done
|
||||||
|
|
||||||
|
psf-vgaw: $(PSF_VGAW)
|
||||||
|
|
||||||
|
install-psf-vgaw: $(PSF_VGAW)
|
||||||
|
mkdir -p $(DESTDIR)$(psfdir)
|
||||||
|
for i in $(PSF_VGAW) ; do gzip -c $$i > $(DESTDIR)$(psfdir)/$$i.gz ; done
|
||||||
|
|
||||||
|
uninstall-psf-vgaw:
|
||||||
|
for i in $(PSF_VGAW) ; do rm -f $(DESTDIR)$(psfdir)/$$i.gz ; done
|
||||||
|
|
||||||
|
psfref = $(psfdir)/README.terminus
|
||||||
|
|
||||||
|
install-psf-ref: README
|
||||||
|
mkdir -p $(DESTDIR)$(psfdir)
|
||||||
|
sed -e"/^2\.4/,/^2\.5/p" -n README | grep -v "^2\." > $(DESTDIR)$(psfref)
|
||||||
|
|
||||||
|
uninstall-psf-ref:
|
||||||
|
rm -f $(DESTDIR)$(psfref)
|
||||||
|
|
||||||
|
# X11 Window System
|
||||||
|
|
||||||
|
X11_8859_1 = uni/x11gr.uni uni/ascii-h.uni uni/win-1252.uni
|
||||||
|
X11_8859_2 = uni/x11gr.uni uni/ascii-h.uni uni/empty.uni uni/8859-2.uni
|
||||||
|
X11_8859_5 = uni/x11gr.uni uni/ascii-h.uni uni/empty.uni uni/8859-5.uni
|
||||||
|
X11_8859_7 = uni/x11gr.uni uni/ascii-h.uni uni/empty.uni uni/8859-7.uni
|
||||||
|
X11_8859_9 = uni/x11gr.uni uni/ascii-h.uni uni/win-1254.uni
|
||||||
|
X11_MS_1251 = uni/x11gr.uni uni/ascii-h.uni uni/x11-1251.uni uni/win-1251.uni
|
||||||
|
X11_8859_13 = uni/x11gr.uni uni/ascii-h.uni uni/x11-1257.uni uni/8859-13.uni
|
||||||
|
X11_8859_15 = uni/x11gr.uni uni/ascii-h.uni uni/empty.uni uni/8859-15.uni
|
||||||
|
X11_8859_16 = uni/x11gr.uni uni/ascii-h.uni uni/empty.uni uni/8859-16.uni
|
||||||
|
X11_IBM_437 = uni/cntrl.uni uni/ascii-h.uni uni/ibm-437.uni
|
||||||
|
X11_KOI8_R = uni/x11gr.uni uni/ascii-h.uni uni/koi8-r.uni
|
||||||
|
X11_PT_154 = uni/x11gr.uni uni/ascii-h.uni uni/pt-154.uni
|
||||||
|
X11_KOI8_U = uni/x11gr.uni uni/ascii-h.uni uni/koi8-u.uni
|
||||||
|
X11_10646_1 = uni/x11gr.uni uni/10646-1.uni
|
||||||
|
|
||||||
|
$(PCF_8859_1): ter-1%.pcf : ter-u%.bdf $(X11_8859_1)
|
||||||
|
$(UCS2X11) $< $(REG_8859_1) $(X11_8859_1) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_8859_2): ter-2%.pcf : ter-u%.bdf $(X11_8859_2)
|
||||||
|
$(UCS2X11) $< $(REG_8859_2) $(X11_8859_2) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_8859_5): ter-5%.pcf : ter-u%.bdf $(X11_8859_5)
|
||||||
|
$(UCS2X11) $< $(REG_8859_5) $(X11_8859_5) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_8859_7): ter-7%.pcf : ter-u%.bdf $(X11_8859_7)
|
||||||
|
$(UCS2X11) $< $(REG_8859_7) $(X11_8859_7) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_8859_9): ter-9%.pcf : ter-u%.bdf $(X11_8859_9)
|
||||||
|
$(UCS2X11) $< $(REG_8859_9) $(X11_8859_9) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_MS_1251): ter-c%.pcf : ter-u%.bdf $(X11_MS_1251)
|
||||||
|
$(UCS2X11) $< $(REG_MS_1251) $(X11_MS_1251) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_8859_13): ter-d%.pcf : ter-u%.bdf $(X11_8859_13)
|
||||||
|
$(UCS2X11) $< $(REG_8859_13) $(X11_8859_13) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_8859_15): ter-f%.pcf : ter-u%.bdf $(X11_8859_15)
|
||||||
|
$(UCS2X11) $< $(REG_8859_15) $(X11_8859_15) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_8859_16): ter-g%.pcf : ter-u%.bdf $(X11_8859_16)
|
||||||
|
$(UCS2X11) $< $(REG_8859_16) $(X11_8859_16) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_IBM_437): ter-i%.pcf : ter-u%.bdf $(X11_IBM_437)
|
||||||
|
$(UCS2X11) $< $(REG_IBM_437) $(X11_IBM_437) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_KOI8_R): ter-k%.pcf : ter-u%.bdf $(X11_KOI8_R)
|
||||||
|
$(UCS2X11) $< $(REG_KOI8_R) $(X11_KOI8_R) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_PT_154): ter-p%.pcf : ter-u%.bdf $(X11_PT_154)
|
||||||
|
$(UCS2X11) $< $(REG_PT_154) $(X11_PT_154) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_KOI8_U): ter-u%.pcf : ter-u%.bdf $(X11_KOI8_U)
|
||||||
|
$(UCS2X11) $< $(REG_KOI8_U) $(X11_KOI8_U) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
$(PCF_10646_1): ter-x%.pcf : ter-u%.bdf $(X11_10646_1)
|
||||||
|
$(UCS2X11) $< $(REG_10646_1) $(X11_10646_1) | $(BDF2PCF) -o $@
|
||||||
|
|
||||||
|
pcf: $(PCF)
|
||||||
|
|
||||||
|
install-pcf: $(PCF)
|
||||||
|
mkdir -p $(DESTDIR)$(x11dir)
|
||||||
|
for i in $(PCF) ; do gzip -c $$i > $(DESTDIR)$(x11dir)/$$i.gz ; done
|
||||||
|
|
||||||
|
uninstall-pcf:
|
||||||
|
for i in $(PCF) ; do rm -f $(DESTDIR)$(x11dir)/$$i.gz ; done
|
||||||
|
|
||||||
|
pcf-8bit: $(PCF_8BIT)
|
||||||
|
|
||||||
|
install-pcf-8bit: $(PCF_8BIT)
|
||||||
|
mkdir -p $(DESTDIR)$(x11dir)
|
||||||
|
for i in $(PCF_8BIT) ; do gzip -c $$i > $(DESTDIR)$(x11dir)/$$i.gz ; done
|
||||||
|
|
||||||
|
uninstall-pcf-8bit:
|
||||||
|
for i in $(PCF_8BIT) ; do rm -f $(DESTDIR)$(x11dir)/$$i.gz ; done
|
||||||
|
|
||||||
|
# Open Type Bitmap
|
||||||
|
|
||||||
|
$(OTB): ter-u%.otb : ter-u%.bdf
|
||||||
|
$(BDF2OTB) -o $@ $<
|
||||||
|
|
||||||
|
otb: $(OTB)
|
||||||
|
|
||||||
|
install-otb: $(OTB)
|
||||||
|
mkdir -p $(DESTDIR)$(otbdir)
|
||||||
|
cp -f $(OTB) $(DESTDIR)$(otbdir)
|
||||||
|
|
||||||
|
uninstall-otb:
|
||||||
|
for i in $(OTB) ; do rm -f $(DESTDIR)$(otbdir)/$$i ; done
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(PSF) $(PSF_VGAW) $(PCF) $(PCF_8BIT) $(OTB)
|
||||||
|
|
||||||
|
.PHONY: all install uninstall fontdir psf install-psf uninstall-psf psf-vgaw install-psf-vgaw uninstall-psf-vgaw install-psf-ref uninstall-psf-ref pcf install-pcf uninstall-pcf pcf-8bit install-pcf-8bit uninstall-pcf-8bit otb install-otb uninstall-otb clean
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
See CHANGES
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
Copyright (C) 2020 Dimitar Toshkov Zhekov,
|
||||||
|
with Reserved Font Name "Terminus Font".
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
@@ -0,0 +1,395 @@
|
|||||||
|
Contents:
|
||||||
|
|
||||||
|
1. About.
|
||||||
|
1.1. Build requitements.
|
||||||
|
1.2. Quick installation.
|
||||||
|
1.3. Legend.
|
||||||
|
1.4. Variants.
|
||||||
|
1.5. Notes.
|
||||||
|
1.6. Alternative tools.
|
||||||
|
|
||||||
|
2. Linux console.
|
||||||
|
2.1. Installation.
|
||||||
|
2.2. Usage.
|
||||||
|
2.3. Quick reference.
|
||||||
|
2.4. Legend.
|
||||||
|
2.5. Notes.
|
||||||
|
|
||||||
|
3. X11 Window System.
|
||||||
|
3.1. Installation.
|
||||||
|
3.2. Notes.
|
||||||
|
|
||||||
|
4. Open Type Bitmap.
|
||||||
|
4.1. Installation.
|
||||||
|
4.2. Notes.
|
||||||
|
|
||||||
|
5. Microsoft Windows.
|
||||||
|
5.1. Installation package.
|
||||||
|
5.2. Font file only.
|
||||||
|
5.3. Notes.
|
||||||
|
|
||||||
|
6. Frequently Asked Questions.
|
||||||
|
|
||||||
|
7. Legal information.
|
||||||
|
7.1. Licenses.
|
||||||
|
7.2. Copyright.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
1. About.
|
||||||
|
|
||||||
|
This archive contains source code for generating and installing Terminus
|
||||||
|
Font for Linux console, X11 Window System, Microsoft Windows and Open Type
|
||||||
|
Bitmap capable systems.
|
||||||
|
|
||||||
|
- version 4.49.1
|
||||||
|
- sizes 6x12, 8x14, 8x16, 10x18, 10x20, 11x22, 12x24, 14x28, 16x32
|
||||||
|
- weights normal, bold, CRT VGA bold
|
||||||
|
- characters 1356
|
||||||
|
- format Bitmap Distribution Format (BDF) version 2.1
|
||||||
|
|
||||||
|
The character set covers about 120 language sets and supports ISO8859-1/2/5/
|
||||||
|
7/9/13/15/16, Paratype-PT154/PT254, KOI8-R/U/E/F, Esperanto and many IBM,
|
||||||
|
Windows and Macintosh code pages, as well as the IBM VGA, vt100 and xterm
|
||||||
|
pseudographic characters.
|
||||||
|
|
||||||
|
|
||||||
|
1.1. Build requirements.
|
||||||
|
|
||||||
|
- GNU make
|
||||||
|
- Python 3.5.0+ (or node.js 6.9.0+ as alternative)
|
||||||
|
- for X11 only: bdftopcf
|
||||||
|
- for Windows only: GCC for Win32/i686
|
||||||
|
- for the Windows installer only: NSIS and patch(1).
|
||||||
|
|
||||||
|
|
||||||
|
1.2. Quick installation.
|
||||||
|
|
||||||
|
The commands:
|
||||||
|
|
||||||
|
$ ./configure [--prefix=PREFIX]
|
||||||
|
$ make -j8
|
||||||
|
# make install fontdir
|
||||||
|
|
||||||
|
compile and install the Linux console and X11 Window System fonts.
|
||||||
|
The default PREFIX is /usr/local.
|
||||||
|
|
||||||
|
|
||||||
|
1.3. Legend.
|
||||||
|
|
||||||
|
The file names are structured as follows:
|
||||||
|
|
||||||
|
ter-u<SIZE><STYLE>.bdf
|
||||||
|
|
||||||
|
<SIZE> is the font height. <STYLE> is n for normal (all sizes), b for bold
|
||||||
|
(all sizes except 6x12), and v for CRT VGA bold (8x14 and 8x16 only, uses
|
||||||
|
the eight character matrix column).
|
||||||
|
|
||||||
|
|
||||||
|
1.4. Variants.
|
||||||
|
|
||||||
|
Some characters are implemented in two variants. To use the alternate
|
||||||
|
variant, execute:
|
||||||
|
|
||||||
|
$ patch -p1 -i alt/<NAME>.diff
|
||||||
|
|
||||||
|
before making the font. See the font WEB page for examples. If you want to
|
||||||
|
combine hi2 with dv1 and/or ka2, apply hi2 and then hi2-dv1 and/or hi2-ka2.
|
||||||
|
The default variant for unicode range 2800-28FF is oriented towards
|
||||||
|
pseudographics.
|
||||||
|
|
||||||
|
|
||||||
|
1.5. Notes.
|
||||||
|
|
||||||
|
The commands marked with $ can be executed by a regular user.
|
||||||
|
The configure commands are optional.
|
||||||
|
"make -j8" runs 8 jobs in parallel.
|
||||||
|
|
||||||
|
Sizes 6x12, 11x22, 14x28-bold and 16x32-normal are worse than the others.
|
||||||
|
Avoid them.
|
||||||
|
|
||||||
|
210E and 210F are not italic.
|
||||||
|
|
||||||
|
226A, 226B and the double struck letters are not very good.
|
||||||
|
|
||||||
|
2135 may be wrong.
|
||||||
|
|
||||||
|
The hebrew letters and sheqel are uppercase height, which is an attempt to
|
||||||
|
compensate for the missing width.
|
||||||
|
|
||||||
|
|
||||||
|
1.6. Alternative tools.
|
||||||
|
|
||||||
|
If your Python 3 executable is named python instead if python3:
|
||||||
|
|
||||||
|
$ ./configure INT=python
|
||||||
|
|
||||||
|
To use node.js instead of python:
|
||||||
|
|
||||||
|
$ ./configure INT=node EXT=js
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
2. Linux console.
|
||||||
|
|
||||||
|
- weights normal, bold, CRT VGA-bold
|
||||||
|
- code pages ISO8859-1/ISO8859-15/Windows-1252, ISO8859-2/Windows-1250,
|
||||||
|
Windows-1251/ISO8859-5, ISO8859-9/Windows-1254, ISO8859-16,
|
||||||
|
ISO8859-7/Windows-1253, ISO8859-13/Windows-1257, IBM-437,
|
||||||
|
Bulgarian-MIK, KOI8-R, KOI8-U, Paratype-PT154, combined
|
||||||
|
- format PC Screen Font (PSF) with unicode data
|
||||||
|
|
||||||
|
|
||||||
|
2.1. Installation.
|
||||||
|
|
||||||
|
$ ./configure [--prefix=PREFIX | --psfdir=DIRECTORY]
|
||||||
|
$ make -j8 psf
|
||||||
|
# make install-psf
|
||||||
|
|
||||||
|
The files are compressed with gzip and installed in DIRECTORY. The default
|
||||||
|
DIRECTORY is PREFIX/share/consolefonts. For kbd, you may need to change it
|
||||||
|
to PREFIX/lib/kbd/consolefonts or PREFIX/share/kbd/consolefonts, depending
|
||||||
|
on the kbd version.
|
||||||
|
|
||||||
|
The CRT VGA bold weight fonts, suitable for real CRT text modes only, are
|
||||||
|
not installed by default. To install them, execute:
|
||||||
|
|
||||||
|
$ make -j8 psf-vgaw
|
||||||
|
# make install-psf-vgaw
|
||||||
|
|
||||||
|
|
||||||
|
2.2. Usage.
|
||||||
|
|
||||||
|
To load a cont in consoletools:
|
||||||
|
|
||||||
|
$ consolechars [-m MAPPING] -f ter-<X><SIZE><STYLE>
|
||||||
|
|
||||||
|
To load a font in kbd:
|
||||||
|
|
||||||
|
$ setfont [-m MAPPING] ter-<X><SIZE><STYLE>
|
||||||
|
|
||||||
|
where <X> is a character identifying the code page as listed in p.2.4.
|
||||||
|
|
||||||
|
|
||||||
|
2.3. Quick reference.
|
||||||
|
|
||||||
|
The commands:
|
||||||
|
|
||||||
|
$ ./configure [--prefix=PREFIX | --psfdir=DIRECTORY | --psfref=FILENAME]
|
||||||
|
# make install-psf-ref
|
||||||
|
|
||||||
|
install the text from p.2.4 as FILENAME (the default is README.terminus)
|
||||||
|
in DIRECTORY.
|
||||||
|
|
||||||
|
|
||||||
|
2.4. Legend.
|
||||||
|
|
||||||
|
names mappings covered codepage(s)
|
||||||
|
|
||||||
|
ter-1* iso01, iso15, cp1252 ISO8859-1, ISO8859-15, Windows-1252
|
||||||
|
ter-2* iso02, cp1250 ISO8859-2, Windows-1250
|
||||||
|
ter-7* iso07, cp1253 ISO8859-7, Windows-1253
|
||||||
|
ter-9* iso09, cp1254 ISO8859-9, Windows-1254
|
||||||
|
ter-c* cp1251, iso05 Windows-1251, ISO8859-5
|
||||||
|
ter-d* iso13, cp1257 ISO8859-13, Windows-1257
|
||||||
|
ter-g* iso16 ISO8859-16
|
||||||
|
ter-h* cp1255, iso08 Windows-1258, ISO8859-8
|
||||||
|
ter-i* cp437 IBM-437
|
||||||
|
ter-k* koi8r KOI8-R
|
||||||
|
ter-m* mik Bulgarian-MIK
|
||||||
|
ter-p* pt154 Paratype-PT154
|
||||||
|
ter-u* koi8u KOI8-U
|
||||||
|
|
||||||
|
ter-v* all mappings / code pages listed above and many others, about 110
|
||||||
|
language sets, 8 or 16 foreground colors depending on the kernel and
|
||||||
|
console driver versions
|
||||||
|
|
||||||
|
names weight
|
||||||
|
|
||||||
|
ter-*n normal
|
||||||
|
ter-*b bold
|
||||||
|
ter-*v CRT VGA bold
|
||||||
|
|
||||||
|
|
||||||
|
2.5. Notes.
|
||||||
|
|
||||||
|
The combined code page is based on IBM-437 (character 0xFF is ogonek).
|
||||||
|
The ISO8859-16 font also includes all letters and accents from Windows-1250.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
3. X11 Window System.
|
||||||
|
|
||||||
|
- weights normal, bold
|
||||||
|
- code pages ISO8859-1/Windows-1252, ISO8859-2, ISO8859-5, ISO8859-7,
|
||||||
|
ISO8859-9/Windows-1254, ISO8859-13, ISO8859-15, ISO8859-16,
|
||||||
|
Windows-1251, IBM-437, KOI8-R, KOI8-U, Paratype-PT154 and
|
||||||
|
ISO10646-1 (unicode)
|
||||||
|
- format Portable Compiled Font (PCF)
|
||||||
|
|
||||||
|
|
||||||
|
3.1. Installation.
|
||||||
|
|
||||||
|
$ ./configure [--prefix=PREFIX | --x11dir=DIRECTORY]
|
||||||
|
$ make -j8 pcf
|
||||||
|
# make install-pcf
|
||||||
|
|
||||||
|
The files are compressed with gzip and installed in DIRECTORY. The default
|
||||||
|
DIRECTORY is PREFIX/share/fonts/terminus. Requires bdftopcf.
|
||||||
|
|
||||||
|
A copy of the normal 6x12 font is installed as "bold", because some X11
|
||||||
|
libraries and applications substitute the missing bold fonts by shifting the
|
||||||
|
normal fonts, and others do not recognize the bold weight at all if the
|
||||||
|
lowest font size lacks it.
|
||||||
|
|
||||||
|
To update the font cache in DIRECTORY after (un)installation, run:
|
||||||
|
|
||||||
|
# make fontdir
|
||||||
|
|
||||||
|
The configuration file which lists the font directories must contain
|
||||||
|
DIRECTORY. The X11 server may need to be restarted so the font list can be
|
||||||
|
updated.
|
||||||
|
|
||||||
|
By default, only the unicode (ISO10646-1) font is installed. To install the
|
||||||
|
other code pages:
|
||||||
|
|
||||||
|
$ make -j8 pcf-8bit
|
||||||
|
# make install-pcf-8bit
|
||||||
|
|
||||||
|
|
||||||
|
3.2. Notes.
|
||||||
|
|
||||||
|
The ISO8859-1 and ISO8859-9 fonts contain the Windows Western characters and
|
||||||
|
can be used as Windows-1252 and Windows-1254 respectively.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
4. Open Type Bitmap.
|
||||||
|
|
||||||
|
- weights normal, bold
|
||||||
|
- code pages ISO10646-1 (unicode)
|
||||||
|
- format Linux/UNIX bitmap-only TrueType
|
||||||
|
|
||||||
|
|
||||||
|
4.1. Installation.
|
||||||
|
|
||||||
|
$ ./configure [--prefix=PREFIX | --otbdir=DIRECTORY]
|
||||||
|
$ make otb
|
||||||
|
# make install-otb
|
||||||
|
|
||||||
|
The files are installed in DIRECTORY.
|
||||||
|
The default DIRECTORY is PREFIX/share/fonts/terminus.
|
||||||
|
|
||||||
|
|
||||||
|
4.2. Notes
|
||||||
|
|
||||||
|
An OTB file is generated for each BDF file, instead of combining sizes by
|
||||||
|
weight, for the following reasons:
|
||||||
|
|
||||||
|
- KDE compatibility. With combined files, only the first size is available.
|
||||||
|
|
||||||
|
- Correct global font metrics. For example, the base line and character
|
||||||
|
width for 8x14 and 8x16 (relative to height) may never be identical.
|
||||||
|
|
||||||
|
otb1cli is NOT a full-featured BDF to sfnt convertor. It expands the bitmaps
|
||||||
|
first, uses the expanded widths, does not support overlapping characters,
|
||||||
|
and targets Linux/UNIX only.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
5. Microsoft Windows.
|
||||||
|
|
||||||
|
- weights normal, bold
|
||||||
|
- code pages Windows-1252, 1250, 1253, 1254, 1251 and 1257
|
||||||
|
- format Font File Format version 2.0, compiled into FON
|
||||||
|
|
||||||
|
|
||||||
|
5.1. Installation package.
|
||||||
|
|
||||||
|
Make sure that no variant patches are applied to the font (p.1.4).
|
||||||
|
|
||||||
|
> cd win32
|
||||||
|
> build
|
||||||
|
|
||||||
|
Be patient, the process may take several minutes.
|
||||||
|
After that, open terminus.nsi and compile it.
|
||||||
|
|
||||||
|
|
||||||
|
5.2. Font file only.
|
||||||
|
|
||||||
|
> copy *.bdf win32
|
||||||
|
> cd win32
|
||||||
|
> make -j8
|
||||||
|
|
||||||
|
You can install terminus.fon via the regular means.
|
||||||
|
|
||||||
|
|
||||||
|
5.3. Notes.
|
||||||
|
|
||||||
|
The Windows code pages contain a total of 384 characters. All other
|
||||||
|
characters (math, pseudographics etc.) are not currently available.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
6. Frequently Asked Questions.
|
||||||
|
|
||||||
|
Q. Italic version?
|
||||||
|
|
||||||
|
A. No. The quality is significantly lower, and preserving the font width
|
||||||
|
requires overlapping characters, which are not handled very well by X11/Xft.
|
||||||
|
You can try mkitalic from FreeBSD or bdfslant from Debian.
|
||||||
|
|
||||||
|
Q. Scalable version?
|
||||||
|
|
||||||
|
A. Probably not. The font uses a lot of straight horizontal and vertical
|
||||||
|
lines, which is good for a bitmap, but not so much for a vector font. A
|
||||||
|
bitmap font packaged as TTF seems possible.
|
||||||
|
|
||||||
|
Q. How about some new characters?
|
||||||
|
|
||||||
|
A. Contact me and be ready to help.
|
||||||
|
|
||||||
|
Q. The bold 6x12 font...
|
||||||
|
|
||||||
|
A. ...does not exist, there is no space for a bold font in a 6x12 matrix.
|
||||||
|
However, the "normal" font is somewhere between.
|
||||||
|
|
||||||
|
Q. The font works in X11/Motif, but not in GNOME/KDE/Xfce.
|
||||||
|
|
||||||
|
A. Try adding 75-yes-terminus.conf to the Fontconfig configuration files.
|
||||||
|
For some Fontconfig versions, you may need to replace the text "Terminus"
|
||||||
|
in 75-yes-terminus.conf with "xos4 Terminus", though that is unlikely.
|
||||||
|
See also mkfontscale(1), mkfontdir(1), fc-cache(1), xorg.conf(5), xfs(1),
|
||||||
|
xlsfonts(1), fonts-conf(5) etc.
|
||||||
|
|
||||||
|
Q. My terminal emulator does not display cyrillic/pseudographics/...
|
||||||
|
A. If you have the 8-bit X11 code pages installed, and your emulator uses
|
||||||
|
"XLFD" font names, make sure that the font name ends with "-10616-1" instead
|
||||||
|
of "-*-*".
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
7. Legal information.
|
||||||
|
|
||||||
|
|
||||||
|
7.1. Licenses.
|
||||||
|
|
||||||
|
Terminus Font is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
The license is included as OFL.TXT, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
The font includes two variants of unicode range 2800-28FF, but does not
|
||||||
|
support Braille in any way.
|
||||||
|
|
||||||
|
The configure files, python and javascript sources are distributed under
|
||||||
|
the GNU General Public License version 2.0 or (at your choice) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
|
||||||
|
7.2. Copyright.
|
||||||
|
|
||||||
|
Terminus Font 4.49.1, Copyright (C) 2020 Dimitar Toshkov Zhekov.
|
||||||
|
Report bugs to <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
Thanks to Anton Zinoviev, Tim Allen, Kir Koliushkin, Antonios Galanopoulos
|
||||||
|
and everyone else who helped.
|
||||||
@@ -0,0 +1,395 @@
|
|||||||
|
Съдържание:
|
||||||
|
|
||||||
|
1. Обща информация.
|
||||||
|
1.1. Изисквания за компилация.
|
||||||
|
1.2. Бърза инсталация.
|
||||||
|
1.3. Легенда.
|
||||||
|
1.4. Варианти.
|
||||||
|
1.5. Забележки.
|
||||||
|
1.6. Алтернативни средства.
|
||||||
|
|
||||||
|
2. Линукс конзола.
|
||||||
|
2.1. Инсталация.
|
||||||
|
2.2. Използване.
|
||||||
|
2.3. Кратко описание.
|
||||||
|
2.4. Легенда.
|
||||||
|
2.5. Забележки.
|
||||||
|
|
||||||
|
3. X11 Window System.
|
||||||
|
3.1. Инсталация.
|
||||||
|
3.2. Забележки.
|
||||||
|
|
||||||
|
4. Open Type Bitmap.
|
||||||
|
4.1. Инсталация.
|
||||||
|
4.2. Забележки.
|
||||||
|
|
||||||
|
5. Microsoft Windows.
|
||||||
|
5.1. Инсталационен пакет.
|
||||||
|
5.2. Само файл с шрифта.
|
||||||
|
5.3. Забележки.
|
||||||
|
|
||||||
|
6. Често задавани въпроси.
|
||||||
|
|
||||||
|
7. Правна информация.
|
||||||
|
7.1. Лицензи.
|
||||||
|
7.2. Авторство.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
1. Обща информация.
|
||||||
|
|
||||||
|
Този архив съдържа изходен код за генериране и инсталиране на шрифта
|
||||||
|
Терминус за Линукс конзола, X11 Window System, Microsoft Windows и системи
|
||||||
|
поддържащи Open Type Bitmap.
|
||||||
|
|
||||||
|
- версия 4.49.1
|
||||||
|
- размери 6x12, 8x14, 8x16, 10x18, 10x20, 11x22, 12x24, 14x28, 16x32
|
||||||
|
- тежести нормален, удебелен, CRT VGA-удебелен
|
||||||
|
- символи 1356
|
||||||
|
- формат Bitmap Distribution Format (BDF) версия 2.1
|
||||||
|
|
||||||
|
Набора символи покрива около 120 езикови набора и поддържа ISO8859-1/2/5/7/
|
||||||
|
9/13/15/16, Paratype-PT154/PT254, KOI8-R/U/E/F, Есперанто, много кодови
|
||||||
|
страници на IBM, Windows и Macintosh, а също и превдографичните символи на
|
||||||
|
VGA, vt100 и xterm.
|
||||||
|
|
||||||
|
|
||||||
|
1.1. Изисквания за компилация.
|
||||||
|
|
||||||
|
- GNU make
|
||||||
|
- Python 3.5.0+ (или node.js 6.9.0+ като алтернатива)
|
||||||
|
- само за X11: bdftopcf
|
||||||
|
- само за Windows: GCC за Win32/i686
|
||||||
|
- само за Windows инсталатора: NSIS и patch(1).
|
||||||
|
|
||||||
|
|
||||||
|
1.2. Бърза инсталация.
|
||||||
|
|
||||||
|
Командите:
|
||||||
|
|
||||||
|
$ ./configure [--prefix=PREFIX]
|
||||||
|
$ make -j8
|
||||||
|
# make install fontdir
|
||||||
|
|
||||||
|
компилират и инсталират шрифтовете за Линукс конзола и X11 Window System.
|
||||||
|
Подразбиращият се префикс е /usr/local.
|
||||||
|
|
||||||
|
|
||||||
|
1.3. Легенда.
|
||||||
|
|
||||||
|
Имената на файловете са структурирани както следва:
|
||||||
|
|
||||||
|
ter-u<РАЗМЕР><СТИЛ>.bdf
|
||||||
|
|
||||||
|
където <РАЗМЕР> е височината в точки, а <СТИЛ> е n за нормален (всички
|
||||||
|
размери), b за удебелен (всички размери освен 6x12), и v за CRT VGA удебелен
|
||||||
|
(само за 8x14 и 8x16, използва 8 колона на символната матрица).
|
||||||
|
|
||||||
|
|
||||||
|
1.4. Варианти.
|
||||||
|
|
||||||
|
Някои символи са реализирани в два варианта. За да използвате алтернативния
|
||||||
|
вариант, преди инсталация изпълнете:
|
||||||
|
|
||||||
|
$ patch -p1 -i alt/<ИМЕ>.diff
|
||||||
|
|
||||||
|
Примери за разликите межда вариантите са дадени на страницата на шрифта.
|
||||||
|
Ако желаете да комбинирате hi2 с dv1 и/или ka2, приложете първо hi2, и след
|
||||||
|
това hi2-dv1 и/или hi2-ka2. Подразбиращия се вариант на юникод обхвата
|
||||||
|
2800-28FF е ориентиран към псевдографика.
|
||||||
|
|
||||||
|
|
||||||
|
1.5. Забележки.
|
||||||
|
|
||||||
|
Командите отбелязани с $ могат да се изпълняват от обикновен потребител.
|
||||||
|
Командите за конфигуриране не са задължителни.
|
||||||
|
"make -j8" изпълнява паралелно 8 задачи.
|
||||||
|
|
||||||
|
Размери 6x12, 11x22, 14x28-удебелен и 16x32-нормален са с по-лошо качество
|
||||||
|
от останалите. Избягвайте ги.
|
||||||
|
|
||||||
|
210E и 210F не са наклонени.
|
||||||
|
|
||||||
|
226A, 226B и двойно начертаните букви не са много добри.
|
||||||
|
|
||||||
|
2135 може би е грешен.
|
||||||
|
|
||||||
|
В опит да се компенсира липсващата ширина, буквите от иврит и знака шекел са
|
||||||
|
с височина на главни букви.
|
||||||
|
|
||||||
|
|
||||||
|
1.6. Алтернативни средства.
|
||||||
|
|
||||||
|
Ако изпълнимия файл на Python 3 интерпретатора е python вместо python3:
|
||||||
|
|
||||||
|
$ ./configure INT=python
|
||||||
|
|
||||||
|
За използване на node.js вместо python:
|
||||||
|
|
||||||
|
$ ./configure INT=node EXT=js
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
2. Линукс конзола.
|
||||||
|
|
||||||
|
- тежести нормален, удебелен, CRT VGA-удебелен
|
||||||
|
- кодировки ISO8859-1/ISO8859-15/Windows-1252, ISO8859-2/Windows-1250,
|
||||||
|
Windows-1251/ISO8859-5, ISO8859-9/Windows-1254, ISO8859-16,
|
||||||
|
ISO8859-7/Windows-1253, ISO8859-13/Windows-1257, IBM-437,
|
||||||
|
Bulgarian-MIK, KOI8-R, KOI8-U, Paratype-PT154, комбинирана
|
||||||
|
- формат PC Screen Font (PSF) с unicode данни
|
||||||
|
|
||||||
|
|
||||||
|
2.1. Инсталация.
|
||||||
|
|
||||||
|
$ ./configure [--prefix=ПРЕФИКС | --psfdir=ДИРЕКТОРИЯ]
|
||||||
|
$ make -j8 psf
|
||||||
|
# make install-psf
|
||||||
|
|
||||||
|
Файловете се компресират с gzip и инсталират в ДИРЕКТОРИЯ. Подразбиращата се
|
||||||
|
ДИРЕКТОРИЯ е ПРЕФИКС/share/consolefonts. За kbd може да се наложи да смените
|
||||||
|
директорията на PREFIX/lib/kbd/consolefonts или
|
||||||
|
PREFIX/share/kbd/consolefonts, в зависимост от версията на kbd.
|
||||||
|
|
||||||
|
CRT VGA-удебелените шрифтове, подходящи за само истински CRT текстови
|
||||||
|
режими, не се инсталират по подразбиране. За инсталирането им изпълнете:
|
||||||
|
|
||||||
|
$ make -j8 psf-vgaw
|
||||||
|
# make install-psf-vgaw
|
||||||
|
|
||||||
|
|
||||||
|
2.2. Използване.
|
||||||
|
|
||||||
|
За зареждане на шрифт с consoletools:
|
||||||
|
|
||||||
|
$ consolechars [-m КОДИРОВКА] -f ter-<X><РАЗМЕР><СТИЛ>
|
||||||
|
|
||||||
|
За зареждане на шрифт с kbd:
|
||||||
|
|
||||||
|
$ setfont [-m MAPPING] ter-<X><SIZE><STYLE>
|
||||||
|
|
||||||
|
където <X> е символ идентифициращ кодовата страница по списъка от т.2.4.
|
||||||
|
|
||||||
|
|
||||||
|
2.3. Кратко описание.
|
||||||
|
|
||||||
|
Командите:
|
||||||
|
|
||||||
|
$ ./configure [--prefix=ПРЕФИКС | --psfdir=ДИРЕКТОРИЯ | --psfref=ИМЕНАФАЙЛ]
|
||||||
|
# make install-psf-ref
|
||||||
|
|
||||||
|
инсталират текста от т.2.4 (на английски) под името ИМЕНАФАЙЛ (подразбира
|
||||||
|
се README.terminus) в ДИРЕКТОРИЯ.
|
||||||
|
|
||||||
|
|
||||||
|
2.4. Легенда.
|
||||||
|
|
||||||
|
имена кодировки кодови страници
|
||||||
|
|
||||||
|
ter-1* iso01, iso15, cp1252 ISO8859-1, ISO8859-15, Windows-1252
|
||||||
|
ter-2* iso02, cp1250 ISO8859-2, Windows-1250
|
||||||
|
ter-7* iso07, cp1253 ISO8859-7, Windows-1253
|
||||||
|
ter-9* iso09, cp1254 ISO8859-9, Windows-1254
|
||||||
|
ter-c* cp1251, iso05 Windows-1251, ISO8859-5
|
||||||
|
ter-d* iso13, cp1257 ISO8859-13, Windows-1257
|
||||||
|
ter-g* iso16 ISO8859-16
|
||||||
|
ter-h* cp1255, iso08 Windows-1255, ISO8859-8
|
||||||
|
ter-i* cp437 IBM-437
|
||||||
|
ter-k* koi8r KOI8-R
|
||||||
|
ter-m* mik Bulgarian-MIK
|
||||||
|
ter-p* pt154 Paratype-PT154
|
||||||
|
ter-k* koi8u KOI8-U
|
||||||
|
|
||||||
|
ter-v* всички изброени по-горе кодировки / страници и много други, около
|
||||||
|
110 езикови набора, 8 или 16 цвята за текст в зависимост от ядрото и
|
||||||
|
конзолния драйвер
|
||||||
|
|
||||||
|
имена тежест
|
||||||
|
|
||||||
|
ter-*n нормален
|
||||||
|
ter-*b удебелен
|
||||||
|
ter-*v CRT VGA-удебелен
|
||||||
|
|
||||||
|
|
||||||
|
2.5. Забележки.
|
||||||
|
|
||||||
|
Комбинираната кодова страница е базирана IBM-437 (символ 0xFF е ogonek).
|
||||||
|
ISO8859-16 шрифта включва също всички букви и акценти от Windows-1250.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
3. X11 Window System.
|
||||||
|
|
||||||
|
- тежести нормален, удебелен
|
||||||
|
- кодировки ISO8859-1/Windows-1252, ISO8859-2, ISO8859-5, ISO8859-7,
|
||||||
|
ISO8859-9/Windows-1254, ISO8859-13, ISO8859-15, ISO8859-16,
|
||||||
|
Windows-1251, IBM-437, KOI8-R, KOI8-U, Paratype-PT154 и
|
||||||
|
ISO10646-1 (уникод)
|
||||||
|
- формат Portable Compiled Font (PCF)
|
||||||
|
|
||||||
|
|
||||||
|
3.1. Инсталация.
|
||||||
|
|
||||||
|
$ ./configure [--prefix=ПРЕФИКС | --x11dir=ДИРЕКТОРИЯ]
|
||||||
|
$ make pcf
|
||||||
|
# make install-pcf
|
||||||
|
|
||||||
|
Файловете се компресират с gzip и инсталират в ДИРЕКТОРИЯ. Подразбиращата се
|
||||||
|
ДИРЕКТОРИЯ е ПРЕФИКС/share/fonts/terminus. Изисква се bdftopcf.
|
||||||
|
|
||||||
|
Копие на нормалния 6x12 шрифт се инсталира като "удебелен", защото някои
|
||||||
|
X11 библиотеки и програми заменят липсващите удебелени шрифтове чрез
|
||||||
|
отместване на нормалните, а други изобщо не разпознават удебелена тежест,
|
||||||
|
ако такава липсва в най-малкия размер на шрифта.
|
||||||
|
|
||||||
|
За да актуализирате fonts.dir в ДИРЕКТОРИЯ след (де)инсталация, изпълнете:
|
||||||
|
|
||||||
|
# make fontdir
|
||||||
|
|
||||||
|
Конфигурационния файл, изброяващ директориите за шрифтове, трябва да включва
|
||||||
|
ДИРЕКТОРИЯ. За да се обнови списъка от шрифтове може да се наложи рестарт на
|
||||||
|
X11 сървъра.
|
||||||
|
|
||||||
|
По подразбиране се инсталира само уникод (ISO10646-1) шрифта. За инсталиране
|
||||||
|
на останалите кодови страници:
|
||||||
|
|
||||||
|
$ make -j8 pcf-8bit
|
||||||
|
# make install-pcf-8bit
|
||||||
|
|
||||||
|
|
||||||
|
3.2. Забележки.
|
||||||
|
|
||||||
|
ISO8859-1 и ISO8859-9 шрифтовете съдържат Windows Western символите и могат
|
||||||
|
да бъдат използвани съответно като Windows-1252 и Windows-1254.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
4. Open Type Bitmap.
|
||||||
|
|
||||||
|
- тежести нормален, удебелен
|
||||||
|
- кодировки ISO10646-1 (уникод)
|
||||||
|
- формат растерен TrueType за Linux/UNIX
|
||||||
|
|
||||||
|
|
||||||
|
4.1. Инсталация.
|
||||||
|
|
||||||
|
$ ./configure [--prefix=ПРЕФИКС | --otbdir=ДИРЕКТОРИЯ]
|
||||||
|
$ make otb
|
||||||
|
# make install-otb
|
||||||
|
|
||||||
|
Файловете се инсталират в ДИРЕКТОРИЯ.
|
||||||
|
Подразбиращата се ДИРЕКТОРИЯ е ПРЕФИКС/share/fonts/terminus.
|
||||||
|
|
||||||
|
|
||||||
|
4.2. Забележки.
|
||||||
|
|
||||||
|
За всеки BDF файл се генерира отделен OTB файл, вместо да се комбинират
|
||||||
|
по тежест, по следните причини:
|
||||||
|
|
||||||
|
- Съвместимост с КДЕ. При комбинирани файлове е достъпен само първия размер.
|
||||||
|
|
||||||
|
- Коректни глобални размери. Например базовата линия и ширината на символите
|
||||||
|
(измервани по височината) не могат да бъдат еднакви за 8x14 и 8x16.
|
||||||
|
|
||||||
|
otb1cli НЕ Е пълноценен конвертор от BDF към TTF. Символите предварително
|
||||||
|
се растеризират, използват се растеризизираните ширини, не се поддържат
|
||||||
|
застъпващи се символи, и резултата е предназначен само за Linux/UNIX.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
5. Microsoft Windows.
|
||||||
|
|
||||||
|
- тежести нормален, удебелен
|
||||||
|
- кодировки Windows-1252, 1250, 1253, 1254, 1251 and 1257
|
||||||
|
- формат Font File Format версия 2.0, компилиран във FON
|
||||||
|
|
||||||
|
|
||||||
|
5.1. Инстанационен пакет.
|
||||||
|
|
||||||
|
Уверете се, че към шрифта не са прилагани корекции за варианти (т.1.4).
|
||||||
|
|
||||||
|
> cd win32
|
||||||
|
> build
|
||||||
|
|
||||||
|
Бъдете търпеливи, процеса може да отнеме няколко минути.
|
||||||
|
След това отворете terminus.nsi и го компилирайте.
|
||||||
|
|
||||||
|
|
||||||
|
5.2. Само файл с шрифта.
|
||||||
|
|
||||||
|
> copy *.bdf win32
|
||||||
|
> cd win32
|
||||||
|
> make -j8
|
||||||
|
|
||||||
|
Можете са инсталирате terminus.fon по стандартните начини.
|
||||||
|
|
||||||
|
|
||||||
|
5.3. Забележки.
|
||||||
|
|
||||||
|
Кодовите страници за Windows съдържат общо 384 символа. Всички останали
|
||||||
|
символи (математика, превдографика и т.н.) засега не са достъпни.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
6. Често задавани въпроси.
|
||||||
|
|
||||||
|
В. Наклонена версия?
|
||||||
|
|
||||||
|
О. Не. Качеството е доста по-ниско, а и запазването ширината на символите
|
||||||
|
изисква припокриване, което не се обработва много добре от X11/Xft. Ако Ви
|
||||||
|
е много необходима, пробвайте mkitalic от FreeBSD или bdfslant от Debian.
|
||||||
|
|
||||||
|
В. Мащабируема версия?
|
||||||
|
|
||||||
|
О. Вероятно не. Шрифта използва мого хоризонтални и вертикални линии, които
|
||||||
|
са подходящш ра растерна графика, но не толкова за векторна. Може би
|
||||||
|
растерен шрифт, комплектован като TrueType.
|
||||||
|
|
||||||
|
В. Какво ще кажете за някои нови символи?
|
||||||
|
|
||||||
|
О. Пишете ми и имайте готовност да помогнете.
|
||||||
|
|
||||||
|
В. Удебеленият 6x12 шрифт...
|
||||||
|
|
||||||
|
О. ...не съществува, в матрица 6x12 няма достатъчно място за добър удебелен
|
||||||
|
шрифт. Всъщност "нормалният" шрифт е някъде по средата.
|
||||||
|
|
||||||
|
В. Шрифтът работи с X11/Motif, но не и с GNOME/KDE/Xfce.
|
||||||
|
|
||||||
|
О. Опитайте да добавите 75-yes-terminus.conf към конфигурационните файлове
|
||||||
|
на Fontconfig. За някои версии на Fontconfig, може да се наложи да замените
|
||||||
|
текста "Terminus" във файла с "xos4 Terminus", макар че е слабо вероятно.
|
||||||
|
Вижте също mkfontscale(1), mkfontdir(1), fc-cache(1), xorg.conf(5), xfs(1),
|
||||||
|
xlsfonts(1), fonts-conf(5) и т.н.
|
||||||
|
|
||||||
|
В. Моя терминален емулатор не извежда кирилица/псевдографика/...
|
||||||
|
О. Ако имате инсталирани 8-битовите кодови страници за X11, и емулатора
|
||||||
|
използва "XLFD" имена на шрифтовете, уверете се че името на шрифта завършва
|
||||||
|
на "-10616-1" вместо "-*-*".
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
7. Правна информация.
|
||||||
|
|
||||||
|
|
||||||
|
7.1. Лицензи.
|
||||||
|
|
||||||
|
Terminus Font е лицензизан под SIL Open Font License, версия 1.1.
|
||||||
|
Лицензът е включен като OFL.TXT, и е достъпен заедно с FAQ на адрес:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
Шрифтът включва два варианта на юникод обхвата 2800-28FF, но по никакъв
|
||||||
|
начин не поддържа Брайловата азбука.
|
||||||
|
|
||||||
|
Конфигурационните файлове, както и изходния код на python и javascript, се
|
||||||
|
разпространяват под GNU General Public License версия 2.0 или (по Ваше
|
||||||
|
усмотрение) която и да е по-късна версия.
|
||||||
|
|
||||||
|
|
||||||
|
7.2. Авторство.
|
||||||
|
|
||||||
|
Terminus Font 4.49.1, Copyright (C) 2020 Димитър Тошков Жеков.
|
||||||
|
Адрес за кореспонденция <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
Благодаря на Антон Зиновиев, Тим Алън, Кир Колышкин, Антониос Галанопулос и
|
||||||
|
всички останали, които помогнаха.
|
||||||
@@ -0,0 +1,860 @@
|
|||||||
|
--- ./ter-u12b.bdf.orig 2020-12-28 20:34:18.635118400 +0200
|
||||||
|
+++ ./ter-u12b.bdf 2020-12-28 20:34:21.775122800 +0200
|
||||||
|
@@ -10030,3 +10030,2 @@
|
||||||
|
-E0
|
||||||
|
-90
|
||||||
|
-90
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -10034,0 +10034 @@
|
||||||
|
+F0
|
||||||
|
@@ -10070,8 +10070,8 @@
|
||||||
|
-78
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-78
|
||||||
|
-08
|
||||||
|
-70
|
||||||
|
+38
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+FC
|
||||||
|
+84
|
||||||
|
+00
|
||||||
|
--- ./ter-u12n.bdf.orig 2020-12-28 20:34:18.605118300 +0200
|
||||||
|
+++ ./ter-u12n.bdf 2020-12-28 20:34:21.775122800 +0200
|
||||||
|
@@ -10030,3 +10030,2 @@
|
||||||
|
-E0
|
||||||
|
-90
|
||||||
|
-90
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -10034,0 +10034 @@
|
||||||
|
+F0
|
||||||
|
@@ -10070,8 +10070,8 @@
|
||||||
|
-78
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-78
|
||||||
|
-08
|
||||||
|
-70
|
||||||
|
+38
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+FC
|
||||||
|
+84
|
||||||
|
+00
|
||||||
|
--- ./ter-u14b.bdf.orig 2020-12-28 20:34:18.655118400 +0200
|
||||||
|
+++ ./ter-u14b.bdf 2020-12-28 20:34:21.815122800 +0200
|
||||||
|
@@ -11082,4 +11082,3 @@
|
||||||
|
-78
|
||||||
|
-CC
|
||||||
|
-CC
|
||||||
|
-C8
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -11088,0 +11088 @@
|
||||||
|
+FC
|
||||||
|
@@ -11127,9 +11127,9 @@
|
||||||
|
-7E
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-7E
|
||||||
|
-06
|
||||||
|
-7C
|
||||||
|
+3E
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+FF
|
||||||
|
+C3
|
||||||
|
+00
|
||||||
|
--- ./ter-u14n.bdf.orig 2020-12-28 20:34:18.645118400 +0200
|
||||||
|
+++ ./ter-u14n.bdf 2020-12-28 20:34:21.785122800 +0200
|
||||||
|
@@ -11082,4 +11082,3 @@
|
||||||
|
-38
|
||||||
|
-44
|
||||||
|
-44
|
||||||
|
-48
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -11088,0 +11088 @@
|
||||||
|
+7C
|
||||||
|
@@ -11127,8 +11126,0 @@
|
||||||
|
-3E
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-3E
|
||||||
|
-02
|
||||||
|
@@ -11135,0 +11128,8 @@
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+FE
|
||||||
|
+82
|
||||||
|
+00
|
||||||
|
--- ./ter-u14v.bdf.orig 2020-12-28 20:34:18.675118400 +0200
|
||||||
|
+++ ./ter-u14v.bdf 2020-12-28 20:34:21.815122800 +0200
|
||||||
|
@@ -11082,4 +11082,3 @@
|
||||||
|
-78
|
||||||
|
-CC
|
||||||
|
-CC
|
||||||
|
-C8
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -11088,0 +11088 @@
|
||||||
|
+FC
|
||||||
|
@@ -11127,9 +11127,9 @@
|
||||||
|
-7E
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-7E
|
||||||
|
-06
|
||||||
|
-7C
|
||||||
|
+3E
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+FF
|
||||||
|
+C3
|
||||||
|
+00
|
||||||
|
--- ./ter-u16b.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16b.bdf 2020-12-28 20:34:21.825122800 +0200
|
||||||
|
@@ -12134,4 +12134,3 @@
|
||||||
|
-78
|
||||||
|
-CC
|
||||||
|
-CC
|
||||||
|
-C8
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -12140,0 +12140 @@
|
||||||
|
+FC
|
||||||
|
@@ -12183,10 +12183,10 @@
|
||||||
|
-7E
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-7E
|
||||||
|
-06
|
||||||
|
-06
|
||||||
|
-7C
|
||||||
|
+3E
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+FF
|
||||||
|
+C3
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
--- ./ter-u16n.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16n.bdf 2020-12-28 20:34:21.825122800 +0200
|
||||||
|
@@ -12134,4 +12134,3 @@
|
||||||
|
-38
|
||||||
|
-44
|
||||||
|
-44
|
||||||
|
-48
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -12140,0 +12140 @@
|
||||||
|
+7C
|
||||||
|
@@ -12183,9 +12182,0 @@
|
||||||
|
-3E
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-3E
|
||||||
|
-02
|
||||||
|
-02
|
||||||
|
@@ -12192,0 +12184,9 @@
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+FE
|
||||||
|
+82
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
--- ./ter-u16v.bdf.orig 2020-12-28 20:34:18.695118400 +0200
|
||||||
|
+++ ./ter-u16v.bdf 2020-12-28 20:34:21.855122900 +0200
|
||||||
|
@@ -12134,4 +12134,3 @@
|
||||||
|
-78
|
||||||
|
-CC
|
||||||
|
-CC
|
||||||
|
-C8
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -12140,0 +12140 @@
|
||||||
|
+FC
|
||||||
|
@@ -12183,10 +12183,10 @@
|
||||||
|
-7E
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-7E
|
||||||
|
-06
|
||||||
|
-06
|
||||||
|
-7C
|
||||||
|
+3E
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+FF
|
||||||
|
+C3
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
--- ./ter-u18b.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18b.bdf 2020-12-28 20:34:21.865122900 +0200
|
||||||
|
@@ -13187,5 +13187,3 @@
|
||||||
|
-3E00
|
||||||
|
-6300
|
||||||
|
-6300
|
||||||
|
-6300
|
||||||
|
-6200
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -13195,0 +13194,2 @@
|
||||||
|
+7F00
|
||||||
|
+6180
|
||||||
|
@@ -13240,12 +13240,12 @@
|
||||||
|
-3F80
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-3F80
|
||||||
|
-0180
|
||||||
|
-0180
|
||||||
|
-3F00
|
||||||
|
+1F00
|
||||||
|
+3300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+FF80
|
||||||
|
+C180
|
||||||
|
+C180
|
||||||
|
+0000
|
||||||
|
--- ./ter-u18n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18n.bdf 2020-12-28 20:34:21.865122900 +0200
|
||||||
|
@@ -13187,5 +13187,3 @@
|
||||||
|
-3C00
|
||||||
|
-4200
|
||||||
|
-4200
|
||||||
|
-4200
|
||||||
|
-4400
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -13195,0 +13194,2 @@
|
||||||
|
+7E00
|
||||||
|
+4100
|
||||||
|
@@ -13240,12 +13240,12 @@
|
||||||
|
-3F00
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-3F00
|
||||||
|
-0100
|
||||||
|
-0100
|
||||||
|
-3E00
|
||||||
|
+0F00
|
||||||
|
+1100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+7F80
|
||||||
|
+4080
|
||||||
|
+4080
|
||||||
|
+0000
|
||||||
|
--- ./ter-u20b.bdf.orig 2020-12-28 20:34:18.735118500 +0200
|
||||||
|
+++ ./ter-u20b.bdf 2020-12-28 20:34:21.905122900 +0200
|
||||||
|
@@ -14239,5 +14239,4 @@
|
||||||
|
-3E00
|
||||||
|
-6300
|
||||||
|
-6300
|
||||||
|
-6300
|
||||||
|
-6200
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -14247,0 +14247 @@
|
||||||
|
+7F00
|
||||||
|
@@ -14297,12 +14297,12 @@
|
||||||
|
-3F80
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-3F80
|
||||||
|
-0180
|
||||||
|
-0180
|
||||||
|
-3F00
|
||||||
|
+1F00
|
||||||
|
+3300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+FF80
|
||||||
|
+C180
|
||||||
|
+C180
|
||||||
|
+0000
|
||||||
|
--- ./ter-u20n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u20n.bdf 2020-12-28 20:34:21.865122900 +0200
|
||||||
|
@@ -14239,5 +14239,4 @@
|
||||||
|
-3C00
|
||||||
|
-4200
|
||||||
|
-4200
|
||||||
|
-4200
|
||||||
|
-4400
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -14247,0 +14247 @@
|
||||||
|
+7E00
|
||||||
|
@@ -14297,12 +14297,12 @@
|
||||||
|
-3F00
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-3F00
|
||||||
|
-0100
|
||||||
|
-0100
|
||||||
|
-3E00
|
||||||
|
+0F00
|
||||||
|
+1100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+7F80
|
||||||
|
+4080
|
||||||
|
+4080
|
||||||
|
+0000
|
||||||
|
--- ./ter-u22b.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22b.bdf 2020-12-28 20:34:21.905122900 +0200
|
||||||
|
@@ -15291,8 +15291,5 @@
|
||||||
|
-3E00
|
||||||
|
-6300
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6300
|
||||||
|
-7F00
|
||||||
|
-6180
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F80
|
||||||
|
@@ -15301,0 +15299 @@
|
||||||
|
+7F80
|
||||||
|
@@ -15303,2 +15301,4 @@
|
||||||
|
-6180
|
||||||
|
-7F00
|
||||||
|
+60C0
|
||||||
|
+60C0
|
||||||
|
+60C0
|
||||||
|
+7F80
|
||||||
|
@@ -15353,14 +15353,14 @@
|
||||||
|
-1FC0
|
||||||
|
-30C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-30C0
|
||||||
|
-1FC0
|
||||||
|
-00C0
|
||||||
|
-00C0
|
||||||
|
-0180
|
||||||
|
-3F00
|
||||||
|
+1F80
|
||||||
|
+3180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+FFC0
|
||||||
|
+C0C0
|
||||||
|
+C0C0
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u22n.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22n.bdf 2020-12-28 20:34:21.915123000 +0200
|
||||||
|
@@ -15291,8 +15291,6 @@
|
||||||
|
-3C00
|
||||||
|
-4200
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4200
|
||||||
|
-7E00
|
||||||
|
-4100
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F00
|
||||||
|
+4080
|
||||||
|
@@ -15300,0 +15299 @@
|
||||||
|
+7F00
|
||||||
|
@@ -15303,2 +15302,3 @@
|
||||||
|
-4100
|
||||||
|
-7E00
|
||||||
|
+4080
|
||||||
|
+4080
|
||||||
|
+7F00
|
||||||
|
@@ -15353 +15353,4 @@
|
||||||
|
-1F80
|
||||||
|
+0F80
|
||||||
|
+1080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
@@ -15355,6 +15357,0 @@
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
@@ -15362,5 +15359,8 @@
|
||||||
|
-1F80
|
||||||
|
-0080
|
||||||
|
-0080
|
||||||
|
-0100
|
||||||
|
-3E00
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+7FC0
|
||||||
|
+4040
|
||||||
|
+4040
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u24b.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24b.bdf 2020-12-28 20:34:21.955123000 +0200
|
||||||
|
@@ -16344,2 +16344,5 @@
|
||||||
|
-3F00
|
||||||
|
-6180
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F80
|
||||||
|
@@ -16349,2 +16351,0 @@
|
||||||
|
-6180
|
||||||
|
-7F80
|
||||||
|
@@ -16351,0 +16353 @@
|
||||||
|
+7FC0
|
||||||
|
@@ -16356,3 +16358 @@
|
||||||
|
-6060
|
||||||
|
-60C0
|
||||||
|
-7F80
|
||||||
|
+7FC0
|
||||||
|
@@ -16410,7 +16410,11 @@
|
||||||
|
-1FE0
|
||||||
|
-3060
|
||||||
|
-6060
|
||||||
|
-6060
|
||||||
|
-6060
|
||||||
|
-6060
|
||||||
|
-6060
|
||||||
|
+0FC0
|
||||||
|
+18C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+7FE0
|
||||||
|
@@ -16419,6 +16423,2 @@
|
||||||
|
-30E0
|
||||||
|
-1FE0
|
||||||
|
-0060
|
||||||
|
-0060
|
||||||
|
-00C0
|
||||||
|
-3F80
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u24n.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24n.bdf 2020-12-28 20:34:21.915123000 +0200
|
||||||
|
@@ -16344,2 +16344,5 @@
|
||||||
|
-3E00
|
||||||
|
-4100
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F00
|
||||||
|
@@ -16349,2 +16351,0 @@
|
||||||
|
-4100
|
||||||
|
-7F00
|
||||||
|
@@ -16351,0 +16353 @@
|
||||||
|
+7F80
|
||||||
|
@@ -16356,3 +16358 @@
|
||||||
|
-4040
|
||||||
|
-4080
|
||||||
|
-7F00
|
||||||
|
+7F80
|
||||||
|
@@ -16410,7 +16410,11 @@
|
||||||
|
-1FC0
|
||||||
|
-2040
|
||||||
|
-4040
|
||||||
|
-4040
|
||||||
|
-4040
|
||||||
|
-4040
|
||||||
|
-4040
|
||||||
|
+0F80
|
||||||
|
+1080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+7FC0
|
||||||
|
@@ -16419,6 +16423,2 @@
|
||||||
|
-20C0
|
||||||
|
-1F40
|
||||||
|
-0040
|
||||||
|
-0040
|
||||||
|
-0080
|
||||||
|
-3F00
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u28b.bdf.orig 2020-12-28 20:34:18.845118700 +0200
|
||||||
|
+++ ./ter-u28b.bdf 2020-12-28 20:34:21.975123000 +0200
|
||||||
|
@@ -18448 +18448,5 @@
|
||||||
|
-3F00
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -18450,5 +18453,0 @@
|
||||||
|
-61C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-6180
|
||||||
|
@@ -18456,4 +18455,6 @@
|
||||||
|
-7FE0
|
||||||
|
-6070
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
+6060
|
||||||
|
+6060
|
||||||
|
+6060
|
||||||
|
+7FC0
|
||||||
|
+7FC0
|
||||||
|
+6060
|
||||||
|
@@ -18463 +18463,0 @@
|
||||||
|
-6070
|
||||||
|
@@ -18523 +18523,11 @@
|
||||||
|
-1FF0
|
||||||
|
+07F0
|
||||||
|
+0FF0
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
@@ -18525,16 +18535,6 @@
|
||||||
|
-7030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-7030
|
||||||
|
-3FF0
|
||||||
|
-1FF0
|
||||||
|
-0030
|
||||||
|
-0030
|
||||||
|
-0070
|
||||||
|
-3FE0
|
||||||
|
-3FC0
|
||||||
|
+7FF8
|
||||||
|
+6018
|
||||||
|
+6018
|
||||||
|
+6018
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u28n.bdf.orig 2020-12-28 20:34:18.835118600 +0200
|
||||||
|
+++ ./ter-u28n.bdf 2020-12-28 20:34:21.965123000 +0200
|
||||||
|
@@ -18448,4 +18448,6 @@
|
||||||
|
-3F00
|
||||||
|
-6180
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F80
|
||||||
|
@@ -18452,0 +18455,3 @@
|
||||||
|
+6060
|
||||||
|
+6060
|
||||||
|
+6060
|
||||||
|
@@ -18454 +18458,0 @@
|
||||||
|
-6180
|
||||||
|
@@ -18460,4 +18463,0 @@
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
@@ -18523,18 +18523,18 @@
|
||||||
|
-1FF0
|
||||||
|
-3030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-3030
|
||||||
|
-1FF0
|
||||||
|
-0030
|
||||||
|
-0030
|
||||||
|
-0030
|
||||||
|
-0060
|
||||||
|
-3FC0
|
||||||
|
+07F0
|
||||||
|
+0C30
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+7FF8
|
||||||
|
+6018
|
||||||
|
+6018
|
||||||
|
+6018
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u32b.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32b.bdf 2020-12-28 20:34:22.025123100 +0200
|
||||||
|
@@ -20554,8 +20554,6 @@
|
||||||
|
-3FC0
|
||||||
|
-7FE0
|
||||||
|
-70F0
|
||||||
|
-7070
|
||||||
|
-7070
|
||||||
|
-7070
|
||||||
|
-7070
|
||||||
|
-70E0
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -20563,0 +20562 @@
|
||||||
|
+7078
|
||||||
|
@@ -20565,4 +20564,5 @@
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
+7038
|
||||||
|
+7038
|
||||||
|
+7FF0
|
||||||
|
+7FF8
|
||||||
|
+703C
|
||||||
|
@@ -20638 +20638,12 @@
|
||||||
|
-1FFC
|
||||||
|
+07FC
|
||||||
|
+0FFC
|
||||||
|
+1E1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
@@ -20640,17 +20651,6 @@
|
||||||
|
-781C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-781C
|
||||||
|
-3FFC
|
||||||
|
-1FFC
|
||||||
|
-001C
|
||||||
|
-001C
|
||||||
|
-003C
|
||||||
|
-3FF8
|
||||||
|
-3FF0
|
||||||
|
+7FFE
|
||||||
|
+700E
|
||||||
|
+700E
|
||||||
|
+700E
|
||||||
|
+700E
|
||||||
|
+0000
|
||||||
|
--- ./ter-u32n.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32n.bdf 2020-12-28 20:34:21.985123000 +0200
|
||||||
|
@@ -20554,8 +20554,6 @@
|
||||||
|
-1FC0
|
||||||
|
-3FE0
|
||||||
|
-3070
|
||||||
|
-3030
|
||||||
|
-3030
|
||||||
|
-3030
|
||||||
|
-3030
|
||||||
|
-3070
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -20564,0 +20563,5 @@
|
||||||
|
+3018
|
||||||
|
+3018
|
||||||
|
+3038
|
||||||
|
+3FF0
|
||||||
|
+3FF8
|
||||||
|
@@ -20568,3 +20570,0 @@
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
@@ -20638,19 +20638,19 @@
|
||||||
|
-0FFC
|
||||||
|
-1FFC
|
||||||
|
-380C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-380C
|
||||||
|
-1FFC
|
||||||
|
-0FFC
|
||||||
|
-000C
|
||||||
|
-000C
|
||||||
|
-001C
|
||||||
|
-1FF8
|
||||||
|
-1FF0
|
||||||
|
+07F8
|
||||||
|
+0FF8
|
||||||
|
+1C18
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+3FF8
|
||||||
|
+7FFC
|
||||||
|
+600C
|
||||||
|
+600C
|
||||||
|
+600C
|
||||||
|
+600C
|
||||||
|
+0000
|
||||||
@@ -0,0 +1,992 @@
|
|||||||
|
--- ./ter-u12b.bdf.orig 2020-12-28 20:34:18.635118400 +0200
|
||||||
|
+++ ./ter-u12b.bdf 2020-12-28 20:34:22.635124000 +0200
|
||||||
|
@@ -10051,4 +10051,3 @@
|
||||||
|
-F8
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
+70
|
||||||
|
+08
|
||||||
|
+70
|
||||||
|
@@ -10056,0 +10056 @@
|
||||||
|
+70
|
||||||
|
@@ -10659,4 +10659,3 @@
|
||||||
|
-F8
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
+70
|
||||||
|
+08
|
||||||
|
+70
|
||||||
|
@@ -10664,0 +10664 @@
|
||||||
|
+70
|
||||||
|
@@ -10998,0 +10999,3 @@
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+70
|
||||||
|
@@ -11000,5 +11003 @@
|
||||||
|
-08
|
||||||
|
-F8
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
+70
|
||||||
|
@@ -11006,0 +11006 @@
|
||||||
|
+70
|
||||||
|
--- ./ter-u12n.bdf.orig 2020-12-28 20:34:18.605118300 +0200
|
||||||
|
+++ ./ter-u12n.bdf 2020-12-28 20:34:22.625123900 +0200
|
||||||
|
@@ -10051,4 +10051,3 @@
|
||||||
|
-F8
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
+70
|
||||||
|
+08
|
||||||
|
+70
|
||||||
|
@@ -10056,0 +10056 @@
|
||||||
|
+70
|
||||||
|
@@ -10659,4 +10659,3 @@
|
||||||
|
-F8
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
+70
|
||||||
|
+08
|
||||||
|
+70
|
||||||
|
@@ -10664,0 +10664 @@
|
||||||
|
+70
|
||||||
|
@@ -10998,0 +10999,3 @@
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+70
|
||||||
|
@@ -11000,5 +11003 @@
|
||||||
|
-08
|
||||||
|
-F8
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
-80
|
||||||
|
+70
|
||||||
|
@@ -11006,0 +11006 @@
|
||||||
|
+70
|
||||||
|
--- ./ter-u14b.bdf.orig 2020-12-28 20:34:18.655118400 +0200
|
||||||
|
+++ ./ter-u14b.bdf 2020-12-28 20:34:22.675124000 +0200
|
||||||
|
@@ -11106,5 +11106,4 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
+06
|
||||||
|
+06
|
||||||
|
+7C
|
||||||
|
@@ -11112,0 +11112 @@
|
||||||
|
+7C
|
||||||
|
@@ -11778,5 +11778,4 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
+06
|
||||||
|
+06
|
||||||
|
+7C
|
||||||
|
@@ -11784,0 +11784 @@
|
||||||
|
+7C
|
||||||
|
@@ -12153,0 +12154,3 @@
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+7C
|
||||||
|
@@ -12156,5 +12159 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
@@ -12162,0 +12162 @@
|
||||||
|
+7C
|
||||||
|
--- ./ter-u14n.bdf.orig 2020-12-28 20:34:18.645118400 +0200
|
||||||
|
+++ ./ter-u14n.bdf 2020-12-28 20:34:22.655124000 +0200
|
||||||
|
@@ -11106,5 +11106,4 @@
|
||||||
|
-7E
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
+3C
|
||||||
|
+02
|
||||||
|
+02
|
||||||
|
+3C
|
||||||
|
@@ -11112,0 +11112 @@
|
||||||
|
+3C
|
||||||
|
@@ -11778,5 +11778,4 @@
|
||||||
|
-7E
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
+3C
|
||||||
|
+02
|
||||||
|
+02
|
||||||
|
+3C
|
||||||
|
@@ -11784,0 +11784 @@
|
||||||
|
+3C
|
||||||
|
@@ -12153,0 +12154,3 @@
|
||||||
|
+20
|
||||||
|
+20
|
||||||
|
+3C
|
||||||
|
@@ -12156,5 +12159 @@
|
||||||
|
-7E
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
+3C
|
||||||
|
@@ -12162,0 +12162 @@
|
||||||
|
+3C
|
||||||
|
--- ./ter-u14v.bdf.orig 2020-12-28 20:34:18.675118400 +0200
|
||||||
|
+++ ./ter-u14v.bdf 2020-12-28 20:34:22.665124000 +0200
|
||||||
|
@@ -11106,5 +11106,4 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
+06
|
||||||
|
+06
|
||||||
|
+7C
|
||||||
|
@@ -11112,0 +11112 @@
|
||||||
|
+7C
|
||||||
|
@@ -11778,5 +11778,4 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
+06
|
||||||
|
+06
|
||||||
|
+7C
|
||||||
|
@@ -11784,0 +11784 @@
|
||||||
|
+7C
|
||||||
|
@@ -12153,0 +12154,3 @@
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+7C
|
||||||
|
@@ -12156,5 +12159 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
@@ -12162,0 +12162 @@
|
||||||
|
+7C
|
||||||
|
--- ./ter-u16b.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16b.bdf 2020-12-28 20:34:22.695124000 +0200
|
||||||
|
@@ -12160,5 +12160,4 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
+06
|
||||||
|
+06
|
||||||
|
+7C
|
||||||
|
@@ -12166,0 +12166 @@
|
||||||
|
+7C
|
||||||
|
@@ -12896,5 +12896,4 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
+06
|
||||||
|
+06
|
||||||
|
+7C
|
||||||
|
@@ -12902,0 +12902 @@
|
||||||
|
+7C
|
||||||
|
@@ -13307,0 +13308,3 @@
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+7C
|
||||||
|
@@ -13310,5 +13313 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
@@ -13316,0 +13316 @@
|
||||||
|
+7C
|
||||||
|
--- ./ter-u16n.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16n.bdf 2020-12-28 20:34:22.685124000 +0200
|
||||||
|
@@ -12160,5 +12160,4 @@
|
||||||
|
-7E
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
+3C
|
||||||
|
+02
|
||||||
|
+02
|
||||||
|
+3C
|
||||||
|
@@ -12166,0 +12166 @@
|
||||||
|
+3C
|
||||||
|
@@ -12896,5 +12896,4 @@
|
||||||
|
-7E
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
+3C
|
||||||
|
+02
|
||||||
|
+02
|
||||||
|
+3C
|
||||||
|
@@ -12902,0 +12902 @@
|
||||||
|
+3C
|
||||||
|
@@ -13307,0 +13308,3 @@
|
||||||
|
+20
|
||||||
|
+20
|
||||||
|
+3C
|
||||||
|
@@ -13310,5 +13313 @@
|
||||||
|
-7E
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
-40
|
||||||
|
+3C
|
||||||
|
@@ -13316,0 +13316 @@
|
||||||
|
+3C
|
||||||
|
--- ./ter-u16v.bdf.orig 2020-12-28 20:34:18.695118400 +0200
|
||||||
|
+++ ./ter-u16v.bdf 2020-12-28 20:34:22.715124100 +0200
|
||||||
|
@@ -12160,5 +12160,4 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
+06
|
||||||
|
+06
|
||||||
|
+7C
|
||||||
|
@@ -12166,0 +12166 @@
|
||||||
|
+7C
|
||||||
|
@@ -12896,5 +12896,4 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
+06
|
||||||
|
+06
|
||||||
|
+7C
|
||||||
|
@@ -12902,0 +12902 @@
|
||||||
|
+7C
|
||||||
|
@@ -13307,0 +13308,3 @@
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+7C
|
||||||
|
@@ -13310,5 +13313 @@
|
||||||
|
-FE
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
-C0
|
||||||
|
+7C
|
||||||
|
@@ -13316,0 +13316 @@
|
||||||
|
+7C
|
||||||
|
--- ./ter-u18b.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18b.bdf 2020-12-28 20:34:22.725124100 +0200
|
||||||
|
@@ -13215,6 +13215,5 @@
|
||||||
|
-7F80
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3F00
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+3F00
|
||||||
|
@@ -13223,0 +13223 @@
|
||||||
|
+3F00
|
||||||
|
@@ -14015,6 +14015,5 @@
|
||||||
|
-7F80
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3F00
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+3F00
|
||||||
|
@@ -14023,0 +14023 @@
|
||||||
|
+3F00
|
||||||
|
@@ -14462,0 +14463,3 @@
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3F00
|
||||||
|
@@ -14465,6 +14468,2 @@
|
||||||
|
-7F80
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+0180
|
||||||
|
+3F00
|
||||||
|
@@ -14473,0 +14473 @@
|
||||||
|
+3F00
|
||||||
|
--- ./ter-u18n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18n.bdf 2020-12-28 20:34:22.715124100 +0200
|
||||||
|
@@ -13215,6 +13215,5 @@
|
||||||
|
-7F00
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3E00
|
||||||
|
+0100
|
||||||
|
+0100
|
||||||
|
+0100
|
||||||
|
+3E00
|
||||||
|
@@ -13223,0 +13223 @@
|
||||||
|
+3E00
|
||||||
|
@@ -14015,6 +14015,5 @@
|
||||||
|
-7F00
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3E00
|
||||||
|
+0100
|
||||||
|
+0100
|
||||||
|
+0100
|
||||||
|
+3E00
|
||||||
|
@@ -14023,0 +14023 @@
|
||||||
|
+3E00
|
||||||
|
@@ -14462,0 +14463,3 @@
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+3E00
|
||||||
|
@@ -14465,6 +14468,2 @@
|
||||||
|
-7F00
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+0100
|
||||||
|
+3E00
|
||||||
|
@@ -14473,0 +14473 @@
|
||||||
|
+3E00
|
||||||
|
--- ./ter-u20b.bdf.orig 2020-12-28 20:34:18.735118500 +0200
|
||||||
|
+++ ./ter-u20b.bdf 2020-12-28 20:34:22.775124200 +0200
|
||||||
|
@@ -14270,6 +14270,5 @@
|
||||||
|
-7F80
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3F00
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+3F00
|
||||||
|
@@ -14278,0 +14278 @@
|
||||||
|
+3F00
|
||||||
|
@@ -15134,6 +15134,5 @@
|
||||||
|
-7F80
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3F00
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+3F00
|
||||||
|
@@ -15142,0 +15142 @@
|
||||||
|
+3F00
|
||||||
|
@@ -15617,0 +15618,3 @@
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3F00
|
||||||
|
@@ -15620,6 +15623,2 @@
|
||||||
|
-7F80
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+0180
|
||||||
|
+3F00
|
||||||
|
@@ -15628,0 +15628 @@
|
||||||
|
+3F00
|
||||||
|
--- ./ter-u20n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u20n.bdf 2020-12-28 20:34:22.735124100 +0200
|
||||||
|
@@ -14270,6 +14270,5 @@
|
||||||
|
-7F00
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3E00
|
||||||
|
+0100
|
||||||
|
+0100
|
||||||
|
+0100
|
||||||
|
+3E00
|
||||||
|
@@ -14278,0 +14278 @@
|
||||||
|
+3E00
|
||||||
|
@@ -15134,6 +15134,5 @@
|
||||||
|
-7F00
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3E00
|
||||||
|
+0100
|
||||||
|
+0100
|
||||||
|
+0100
|
||||||
|
+3E00
|
||||||
|
@@ -15142,0 +15142 @@
|
||||||
|
+3E00
|
||||||
|
@@ -15617,0 +15618,3 @@
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+3E00
|
||||||
|
@@ -15620,6 +15623,2 @@
|
||||||
|
-7F00
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+0100
|
||||||
|
+3E00
|
||||||
|
@@ -15628,0 +15628 @@
|
||||||
|
+3E00
|
||||||
|
--- ./ter-u22b.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22b.bdf 2020-12-28 20:34:22.775124200 +0200
|
||||||
|
@@ -15324,6 +15324,5 @@
|
||||||
|
-7FC0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3F80
|
||||||
|
+00C0
|
||||||
|
+00C0
|
||||||
|
+00C0
|
||||||
|
+3F80
|
||||||
|
@@ -15333,0 +15333 @@
|
||||||
|
+3F80
|
||||||
|
@@ -16252,6 +16252,5 @@
|
||||||
|
-7FC0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3F80
|
||||||
|
+00C0
|
||||||
|
+00C0
|
||||||
|
+00C0
|
||||||
|
+3F80
|
||||||
|
@@ -16261,0 +16261 @@
|
||||||
|
+3F80
|
||||||
|
@@ -16770,0 +16771,4 @@
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3F80
|
||||||
|
@@ -16774,6 +16778 @@
|
||||||
|
-7FC0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3F80
|
||||||
|
@@ -16783,0 +16783 @@
|
||||||
|
+3F80
|
||||||
|
--- ./ter-u22n.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22n.bdf 2020-12-28 20:34:22.775124200 +0200
|
||||||
|
@@ -15324,6 +15324,5 @@
|
||||||
|
-7F80
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3F00
|
||||||
|
+0080
|
||||||
|
+0080
|
||||||
|
+0080
|
||||||
|
+3F00
|
||||||
|
@@ -15333,0 +15333 @@
|
||||||
|
+3F00
|
||||||
|
@@ -16252,6 +16252,5 @@
|
||||||
|
-7F80
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3F00
|
||||||
|
+0080
|
||||||
|
+0080
|
||||||
|
+0080
|
||||||
|
+3F00
|
||||||
|
@@ -16261,0 +16261 @@
|
||||||
|
+3F00
|
||||||
|
@@ -16770,0 +16771,4 @@
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+3F00
|
||||||
|
@@ -16774,6 +16778 @@
|
||||||
|
-7F80
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3F00
|
||||||
|
@@ -16783,0 +16783 @@
|
||||||
|
+3F00
|
||||||
|
--- ./ter-u24b.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24b.bdf 2020-12-28 20:34:22.825124200 +0200
|
||||||
|
@@ -16379,7 +16379,6 @@
|
||||||
|
-7FE0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3FC0
|
||||||
|
+0060
|
||||||
|
+0060
|
||||||
|
+0060
|
||||||
|
+0060
|
||||||
|
+3FC0
|
||||||
|
@@ -16389,0 +16389 @@
|
||||||
|
+3FC0
|
||||||
|
@@ -17371,7 +17371,6 @@
|
||||||
|
-7FE0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3FC0
|
||||||
|
+0060
|
||||||
|
+0060
|
||||||
|
+0060
|
||||||
|
+0060
|
||||||
|
+3FC0
|
||||||
|
@@ -17381,0 +17381 @@
|
||||||
|
+3FC0
|
||||||
|
@@ -17925,0 +17926,4 @@
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3FC0
|
||||||
|
@@ -17929,7 +17933,2 @@
|
||||||
|
-7FE0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+0060
|
||||||
|
+3FC0
|
||||||
|
@@ -17939,0 +17939 @@
|
||||||
|
+3FC0
|
||||||
|
--- ./ter-u24n.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24n.bdf 2020-12-28 20:34:22.775124200 +0200
|
||||||
|
@@ -16379,7 +16379,6 @@
|
||||||
|
-7FC0
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3F80
|
||||||
|
+0040
|
||||||
|
+0040
|
||||||
|
+0040
|
||||||
|
+0040
|
||||||
|
+3F80
|
||||||
|
@@ -16389,0 +16389 @@
|
||||||
|
+3F80
|
||||||
|
@@ -17371,7 +17371,6 @@
|
||||||
|
-7FC0
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+3F80
|
||||||
|
+0040
|
||||||
|
+0040
|
||||||
|
+0040
|
||||||
|
+0040
|
||||||
|
+3F80
|
||||||
|
@@ -17381,0 +17381 @@
|
||||||
|
+3F80
|
||||||
|
@@ -17925,0 +17926,4 @@
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+3F80
|
||||||
|
@@ -17929,7 +17933,2 @@
|
||||||
|
-7FC0
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
-4000
|
||||||
|
+0040
|
||||||
|
+3F80
|
||||||
|
@@ -17939,0 +17939 @@
|
||||||
|
+3F80
|
||||||
|
--- ./ter-u28b.bdf.orig 2020-12-28 20:34:18.845118700 +0200
|
||||||
|
+++ ./ter-u28b.bdf 2020-12-28 20:34:22.845124300 +0200
|
||||||
|
@@ -18488,11 +18488,8 @@
|
||||||
|
-7FF0
|
||||||
|
-7FF0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3FC0
|
||||||
|
+3FE0
|
||||||
|
+0070
|
||||||
|
+0030
|
||||||
|
+0030
|
||||||
|
+1FE0
|
||||||
|
+3FC0
|
||||||
|
+7000
|
||||||
|
@@ -18500,0 +18498,3 @@
|
||||||
|
+7000
|
||||||
|
+3FE0
|
||||||
|
+1FE0
|
||||||
|
@@ -19608,11 +19608,8 @@
|
||||||
|
-7FF0
|
||||||
|
-7FF0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3FC0
|
||||||
|
+3FE0
|
||||||
|
+0070
|
||||||
|
+0030
|
||||||
|
+0030
|
||||||
|
+1FE0
|
||||||
|
+3FC0
|
||||||
|
+7000
|
||||||
|
@@ -19620,0 +19618,3 @@
|
||||||
|
+7000
|
||||||
|
+3FE0
|
||||||
|
+1FE0
|
||||||
|
@@ -20234,0 +20235,6 @@
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3FC0
|
||||||
|
+3FE0
|
||||||
|
+0070
|
||||||
|
@@ -20237,12 +20243,3 @@
|
||||||
|
-0030
|
||||||
|
-7FF0
|
||||||
|
-7FF0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+1FE0
|
||||||
|
+3FC0
|
||||||
|
+7000
|
||||||
|
@@ -20250,0 +20248,3 @@
|
||||||
|
+7000
|
||||||
|
+3FE0
|
||||||
|
+1FE0
|
||||||
|
--- ./ter-u28n.bdf.orig 2020-12-28 20:34:18.835118600 +0200
|
||||||
|
+++ ./ter-u28n.bdf 2020-12-28 20:34:22.835124200 +0200
|
||||||
|
@@ -18488,10 +18488,8 @@
|
||||||
|
-7FF0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3FC0
|
||||||
|
+0060
|
||||||
|
+0030
|
||||||
|
+0030
|
||||||
|
+0030
|
||||||
|
+0060
|
||||||
|
+1FC0
|
||||||
|
+3000
|
||||||
|
@@ -18500,0 +18499,2 @@
|
||||||
|
+3000
|
||||||
|
+1FE0
|
||||||
|
@@ -19608,10 +19608,8 @@
|
||||||
|
-7FF0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+3FC0
|
||||||
|
+0060
|
||||||
|
+0030
|
||||||
|
+0030
|
||||||
|
+0030
|
||||||
|
+0060
|
||||||
|
+1FC0
|
||||||
|
+3000
|
||||||
|
@@ -19620,0 +19619,2 @@
|
||||||
|
+3000
|
||||||
|
+1FE0
|
||||||
|
@@ -20234,0 +20235,5 @@
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3FC0
|
||||||
|
+0060
|
||||||
|
@@ -20238,10 +20243,3 @@
|
||||||
|
-7FF0
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
-6000
|
||||||
|
+0060
|
||||||
|
+1FC0
|
||||||
|
+3000
|
||||||
|
@@ -20250,0 +20249,2 @@
|
||||||
|
+3000
|
||||||
|
+1FE0
|
||||||
|
--- ./ter-u32b.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32b.bdf 2020-12-28 20:34:22.905124300 +0200
|
||||||
|
@@ -20599,12 +20599,9 @@
|
||||||
|
-7FFC
|
||||||
|
-7FFC
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
+3FF0
|
||||||
|
+3FF8
|
||||||
|
+003C
|
||||||
|
+001C
|
||||||
|
+001C
|
||||||
|
+003C
|
||||||
|
+1FF8
|
||||||
|
+3FF0
|
||||||
|
+7800
|
||||||
|
@@ -20612,0 +20610,3 @@
|
||||||
|
+7800
|
||||||
|
+3FF8
|
||||||
|
+1FF8
|
||||||
|
@@ -21847,12 +21847,9 @@
|
||||||
|
-7FFC
|
||||||
|
-7FFC
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
+3FF0
|
||||||
|
+3FF8
|
||||||
|
+003C
|
||||||
|
+001C
|
||||||
|
+001C
|
||||||
|
+003C
|
||||||
|
+1FF8
|
||||||
|
+3FF0
|
||||||
|
+7800
|
||||||
|
@@ -21860,0 +21858,3 @@
|
||||||
|
+7800
|
||||||
|
+3FF8
|
||||||
|
+1FF8
|
||||||
|
@@ -22544,0 +22545,7 @@
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3FF0
|
||||||
|
+3FF8
|
||||||
|
+003C
|
||||||
|
@@ -22547,14 +22554,4 @@
|
||||||
|
-001C
|
||||||
|
-001C
|
||||||
|
-7FFC
|
||||||
|
-7FFC
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
-7000
|
||||||
|
+003C
|
||||||
|
+1FF8
|
||||||
|
+3FF0
|
||||||
|
+7800
|
||||||
|
@@ -22562,0 +22560,3 @@
|
||||||
|
+7800
|
||||||
|
+3FF8
|
||||||
|
+1FF8
|
||||||
|
--- ./ter-u32n.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32n.bdf 2020-12-28 20:34:22.855124300 +0200
|
||||||
|
@@ -20599,12 +20599,9 @@
|
||||||
|
-3FFC
|
||||||
|
-3FFC
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
+1FF0
|
||||||
|
+1FF8
|
||||||
|
+001C
|
||||||
|
+000C
|
||||||
|
+000C
|
||||||
|
+001C
|
||||||
|
+0FF8
|
||||||
|
+1FF0
|
||||||
|
+3800
|
||||||
|
@@ -20612,0 +20610,3 @@
|
||||||
|
+3800
|
||||||
|
+1FF8
|
||||||
|
+0FF8
|
||||||
|
@@ -21847,12 +21847,9 @@
|
||||||
|
-3FFC
|
||||||
|
-3FFC
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
+1FF0
|
||||||
|
+1FF8
|
||||||
|
+001C
|
||||||
|
+000C
|
||||||
|
+000C
|
||||||
|
+001C
|
||||||
|
+0FF8
|
||||||
|
+1FF0
|
||||||
|
+3800
|
||||||
|
@@ -21860,0 +21858,3 @@
|
||||||
|
+3800
|
||||||
|
+1FF8
|
||||||
|
+0FF8
|
||||||
|
@@ -22544,0 +22545,7 @@
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1FF0
|
||||||
|
+1FF8
|
||||||
|
+001C
|
||||||
|
@@ -22547,14 +22554,4 @@
|
||||||
|
-000C
|
||||||
|
-000C
|
||||||
|
-3FFC
|
||||||
|
-3FFC
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
-3000
|
||||||
|
+001C
|
||||||
|
+0FF8
|
||||||
|
+1FF0
|
||||||
|
+3800
|
||||||
|
@@ -22562,0 +22560,3 @@
|
||||||
|
+3800
|
||||||
|
+1FF8
|
||||||
|
+0FF8
|
||||||
@@ -0,0 +1,304 @@
|
|||||||
|
--- ./ter-u12b.bdf.orig 2020-12-28 20:34:18.635118400 +0200
|
||||||
|
+++ ./ter-u12b.bdf 2020-12-28 20:34:23.545125200 +0200
|
||||||
|
@@ -189 +189 @@
|
||||||
|
-20
|
||||||
|
+40
|
||||||
|
@@ -1269,3 +1268,0 @@
|
||||||
|
-40
|
||||||
|
-20
|
||||||
|
-00
|
||||||
|
@@ -1272,0 +1270,3 @@
|
||||||
|
+20
|
||||||
|
+20
|
||||||
|
+10
|
||||||
|
--- ./ter-u12n.bdf.orig 2020-12-28 20:34:18.605118300 +0200
|
||||||
|
+++ ./ter-u12n.bdf 2020-12-28 20:34:23.535125200 +0200
|
||||||
|
@@ -189 +189 @@
|
||||||
|
-20
|
||||||
|
+40
|
||||||
|
@@ -1269,3 +1268,0 @@
|
||||||
|
-40
|
||||||
|
-20
|
||||||
|
-00
|
||||||
|
@@ -1272,0 +1270,3 @@
|
||||||
|
+20
|
||||||
|
+20
|
||||||
|
+10
|
||||||
|
--- ./ter-u14b.bdf.orig 2020-12-28 20:34:18.655118400 +0200
|
||||||
|
+++ ./ter-u14b.bdf 2020-12-28 20:34:23.575125300 +0200
|
||||||
|
@@ -205 +205 @@
|
||||||
|
-18
|
||||||
|
+30
|
||||||
|
@@ -1398,0 +1399,2 @@
|
||||||
|
+00
|
||||||
|
+30
|
||||||
|
@@ -1401,2 +1402,0 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
--- ./ter-u14n.bdf.orig 2020-12-28 20:34:18.645118400 +0200
|
||||||
|
+++ ./ter-u14n.bdf 2020-12-28 20:34:23.555125200 +0200
|
||||||
|
@@ -203,2 +203,2 @@
|
||||||
|
-10
|
||||||
|
-10
|
||||||
|
+08
|
||||||
|
+08
|
||||||
|
@@ -1398,0 +1399,2 @@
|
||||||
|
+00
|
||||||
|
+10
|
||||||
|
@@ -1401,2 +1402,0 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
--- ./ter-u14v.bdf.orig 2020-12-28 20:34:18.675118400 +0200
|
||||||
|
+++ ./ter-u14v.bdf 2020-12-28 20:34:23.575125300 +0200
|
||||||
|
@@ -205 +205 @@
|
||||||
|
-18
|
||||||
|
+30
|
||||||
|
@@ -1398,0 +1399,2 @@
|
||||||
|
+00
|
||||||
|
+30
|
||||||
|
@@ -1401,2 +1402,0 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
--- ./ter-u16b.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16b.bdf 2020-12-28 20:34:23.595125300 +0200
|
||||||
|
@@ -221 +221 @@
|
||||||
|
-18
|
||||||
|
+30
|
||||||
|
@@ -1528,0 +1529,2 @@
|
||||||
|
+00
|
||||||
|
+30
|
||||||
|
@@ -1531,2 +1532,0 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
--- ./ter-u16n.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16n.bdf 2020-12-28 20:34:23.585125300 +0200
|
||||||
|
@@ -219,2 +219,2 @@
|
||||||
|
-10
|
||||||
|
-10
|
||||||
|
+08
|
||||||
|
+08
|
||||||
|
@@ -1528,0 +1529,2 @@
|
||||||
|
+00
|
||||||
|
+10
|
||||||
|
@@ -1531,2 +1532,0 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
--- ./ter-u16v.bdf.orig 2020-12-28 20:34:18.695118400 +0200
|
||||||
|
+++ ./ter-u16v.bdf 2020-12-28 20:34:23.615125300 +0200
|
||||||
|
@@ -221 +221 @@
|
||||||
|
-18
|
||||||
|
+30
|
||||||
|
@@ -1528,0 +1529,2 @@
|
||||||
|
+00
|
||||||
|
+30
|
||||||
|
@@ -1531,2 +1532,0 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
--- ./ter-u18b.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18b.bdf 2020-12-28 20:34:23.635125400 +0200
|
||||||
|
@@ -238 +238 @@
|
||||||
|
-0C00
|
||||||
|
+1800
|
||||||
|
@@ -1659 +1659,3 @@
|
||||||
|
-3000
|
||||||
|
+0000
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
@@ -1662,2 +1663,0 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
--- ./ter-u18n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18n.bdf 2020-12-28 20:34:23.625125300 +0200
|
||||||
|
@@ -238 +238 @@
|
||||||
|
-0800
|
||||||
|
+1000
|
||||||
|
@@ -1659 +1659,3 @@
|
||||||
|
-2000
|
||||||
|
+0000
|
||||||
|
+1000
|
||||||
|
+1000
|
||||||
|
@@ -1662,2 +1663,0 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
--- ./ter-u20b.bdf.orig 2020-12-28 20:34:18.735118500 +0200
|
||||||
|
+++ ./ter-u20b.bdf 2020-12-28 20:34:23.665125400 +0200
|
||||||
|
@@ -254 +254 @@
|
||||||
|
-0C00
|
||||||
|
+1800
|
||||||
|
@@ -1789 +1789,3 @@
|
||||||
|
-3000
|
||||||
|
+0000
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
@@ -1792,2 +1793,0 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
--- ./ter-u20n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u20n.bdf 2020-12-28 20:34:23.635125400 +0200
|
||||||
|
@@ -254 +254 @@
|
||||||
|
-0800
|
||||||
|
+1000
|
||||||
|
@@ -1789 +1789,3 @@
|
||||||
|
-2000
|
||||||
|
+0000
|
||||||
|
+1000
|
||||||
|
+1000
|
||||||
|
@@ -1792,2 +1793,0 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
--- ./ter-u22b.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22b.bdf 2020-12-28 20:34:23.675125400 +0200
|
||||||
|
@@ -267,4 +267,4 @@
|
||||||
|
-0C00
|
||||||
|
-0C00
|
||||||
|
-0C00
|
||||||
|
-0C00
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
@@ -1919 +1919,4 @@
|
||||||
|
-1800
|
||||||
|
+0000
|
||||||
|
+0C00
|
||||||
|
+0C00
|
||||||
|
+0C00
|
||||||
|
@@ -1922,3 +1924,0 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
--- ./ter-u22n.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22n.bdf 2020-12-28 20:34:23.675125400 +0200
|
||||||
|
@@ -271 +271 @@
|
||||||
|
-0400
|
||||||
|
+0800
|
||||||
|
@@ -1919,5 +1918,0 @@
|
||||||
|
-1000
|
||||||
|
-0800
|
||||||
|
-0400
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
@@ -1924,0 +1920,5 @@
|
||||||
|
+0400
|
||||||
|
+0400
|
||||||
|
+0400
|
||||||
|
+0400
|
||||||
|
+0200
|
||||||
|
--- ./ter-u24b.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24b.bdf 2020-12-28 20:34:23.715125500 +0200
|
||||||
|
@@ -288 +288 @@
|
||||||
|
-0600
|
||||||
|
+0C00
|
||||||
|
@@ -2050,5 +2049,0 @@
|
||||||
|
-1800
|
||||||
|
-0C00
|
||||||
|
-0600
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
@@ -2055,0 +2051,5 @@
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0300
|
||||||
|
--- ./ter-u24n.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24n.bdf 2020-12-28 20:34:23.685125400 +0200
|
||||||
|
@@ -288 +288 @@
|
||||||
|
-0400
|
||||||
|
+0800
|
||||||
|
@@ -2050,5 +2049,0 @@
|
||||||
|
-1000
|
||||||
|
-0800
|
||||||
|
-0400
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
@@ -2055,0 +2051,5 @@
|
||||||
|
+0400
|
||||||
|
+0400
|
||||||
|
+0400
|
||||||
|
+0400
|
||||||
|
+0200
|
||||||
|
--- ./ter-u28b.bdf.orig 2020-12-28 20:34:18.845118700 +0200
|
||||||
|
+++ ./ter-u28b.bdf 2020-12-28 20:34:23.735125500 +0200
|
||||||
|
@@ -320,2 +320,2 @@
|
||||||
|
-0300
|
||||||
|
-0300
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
@@ -2309,6 +2308,0 @@
|
||||||
|
-3800
|
||||||
|
-1C00
|
||||||
|
-0E00
|
||||||
|
-0700
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
@@ -2316,0 +2311,6 @@
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0300
|
||||||
|
+0300
|
||||||
|
--- ./ter-u28n.bdf.orig 2020-12-28 20:34:18.835118600 +0200
|
||||||
|
+++ ./ter-u28n.bdf 2020-12-28 20:34:23.735125500 +0200
|
||||||
|
@@ -320,2 +320,2 @@
|
||||||
|
-0300
|
||||||
|
-0300
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
@@ -2309,6 +2308,0 @@
|
||||||
|
-1800
|
||||||
|
-0C00
|
||||||
|
-0600
|
||||||
|
-0300
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
@@ -2316,0 +2311,6 @@
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0600
|
||||||
|
+0300
|
||||||
|
+0300
|
||||||
|
--- ./ter-u32b.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32b.bdf 2020-12-28 20:34:23.775125600 +0200
|
||||||
|
@@ -354,2 +354,2 @@
|
||||||
|
-0380
|
||||||
|
-0380
|
||||||
|
+0700
|
||||||
|
+0700
|
||||||
|
@@ -2571,6 +2570,0 @@
|
||||||
|
-1C00
|
||||||
|
-0E00
|
||||||
|
-0700
|
||||||
|
-0380
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
@@ -2578,0 +2573,6 @@
|
||||||
|
+0380
|
||||||
|
+0380
|
||||||
|
+0380
|
||||||
|
+0380
|
||||||
|
+01C0
|
||||||
|
+01C0
|
||||||
|
--- ./ter-u32n.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32n.bdf 2020-12-28 20:34:23.765125500 +0200
|
||||||
|
@@ -354,2 +354,2 @@
|
||||||
|
-0180
|
||||||
|
-0180
|
||||||
|
+0300
|
||||||
|
+0300
|
||||||
|
@@ -2571,6 +2570,0 @@
|
||||||
|
-0E00
|
||||||
|
-0700
|
||||||
|
-0380
|
||||||
|
-01C0
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
@@ -2578,0 +2573,6 @@
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+0180
|
||||||
|
+00C0
|
||||||
|
+00C0
|
||||||
@@ -0,0 +1,860 @@
|
|||||||
|
--- ./ter-u12b.bdf.orig 2020-12-28 20:34:27.995131500 +0200
|
||||||
|
+++ ./ter-u12b.bdf 2020-12-28 20:34:29.445133500 +0200
|
||||||
|
@@ -10030,3 +10030,2 @@
|
||||||
|
-E0
|
||||||
|
-90
|
||||||
|
-90
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -10034,0 +10034 @@
|
||||||
|
+F0
|
||||||
|
@@ -10070,8 +10070,8 @@
|
||||||
|
-78
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-78
|
||||||
|
-08
|
||||||
|
-70
|
||||||
|
+38
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+FC
|
||||||
|
+84
|
||||||
|
+00
|
||||||
|
--- ./ter-u12n.bdf.orig 2020-12-28 20:34:27.975131400 +0200
|
||||||
|
+++ ./ter-u12n.bdf 2020-12-28 20:34:29.425133500 +0200
|
||||||
|
@@ -10030,3 +10030,2 @@
|
||||||
|
-E0
|
||||||
|
-90
|
||||||
|
-90
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -10034,0 +10034 @@
|
||||||
|
+F0
|
||||||
|
@@ -10070,8 +10070,8 @@
|
||||||
|
-78
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-88
|
||||||
|
-78
|
||||||
|
-08
|
||||||
|
-70
|
||||||
|
+38
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+48
|
||||||
|
+FC
|
||||||
|
+84
|
||||||
|
+00
|
||||||
|
--- ./ter-u14b.bdf.orig 2020-12-28 20:34:28.025131500 +0200
|
||||||
|
+++ ./ter-u14b.bdf 2020-12-28 20:34:29.465133500 +0200
|
||||||
|
@@ -11082,4 +11082,3 @@
|
||||||
|
-78
|
||||||
|
-CC
|
||||||
|
-CC
|
||||||
|
-C8
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -11088,0 +11088 @@
|
||||||
|
+FC
|
||||||
|
@@ -11127,9 +11127,9 @@
|
||||||
|
-7E
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-7E
|
||||||
|
-06
|
||||||
|
-7C
|
||||||
|
+3E
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+FF
|
||||||
|
+C3
|
||||||
|
+00
|
||||||
|
--- ./ter-u14n.bdf.orig 2020-12-28 20:34:27.995131500 +0200
|
||||||
|
+++ ./ter-u14n.bdf 2020-12-28 20:34:29.465133500 +0200
|
||||||
|
@@ -11082,4 +11082,3 @@
|
||||||
|
-38
|
||||||
|
-44
|
||||||
|
-44
|
||||||
|
-48
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -11088,0 +11088 @@
|
||||||
|
+7C
|
||||||
|
@@ -11127,8 +11126,0 @@
|
||||||
|
-3E
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-3E
|
||||||
|
-02
|
||||||
|
@@ -11135,0 +11128,8 @@
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+FE
|
||||||
|
+82
|
||||||
|
+00
|
||||||
|
--- ./ter-u14v.bdf.orig 2020-12-28 20:34:28.025131500 +0200
|
||||||
|
+++ ./ter-u14v.bdf 2020-12-28 20:34:29.475133500 +0200
|
||||||
|
@@ -11082,4 +11082,3 @@
|
||||||
|
-78
|
||||||
|
-CC
|
||||||
|
-CC
|
||||||
|
-C8
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -11088,0 +11088 @@
|
||||||
|
+FC
|
||||||
|
@@ -11127,9 +11127,9 @@
|
||||||
|
-7E
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-7E
|
||||||
|
-06
|
||||||
|
-7C
|
||||||
|
+3E
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+FF
|
||||||
|
+C3
|
||||||
|
+00
|
||||||
|
--- ./ter-u16b.bdf.orig 2020-12-28 20:34:28.035131500 +0200
|
||||||
|
+++ ./ter-u16b.bdf 2020-12-28 20:34:29.515133600 +0200
|
||||||
|
@@ -12134,4 +12134,3 @@
|
||||||
|
-78
|
||||||
|
-CC
|
||||||
|
-CC
|
||||||
|
-C8
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -12140,0 +12140 @@
|
||||||
|
+FC
|
||||||
|
@@ -12183,10 +12183,10 @@
|
||||||
|
-7E
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-7E
|
||||||
|
-06
|
||||||
|
-06
|
||||||
|
-7C
|
||||||
|
+3E
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+FF
|
||||||
|
+C3
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
--- ./ter-u16n.bdf.orig 2020-12-28 20:34:28.035131500 +0200
|
||||||
|
+++ ./ter-u16n.bdf 2020-12-28 20:34:29.485133500 +0200
|
||||||
|
@@ -12134,4 +12134,3 @@
|
||||||
|
-38
|
||||||
|
-44
|
||||||
|
-44
|
||||||
|
-48
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -12140,0 +12140 @@
|
||||||
|
+7C
|
||||||
|
@@ -12183,9 +12182,0 @@
|
||||||
|
-3E
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-42
|
||||||
|
-3E
|
||||||
|
-02
|
||||||
|
-02
|
||||||
|
@@ -12192,0 +12184,9 @@
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+44
|
||||||
|
+FE
|
||||||
|
+82
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
--- ./ter-u16v.bdf.orig 2020-12-28 20:34:28.065131600 +0200
|
||||||
|
+++ ./ter-u16v.bdf 2020-12-28 20:34:29.515133600 +0200
|
||||||
|
@@ -12134,4 +12134,3 @@
|
||||||
|
-78
|
||||||
|
-CC
|
||||||
|
-CC
|
||||||
|
-C8
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
@@ -12140,0 +12140 @@
|
||||||
|
+FC
|
||||||
|
@@ -12183,10 +12183,10 @@
|
||||||
|
-7E
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-C6
|
||||||
|
-7E
|
||||||
|
-06
|
||||||
|
-06
|
||||||
|
-7C
|
||||||
|
+3E
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+66
|
||||||
|
+FF
|
||||||
|
+C3
|
||||||
|
+00
|
||||||
|
+00
|
||||||
|
--- ./ter-u18b.bdf.orig 2020-12-28 20:34:28.085131600 +0200
|
||||||
|
+++ ./ter-u18b.bdf 2020-12-28 20:34:29.535133600 +0200
|
||||||
|
@@ -13186,5 +13186,4 @@
|
||||||
|
-3E00
|
||||||
|
-6300
|
||||||
|
-6300
|
||||||
|
-6300
|
||||||
|
-6200
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -13194,0 +13194 @@
|
||||||
|
+7F00
|
||||||
|
@@ -13240,12 +13240,12 @@
|
||||||
|
-3F80
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-3F80
|
||||||
|
-0180
|
||||||
|
-0180
|
||||||
|
-3F00
|
||||||
|
+1F00
|
||||||
|
+3300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+FF80
|
||||||
|
+C180
|
||||||
|
+C180
|
||||||
|
+0000
|
||||||
|
--- ./ter-u18n.bdf.orig 2020-12-28 20:34:28.065131600 +0200
|
||||||
|
+++ ./ter-u18n.bdf 2020-12-28 20:34:29.515133600 +0200
|
||||||
|
@@ -13186,5 +13186,4 @@
|
||||||
|
-3C00
|
||||||
|
-4200
|
||||||
|
-4200
|
||||||
|
-4200
|
||||||
|
-4400
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -13194,0 +13194 @@
|
||||||
|
+7E00
|
||||||
|
@@ -13240,12 +13240,12 @@
|
||||||
|
-3F00
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-3F00
|
||||||
|
-0100
|
||||||
|
-0100
|
||||||
|
-3E00
|
||||||
|
+0F00
|
||||||
|
+1100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+7F80
|
||||||
|
+4080
|
||||||
|
+4080
|
||||||
|
+0000
|
||||||
|
--- ./ter-u20b.bdf.orig 2020-12-28 20:34:28.115131600 +0200
|
||||||
|
+++ ./ter-u20b.bdf 2020-12-28 20:34:29.575133700 +0200
|
||||||
|
@@ -14239,5 +14239,4 @@
|
||||||
|
-3E00
|
||||||
|
-6300
|
||||||
|
-6300
|
||||||
|
-6300
|
||||||
|
-6200
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -14247,0 +14247 @@
|
||||||
|
+7F00
|
||||||
|
@@ -14297,12 +14297,12 @@
|
||||||
|
-3F80
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-3F80
|
||||||
|
-0180
|
||||||
|
-0180
|
||||||
|
-3F00
|
||||||
|
+1F00
|
||||||
|
+3300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+6300
|
||||||
|
+FF80
|
||||||
|
+C180
|
||||||
|
+C180
|
||||||
|
+0000
|
||||||
|
--- ./ter-u20n.bdf.orig 2020-12-28 20:34:28.085131600 +0200
|
||||||
|
+++ ./ter-u20n.bdf 2020-12-28 20:34:29.565133700 +0200
|
||||||
|
@@ -14239,5 +14239,4 @@
|
||||||
|
-3C00
|
||||||
|
-4200
|
||||||
|
-4200
|
||||||
|
-4200
|
||||||
|
-4400
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -14247,0 +14247 @@
|
||||||
|
+7E00
|
||||||
|
@@ -14297,12 +14297,12 @@
|
||||||
|
-3F00
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-3F00
|
||||||
|
-0100
|
||||||
|
-0100
|
||||||
|
-3E00
|
||||||
|
+0F00
|
||||||
|
+1100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+2100
|
||||||
|
+7F80
|
||||||
|
+4080
|
||||||
|
+4080
|
||||||
|
+0000
|
||||||
|
--- ./ter-u22b.bdf.orig 2020-12-28 20:34:28.135131700 +0200
|
||||||
|
+++ ./ter-u22b.bdf 2020-12-28 20:34:29.605133700 +0200
|
||||||
|
@@ -15291,8 +15291,5 @@
|
||||||
|
-3E00
|
||||||
|
-6300
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6180
|
||||||
|
-6300
|
||||||
|
-7F00
|
||||||
|
-6180
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F80
|
||||||
|
@@ -15301,0 +15299 @@
|
||||||
|
+7F80
|
||||||
|
@@ -15303,2 +15301,4 @@
|
||||||
|
-6180
|
||||||
|
-7F00
|
||||||
|
+60C0
|
||||||
|
+60C0
|
||||||
|
+60C0
|
||||||
|
+7F80
|
||||||
|
@@ -15353,14 +15353,14 @@
|
||||||
|
-1FC0
|
||||||
|
-30C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-30C0
|
||||||
|
-1FC0
|
||||||
|
-00C0
|
||||||
|
-00C0
|
||||||
|
-0180
|
||||||
|
-3F00
|
||||||
|
+1F80
|
||||||
|
+3180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+6180
|
||||||
|
+FFC0
|
||||||
|
+C0C0
|
||||||
|
+C0C0
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u22n.bdf.orig 2020-12-28 20:34:28.115131600 +0200
|
||||||
|
+++ ./ter-u22n.bdf 2020-12-28 20:34:29.575133700 +0200
|
||||||
|
@@ -15291,8 +15291,6 @@
|
||||||
|
-3C00
|
||||||
|
-4200
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4100
|
||||||
|
-4200
|
||||||
|
-7E00
|
||||||
|
-4100
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F00
|
||||||
|
+4080
|
||||||
|
@@ -15300,0 +15299 @@
|
||||||
|
+7F00
|
||||||
|
@@ -15303,2 +15302,3 @@
|
||||||
|
-4100
|
||||||
|
-7E00
|
||||||
|
+4080
|
||||||
|
+4080
|
||||||
|
+7F00
|
||||||
|
@@ -15353 +15353,4 @@
|
||||||
|
-1F80
|
||||||
|
+0F80
|
||||||
|
+1080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
@@ -15355,6 +15357,0 @@
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
-4080
|
||||||
|
@@ -15362,5 +15359,8 @@
|
||||||
|
-1F80
|
||||||
|
-0080
|
||||||
|
-0080
|
||||||
|
-0100
|
||||||
|
-3E00
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+7FC0
|
||||||
|
+4040
|
||||||
|
+4040
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u24b.bdf.orig 2020-12-28 20:34:28.165131700 +0200
|
||||||
|
+++ ./ter-u24b.bdf 2020-12-28 20:34:29.615133700 +0200
|
||||||
|
@@ -16344,2 +16344,5 @@
|
||||||
|
-3F00
|
||||||
|
-6180
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F80
|
||||||
|
@@ -16349,2 +16351,0 @@
|
||||||
|
-6180
|
||||||
|
-7F80
|
||||||
|
@@ -16351,0 +16353 @@
|
||||||
|
+7FC0
|
||||||
|
@@ -16356,3 +16358 @@
|
||||||
|
-6060
|
||||||
|
-60C0
|
||||||
|
-7F80
|
||||||
|
+7FC0
|
||||||
|
@@ -16410,7 +16410,11 @@
|
||||||
|
-1FE0
|
||||||
|
-3060
|
||||||
|
-6060
|
||||||
|
-6060
|
||||||
|
-6060
|
||||||
|
-6060
|
||||||
|
-6060
|
||||||
|
+0FC0
|
||||||
|
+18C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+30C0
|
||||||
|
+7FE0
|
||||||
|
@@ -16419,6 +16423,2 @@
|
||||||
|
-30E0
|
||||||
|
-1FE0
|
||||||
|
-0060
|
||||||
|
-0060
|
||||||
|
-00C0
|
||||||
|
-3F80
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u24n.bdf.orig 2020-12-28 20:34:28.135131700 +0200
|
||||||
|
+++ ./ter-u24n.bdf 2020-12-28 20:34:29.625133700 +0200
|
||||||
|
@@ -16344,2 +16344,5 @@
|
||||||
|
-3E00
|
||||||
|
-4100
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F00
|
||||||
|
@@ -16349,2 +16351,0 @@
|
||||||
|
-4100
|
||||||
|
-7F00
|
||||||
|
@@ -16351,0 +16353 @@
|
||||||
|
+7F80
|
||||||
|
@@ -16356,3 +16358 @@
|
||||||
|
-4040
|
||||||
|
-4080
|
||||||
|
-7F00
|
||||||
|
+7F80
|
||||||
|
@@ -16410,7 +16410,11 @@
|
||||||
|
-1FC0
|
||||||
|
-2040
|
||||||
|
-4040
|
||||||
|
-4040
|
||||||
|
-4040
|
||||||
|
-4040
|
||||||
|
-4040
|
||||||
|
+0F80
|
||||||
|
+1080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+2080
|
||||||
|
+7FC0
|
||||||
|
@@ -16419,6 +16423,2 @@
|
||||||
|
-20C0
|
||||||
|
-1F40
|
||||||
|
-0040
|
||||||
|
-0040
|
||||||
|
-0080
|
||||||
|
-3F00
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u28b.bdf.orig 2020-12-28 20:34:28.185131700 +0200
|
||||||
|
+++ ./ter-u28b.bdf 2020-12-28 20:34:29.665133800 +0200
|
||||||
|
@@ -18448 +18448,5 @@
|
||||||
|
-3F00
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -18450,5 +18453,0 @@
|
||||||
|
-61C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
-6180
|
||||||
|
@@ -18456,4 +18455,6 @@
|
||||||
|
-7FE0
|
||||||
|
-6070
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
+6060
|
||||||
|
+6060
|
||||||
|
+6060
|
||||||
|
+7FC0
|
||||||
|
+7FC0
|
||||||
|
+6060
|
||||||
|
@@ -18463 +18463,0 @@
|
||||||
|
-6070
|
||||||
|
@@ -18523 +18523,11 @@
|
||||||
|
-1FF0
|
||||||
|
+07F0
|
||||||
|
+0FF0
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
@@ -18525,16 +18535,6 @@
|
||||||
|
-7030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-7030
|
||||||
|
-3FF0
|
||||||
|
-1FF0
|
||||||
|
-0030
|
||||||
|
-0030
|
||||||
|
-0070
|
||||||
|
-3FE0
|
||||||
|
-3FC0
|
||||||
|
+7FF8
|
||||||
|
+6018
|
||||||
|
+6018
|
||||||
|
+6018
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u28n.bdf.orig 2020-12-28 20:34:28.175131700 +0200
|
||||||
|
+++ ./ter-u28n.bdf 2020-12-28 20:34:29.635133800 +0200
|
||||||
|
@@ -18448,4 +18448,6 @@
|
||||||
|
-3F00
|
||||||
|
-6180
|
||||||
|
-60C0
|
||||||
|
-60C0
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+7F80
|
||||||
|
@@ -18452,0 +18455,3 @@
|
||||||
|
+6060
|
||||||
|
+6060
|
||||||
|
+6060
|
||||||
|
@@ -18454 +18458,0 @@
|
||||||
|
-6180
|
||||||
|
@@ -18460,4 +18463,0 @@
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
@@ -18523,18 +18523,18 @@
|
||||||
|
-1FF0
|
||||||
|
-3030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-6030
|
||||||
|
-3030
|
||||||
|
-1FF0
|
||||||
|
-0030
|
||||||
|
-0030
|
||||||
|
-0030
|
||||||
|
-0060
|
||||||
|
-3FC0
|
||||||
|
+07F0
|
||||||
|
+0C30
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+1830
|
||||||
|
+7FF8
|
||||||
|
+6018
|
||||||
|
+6018
|
||||||
|
+6018
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
--- ./ter-u32b.bdf.orig 2020-12-28 20:34:28.225131800 +0200
|
||||||
|
+++ ./ter-u32b.bdf 2020-12-28 20:34:29.675133800 +0200
|
||||||
|
@@ -20554,8 +20554,6 @@
|
||||||
|
-3FC0
|
||||||
|
-7FE0
|
||||||
|
-70F0
|
||||||
|
-7070
|
||||||
|
-7070
|
||||||
|
-7070
|
||||||
|
-7070
|
||||||
|
-70E0
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -20563,0 +20562 @@
|
||||||
|
+7078
|
||||||
|
@@ -20565,4 +20564,5 @@
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
+7038
|
||||||
|
+7038
|
||||||
|
+7FF0
|
||||||
|
+7FF8
|
||||||
|
+703C
|
||||||
|
@@ -20638 +20638,12 @@
|
||||||
|
-1FFC
|
||||||
|
+07FC
|
||||||
|
+0FFC
|
||||||
|
+1E1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
+1C1C
|
||||||
|
@@ -20640,17 +20651,6 @@
|
||||||
|
-781C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-701C
|
||||||
|
-781C
|
||||||
|
-3FFC
|
||||||
|
-1FFC
|
||||||
|
-001C
|
||||||
|
-001C
|
||||||
|
-003C
|
||||||
|
-3FF8
|
||||||
|
-3FF0
|
||||||
|
+7FFE
|
||||||
|
+700E
|
||||||
|
+700E
|
||||||
|
+700E
|
||||||
|
+700E
|
||||||
|
+0000
|
||||||
|
--- ./ter-u32n.bdf.orig 2020-12-28 20:34:28.205131800 +0200
|
||||||
|
+++ ./ter-u32n.bdf 2020-12-28 20:34:29.675133800 +0200
|
||||||
|
@@ -20554,8 +20554,6 @@
|
||||||
|
-1FC0
|
||||||
|
-3FE0
|
||||||
|
-3070
|
||||||
|
-3030
|
||||||
|
-3030
|
||||||
|
-3030
|
||||||
|
-3030
|
||||||
|
-3070
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
+0000
|
||||||
|
@@ -20564,0 +20563,5 @@
|
||||||
|
+3018
|
||||||
|
+3018
|
||||||
|
+3038
|
||||||
|
+3FF0
|
||||||
|
+3FF8
|
||||||
|
@@ -20568,3 +20570,0 @@
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
@@ -20638,19 +20638,19 @@
|
||||||
|
-0FFC
|
||||||
|
-1FFC
|
||||||
|
-380C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-300C
|
||||||
|
-380C
|
||||||
|
-1FFC
|
||||||
|
-0FFC
|
||||||
|
-000C
|
||||||
|
-000C
|
||||||
|
-001C
|
||||||
|
-1FF8
|
||||||
|
-1FF0
|
||||||
|
+07F8
|
||||||
|
+0FF8
|
||||||
|
+1C18
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+1818
|
||||||
|
+3FF8
|
||||||
|
+7FFC
|
||||||
|
+600C
|
||||||
|
+600C
|
||||||
|
+600C
|
||||||
|
+600C
|
||||||
|
+0000
|
||||||
@@ -0,0 +1,945 @@
|
|||||||
|
--- ./ter-u12b.bdf.orig 2020-12-28 20:34:27.995131500 +0200
|
||||||
|
+++ ./ter-u12b.bdf 2020-12-28 20:34:30.355134800 +0200
|
||||||
|
@@ -10182,2 +10182,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -10828,2 +10828,2 @@
|
||||||
|
-08
|
||||||
|
-10
|
||||||
|
+48
|
||||||
|
+50
|
||||||
|
@@ -11189,2 +11189,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -11227,2 +11227,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+80
|
||||||
|
+80
|
||||||
|
@@ -11265,3 +11265,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-C8
|
||||||
|
+C0
|
||||||
|
+40
|
||||||
|
+48
|
||||||
|
--- ./ter-u12n.bdf.orig 2020-12-28 20:34:27.975131400 +0200
|
||||||
|
+++ ./ter-u12n.bdf 2020-12-28 20:34:30.315134700 +0200
|
||||||
|
@@ -10182,2 +10182,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -10828,2 +10828,2 @@
|
||||||
|
-08
|
||||||
|
-10
|
||||||
|
+48
|
||||||
|
+50
|
||||||
|
@@ -11189,2 +11189,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -11227,2 +11227,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+80
|
||||||
|
+80
|
||||||
|
@@ -11265,3 +11265,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-C8
|
||||||
|
+C0
|
||||||
|
+40
|
||||||
|
+48
|
||||||
|
--- ./ter-u14b.bdf.orig 2020-12-28 20:34:28.025131500 +0200
|
||||||
|
+++ ./ter-u14b.bdf 2020-12-28 20:34:30.365134800 +0200
|
||||||
|
@@ -11250,3 +11250,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -11964,3 +11964,3 @@
|
||||||
|
-18
|
||||||
|
-30
|
||||||
|
-00
|
||||||
|
+D8
|
||||||
|
+F0
|
||||||
|
+C0
|
||||||
|
@@ -12363,3 +12363,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -12405,3 +12405,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -12447,4 +12447,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-E3
|
||||||
|
+E0
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+63
|
||||||
|
--- ./ter-u14n.bdf.orig 2020-12-28 20:34:27.995131500 +0200
|
||||||
|
+++ ./ter-u14n.bdf 2020-12-28 20:34:30.365134800 +0200
|
||||||
|
@@ -11250,3 +11250,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -11964,3 +11964,3 @@
|
||||||
|
-08
|
||||||
|
-10
|
||||||
|
-00
|
||||||
|
+48
|
||||||
|
+50
|
||||||
|
+40
|
||||||
|
@@ -12363,3 +12363,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -12405,3 +12405,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -12447,4 +12447,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-C2
|
||||||
|
+C0
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+42
|
||||||
|
--- ./ter-u14v.bdf.orig 2020-12-28 20:34:28.025131500 +0200
|
||||||
|
+++ ./ter-u14v.bdf 2020-12-28 20:34:30.385134800 +0200
|
||||||
|
@@ -11250,3 +11250,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -11964,3 +11964,3 @@
|
||||||
|
-18
|
||||||
|
-30
|
||||||
|
-00
|
||||||
|
+D8
|
||||||
|
+F0
|
||||||
|
+C0
|
||||||
|
@@ -12363,3 +12363,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -12405,3 +12405,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -12447,4 +12447,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-E3
|
||||||
|
+E0
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+63
|
||||||
|
--- ./ter-u16b.bdf.orig 2020-12-28 20:34:28.035131500 +0200
|
||||||
|
+++ ./ter-u16b.bdf 2020-12-28 20:34:30.405134800 +0200
|
||||||
|
@@ -12318,3 +12318,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13100,3 +13100,3 @@
|
||||||
|
-18
|
||||||
|
-30
|
||||||
|
-00
|
||||||
|
+D8
|
||||||
|
+F0
|
||||||
|
+C0
|
||||||
|
@@ -13537,3 +13537,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13583,3 +13583,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13629,4 +13629,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-E3
|
||||||
|
+E0
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+63
|
||||||
|
--- ./ter-u16n.bdf.orig 2020-12-28 20:34:28.035131500 +0200
|
||||||
|
+++ ./ter-u16n.bdf 2020-12-28 20:34:30.395134800 +0200
|
||||||
|
@@ -12318,3 +12318,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -13100,3 +13100,3 @@
|
||||||
|
-08
|
||||||
|
-10
|
||||||
|
-00
|
||||||
|
+48
|
||||||
|
+50
|
||||||
|
+40
|
||||||
|
@@ -13537,3 +13537,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -13583,3 +13583,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -13629,4 +13629,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-C2
|
||||||
|
+C0
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+42
|
||||||
|
--- ./ter-u16v.bdf.orig 2020-12-28 20:34:28.065131600 +0200
|
||||||
|
+++ ./ter-u16v.bdf 2020-12-28 20:34:30.405134800 +0200
|
||||||
|
@@ -12318,3 +12318,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13100,3 +13100,3 @@
|
||||||
|
-18
|
||||||
|
-30
|
||||||
|
-00
|
||||||
|
+D8
|
||||||
|
+F0
|
||||||
|
+C0
|
||||||
|
@@ -13537,3 +13537,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13583,3 +13583,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13629,4 +13629,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-E3
|
||||||
|
+E0
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+63
|
||||||
|
--- ./ter-u18b.bdf.orig 2020-12-28 20:34:28.085131600 +0200
|
||||||
|
+++ ./ter-u18b.bdf 2020-12-28 20:34:30.445134900 +0200
|
||||||
|
@@ -13386,4 +13386,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -14237,3 +14237,3 @@
|
||||||
|
-0600
|
||||||
|
-0C00
|
||||||
|
-0000
|
||||||
|
+6600
|
||||||
|
+6C00
|
||||||
|
+6000
|
||||||
|
@@ -14712,3 +14712,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -14762,3 +14762,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -14811,5 +14811,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-E180
|
||||||
|
+8000
|
||||||
|
+E000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6180
|
||||||
|
--- ./ter-u18n.bdf.orig 2020-12-28 20:34:28.065131600 +0200
|
||||||
|
+++ ./ter-u18n.bdf 2020-12-28 20:34:30.445134900 +0200
|
||||||
|
@@ -13386,4 +13386,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -14237,3 +14237,3 @@
|
||||||
|
-0400
|
||||||
|
-0800
|
||||||
|
-0000
|
||||||
|
+4400
|
||||||
|
+4800
|
||||||
|
+4000
|
||||||
|
@@ -14712,3 +14712,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -14762,3 +14762,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -14811,5 +14811,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-C100
|
||||||
|
+8000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4100
|
||||||
|
--- ./ter-u20b.bdf.orig 2020-12-28 20:34:28.115131600 +0200
|
||||||
|
+++ ./ter-u20b.bdf 2020-12-28 20:34:30.455134900 +0200
|
||||||
|
@@ -14455,4 +14455,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -15373,4 +15373,4 @@
|
||||||
|
-0000
|
||||||
|
-0600
|
||||||
|
-0C00
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6600
|
||||||
|
+6C00
|
||||||
|
+6000
|
||||||
|
@@ -15886,4 +15886,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -15940,4 +15940,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -15994,5 +15994,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-E180
|
||||||
|
+E000
|
||||||
|
+E000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6180
|
||||||
|
--- ./ter-u20n.bdf.orig 2020-12-28 20:34:28.085131600 +0200
|
||||||
|
+++ ./ter-u20n.bdf 2020-12-28 20:34:30.445134900 +0200
|
||||||
|
@@ -14455,4 +14455,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -15373,4 +15373,4 @@
|
||||||
|
-0000
|
||||||
|
-0400
|
||||||
|
-0800
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4400
|
||||||
|
+4800
|
||||||
|
+4000
|
||||||
|
@@ -15886,4 +15886,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -15940,4 +15940,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -15994,5 +15994,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-C100
|
||||||
|
+C000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4100
|
||||||
|
--- ./ter-u22b.bdf.orig 2020-12-28 20:34:28.135131700 +0200
|
||||||
|
+++ ./ter-u22b.bdf 2020-12-28 20:34:30.505135000 +0200
|
||||||
|
@@ -15523,4 +15523,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -16509,4 +16509,4 @@
|
||||||
|
-0180
|
||||||
|
-0300
|
||||||
|
-0600
|
||||||
|
-0000
|
||||||
|
+3180
|
||||||
|
+3300
|
||||||
|
+3600
|
||||||
|
+3000
|
||||||
|
@@ -17060,4 +17060,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -17118,4 +17118,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -17176,6 +17176,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-70C0
|
||||||
|
-7180
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+30C0
|
||||||
|
+3180
|
||||||
|
--- ./ter-u22n.bdf.orig 2020-12-28 20:34:28.115131600 +0200
|
||||||
|
+++ ./ter-u22n.bdf 2020-12-28 20:34:30.485134900 +0200
|
||||||
|
@@ -15523,4 +15523,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -16509,4 +16509,4 @@
|
||||||
|
-0100
|
||||||
|
-0200
|
||||||
|
-0400
|
||||||
|
-0000
|
||||||
|
+2100
|
||||||
|
+2200
|
||||||
|
+2400
|
||||||
|
+2000
|
||||||
|
@@ -17060,4 +17060,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -17118,4 +17118,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -17176,5 +17176,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-E080
|
||||||
|
+E000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2080
|
||||||
|
--- ./ter-u24b.bdf.orig 2020-12-28 20:34:28.165131700 +0200
|
||||||
|
+++ ./ter-u24b.bdf 2020-12-28 20:34:30.515135000 +0200
|
||||||
|
@@ -16592,4 +16592,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -17646,4 +17646,4 @@
|
||||||
|
-0180
|
||||||
|
-0300
|
||||||
|
-0600
|
||||||
|
-0000
|
||||||
|
+3180
|
||||||
|
+3300
|
||||||
|
+3600
|
||||||
|
+3000
|
||||||
|
@@ -18235,4 +18235,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -18297,4 +18297,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -18359,6 +18359,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-7060
|
||||||
|
-70C0
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3060
|
||||||
|
+30C0
|
||||||
|
--- ./ter-u24n.bdf.orig 2020-12-28 20:34:28.135131700 +0200
|
||||||
|
+++ ./ter-u24n.bdf 2020-12-28 20:34:30.505135000 +0200
|
||||||
|
@@ -16592,4 +16592,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -17646,4 +17646,4 @@
|
||||||
|
-0100
|
||||||
|
-0200
|
||||||
|
-0400
|
||||||
|
-0000
|
||||||
|
+2100
|
||||||
|
+2200
|
||||||
|
+2400
|
||||||
|
+2000
|
||||||
|
@@ -18235,4 +18235,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -18297,4 +18297,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -18359,5 +18359,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-E040
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2040
|
||||||
|
--- ./ter-u28b.bdf.orig 2020-12-28 20:34:28.185131700 +0200
|
||||||
|
+++ ./ter-u28b.bdf 2020-12-28 20:34:30.555135000 +0200
|
||||||
|
@@ -18728,5 +18728,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -19918,5 +19918,5 @@
|
||||||
|
-0000
|
||||||
|
-01C0
|
||||||
|
-0380
|
||||||
|
-0700
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+31C0
|
||||||
|
+3380
|
||||||
|
+3700
|
||||||
|
+3000
|
||||||
|
@@ -20583,5 +20583,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -20653,5 +20653,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -20723,7 +20723,7 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-F070
|
||||||
|
-F0E0
|
||||||
|
+F000
|
||||||
|
+F000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3070
|
||||||
|
+30E0
|
||||||
|
--- ./ter-u28n.bdf.orig 2020-12-28 20:34:28.175131700 +0200
|
||||||
|
+++ ./ter-u28n.bdf 2020-12-28 20:34:30.535135000 +0200
|
||||||
|
@@ -18728,5 +18728,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -19918,5 +19918,5 @@
|
||||||
|
-0000
|
||||||
|
-00C0
|
||||||
|
-0180
|
||||||
|
-0300
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+30C0
|
||||||
|
+3180
|
||||||
|
+3300
|
||||||
|
+3000
|
||||||
|
@@ -20583,5 +20583,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -20653,5 +20653,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -20723,7 +20723,7 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-F030
|
||||||
|
-F060
|
||||||
|
+F000
|
||||||
|
+F000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3030
|
||||||
|
+3060
|
||||||
|
--- ./ter-u32b.bdf.orig 2020-12-28 20:34:28.225131800 +0200
|
||||||
|
+++ ./ter-u32b.bdf 2020-12-28 20:34:30.585135100 +0200
|
||||||
|
@@ -20866,6 +20866,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
@@ -22192,6 +22192,6 @@
|
||||||
|
-0070
|
||||||
|
-00E0
|
||||||
|
-01C0
|
||||||
|
-0380
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3838
|
||||||
|
+3870
|
||||||
|
+38E0
|
||||||
|
+39C0
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
@@ -22933,6 +22933,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
@@ -23011,6 +23011,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
@@ -23089,8 +23089,8 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-F81C
|
||||||
|
-F838
|
||||||
|
+F800
|
||||||
|
+F800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+381C
|
||||||
|
+3838
|
||||||
|
--- ./ter-u32n.bdf.orig 2020-12-28 20:34:28.205131800 +0200
|
||||||
|
+++ ./ter-u32n.bdf 2020-12-28 20:34:30.585135100 +0200
|
||||||
|
@@ -20866,6 +20866,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
@@ -22192,6 +22192,6 @@
|
||||||
|
-0070
|
||||||
|
-00E0
|
||||||
|
-01C0
|
||||||
|
-0380
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+1838
|
||||||
|
+1870
|
||||||
|
+18E0
|
||||||
|
+19C0
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
@@ -22933,6 +22933,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
@@ -23011,6 +23011,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -23089,8 +23089,8 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-781C
|
||||||
|
-7838
|
||||||
|
+7800
|
||||||
|
+7800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+181C
|
||||||
|
+1838
|
||||||
|
--- ./dup/xos4-2.dup.orig 2019-03-13 21:55:47.071547500 +0200
|
||||||
|
+++ ./dup/xos4-2.dup 2020-12-28 20:34:27.655131000 +0200
|
||||||
|
@@ -107 +107 @@
|
||||||
|
-0138 043A
|
||||||
|
+006B 043A
|
||||||
@@ -0,0 +1,937 @@
|
|||||||
|
--- ./ter-u12b.bdf.orig 2020-12-28 20:34:18.635118400 +0200
|
||||||
|
+++ ./ter-u12b.bdf 2020-12-28 20:34:27.095130200 +0200
|
||||||
|
@@ -10182,2 +10182,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -10828,2 +10828,2 @@
|
||||||
|
-08
|
||||||
|
-10
|
||||||
|
+48
|
||||||
|
+50
|
||||||
|
@@ -11189,2 +11189,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -11227,2 +11227,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+80
|
||||||
|
+80
|
||||||
|
@@ -11265,3 +11265,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-C8
|
||||||
|
+C0
|
||||||
|
+40
|
||||||
|
+48
|
||||||
|
--- ./ter-u12n.bdf.orig 2020-12-28 20:34:18.605118300 +0200
|
||||||
|
+++ ./ter-u12n.bdf 2020-12-28 20:34:27.065130200 +0200
|
||||||
|
@@ -10182,2 +10182,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -10828,2 +10828,2 @@
|
||||||
|
-08
|
||||||
|
-10
|
||||||
|
+48
|
||||||
|
+50
|
||||||
|
@@ -11189,2 +11189,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -11227,2 +11227,2 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+80
|
||||||
|
+80
|
||||||
|
@@ -11265,3 +11265,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-C8
|
||||||
|
+C0
|
||||||
|
+40
|
||||||
|
+48
|
||||||
|
--- ./ter-u14b.bdf.orig 2020-12-28 20:34:18.655118400 +0200
|
||||||
|
+++ ./ter-u14b.bdf 2020-12-28 20:34:27.105130200 +0200
|
||||||
|
@@ -11250,3 +11250,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -11964,3 +11964,3 @@
|
||||||
|
-18
|
||||||
|
-30
|
||||||
|
-00
|
||||||
|
+D8
|
||||||
|
+F0
|
||||||
|
+C0
|
||||||
|
@@ -12363,3 +12363,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -12405,3 +12405,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -12447,4 +12447,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-E3
|
||||||
|
+E0
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+63
|
||||||
|
--- ./ter-u14n.bdf.orig 2020-12-28 20:34:18.645118400 +0200
|
||||||
|
+++ ./ter-u14n.bdf 2020-12-28 20:34:27.095130200 +0200
|
||||||
|
@@ -11250,3 +11250,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -11964,3 +11964,3 @@
|
||||||
|
-08
|
||||||
|
-10
|
||||||
|
-00
|
||||||
|
+48
|
||||||
|
+50
|
||||||
|
+40
|
||||||
|
@@ -12363,3 +12363,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -12405,3 +12405,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -12447,4 +12447,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-C2
|
||||||
|
+C0
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+42
|
||||||
|
--- ./ter-u14v.bdf.orig 2020-12-28 20:34:18.675118400 +0200
|
||||||
|
+++ ./ter-u14v.bdf 2020-12-28 20:34:27.125130200 +0200
|
||||||
|
@@ -11250,3 +11250,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -11964,3 +11964,3 @@
|
||||||
|
-18
|
||||||
|
-30
|
||||||
|
-00
|
||||||
|
+D8
|
||||||
|
+F0
|
||||||
|
+C0
|
||||||
|
@@ -12363,3 +12363,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -12405,3 +12405,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -12447,4 +12447,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-E3
|
||||||
|
+E0
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+63
|
||||||
|
--- ./ter-u16b.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16b.bdf 2020-12-28 20:34:27.135130300 +0200
|
||||||
|
@@ -12318,3 +12318,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13100,3 +13100,3 @@
|
||||||
|
-18
|
||||||
|
-30
|
||||||
|
-00
|
||||||
|
+D8
|
||||||
|
+F0
|
||||||
|
+C0
|
||||||
|
@@ -13537,3 +13537,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13583,3 +13583,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13629,4 +13629,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-E3
|
||||||
|
+E0
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+63
|
||||||
|
--- ./ter-u16n.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16n.bdf 2020-12-28 20:34:27.135130300 +0200
|
||||||
|
@@ -12318,3 +12318,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -13100,3 +13100,3 @@
|
||||||
|
-08
|
||||||
|
-10
|
||||||
|
-00
|
||||||
|
+48
|
||||||
|
+50
|
||||||
|
+40
|
||||||
|
@@ -13537,3 +13537,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -13583,3 +13583,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
@@ -13629,4 +13629,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-C2
|
||||||
|
+C0
|
||||||
|
+40
|
||||||
|
+40
|
||||||
|
+42
|
||||||
|
--- ./ter-u16v.bdf.orig 2020-12-28 20:34:18.695118400 +0200
|
||||||
|
+++ ./ter-u16v.bdf 2020-12-28 20:34:27.135130300 +0200
|
||||||
|
@@ -12318,3 +12318,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13100,3 +13100,3 @@
|
||||||
|
-18
|
||||||
|
-30
|
||||||
|
-00
|
||||||
|
+D8
|
||||||
|
+F0
|
||||||
|
+C0
|
||||||
|
@@ -13537,3 +13537,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13583,3 +13583,3 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
+C0
|
||||||
|
@@ -13629,4 +13629,4 @@
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-00
|
||||||
|
-E3
|
||||||
|
+E0
|
||||||
|
+60
|
||||||
|
+60
|
||||||
|
+63
|
||||||
|
--- ./ter-u18b.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18b.bdf 2020-12-28 20:34:27.185130300 +0200
|
||||||
|
@@ -13387,3 +13387,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -14237,3 +14237,3 @@
|
||||||
|
-0600
|
||||||
|
-0C00
|
||||||
|
-0000
|
||||||
|
+6600
|
||||||
|
+6C00
|
||||||
|
+6000
|
||||||
|
@@ -14712,3 +14712,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -14762,3 +14762,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -14812,4 +14812,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-E180
|
||||||
|
+E000
|
||||||
|
+E000
|
||||||
|
+6000
|
||||||
|
+6180
|
||||||
|
--- ./ter-u18n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18n.bdf 2020-12-28 20:34:27.175130300 +0200
|
||||||
|
@@ -13387,3 +13387,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -14237,3 +14237,3 @@
|
||||||
|
-0400
|
||||||
|
-0800
|
||||||
|
-0000
|
||||||
|
+4400
|
||||||
|
+4800
|
||||||
|
+4000
|
||||||
|
@@ -14712,3 +14712,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -14762,3 +14762,3 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -14812,4 +14812,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-C100
|
||||||
|
+C000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4100
|
||||||
|
--- ./ter-u20b.bdf.orig 2020-12-28 20:34:18.735118500 +0200
|
||||||
|
+++ ./ter-u20b.bdf 2020-12-28 20:34:27.195130300 +0200
|
||||||
|
@@ -14455,4 +14455,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -15373,4 +15373,4 @@
|
||||||
|
-0000
|
||||||
|
-0600
|
||||||
|
-0C00
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6600
|
||||||
|
+6C00
|
||||||
|
+6000
|
||||||
|
@@ -15886,4 +15886,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -15940,4 +15940,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -15994,5 +15994,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-E180
|
||||||
|
+E000
|
||||||
|
+E000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6180
|
||||||
|
--- ./ter-u20n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u20n.bdf 2020-12-28 20:34:27.185130300 +0200
|
||||||
|
@@ -14455,4 +14455,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -15373,4 +15373,4 @@
|
||||||
|
-0000
|
||||||
|
-0400
|
||||||
|
-0800
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4400
|
||||||
|
+4800
|
||||||
|
+4000
|
||||||
|
@@ -15886,4 +15886,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -15940,4 +15940,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -15994,5 +15994,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-C100
|
||||||
|
+C000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4100
|
||||||
|
--- ./ter-u22b.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22b.bdf 2020-12-28 20:34:27.235130400 +0200
|
||||||
|
@@ -15523,4 +15523,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -16509,4 +16509,4 @@
|
||||||
|
-0180
|
||||||
|
-0300
|
||||||
|
-0600
|
||||||
|
-0000
|
||||||
|
+3180
|
||||||
|
+3300
|
||||||
|
+3600
|
||||||
|
+3000
|
||||||
|
@@ -17060,4 +17060,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -17118,4 +17118,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -17176,6 +17176,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-70C0
|
||||||
|
-7180
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+30C0
|
||||||
|
+3180
|
||||||
|
--- ./ter-u22n.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22n.bdf 2020-12-28 20:34:27.225130400 +0200
|
||||||
|
@@ -15523,4 +15523,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -16509,4 +16509,4 @@
|
||||||
|
-0100
|
||||||
|
-0200
|
||||||
|
-0400
|
||||||
|
-0000
|
||||||
|
+2100
|
||||||
|
+2200
|
||||||
|
+2400
|
||||||
|
+2000
|
||||||
|
@@ -17060,4 +17060,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -17118,4 +17118,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -17176,5 +17176,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-E080
|
||||||
|
+E000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2080
|
||||||
|
--- ./ter-u24b.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24b.bdf 2020-12-28 20:34:27.245130400 +0200
|
||||||
|
@@ -16592,4 +16592,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -17646,4 +17646,4 @@
|
||||||
|
-0180
|
||||||
|
-0300
|
||||||
|
-0600
|
||||||
|
-0000
|
||||||
|
+3180
|
||||||
|
+3300
|
||||||
|
+3600
|
||||||
|
+3000
|
||||||
|
@@ -18235,4 +18235,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -18297,4 +18297,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -18359,6 +18359,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-7060
|
||||||
|
-70C0
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3060
|
||||||
|
+30C0
|
||||||
|
--- ./ter-u24n.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24n.bdf 2020-12-28 20:34:27.245130400 +0200
|
||||||
|
@@ -16592,4 +16592,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -17646,4 +17646,4 @@
|
||||||
|
-0100
|
||||||
|
-0200
|
||||||
|
-0400
|
||||||
|
-0000
|
||||||
|
+2100
|
||||||
|
+2200
|
||||||
|
+2400
|
||||||
|
+2000
|
||||||
|
@@ -18235,4 +18235,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
@@ -18297,4 +18297,4 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
+4000
|
||||||
|
@@ -18359,5 +18359,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-E040
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+2000
|
||||||
|
+2000
|
||||||
|
+2040
|
||||||
|
--- ./ter-u28b.bdf.orig 2020-12-28 20:34:18.845118700 +0200
|
||||||
|
+++ ./ter-u28b.bdf 2020-12-28 20:34:27.295130500 +0200
|
||||||
|
@@ -18728,5 +18728,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -19918,5 +19918,5 @@
|
||||||
|
-0000
|
||||||
|
-01C0
|
||||||
|
-0380
|
||||||
|
-0700
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+31C0
|
||||||
|
+3380
|
||||||
|
+3700
|
||||||
|
+3000
|
||||||
|
@@ -20583,5 +20583,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -20653,5 +20653,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -20723,7 +20723,7 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-F070
|
||||||
|
-F0E0
|
||||||
|
+F000
|
||||||
|
+F000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3070
|
||||||
|
+30E0
|
||||||
|
--- ./ter-u28n.bdf.orig 2020-12-28 20:34:18.835118600 +0200
|
||||||
|
+++ ./ter-u28n.bdf 2020-12-28 20:34:27.285130500 +0200
|
||||||
|
@@ -18728,5 +18728,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -19918,5 +19918,5 @@
|
||||||
|
-0000
|
||||||
|
-00C0
|
||||||
|
-0180
|
||||||
|
-0300
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+30C0
|
||||||
|
+3180
|
||||||
|
+3300
|
||||||
|
+3000
|
||||||
|
@@ -20583,5 +20583,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -20653,5 +20653,5 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
+6000
|
||||||
|
@@ -20723,7 +20723,7 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-F030
|
||||||
|
-F060
|
||||||
|
+F000
|
||||||
|
+F000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3030
|
||||||
|
+3060
|
||||||
|
--- ./ter-u32b.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32b.bdf 2020-12-28 20:34:27.305130500 +0200
|
||||||
|
@@ -20866,6 +20866,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
@@ -22192,6 +22192,6 @@
|
||||||
|
-0070
|
||||||
|
-00E0
|
||||||
|
-01C0
|
||||||
|
-0380
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3838
|
||||||
|
+3870
|
||||||
|
+38E0
|
||||||
|
+39C0
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
@@ -22933,6 +22933,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
@@ -23011,6 +23011,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
+7000
|
||||||
|
@@ -23089,8 +23089,8 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-F81C
|
||||||
|
-F838
|
||||||
|
+F800
|
||||||
|
+F800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+3800
|
||||||
|
+381C
|
||||||
|
+3838
|
||||||
|
--- ./ter-u32n.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32n.bdf 2020-12-28 20:34:27.305130500 +0200
|
||||||
|
@@ -20866,6 +20866,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
@@ -22192,6 +22192,6 @@
|
||||||
|
-0070
|
||||||
|
-00E0
|
||||||
|
-01C0
|
||||||
|
-0380
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+1838
|
||||||
|
+1870
|
||||||
|
+18E0
|
||||||
|
+19C0
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
@@ -22933,6 +22933,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
@@ -23011,6 +23011,6 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
+3000
|
||||||
|
@@ -23089,8 +23089,8 @@
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-0000
|
||||||
|
-781C
|
||||||
|
-7838
|
||||||
|
+7800
|
||||||
|
+7800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+1800
|
||||||
|
+181C
|
||||||
|
+1838
|
||||||
|
--- ./dup/xos4-2.dup.orig 2019-03-13 21:55:47.071547500 +0200
|
||||||
|
+++ ./dup/xos4-2.dup 2020-12-28 20:34:27.655131000 +0200
|
||||||
|
@@ -107 +107 @@
|
||||||
|
-0138 043A
|
||||||
|
+006B 043A
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
--- ./ter-u12b.bdf.orig 2020-12-28 20:34:18.635118400 +0200
|
||||||
|
+++ ./ter-u12b.bdf 2020-12-28 20:34:26.185128900 +0200
|
||||||
|
@@ -1840,3 +1839,0 @@
|
||||||
|
-48
|
||||||
|
-A8
|
||||||
|
-90
|
||||||
|
@@ -1846,0 +1844,3 @@
|
||||||
|
+48
|
||||||
|
+A8
|
||||||
|
+90
|
||||||
|
--- ./ter-u12n.bdf.orig 2020-12-28 20:34:18.605118300 +0200
|
||||||
|
+++ ./ter-u12n.bdf 2020-12-28 20:34:26.185128900 +0200
|
||||||
|
@@ -1840,3 +1839,0 @@
|
||||||
|
-48
|
||||||
|
-A8
|
||||||
|
-90
|
||||||
|
@@ -1846,0 +1844,3 @@
|
||||||
|
+48
|
||||||
|
+A8
|
||||||
|
+90
|
||||||
|
--- ./ter-u14b.bdf.orig 2020-12-28 20:34:18.655118400 +0200
|
||||||
|
+++ ./ter-u14b.bdf 2020-12-28 20:34:26.225129000 +0200
|
||||||
|
@@ -2030,3 +2029,0 @@
|
||||||
|
-73
|
||||||
|
-DB
|
||||||
|
-CE
|
||||||
|
@@ -2037,0 +2035,3 @@
|
||||||
|
+73
|
||||||
|
+DB
|
||||||
|
+CE
|
||||||
|
--- ./ter-u14n.bdf.orig 2020-12-28 20:34:18.645118400 +0200
|
||||||
|
+++ ./ter-u14n.bdf 2020-12-28 20:34:26.205129000 +0200
|
||||||
|
@@ -2030,3 +2029,0 @@
|
||||||
|
-62
|
||||||
|
-92
|
||||||
|
-8C
|
||||||
|
@@ -2037,0 +2035,3 @@
|
||||||
|
+62
|
||||||
|
+92
|
||||||
|
+8C
|
||||||
|
--- ./ter-u14v.bdf.orig 2020-12-28 20:34:18.675118400 +0200
|
||||||
|
+++ ./ter-u14v.bdf 2020-12-28 20:34:26.225129000 +0200
|
||||||
|
@@ -2030,3 +2029,0 @@
|
||||||
|
-73
|
||||||
|
-DB
|
||||||
|
-CE
|
||||||
|
@@ -2037,0 +2035,3 @@
|
||||||
|
+73
|
||||||
|
+DB
|
||||||
|
+CE
|
||||||
|
--- ./ter-u16b.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16b.bdf 2020-12-28 20:34:26.235129000 +0200
|
||||||
|
@@ -2220,3 +2219,0 @@
|
||||||
|
-73
|
||||||
|
-DB
|
||||||
|
-CE
|
||||||
|
@@ -2227,0 +2225,3 @@
|
||||||
|
+73
|
||||||
|
+DB
|
||||||
|
+CE
|
||||||
|
--- ./ter-u16n.bdf.orig 2020-12-28 20:34:18.685118400 +0200
|
||||||
|
+++ ./ter-u16n.bdf 2020-12-28 20:34:26.245129000 +0200
|
||||||
|
@@ -2220,3 +2219,0 @@
|
||||||
|
-62
|
||||||
|
-92
|
||||||
|
-8C
|
||||||
|
@@ -2227,0 +2225,3 @@
|
||||||
|
+62
|
||||||
|
+92
|
||||||
|
+8C
|
||||||
|
--- ./ter-u16v.bdf.orig 2020-12-28 20:34:18.695118400 +0200
|
||||||
|
+++ ./ter-u16v.bdf 2020-12-28 20:34:26.265129000 +0200
|
||||||
|
@@ -2220,3 +2219,0 @@
|
||||||
|
-73
|
||||||
|
-DB
|
||||||
|
-CE
|
||||||
|
@@ -2227,0 +2225,3 @@
|
||||||
|
+73
|
||||||
|
+DB
|
||||||
|
+CE
|
||||||
|
--- ./ter-u18b.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18b.bdf 2020-12-28 20:34:26.275129100 +0200
|
||||||
|
@@ -2410,4 +2409,0 @@
|
||||||
|
-3980
|
||||||
|
-6D80
|
||||||
|
-6D80
|
||||||
|
-6700
|
||||||
|
@@ -2419,0 +2416,4 @@
|
||||||
|
+3980
|
||||||
|
+6D80
|
||||||
|
+6D80
|
||||||
|
+6700
|
||||||
|
--- ./ter-u18n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u18n.bdf 2020-12-28 20:34:26.275129100 +0200
|
||||||
|
@@ -2410,4 +2409,0 @@
|
||||||
|
-3100
|
||||||
|
-4900
|
||||||
|
-4900
|
||||||
|
-4600
|
||||||
|
@@ -2419,0 +2416,4 @@
|
||||||
|
+3100
|
||||||
|
+4900
|
||||||
|
+4900
|
||||||
|
+4600
|
||||||
|
--- ./ter-u20b.bdf.orig 2020-12-28 20:34:18.735118500 +0200
|
||||||
|
+++ ./ter-u20b.bdf 2020-12-28 20:34:26.305129100 +0200
|
||||||
|
@@ -2600,4 +2599,0 @@
|
||||||
|
-3980
|
||||||
|
-6D80
|
||||||
|
-6D80
|
||||||
|
-6700
|
||||||
|
@@ -2610,0 +2607,4 @@
|
||||||
|
+3980
|
||||||
|
+6D80
|
||||||
|
+6D80
|
||||||
|
+6700
|
||||||
|
--- ./ter-u20n.bdf.orig 2020-12-28 20:34:18.725118500 +0200
|
||||||
|
+++ ./ter-u20n.bdf 2020-12-28 20:34:26.295129100 +0200
|
||||||
|
@@ -2600,4 +2599,0 @@
|
||||||
|
-3100
|
||||||
|
-4900
|
||||||
|
-4900
|
||||||
|
-4600
|
||||||
|
@@ -2610,0 +2607,4 @@
|
||||||
|
+3100
|
||||||
|
+4900
|
||||||
|
+4900
|
||||||
|
+4600
|
||||||
|
--- ./ter-u22b.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22b.bdf 2020-12-28 20:34:26.325129100 +0200
|
||||||
|
@@ -2790,4 +2789,0 @@
|
||||||
|
-38C0
|
||||||
|
-6CC0
|
||||||
|
-66C0
|
||||||
|
-6380
|
||||||
|
@@ -2800,0 +2797,4 @@
|
||||||
|
+38C0
|
||||||
|
+6CC0
|
||||||
|
+66C0
|
||||||
|
+6380
|
||||||
|
--- ./ter-u22n.bdf.orig 2020-12-28 20:34:18.775118600 +0200
|
||||||
|
+++ ./ter-u22n.bdf 2020-12-28 20:34:26.325129100 +0200
|
||||||
|
@@ -2790,4 +2789,0 @@
|
||||||
|
-3080
|
||||||
|
-4880
|
||||||
|
-4480
|
||||||
|
-4300
|
||||||
|
@@ -2800,0 +2797,4 @@
|
||||||
|
+3080
|
||||||
|
+4880
|
||||||
|
+4480
|
||||||
|
+4300
|
||||||
|
--- ./ter-u24b.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24b.bdf 2020-12-28 20:34:26.355129200 +0200
|
||||||
|
@@ -2981,4 +2980,0 @@
|
||||||
|
-3C60
|
||||||
|
-6660
|
||||||
|
-6660
|
||||||
|
-63C0
|
||||||
|
@@ -2992,0 +2989,4 @@
|
||||||
|
+3C60
|
||||||
|
+6660
|
||||||
|
+6660
|
||||||
|
+63C0
|
||||||
|
--- ./ter-u24n.bdf.orig 2020-12-28 20:34:18.795118600 +0200
|
||||||
|
+++ ./ter-u24n.bdf 2020-12-28 20:34:26.365129200 +0200
|
||||||
|
@@ -2981,4 +2980,0 @@
|
||||||
|
-3840
|
||||||
|
-4440
|
||||||
|
-4440
|
||||||
|
-4380
|
||||||
|
@@ -2992,0 +2989,4 @@
|
||||||
|
+3840
|
||||||
|
+4440
|
||||||
|
+4440
|
||||||
|
+4380
|
||||||
|
--- ./ter-u28b.bdf.orig 2020-12-28 20:34:18.845118700 +0200
|
||||||
|
+++ ./ter-u28b.bdf 2020-12-28 20:34:26.385129200 +0200
|
||||||
|
@@ -3361,5 +3360,0 @@
|
||||||
|
-3C30
|
||||||
|
-7E30
|
||||||
|
-6730
|
||||||
|
-63F0
|
||||||
|
-61E0
|
||||||
|
@@ -3374,0 +3370,5 @@
|
||||||
|
+3C30
|
||||||
|
+7E30
|
||||||
|
+6730
|
||||||
|
+63F0
|
||||||
|
+61E0
|
||||||
|
--- ./ter-u28n.bdf.orig 2020-12-28 20:34:18.835118600 +0200
|
||||||
|
+++ ./ter-u28n.bdf 2020-12-28 20:34:26.385129200 +0200
|
||||||
|
@@ -3361,5 +3360,0 @@
|
||||||
|
-3C30
|
||||||
|
-6630
|
||||||
|
-6330
|
||||||
|
-6330
|
||||||
|
-61E0
|
||||||
|
@@ -3374,0 +3370,5 @@
|
||||||
|
+3C30
|
||||||
|
+6630
|
||||||
|
+6330
|
||||||
|
+6330
|
||||||
|
+61E0
|
||||||
|
--- ./ter-u32b.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32b.bdf 2020-12-28 20:34:26.435129300 +0200
|
||||||
|
@@ -3743,6 +3742,0 @@
|
||||||
|
-1E1C
|
||||||
|
-3F1C
|
||||||
|
-779C
|
||||||
|
-73DC
|
||||||
|
-71F8
|
||||||
|
-70F0
|
||||||
|
@@ -3757,0 +3752,6 @@
|
||||||
|
+1E1C
|
||||||
|
+3F1C
|
||||||
|
+779C
|
||||||
|
+73DC
|
||||||
|
+71F8
|
||||||
|
+70F0
|
||||||
|
--- ./ter-u32n.bdf.orig 2020-12-28 20:34:18.865118700 +0200
|
||||||
|
+++ ./ter-u32n.bdf 2020-12-28 20:34:26.425129300 +0200
|
||||||
|
@@ -3743,6 +3742,0 @@
|
||||||
|
-0E0C
|
||||||
|
-1F0C
|
||||||
|
-3B8C
|
||||||
|
-31DC
|
||||||
|
-30F8
|
||||||
|
-3070
|
||||||
|
@@ -3757,0 +3752,6 @@
|
||||||
|
+0E0C
|
||||||
|
+1F0C
|
||||||
|
+3B8C
|
||||||
|
+31DC
|
||||||
|
+30F8
|
||||||
|
+3070
|
||||||
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
|
||||||
|
// -- Width --
|
||||||
|
const DPARSE_LIMIT = 512;
|
||||||
|
const SPARSE_LIMIT = 32000;
|
||||||
|
|
||||||
|
class Width {
|
||||||
|
constructor(x, y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static parse(name, value, limit) {
|
||||||
|
const words = fnutil.splitWords(name, value, 2);
|
||||||
|
|
||||||
|
return new Width(fnutil.parseDec(name + '.x', words[0], -limit, limit),
|
||||||
|
fnutil.parseDec(name + '.y', words[1], -limit, limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
static parseS(name, value) {
|
||||||
|
return Width.parse(name, value, SPARSE_LIMIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static parseD(name, value) {
|
||||||
|
return Width.parse(name, value, DPARSE_LIMIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `${this.x} ${this.y}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- BBX --
|
||||||
|
class BBX {
|
||||||
|
constructor(width, height, xoff, yoff) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.xoff = xoff;
|
||||||
|
this.yoff = yoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static parse(name, value) {
|
||||||
|
const words = fnutil.splitWords(name, value, 4);
|
||||||
|
|
||||||
|
return new BBX(fnutil.parseDec(name + '.width', words[0], 1, DPARSE_LIMIT),
|
||||||
|
fnutil.parseDec(name + '.height', words[1], 1, DPARSE_LIMIT),
|
||||||
|
fnutil.parseDec(name + '.xoff', words[2], -DPARSE_LIMIT, DPARSE_LIMIT),
|
||||||
|
fnutil.parseDec(name + '.yoff', words[3], -DPARSE_LIMIT, DPARSE_LIMIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
rowSize() {
|
||||||
|
return (this.width + 7) >> 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `${this.width} ${this.height} ${this.xoff} ${this.yoff}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Props --
|
||||||
|
function skipComments(line) {
|
||||||
|
return line.startsWith('COMMENT') ? null : line;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Props extends Map {
|
||||||
|
forEach(callback) {
|
||||||
|
super.forEach((value, name) => callback(name, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
read(input, name, callback) {
|
||||||
|
return this.parse(input.readLines(skipComments), name, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(line, name, callback) {
|
||||||
|
if (line == null || !line.startsWith(name)) {
|
||||||
|
throw new Error(name + ' expected');
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = line.substring(name.length).trimLeft();
|
||||||
|
|
||||||
|
this.set(name, value);
|
||||||
|
return callback == null ? value : callback(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(name, value) {
|
||||||
|
super.set(name, value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Base --
|
||||||
|
class Base {
|
||||||
|
constructor() {
|
||||||
|
this.props = new Props();
|
||||||
|
this.bbx = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Char --
|
||||||
|
class Char extends Base {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.code = -1;
|
||||||
|
this.swidth = null;
|
||||||
|
this.dwidth = null;
|
||||||
|
this.data = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap() {
|
||||||
|
const bitmap = this.data.toString('hex').toUpperCase();
|
||||||
|
const regex = new RegExp(`.{${this.bbx.rowSize() << 1}}`, 'g');
|
||||||
|
return bitmap.replace(regex, '$&\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
_read(input) {
|
||||||
|
// HEADER
|
||||||
|
this.props.read(input, 'STARTCHAR');
|
||||||
|
this.code = this.props.read(input, 'ENCODING', fnutil.parseDec);
|
||||||
|
this.swidth = this.props.read(input, 'SWIDTH', Width.parseS);
|
||||||
|
this.dwidth = this.props.read(input, 'DWIDTH', Width.parseD);
|
||||||
|
this.bbx = this.props.read(input, 'BBX', BBX.parse);
|
||||||
|
|
||||||
|
let line = input.readLines(skipComments);
|
||||||
|
|
||||||
|
if (line != null && line.startsWith('ATTRIBUTES')) {
|
||||||
|
this.props.parse(line, 'ATTRIBUTES');
|
||||||
|
line = input.readLines(skipComments);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BITMAP
|
||||||
|
if (this.props.parse(line, 'BITMAP') !== '') {
|
||||||
|
throw new Error('BITMAP expected');
|
||||||
|
}
|
||||||
|
|
||||||
|
const rowLen = this.bbx.rowSize() * 2;
|
||||||
|
let bitmap = '';
|
||||||
|
|
||||||
|
for (let y = 0; y < this.bbx.height; y++) {
|
||||||
|
line = input.readLines(skipComments);
|
||||||
|
|
||||||
|
if (line == null) {
|
||||||
|
throw new Error('bitmap data expected');
|
||||||
|
}
|
||||||
|
if (line.match(/^[\dA-Fa-f]+$/) == null) {
|
||||||
|
throw new Error('invalid bitmap character(s)');
|
||||||
|
}
|
||||||
|
if (line.length === rowLen) {
|
||||||
|
bitmap += line;
|
||||||
|
} else {
|
||||||
|
throw new Error('invalid bitmap line length');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = Buffer.from(bitmap, 'hex');
|
||||||
|
|
||||||
|
// FINAL
|
||||||
|
if (input.readLines(skipComments) !== 'ENDCHAR') {
|
||||||
|
throw new Error('ENDCHAR expected');
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static read(input) {
|
||||||
|
return (new Char())._read(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(output) {
|
||||||
|
let header = '';
|
||||||
|
|
||||||
|
this.props.forEach((name, value) => {
|
||||||
|
header += (name + ' ' + value).trim() + '\n';
|
||||||
|
});
|
||||||
|
output.writeLine(header + this.bitmap() + 'ENDCHAR');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Font --
|
||||||
|
const XLFD = {
|
||||||
|
FOUNDRY: 1,
|
||||||
|
FAMILY_NAME: 2,
|
||||||
|
WEIGHT_NAME: 3,
|
||||||
|
SLANT: 4,
|
||||||
|
SETWIDTH_NAME: 5,
|
||||||
|
ADD_STYLE_NAME: 6,
|
||||||
|
PIXEL_SIZE: 7,
|
||||||
|
POINT_SIZE: 8,
|
||||||
|
RESOLUTION_X: 9,
|
||||||
|
RESOLUTION_Y: 10,
|
||||||
|
SPACING: 11,
|
||||||
|
AVERAGE_WIDTH: 12,
|
||||||
|
CHARSET_REGISTRY: 13,
|
||||||
|
CHARSET_ENCODING: 14
|
||||||
|
};
|
||||||
|
|
||||||
|
const CHARS_MAX = 65535;
|
||||||
|
|
||||||
|
class Font extends Base {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.chars = [];
|
||||||
|
this.defaultCode = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get bold() {
|
||||||
|
return this.xlfd[XLFD.WEIGHT_NAME].toLowerCase().includes('bold');
|
||||||
|
}
|
||||||
|
|
||||||
|
get italic() {
|
||||||
|
return ['I', 'O'].indexOf(this.xlfd[XLFD.SLANT]) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get proportional() {
|
||||||
|
return this.xlfd[XLFD.SPACING] === 'P';
|
||||||
|
}
|
||||||
|
|
||||||
|
_read(input) {
|
||||||
|
// HEADER
|
||||||
|
let line = input.readLine();
|
||||||
|
|
||||||
|
if (this.props.parse(line, 'STARTFONT') !== '2.1') {
|
||||||
|
throw new Error('STARTFONT 2.1 expected');
|
||||||
|
}
|
||||||
|
this.xlfd = this.props.read(input, 'FONT', (name, value) => value.split('-', 16));
|
||||||
|
|
||||||
|
if (this.xlfd.length !== 15 || this.xlfd[0] !== '') {
|
||||||
|
throw new Error('non-XLFD font names are not supported');
|
||||||
|
}
|
||||||
|
this.props.read(input, 'SIZE');
|
||||||
|
this.bbx = this.props.read(input, 'FONTBOUNDINGBOX', BBX.parse);
|
||||||
|
line = input.readLines(skipComments);
|
||||||
|
|
||||||
|
if (line != null && line.startsWith('STARTPROPERTIES')) {
|
||||||
|
const numProps = this.props.parse(line, 'STARTPROPERTIES', fnutil.parseDec);
|
||||||
|
|
||||||
|
for (let i = 0; i < numProps; i++) {
|
||||||
|
line = input.readLines(skipComments);
|
||||||
|
|
||||||
|
if (line == null) {
|
||||||
|
throw new Error('property expected');
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = line.match(/^(\w+)\s+([-\d"].*)$/);
|
||||||
|
|
||||||
|
if (match == null) {
|
||||||
|
throw new Error('invalid property format');
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = match[1];
|
||||||
|
const value = match[2];
|
||||||
|
|
||||||
|
if (this.props.get(name) != null) {
|
||||||
|
throw new Error('duplicate property');
|
||||||
|
}
|
||||||
|
if (name === 'DEFAULT_CHAR') {
|
||||||
|
this.defaultCode = fnutil.parseDec(name, value);
|
||||||
|
}
|
||||||
|
this.props.set(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.read(input, 'ENDPROPERTIES') !== '') {
|
||||||
|
throw new Error('ENDPROPERTIES expected');
|
||||||
|
}
|
||||||
|
line = input.readLines(skipComments);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLYPHS
|
||||||
|
const numChars = fnutil.parseDec('CHARS', this.props.parse(line, 'CHARS'), 1, CHARS_MAX);
|
||||||
|
|
||||||
|
for (let i = 0; i < numChars; i++) {
|
||||||
|
this.chars.push(Char.read(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.defaultCode !== -1 && this.chars.find(char => char.code === this.defaultCode) === -1) {
|
||||||
|
throw new Error('invalid DEFAULT_CHAR');
|
||||||
|
}
|
||||||
|
|
||||||
|
// FINAL
|
||||||
|
if (input.readLines(skipComments) !== 'ENDFONT') {
|
||||||
|
throw new Error('ENDFONT expected');
|
||||||
|
}
|
||||||
|
if (input.readLine() != null) {
|
||||||
|
throw new Error('garbage after ENDFONT');
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static read(input) {
|
||||||
|
return (new Font())._read(input, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(output) {
|
||||||
|
this.props.forEach((name, value) => output.writeProp(name, value));
|
||||||
|
this.chars.forEach(char => char.write(output));
|
||||||
|
output.writeLine('ENDFONT');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Export --
|
||||||
|
module.exports = Object.freeze({
|
||||||
|
DPARSE_LIMIT,
|
||||||
|
SPARSE_LIMIT,
|
||||||
|
Width,
|
||||||
|
BBX,
|
||||||
|
skipComments,
|
||||||
|
Props,
|
||||||
|
Base,
|
||||||
|
Char,
|
||||||
|
XLFD,
|
||||||
|
CHARS_MAX,
|
||||||
|
Font
|
||||||
|
});
|
||||||
@@ -0,0 +1,309 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import re
|
||||||
|
import codecs
|
||||||
|
from collections import OrderedDict
|
||||||
|
from enum import IntEnum, unique
|
||||||
|
|
||||||
|
import fnutil
|
||||||
|
|
||||||
|
# -- Width --
|
||||||
|
DPARSE_LIMIT = 512
|
||||||
|
SPARSE_LIMIT = 32000
|
||||||
|
|
||||||
|
class Width:
|
||||||
|
def __init__(self, x, y):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse(name, value, limit):
|
||||||
|
words = fnutil.split_words(name, value, 2)
|
||||||
|
return Width(fnutil.parse_dec(name + '.x', words[0], -limit, limit),
|
||||||
|
fnutil.parse_dec(name + '.y', words[1], -limit, limit))
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_s(name, value):
|
||||||
|
return Width.parse(name, value, SPARSE_LIMIT)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_d(name, value):
|
||||||
|
return Width.parse(name, value, DPARSE_LIMIT)
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%d %d' % (self.x, self.y)
|
||||||
|
|
||||||
|
|
||||||
|
# -- BXX --
|
||||||
|
class BBX:
|
||||||
|
def __init__(self, width, height, xoff, yoff):
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.xoff = xoff
|
||||||
|
self.yoff = yoff
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse(name, value):
|
||||||
|
words = fnutil.split_words(name, value, 4)
|
||||||
|
return BBX(fnutil.parse_dec('width', words[0], 1, DPARSE_LIMIT),
|
||||||
|
fnutil.parse_dec('height', words[1], 1, DPARSE_LIMIT),
|
||||||
|
fnutil.parse_dec('bbxoff', words[2], -DPARSE_LIMIT, DPARSE_LIMIT),
|
||||||
|
fnutil.parse_dec('bbyoff', words[3], -DPARSE_LIMIT, DPARSE_LIMIT))
|
||||||
|
|
||||||
|
|
||||||
|
def row_size(self):
|
||||||
|
return (self.width + 7) >> 3
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%d %d %d %d' % (self.width, self.height, self.xoff, self.yoff)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Props --
|
||||||
|
def skip_comments(line):
|
||||||
|
return None if line[:7] == b'COMMENT' else line
|
||||||
|
|
||||||
|
|
||||||
|
class Props(OrderedDict):
|
||||||
|
def __iter__(self):
|
||||||
|
return self.items().__iter__()
|
||||||
|
|
||||||
|
|
||||||
|
def read(self, input, name, callback=None):
|
||||||
|
return self.parse(input.read_lines(skip_comments), name, callback)
|
||||||
|
|
||||||
|
|
||||||
|
def parse(self, line, name, callback=None):
|
||||||
|
if not line or not line.startswith(bytes(name, 'ascii')):
|
||||||
|
raise Exception(name + ' expected')
|
||||||
|
|
||||||
|
value = line[len(name):].lstrip()
|
||||||
|
self[name] = value
|
||||||
|
return value if callback is None else callback(name, value)
|
||||||
|
|
||||||
|
|
||||||
|
def set(self, name, value):
|
||||||
|
self[name] = value if isinstance(value, (bytes, bytearray)) else bytes(str(value), 'ascii')
|
||||||
|
|
||||||
|
|
||||||
|
# -- Base --
|
||||||
|
class Base:
|
||||||
|
def __init__(self):
|
||||||
|
self.props = Props()
|
||||||
|
self.bbx = None
|
||||||
|
|
||||||
|
|
||||||
|
# -- Char
|
||||||
|
HEX_BYTES = (48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70)
|
||||||
|
|
||||||
|
class Char(Base):
|
||||||
|
def __init__(self):
|
||||||
|
Base.__init__(self)
|
||||||
|
self.code = -1
|
||||||
|
self.swidth = None
|
||||||
|
self.dwidth = None
|
||||||
|
self.data = None
|
||||||
|
|
||||||
|
|
||||||
|
def bitmap(self):
|
||||||
|
bitmap = ''
|
||||||
|
row_size = self.bbx.row_size()
|
||||||
|
|
||||||
|
for index in range(0, len(self.data), row_size):
|
||||||
|
bitmap += self.data[index : index + row_size].hex() + '\n'
|
||||||
|
|
||||||
|
return bytes(bitmap, 'ascii').upper()
|
||||||
|
|
||||||
|
|
||||||
|
def _read(self, input):
|
||||||
|
# HEADER
|
||||||
|
self.props.read(input, 'STARTCHAR')
|
||||||
|
self.code = self.props.read(input, 'ENCODING', fnutil.parse_dec)
|
||||||
|
self.swidth = self.props.read(input, 'SWIDTH', Width.parse_s)
|
||||||
|
self.dwidth = self.props.read(input, 'DWIDTH', Width.parse_d)
|
||||||
|
self.bbx = self.props.read(input, 'BBX', BBX.parse)
|
||||||
|
line = input.read_lines(skip_comments)
|
||||||
|
|
||||||
|
if line and line.startswith(b'ATTRIBUTES'):
|
||||||
|
self.props.parse(line, 'ATTRIBUTES')
|
||||||
|
line = input.read_lines(skip_comments)
|
||||||
|
|
||||||
|
# BITMAP
|
||||||
|
if self.props.parse(line, 'BITMAP'):
|
||||||
|
raise Exception('BITMAP expected')
|
||||||
|
|
||||||
|
row_len = self.bbx.row_size() * 2
|
||||||
|
self.data = bytearray()
|
||||||
|
|
||||||
|
for _ in range(0, self.bbx.height):
|
||||||
|
line = input.read_lines(skip_comments)
|
||||||
|
|
||||||
|
if not line:
|
||||||
|
raise Exception('bitmap data expected')
|
||||||
|
|
||||||
|
if len(line) == row_len:
|
||||||
|
self.data += codecs.decode(line, 'hex')
|
||||||
|
else:
|
||||||
|
raise Exception('invalid bitmap length')
|
||||||
|
|
||||||
|
# FINAL
|
||||||
|
if input.read_lines(skip_comments) != b'ENDCHAR':
|
||||||
|
raise Exception('ENDCHAR expected')
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def read(input):
|
||||||
|
return Char()._read(input) # pylint: disable=protected-access
|
||||||
|
|
||||||
|
|
||||||
|
def write(self, output):
|
||||||
|
for [name, value] in self.props:
|
||||||
|
output.write_prop(name, value)
|
||||||
|
|
||||||
|
output.write_line(self.bitmap() + b'ENDCHAR')
|
||||||
|
|
||||||
|
|
||||||
|
# -- Font --
|
||||||
|
@unique
|
||||||
|
class XLFD(IntEnum):
|
||||||
|
FOUNDRY = 1
|
||||||
|
FAMILY_NAME = 2
|
||||||
|
WEIGHT_NAME = 3
|
||||||
|
SLANT = 4
|
||||||
|
SETWIDTH_NAME = 5
|
||||||
|
ADD_STYLE_NAME = 6
|
||||||
|
PIXEL_SIZE = 7
|
||||||
|
POINT_SIZE = 8
|
||||||
|
RESOLUTION_X = 9
|
||||||
|
RESOLUTION_Y = 10
|
||||||
|
SPACING = 11
|
||||||
|
AVERAGE_WIDTH = 12
|
||||||
|
CHARSET_REGISTRY = 13
|
||||||
|
CHARSET_ENCODING = 14
|
||||||
|
|
||||||
|
CHARS_MAX = 65535
|
||||||
|
|
||||||
|
class Font(Base):
|
||||||
|
def __init__(self):
|
||||||
|
Base.__init__(self)
|
||||||
|
self.xlfd = []
|
||||||
|
self.chars = []
|
||||||
|
self.default_code = -1
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bold(self):
|
||||||
|
return b'bold' in self.xlfd[XLFD.WEIGHT_NAME].lower()
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def italic(self):
|
||||||
|
return self.xlfd[XLFD.SLANT] in [b'I', b'O']
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def proportional(self):
|
||||||
|
return self.xlfd[XLFD.SPACING] == b'P'
|
||||||
|
|
||||||
|
|
||||||
|
def _read(self, input):
|
||||||
|
# HEADER
|
||||||
|
line = input.read_line()
|
||||||
|
|
||||||
|
if self.props.parse(line, 'STARTFONT') != b'2.1':
|
||||||
|
raise Exception('STARTFONT 2.1 expected')
|
||||||
|
|
||||||
|
self.xlfd = self.props.read(input, 'FONT', lambda name, value: value.split(b'-', 15))
|
||||||
|
|
||||||
|
if len(self.xlfd) != 15 or self.xlfd[0] != b'':
|
||||||
|
raise Exception('non-XLFD font names are not supported')
|
||||||
|
|
||||||
|
self.props.read(input, 'SIZE')
|
||||||
|
self.bbx = self.props.read(input, 'FONTBOUNDINGBOX', BBX.parse)
|
||||||
|
line = input.read_lines(skip_comments)
|
||||||
|
|
||||||
|
if line and line.startswith(b'STARTPROPERTIES'):
|
||||||
|
num_props = self.props.parse(line, 'STARTPROPERTIES', fnutil.parse_dec)
|
||||||
|
|
||||||
|
for _ in range(0, num_props):
|
||||||
|
line = input.read_lines(skip_comments)
|
||||||
|
|
||||||
|
if line is None:
|
||||||
|
raise Exception('property expected')
|
||||||
|
|
||||||
|
match = re.fullmatch(br'(\w+)\s+([-\d"].*)', line)
|
||||||
|
|
||||||
|
if not match:
|
||||||
|
raise Exception('invalid property format')
|
||||||
|
|
||||||
|
name = str(match.group(1), 'ascii')
|
||||||
|
value = match.group(2)
|
||||||
|
|
||||||
|
if self.props.get(name) is not None:
|
||||||
|
raise Exception('duplicate property')
|
||||||
|
|
||||||
|
if name == 'DEFAULT_CHAR':
|
||||||
|
self.default_code = fnutil.parse_dec(name, value)
|
||||||
|
|
||||||
|
self.props[name] = value
|
||||||
|
|
||||||
|
if self.props.read(input, 'ENDPROPERTIES') != b'':
|
||||||
|
raise Exception('ENDPROPERTIES expected')
|
||||||
|
|
||||||
|
line = input.read_lines(skip_comments)
|
||||||
|
|
||||||
|
# GLYPHS
|
||||||
|
num_chars = fnutil.parse_dec('CHARS', self.props.parse(line, 'CHARS'), 1, CHARS_MAX)
|
||||||
|
|
||||||
|
for _ in range(0, num_chars):
|
||||||
|
self.chars.append(Char.read(input))
|
||||||
|
|
||||||
|
if next((char.code for char in self.chars if char.code == self.default_code), -1) != self.default_code:
|
||||||
|
raise Exception('invalid DEFAULT_CHAR')
|
||||||
|
|
||||||
|
# FINAL
|
||||||
|
if input.read_lines(skip_comments) != b'ENDFONT':
|
||||||
|
raise Exception('ENDFONT expected')
|
||||||
|
|
||||||
|
if input.read_line() is not None:
|
||||||
|
raise Exception('garbage after ENDFONT')
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def read(input):
|
||||||
|
return Font()._read(input) # pylint: disable=protected-access
|
||||||
|
|
||||||
|
|
||||||
|
def write(self, output):
|
||||||
|
for [name, value] in self.props:
|
||||||
|
output.write_prop(name, value)
|
||||||
|
|
||||||
|
for char in self.chars:
|
||||||
|
char.write(output)
|
||||||
|
|
||||||
|
output.write_line(b'ENDFONT')
|
||||||
@@ -0,0 +1,455 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
const fncli = require('./fncli.js');
|
||||||
|
const fnio = require('./fnio.js');
|
||||||
|
const bdf = require('./bdf.js');
|
||||||
|
|
||||||
|
// -- Params --
|
||||||
|
class Params extends fncli.Params {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.asciiChars = true;
|
||||||
|
this.bbxExceeds = true;
|
||||||
|
this.duplCodes = -1;
|
||||||
|
this.extraBits = true;
|
||||||
|
this.attributes = true;
|
||||||
|
this.duplNames = -1;
|
||||||
|
this.duplProps = true;
|
||||||
|
this.commonSlant = true;
|
||||||
|
this.commonWeight = true;
|
||||||
|
this.xlfdFontNm = true;
|
||||||
|
this.yWidthZero = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Options --
|
||||||
|
const HELP = ('' +
|
||||||
|
'usage: bdfcheck [options] [INPUT...]\n' +
|
||||||
|
'Check BDF font(s) for various problems\n' +
|
||||||
|
'\n' +
|
||||||
|
' -A disable non-ascii characters check\n' +
|
||||||
|
' -B disable BBX exceeding FONTBOUNDINGBOX checks\n' +
|
||||||
|
' -c/-C enable/disable duplicate character codes check\n' +
|
||||||
|
' (default = enabled for registry ISO10646)\n' +
|
||||||
|
' -E disable extra bits check\n' +
|
||||||
|
' -I disable ATTRIBUTES check\n' +
|
||||||
|
' -n/-N enable duplicate character names check\n' +
|
||||||
|
' (default = enabled for registry ISO10646)\n' +
|
||||||
|
' -P disable duplicate properties check\n' +
|
||||||
|
' -S disable common slant check\n' +
|
||||||
|
' -W disable common weight check\n' +
|
||||||
|
' -X disable XLFD font name check\n' +
|
||||||
|
' -Y disable zero WIDTH Y check\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'File directives: COMMENT bdfcheck --enable|disable-<check-name>\n' +
|
||||||
|
' (also available as long command line options)\n' +
|
||||||
|
'\n' +
|
||||||
|
'Check names: ascii-chars, bbx-exceeds, duplicate-codes, extra-bits,\n' +
|
||||||
|
' attributes, duplicate-names, duplicate-properties, common-slant,\n' +
|
||||||
|
' common-weight, xlfd-font, ywidth-zero\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input BDF(s) must be v2.1 with unicode encoding.\n');
|
||||||
|
|
||||||
|
const VERSION = 'bdfcheck 1.61, Copyright (C) 2017-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE;
|
||||||
|
|
||||||
|
class Options extends fncli.Options {
|
||||||
|
constructor() {
|
||||||
|
super([], HELP, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(name, directive, params) {
|
||||||
|
const value = name.startsWith('--enable') || name[1].match('[a-z]');
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case '-A':
|
||||||
|
case '--enable-ascii-chars':
|
||||||
|
case '--disable-ascii-chars':
|
||||||
|
params.asciiChars = value;
|
||||||
|
break;
|
||||||
|
case '-B':
|
||||||
|
case '--enable-bbx-exceeds':
|
||||||
|
case '--disable-bbx-exceeds':
|
||||||
|
params.bbxExceeds = value;
|
||||||
|
break;
|
||||||
|
case '-c':
|
||||||
|
case '-C':
|
||||||
|
case '--enable-duplicate-codes':
|
||||||
|
case '--disable-duplicate-codes':
|
||||||
|
params.duplCodes = value;
|
||||||
|
break;
|
||||||
|
case '-E':
|
||||||
|
case '--enable-extra-bits':
|
||||||
|
case '--disable-extra-bits':
|
||||||
|
params.extraBits = value;
|
||||||
|
break;
|
||||||
|
case '-I':
|
||||||
|
case '--enable-attributes':
|
||||||
|
case '--disable-attributes':
|
||||||
|
params.attributes = value;
|
||||||
|
break;
|
||||||
|
case '-n':
|
||||||
|
case '-N':
|
||||||
|
case '--enable-duplicate-names':
|
||||||
|
case '--disable-duplicate-names':
|
||||||
|
params.duplNames = value;
|
||||||
|
break;
|
||||||
|
case '-P':
|
||||||
|
case '--enable-duplicate-properties':
|
||||||
|
case '--disable-duplicate-properties':
|
||||||
|
params.duplProps = value;
|
||||||
|
break;
|
||||||
|
case '-S':
|
||||||
|
case '--enable-common-slant':
|
||||||
|
case '--disable-common-slant':
|
||||||
|
params.commonSlant = value;
|
||||||
|
break;
|
||||||
|
case '-W':
|
||||||
|
case '--enable-common-weight':
|
||||||
|
case '--disable-common-weight':
|
||||||
|
params.commonWeight = value;
|
||||||
|
break;
|
||||||
|
case '-X':
|
||||||
|
case '--enable-xlfd-font':
|
||||||
|
case '--disable-xlfd-font':
|
||||||
|
params.xlfdFontNm = value;
|
||||||
|
break;
|
||||||
|
case '-Y':
|
||||||
|
case '--enable-ywidth-zero':
|
||||||
|
case '--disable-ywidth-zero':
|
||||||
|
params.yWidthZero = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return directive !== true && this.fallback(name, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return directive !== true || name.startsWith('--');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- DupMap --
|
||||||
|
class DupMap extends Map {
|
||||||
|
constructor(prefix, descript, severity) {
|
||||||
|
super();
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.descript = descript;
|
||||||
|
this.severity = severity;
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
this.forEach((lines, value) => {
|
||||||
|
if (lines.length > 1) {
|
||||||
|
let text = `duplicate ${this.descript} ${value} at lines`;
|
||||||
|
|
||||||
|
for (let index = 0; index < lines.length; index++) {
|
||||||
|
text += (index === 0 ? ' ' : index === lines.length - 1 ? ' and ' : ', ');
|
||||||
|
text += lines[index];
|
||||||
|
}
|
||||||
|
fnutil.message(this.prefix, this.severity, text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
push(value, lineNo) {
|
||||||
|
let lines = this.get(value);
|
||||||
|
|
||||||
|
if (lines != null) {
|
||||||
|
lines.push(lineNo);
|
||||||
|
} else {
|
||||||
|
this.set(value, [lineNo]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- InputFileStream --
|
||||||
|
const MODE = Object.freeze({
|
||||||
|
META: 0,
|
||||||
|
PROPS: 1,
|
||||||
|
BITMAP: 2
|
||||||
|
});
|
||||||
|
|
||||||
|
class InputFileStream extends fnio.InputFileStream {
|
||||||
|
constructor(fileName, parsed) {
|
||||||
|
super(fileName);
|
||||||
|
this.parsed = parsed;
|
||||||
|
this.mode = MODE.META;
|
||||||
|
this.proplocs = new DupMap(this.location(), 'property');
|
||||||
|
this.namelocs = new DupMap(this.location(), 'character name', 'warning');
|
||||||
|
this.codelocs = new DupMap(this.location(), 'encoding', 'warning');
|
||||||
|
this.HANDLERS = [
|
||||||
|
[ 'STARTCHAR', value => this.appendName(value) ],
|
||||||
|
[ 'ENCODING', value => this.appendCode(value) ],
|
||||||
|
[ 'SWIDTH', value => this.checkWidth('SWIDTH', value, bdf.Width.parseS) ],
|
||||||
|
[ 'DWIDTH', value => this.checkWidth('DWIDTH', value, bdf.Width.parseD) ],
|
||||||
|
[ 'BBX', value => this.setLastBox(value) ],
|
||||||
|
[ 'BITMAP', () => this.setMode(MODE.BITMAP) ],
|
||||||
|
[ 'SIZE', InputFileStream.checkSize ],
|
||||||
|
[ 'ATTRIBUTES', value => this.checkAttr(value) ],
|
||||||
|
[ 'STARTPROPERTIES', () => this.setMode(MODE.PROPS) ],
|
||||||
|
[ 'FONTBOUNDINGBOX', value => this.setFontBox(value) ]
|
||||||
|
];
|
||||||
|
this.xlfdName = false;
|
||||||
|
this.lastBox = null;
|
||||||
|
this.fontBox = null;
|
||||||
|
this.options = new Options();
|
||||||
|
}
|
||||||
|
|
||||||
|
append(option, valocs, value) {
|
||||||
|
if (option) {
|
||||||
|
valocs.push(value, this.lineNo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appendCode(value) {
|
||||||
|
fnutil.parseDec('encoding', value);
|
||||||
|
this.append(this.parsed.duplCodes, this.codelocs, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
appendName(value) {
|
||||||
|
this.append(this.parsed.duplNames, this.namelocs, `"${value}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkWidth(name, value, parse) {
|
||||||
|
if (this.parsed.yWidthZero && parse(name, value).y !== 0) {
|
||||||
|
fnutil.warning(this.location(), `non-zero ${name} Y`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setFontBox(value) {
|
||||||
|
this.fontBox = bdf.BBX.parse('FONTBOUNDINGBOX', value);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLastBox(value) {
|
||||||
|
const bbx = bdf.BBX.parse('BBX', value);
|
||||||
|
|
||||||
|
if (this.parsed.bbxExceeds) {
|
||||||
|
let exceeds = [];
|
||||||
|
|
||||||
|
if (bbx.xoff < this.fontBox.xoff) {
|
||||||
|
exceeds.push('xoff < FONTBOUNDINGBOX xoff');
|
||||||
|
}
|
||||||
|
if (bbx.yoff < this.fontBox.yoff) {
|
||||||
|
exceeds.push('yoff < FONTBOUNDINGBOX yoff');
|
||||||
|
}
|
||||||
|
if (bbx.width > this.fontBox.width) {
|
||||||
|
exceeds.push('width > FONTBOUNDINGBOX width');
|
||||||
|
}
|
||||||
|
if (bbx.height > this.fontBox.height) {
|
||||||
|
exceeds.push('height > FONTBOUNDINGBOX height');
|
||||||
|
}
|
||||||
|
exceeds.forEach(exceed => {
|
||||||
|
fnutil.message(this.location(), '', exceed);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.lastBox = bbx;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMode(newMode) {
|
||||||
|
this.mode = newMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static checkSize(value) {
|
||||||
|
const words = fnutil.splitWords('SIZE', value, 3);
|
||||||
|
|
||||||
|
fnutil.parseDec('point size', words[0], 1, null);
|
||||||
|
fnutil.parseDec('x resolution', words[1], 1, null);
|
||||||
|
fnutil.parseDec('y resolution', words[2], 1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkAttr(value) {
|
||||||
|
if (!value.match(/^[\dA-Fa-f]{4}$/)) {
|
||||||
|
throw new Error('ATTRIBUTES must be 4 hex-encoded characters');
|
||||||
|
}
|
||||||
|
if (this.parsed.attributes) {
|
||||||
|
fnutil.warning(this.location(), 'ATTRIBUTES may cause problems with freetype');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkFont(value) {
|
||||||
|
const xlfd = value.substring(4).trimLeft().split('-', 16);
|
||||||
|
|
||||||
|
if (xlfd.length === 15 && xlfd[0] === '') {
|
||||||
|
let unicode = (xlfd[bdf.XLFD.CHARSET_REGISTRY].toUpperCase() === 'ISO10646');
|
||||||
|
|
||||||
|
if (this.parsed.duplCodes === -1) {
|
||||||
|
this.parsed.duplCodes = unicode;
|
||||||
|
}
|
||||||
|
if (this.parsed.duplNames === -1) {
|
||||||
|
this.parsed.duplNames = unicode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.parsed.commonWeight) {
|
||||||
|
let weight = xlfd[bdf.XLFD.WEIGHT_NAME];
|
||||||
|
let compare = weight.toLowerCase();
|
||||||
|
let consider = compare.includes('bold') ? 'Bold' : 'Normal';
|
||||||
|
|
||||||
|
if (compare === 'medium' || compare === 'regular') {
|
||||||
|
compare = 'normal';
|
||||||
|
}
|
||||||
|
if (compare !== consider.toLowerCase()) {
|
||||||
|
fnutil.warning(this.location(), `weight "${weight}" may be considered ${consider}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.parsed.commonSlant) {
|
||||||
|
let slant = xlfd[bdf.XLFD.SLANT];
|
||||||
|
let consider = slant.match(/^[IO]/) ? 'Italic' : 'Regular';
|
||||||
|
|
||||||
|
if (slant.match(/^[IOR]$/) == null) {
|
||||||
|
fnutil.warning(this.location(), `slant "${slant}" may be considered ${consider}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.parsed.xlfdFontNm) {
|
||||||
|
fnutil.warning(this.location(), 'non-XLFD font name');
|
||||||
|
}
|
||||||
|
value = 'FONT --------------';
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkProp(line) {
|
||||||
|
const match = line.match(/^(\w+)\s+([-\d"].*)$/);
|
||||||
|
|
||||||
|
if (match == null) {
|
||||||
|
throw new Error('invalid property format');
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = match[1];
|
||||||
|
const value = match[2];
|
||||||
|
|
||||||
|
if (value.startsWith('"')) {
|
||||||
|
if (value.length < 2 || !value.endsWith('"')) {
|
||||||
|
throw new Error('no closing double quote');
|
||||||
|
}
|
||||||
|
if (value.substring(1, value.length - 1).match(/[^"]"[^"]/)) {
|
||||||
|
throw new Error('unescaped double quote');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fnutil.parseDec('value', value, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.append(this.parsed.duplProps, this.proplocs, name);
|
||||||
|
return `P${this.lineNo} 1`;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkBitmap(line) {
|
||||||
|
if (line.length !== this.lastBox.rowSize() * 2) {
|
||||||
|
throw new Error('invalid bitmap length');
|
||||||
|
} else if (line.match(/^[\dA-Fa-f]+$/) == null) {
|
||||||
|
throw new Error('invalid bitmap data');
|
||||||
|
} else if (this.parsed.extraBits) {
|
||||||
|
const data = Buffer.from(line, 'hex');
|
||||||
|
const checkX = (this.lastBox.width - 1) | 7;
|
||||||
|
const lastByte = data[data.length - 1];
|
||||||
|
let bitNo = 7 - (this.lastBox.Width & 7);
|
||||||
|
|
||||||
|
for (let x = this.lastBox.Width; x <= checkX; x++) {
|
||||||
|
if (lastByte & (1 << bitNo)) {
|
||||||
|
fnutil.warning(this.location(), `extra bit(s) starting with x=${x}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bitNo--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkLine(line) {
|
||||||
|
if (line.match(/[^\t\f\v\u0020-\u00ff]/)) {
|
||||||
|
throw new Error('control character(s)');
|
||||||
|
}
|
||||||
|
if (this.parsed.asciiChars && line.match(/[\u007f-\u00ff]/)) {
|
||||||
|
fnutil.warning(this.location(), 'non-ascii character(s)');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (this.mode) {
|
||||||
|
case MODE.META:
|
||||||
|
if (!this.xlfdName && line.startsWith('FONT')) {
|
||||||
|
line = this.checkFont(line);
|
||||||
|
this.xlfdName = true;
|
||||||
|
} else {
|
||||||
|
this.HANDLERS.findIndex(function(handler) {
|
||||||
|
if (line.startsWith(handler[0])) {
|
||||||
|
handler[1](line.substring(handler[0].length).trimLeft());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE.PROPS:
|
||||||
|
if (line.startsWith('ENDPROPERTIES')) {
|
||||||
|
this.mode = MODE.META;
|
||||||
|
} else {
|
||||||
|
line = this.checkProp(line);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // MODE.BITMAP
|
||||||
|
if (line.startsWith('ENDCHAR')) {
|
||||||
|
this.mode = MODE.META;
|
||||||
|
} else {
|
||||||
|
this.checkBitmap(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
readCheck(line, callback) {
|
||||||
|
const match = line.match(/^COMMENT\s*bdfcheck\s+(-.*)$/);
|
||||||
|
|
||||||
|
if (match && !this.options.parse(match[1], true, this.parsed)) {
|
||||||
|
throw new Error('invalid bdfcheck directive');
|
||||||
|
}
|
||||||
|
|
||||||
|
line = callback(line);
|
||||||
|
return line != null ? this.checkLine(line) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
readLines(callback) {
|
||||||
|
return super.readLines(line => this.readCheck(line, callback));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Main --
|
||||||
|
function mainProgram(nonopt, parsed) {
|
||||||
|
(nonopt.length >= 1 ? nonopt : [null]).forEach(input => {
|
||||||
|
let ifs = new InputFileStream(input, parsed);
|
||||||
|
|
||||||
|
try {
|
||||||
|
bdf.Font.read(ifs);
|
||||||
|
ifs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
ifs.proplocs.check();
|
||||||
|
ifs.namelocs.check();
|
||||||
|
ifs.codelocs.check();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
fncli.start('bdfcheck.js', new Options(), new Params(), mainProgram);
|
||||||
|
}
|
||||||
@@ -0,0 +1,380 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import re
|
||||||
|
import codecs
|
||||||
|
from collections import OrderedDict
|
||||||
|
from enum import IntEnum, unique
|
||||||
|
|
||||||
|
import fnutil
|
||||||
|
import fncli
|
||||||
|
import fnio
|
||||||
|
import bdf
|
||||||
|
|
||||||
|
# -- Params --
|
||||||
|
class Params(fncli.Params): # pylint: disable=too-many-instance-attributes
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Params.__init__(self)
|
||||||
|
self.ascii_chars = True
|
||||||
|
self.bbx_exceeds = True
|
||||||
|
self.dupl_codes = -1
|
||||||
|
self.extra_bits = True
|
||||||
|
self.attributes = True
|
||||||
|
self.dupl_names = -1
|
||||||
|
self.dupl_props = True
|
||||||
|
self.common_slant = True
|
||||||
|
self.common_weight = True
|
||||||
|
self.xlfd_fontnm = True
|
||||||
|
self.ywidth_zero = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options --
|
||||||
|
HELP = ('' +
|
||||||
|
'usage: bdfcheck [options] [INPUT...]\n' +
|
||||||
|
'Check BDF font(s) for various problems\n' +
|
||||||
|
'\n' +
|
||||||
|
' -A disable non-ascii characters check\n' +
|
||||||
|
' -B disable BBX exceeding FONTBOUNDINGBOX checks\n' +
|
||||||
|
' -c/-C enable/disable duplicate character codes check\n' +
|
||||||
|
' (default = enabled for registry ISO10646)\n' +
|
||||||
|
' -E disable extra bits check\n' +
|
||||||
|
' -I disable ATTRIBUTES check\n' +
|
||||||
|
' -n/-N enable duplicate character names check\n' +
|
||||||
|
' (default = enabled for registry ISO10646)\n' +
|
||||||
|
' -P disable duplicate properties check\n' +
|
||||||
|
' -S disable common slant check\n' +
|
||||||
|
' -W disable common weight check\n' +
|
||||||
|
' -X disable XLFD font name check\n' +
|
||||||
|
' -Y disable zero WIDTH Y check\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'File directives: COMMENT bdfcheck --enable|disable-<check-name>\n' +
|
||||||
|
' (also available as long command line options)\n' +
|
||||||
|
'\n' +
|
||||||
|
'Check names: ascii-chars, bbx-exceeds, duplicate-codes, extra-bits,\n' +
|
||||||
|
' attributes, duplicate-names, duplicate-properties, common-slant,\n' +
|
||||||
|
' common-weight, xlfd-font, ywidth-zero\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input BDF(s) must be v2.1 with unicode encoding.\n')
|
||||||
|
|
||||||
|
VERSION = 'bdfcheck 1.62, Copyright (C) 2017-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE
|
||||||
|
|
||||||
|
class Options(fncli.Options):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Options.__init__(self, [], HELP, VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
def parse(self, name, directive, params):
|
||||||
|
value = name.startswith('--enable') or name[1].islower()
|
||||||
|
|
||||||
|
if name in ['-A', '--enable-ascii-chars', '--disable-ascii-chars']:
|
||||||
|
params.ascii_chars = value
|
||||||
|
elif name in ['-B', '--enable-bbx-exceeds', '--disable-bbx-exceeds']:
|
||||||
|
params.bbx_exceeds = value
|
||||||
|
elif name in ['-c', '-C', '--enable-duplicate-codes', '--disable-duplicate-codes']:
|
||||||
|
params.dupl_codes = value
|
||||||
|
elif name in ['-E', '--enable-extra-bits', '--disable-extra-bits']:
|
||||||
|
params.extra_bits = value
|
||||||
|
elif name in ['-I', '--enable-attributes', '--disable-attributes']:
|
||||||
|
params.attributes = value
|
||||||
|
elif name in ['-n', '-N', '--enable-duplicate-names', '--disable-duplicate-names']:
|
||||||
|
params.dupl_names = value
|
||||||
|
elif name in ['-P', '--enable-duplicate-properties', '--disable-duplicate-properties']:
|
||||||
|
params.dupl_props = value
|
||||||
|
elif name in ['-S', '--enable-common-slant', '--disable-common-slant']:
|
||||||
|
params.common_slant = value
|
||||||
|
elif name in ['-W', '--enable-common-weight', '--disable-common-weight']:
|
||||||
|
params.common_weight = value
|
||||||
|
elif name in ['-X', '--enable-xlfd-font', '--disable-xlfd-font']:
|
||||||
|
params.xlfd_fontnm = value
|
||||||
|
elif name in ['-Y', '--enable-ywidth-zero', '--disable-ywidth-zero']:
|
||||||
|
params.ywidth_zero = value
|
||||||
|
else:
|
||||||
|
return directive is not True and self.fallback(name, params)
|
||||||
|
|
||||||
|
return directive is not True or name.startswith('--')
|
||||||
|
|
||||||
|
|
||||||
|
# -- DupMap --
|
||||||
|
class DupMap(OrderedDict):
|
||||||
|
def __init__(self, prefix, severity, descript, quote):
|
||||||
|
OrderedDict.__init__(self)
|
||||||
|
self.prefix = prefix
|
||||||
|
self.descript = descript
|
||||||
|
self.severity = severity
|
||||||
|
self.quote = quote
|
||||||
|
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
for value, lines in self.items():
|
||||||
|
if len(lines) > 1:
|
||||||
|
text = 'duplicate %s %s at lines' % (self.descript, str(value))
|
||||||
|
|
||||||
|
for index, line in enumerate(lines):
|
||||||
|
text += ' ' if index == 0 else ' and ' if index == len(lines) - 1 else ', '
|
||||||
|
text += str(line)
|
||||||
|
|
||||||
|
fnutil.message(self.prefix, self.severity, text)
|
||||||
|
|
||||||
|
|
||||||
|
def push(self, value, line_no):
|
||||||
|
try:
|
||||||
|
self[value].append(line_no)
|
||||||
|
except KeyError:
|
||||||
|
self[value] = [line_no]
|
||||||
|
|
||||||
|
|
||||||
|
# -- InputFileStream --
|
||||||
|
@unique
|
||||||
|
class MODE(IntEnum):
|
||||||
|
META = 0
|
||||||
|
PROPS = 1
|
||||||
|
BITMAP = 2
|
||||||
|
|
||||||
|
class InputFileStream(fnio.InputFileStream):
|
||||||
|
def __init__(self, file_name, parsed):
|
||||||
|
fnio.InputFileStream.__init__(self, file_name)
|
||||||
|
self.parsed = parsed
|
||||||
|
self.mode = MODE.META
|
||||||
|
self.proplocs = DupMap(self.location(), 'error', 'property', '')
|
||||||
|
self.namelocs = DupMap(self.location(), 'warning', 'character name', '"')
|
||||||
|
self.codelocs = DupMap(self.location(), 'warning', 'encoding', '')
|
||||||
|
self.handlers = [
|
||||||
|
(b'STARTCHAR', lambda value: self.append_name(value)),
|
||||||
|
(b'ENCODING', lambda value: self.append_code(value)),
|
||||||
|
(b'SWIDTH', lambda value: self.check_width('SWIDTH', value, bdf.Width.parse_s)),
|
||||||
|
(b'DWIDTH', lambda value: self.check_width('DWIDTH', value, bdf.Width.parse_d)),
|
||||||
|
(b'BBX', lambda value: self.set_last_box(value)),
|
||||||
|
(b'BITMAP', lambda _: self.set_mode(MODE.BITMAP)),
|
||||||
|
(b'SIZE', InputFileStream.check_size),
|
||||||
|
(b'ATTRIBUTES', lambda value: self.check_attr(value)),
|
||||||
|
(b'STARTPROPERTIES', lambda _: self.set_mode(MODE.PROPS)),
|
||||||
|
(b'FONTBOUNDINGBOX', lambda value: self.set_font_box(value)),
|
||||||
|
]
|
||||||
|
self.xlfd_name = False
|
||||||
|
self.last_box = None
|
||||||
|
self.font_box = None
|
||||||
|
self.options = Options()
|
||||||
|
|
||||||
|
|
||||||
|
def append(self, option, valocs, value):
|
||||||
|
if option:
|
||||||
|
valocs.push(str(value, 'ascii'), self.line_no)
|
||||||
|
|
||||||
|
|
||||||
|
def append_code(self, value):
|
||||||
|
fnutil.parse_dec('encoding', value)
|
||||||
|
self.append(self.parsed.dupl_codes, self.codelocs, value)
|
||||||
|
|
||||||
|
|
||||||
|
def append_name(self, value):
|
||||||
|
self.append(self.parsed.dupl_names, self.namelocs, b'"%s"' % value)
|
||||||
|
|
||||||
|
|
||||||
|
def check_width(self, name, value, parse):
|
||||||
|
if self.parsed.ywidth_zero and parse(name, value).y != 0:
|
||||||
|
fnutil.warning(self.location(), 'non-zero %s Y' % name)
|
||||||
|
|
||||||
|
|
||||||
|
def set_font_box(self, value):
|
||||||
|
self.font_box = bdf.BBX.parse('FONTBOUNDINGBOX', value)
|
||||||
|
|
||||||
|
|
||||||
|
def set_last_box(self, value):
|
||||||
|
bbx = bdf.BBX.parse('BBX', value)
|
||||||
|
|
||||||
|
if self.parsed.bbx_exceeds:
|
||||||
|
exceeds = []
|
||||||
|
|
||||||
|
if bbx.xoff < self.font_box.xoff:
|
||||||
|
exceeds.append('xoff < FONTBOUNDINGBOX xoff')
|
||||||
|
|
||||||
|
if bbx.yoff < self.font_box.yoff:
|
||||||
|
exceeds.append('yoff < FONTBOUNDINGBOX yoff')
|
||||||
|
|
||||||
|
if bbx.width > self.font_box.width:
|
||||||
|
exceeds.append('width > FONTBOUNDINGBOX width')
|
||||||
|
|
||||||
|
if bbx.height > self.font_box.height:
|
||||||
|
exceeds.append('height > FONTBOUNDINGBOX height')
|
||||||
|
|
||||||
|
for exceed in exceeds:
|
||||||
|
fnutil.message(self.location(), '', exceed)
|
||||||
|
|
||||||
|
self.last_box = bbx
|
||||||
|
|
||||||
|
|
||||||
|
def set_mode(self, new_mode):
|
||||||
|
self.mode = new_mode
|
||||||
|
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
self.process(bdf.Font.read)
|
||||||
|
self.proplocs.check()
|
||||||
|
self.namelocs.check()
|
||||||
|
self.codelocs.check()
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_size(value):
|
||||||
|
words = fnutil.split_words('SIZE', value, 3)
|
||||||
|
fnutil.parse_dec('point size', words[0], 1, None)
|
||||||
|
fnutil.parse_dec('x resolution', words[1], 1, None)
|
||||||
|
fnutil.parse_dec('y resolution', words[2], 1, None)
|
||||||
|
|
||||||
|
|
||||||
|
def check_attr(self, value):
|
||||||
|
if not re.fullmatch(br'[\dA-Fa-f]{4}', value):
|
||||||
|
raise Exception('ATTRIBUTES must be 4 hex-encoded characters')
|
||||||
|
|
||||||
|
if self.parsed.attributes:
|
||||||
|
fnutil.warning(self.location(), 'ATTRIBUTES may cause problems with freetype')
|
||||||
|
|
||||||
|
|
||||||
|
def check_font(self, value):
|
||||||
|
xlfd = value[4:].lstrip().split(b'-', 15)
|
||||||
|
|
||||||
|
if len(xlfd) == 15 and xlfd[0] == b'':
|
||||||
|
unicode = (xlfd[bdf.XLFD.CHARSET_REGISTRY].upper() == b'ISO10646')
|
||||||
|
|
||||||
|
if self.parsed.dupl_codes == -1:
|
||||||
|
self.parsed.dupl_codes = unicode
|
||||||
|
|
||||||
|
if self.parsed.dupl_names == -1:
|
||||||
|
self.parsed.dupl_names = unicode
|
||||||
|
|
||||||
|
if self.parsed.common_weight:
|
||||||
|
weight = str(xlfd[bdf.XLFD.WEIGHT_NAME], 'ascii')
|
||||||
|
compare = weight.lower()
|
||||||
|
consider = 'Bold' if 'bold' in compare else 'Normal'
|
||||||
|
|
||||||
|
if compare in ['medium', 'regular']:
|
||||||
|
compare = 'normal'
|
||||||
|
|
||||||
|
if compare != consider.lower():
|
||||||
|
fnutil.warning(self.location(), 'weight "%s" may be considered %s' % (weight, consider))
|
||||||
|
|
||||||
|
if self.parsed.common_slant:
|
||||||
|
slant = str(xlfd[bdf.XLFD.SLANT], 'ascii')
|
||||||
|
consider = 'Italic' if re.search('^[IO]', slant) else 'Regular'
|
||||||
|
|
||||||
|
if not re.fullmatch('[IOR]', slant):
|
||||||
|
fnutil.warning(self.location(), 'slant "%s" may be considered %s' % (slant, consider))
|
||||||
|
|
||||||
|
else:
|
||||||
|
if self.parsed.xlfd_fontnm:
|
||||||
|
fnutil.warning(self.location(), 'non-XLFD font name')
|
||||||
|
|
||||||
|
value = b'FONT --------------'
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def check_prop(self, line):
|
||||||
|
match = re.fullmatch(br'(\w+)\s+([-\d"].*)', line)
|
||||||
|
|
||||||
|
if not match:
|
||||||
|
raise Exception('invalid property format')
|
||||||
|
|
||||||
|
name = match.group(1)
|
||||||
|
value = match.group(2)
|
||||||
|
|
||||||
|
if value.startswith(b'"'):
|
||||||
|
if len(value) < 2 or not value.endswith(b'"'):
|
||||||
|
raise Exception('no closing double quote')
|
||||||
|
if re.search(b'[^"]"[^"]', value[1 : len(value) - 1]):
|
||||||
|
raise Exception('unescaped double quote')
|
||||||
|
else:
|
||||||
|
fnutil.parse_dec('value', value, None, None)
|
||||||
|
|
||||||
|
self.append(self.parsed.dupl_props, self.proplocs, name)
|
||||||
|
return b'P%d 1' % self.line_no
|
||||||
|
|
||||||
|
|
||||||
|
def check_bitmap(self, line):
|
||||||
|
if len(line) != self.last_box.row_size() * 2:
|
||||||
|
raise Exception('invalid bitmap length')
|
||||||
|
|
||||||
|
data = codecs.decode(line, 'hex')
|
||||||
|
|
||||||
|
if self.parsed.extra_bits:
|
||||||
|
check_x = (self.last_box.width - 1) | 7
|
||||||
|
last_byte = data[len(data) - 1]
|
||||||
|
bit_no = 7 - (self.last_box.width & 7)
|
||||||
|
|
||||||
|
for x in range(self.last_box.width, check_x + 1):
|
||||||
|
if last_byte & (1 << bit_no):
|
||||||
|
fnutil.warning(self.location(), 'extra bit(s) starting with x=%d' % x)
|
||||||
|
break
|
||||||
|
bit_no -= 1
|
||||||
|
|
||||||
|
|
||||||
|
def check_line(self, line):
|
||||||
|
if re.search(b'[^\t\f\v\x20-\xff]', line):
|
||||||
|
raise Exception('control character(s)')
|
||||||
|
|
||||||
|
if self.parsed.ascii_chars and re.search(b'[\x7f-\xff]', line):
|
||||||
|
fnutil.warning(self.location(), 'non-ascii character(s)')
|
||||||
|
|
||||||
|
if self.mode == MODE.META:
|
||||||
|
if not self.xlfd_name and line.startswith(b'FONT'):
|
||||||
|
line = self.check_font(line)
|
||||||
|
self.xlfd_name = True
|
||||||
|
else:
|
||||||
|
for handler in self.handlers:
|
||||||
|
if line.startswith(handler[0]):
|
||||||
|
handler[1](line[len(handler[0]):].lstrip())
|
||||||
|
break
|
||||||
|
elif self.mode == MODE.PROPS:
|
||||||
|
if line.startswith(b'ENDPROPERTIES'):
|
||||||
|
self.mode = MODE.META
|
||||||
|
else:
|
||||||
|
line = self.check_prop(line)
|
||||||
|
else: # MODE.BITMAP
|
||||||
|
if line.startswith(b'ENDCHAR'):
|
||||||
|
self.mode = MODE.META
|
||||||
|
else:
|
||||||
|
self.check_bitmap(line)
|
||||||
|
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
def read_check(self, line, callback):
|
||||||
|
match = re.search(br'^COMMENT\s*bdfcheck\s+(-.*)$', line)
|
||||||
|
|
||||||
|
if match and not self.options.parse(str(match[1], 'ascii'), True, self.parsed):
|
||||||
|
raise Exception('invalid bdfcheck directive')
|
||||||
|
|
||||||
|
line = callback(line)
|
||||||
|
return self.check_line(line) if line is not None else None
|
||||||
|
|
||||||
|
|
||||||
|
def read_lines(self, callback):
|
||||||
|
return fnio.InputFileStream.read_lines(self, lambda line: self.read_check(line, callback))
|
||||||
|
|
||||||
|
|
||||||
|
# -- Main --
|
||||||
|
def main_program(nonopt, parsed):
|
||||||
|
for input_name in nonopt or [None]:
|
||||||
|
InputFileStream(input_name, parsed).check()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fncli.start('bdfcheck.py', Options(), Params(), main_program)
|
||||||
@@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
const fncli = require('./fncli.js');
|
||||||
|
const fnio = require('./fnio.js');
|
||||||
|
const bdf = require('./bdf.js');
|
||||||
|
|
||||||
|
// -- Font --
|
||||||
|
class Font extends bdf.Font {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.minWidth = 0; // used in proportional()
|
||||||
|
this.avgWidth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_expand(char) {
|
||||||
|
if (char.dwidth.x >= 0) {
|
||||||
|
if (char.bbx.xoff >= 0) {
|
||||||
|
var width = Math.max(char.bbx.xoff + char.bbx.width, char.dwidth.x);
|
||||||
|
var dstXOff = char.bbx.xoff;
|
||||||
|
var expXOff = 0;
|
||||||
|
} else {
|
||||||
|
width = Math.max(char.bbx.width, char.dwidth.x - char.bbx.xoff);
|
||||||
|
dstXOff = 0;
|
||||||
|
expXOff = char.bbx.xoff;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const revXOff = char.bbx.xoff + char.bbx.width;
|
||||||
|
|
||||||
|
if (revXOff <= 0) {
|
||||||
|
width = -Math.min(char.dwidth.x, char.bbx.xoff);
|
||||||
|
dstXOff = width + char.bbx.xoff;
|
||||||
|
expXOff = -width;
|
||||||
|
} else {
|
||||||
|
width = Math.max(char.bbx.width, revXOff - char.dwidth.x);
|
||||||
|
dstXOff = width - char.bbx.width;
|
||||||
|
expXOff = revXOff - width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const height = this.bbx.height;
|
||||||
|
|
||||||
|
if (width === char.bbx.width && height === char.bbx.height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const srcRowSize = char.bbx.rowSize();
|
||||||
|
const dstRowSize = (width + 7) >> 3;
|
||||||
|
const dstYMax = this.pxAscender - char.bbx.yoff;
|
||||||
|
const dstYMin = dstYMax - char.bbx.height;
|
||||||
|
const copyRow = (dstXOff & 7) === 0;
|
||||||
|
const dstData = Buffer.alloc(dstRowSize * height);
|
||||||
|
|
||||||
|
for (let dstY = dstYMin; dstY < dstYMax; dstY++) {
|
||||||
|
let srcByteNo = (dstY - dstYMin) * srcRowSize;
|
||||||
|
let dstByteNo = dstY * dstRowSize + (dstXOff >> 3);
|
||||||
|
|
||||||
|
if (copyRow) {
|
||||||
|
char.data.copy(dstData, dstByteNo, srcByteNo, srcByteNo + srcRowSize);
|
||||||
|
} else {
|
||||||
|
let srcBitNo = 7;
|
||||||
|
let dstBitNo = 7 - (dstXOff & 7);
|
||||||
|
|
||||||
|
for (let x = 0; x < char.bbx.width; x++) {
|
||||||
|
if (char.data[srcByteNo] & (1 << srcBitNo)) {
|
||||||
|
dstData[dstByteNo] |= (1 << dstBitNo);
|
||||||
|
}
|
||||||
|
if (--srcBitNo < 0) {
|
||||||
|
srcBitNo = 7;
|
||||||
|
srcByteNo++;
|
||||||
|
}
|
||||||
|
if (--dstBitNo < 0) {
|
||||||
|
dstBitNo = 7;
|
||||||
|
dstByteNo++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char.bbx = new bdf.BBX(width, height, expXOff, this.bbx.yoff);
|
||||||
|
char.props.set('BBX', char.bbx);
|
||||||
|
char.data = dstData;
|
||||||
|
}
|
||||||
|
|
||||||
|
expand() {
|
||||||
|
// PREXPAND / VERTICAL
|
||||||
|
const ascent = this.props.get('FONT_ASCENT');
|
||||||
|
const descent = this.props.get('FONT_DESCENT');
|
||||||
|
let pxAscent = (ascent == null ? 0 : fnutil.parseDec('FONT_ASCENT', ascent, 0, bdf.DPARSE_LIMIT));
|
||||||
|
let pxDescent = (descent == null ? 0 : fnutil.parseDec('FONT_DESCENT', descent, 0, bdf.DPARSE_LIMIT));
|
||||||
|
|
||||||
|
this.chars.forEach(char => {
|
||||||
|
pxAscent = Math.max(pxAscent, char.bbx.height + char.bbx.yoff);
|
||||||
|
pxDescent = Math.max(pxDescent, -char.bbx.yoff);
|
||||||
|
});
|
||||||
|
this.bbx.height = pxAscent + pxDescent;
|
||||||
|
this.bbx.yoff = -pxDescent;
|
||||||
|
|
||||||
|
// EXPAND / HORIZONTAL
|
||||||
|
let totalWidth = 0;
|
||||||
|
|
||||||
|
this.minWidth = this.chars[0].bbx.width;
|
||||||
|
this.chars.forEach(char => {
|
||||||
|
this._expand(char);
|
||||||
|
this.minWidth = Math.min(this.minWidth, char.bbx.width);
|
||||||
|
this.bbx.width = Math.max(this.bbx.width, char.bbx.width);
|
||||||
|
this.bbx.xoff = Math.min(this.bbx.xoff, char.bbx.xoff);
|
||||||
|
totalWidth += char.bbx.width;
|
||||||
|
});
|
||||||
|
this.avgWidth = fnutil.round(totalWidth / this.chars.length);
|
||||||
|
this.props.set('FONTBOUNDINGBOX', this.bbx);
|
||||||
|
}
|
||||||
|
|
||||||
|
expandX() {
|
||||||
|
this.chars.forEach(char => {
|
||||||
|
if (char.dwidth.x !== char.bbx.width) { // preserve SWIDTH if possible
|
||||||
|
char.swidth.x = fnutil.round(char.bbx.width * 1000 / this.bbx.height);
|
||||||
|
char.props.set('SWIDTH', char.swidth);
|
||||||
|
char.dwidth.x = char.bbx.width;
|
||||||
|
char.props.set('DWIDTH', char.dwidth);
|
||||||
|
}
|
||||||
|
char.bbx.xoff = 0;
|
||||||
|
char.props.set('BBX', char.bbx);
|
||||||
|
});
|
||||||
|
this.bbx.xoff = 0;
|
||||||
|
this.props.set('FONTBOUNDINGBOX', this.bbx);
|
||||||
|
}
|
||||||
|
|
||||||
|
expandY() {
|
||||||
|
const props = new Map([
|
||||||
|
[ 'FONT_ASCENT', this.pxAscender ],
|
||||||
|
[ 'FONT_DESCENT', -this.pxDescender ],
|
||||||
|
[ 'PIXEL_SIZE', this.bbx.height ]
|
||||||
|
]);
|
||||||
|
|
||||||
|
props.forEach((value, name) => {
|
||||||
|
if (this.props.get(name) != null) {
|
||||||
|
this.props.set(name, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.xlfd[bdf.XLFD.PIXEL_SIZE] = this.bbx.height.toString();
|
||||||
|
this.props.set('FONT', this.xlfd.join('-'));
|
||||||
|
}
|
||||||
|
|
||||||
|
get proportional() {
|
||||||
|
return this.bbx.width > this.minWidth || super.proportional;
|
||||||
|
}
|
||||||
|
|
||||||
|
get pxAscender() {
|
||||||
|
return this.bbx.height + this.bbx.yoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
get pxDescender() {
|
||||||
|
return this.bbx.yoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
_read(input) {
|
||||||
|
super._read(input);
|
||||||
|
this.expand();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static read(input) {
|
||||||
|
return (new Font())._read(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateProp(name, value) {
|
||||||
|
if (this.props.get(name) != null) {
|
||||||
|
this.props.set(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Export --
|
||||||
|
module.exports = Object.freeze({
|
||||||
|
Font
|
||||||
|
});
|
||||||
|
|
||||||
|
// -- Params --
|
||||||
|
class Params extends fncli.Params {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.expandX = false;
|
||||||
|
this.expandY = false;
|
||||||
|
this.output = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Options --
|
||||||
|
const HELP = ('' +
|
||||||
|
'usage: bdfexp [-X] [-Y] [-o OUTPUT] [INPUT]\n' +
|
||||||
|
'Expand BDF font bitmaps\n' +
|
||||||
|
'\n' +
|
||||||
|
' -X zero xoffs, set character S/DWIDTH.X from the output\n' +
|
||||||
|
' BBX.width if needed\n' +
|
||||||
|
' -Y enlarge FONT_ASCENT, FONT_DESCENT and PIXEL_SIZE to\n' +
|
||||||
|
' cover the font bounding box, if needed\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout)\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input must be a BDF 2.1 font with unicode encoding.\n');
|
||||||
|
|
||||||
|
const VERSION = 'bdfexp 1.60, Copyright (C) 2017-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE;
|
||||||
|
|
||||||
|
class Options extends fncli.Options {
|
||||||
|
constructor() {
|
||||||
|
super(['-o'], HELP, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(name, value, params) {
|
||||||
|
switch (name) {
|
||||||
|
case '-X':
|
||||||
|
params.expandX = true;
|
||||||
|
break;
|
||||||
|
case '-Y':
|
||||||
|
params.expandY = true;
|
||||||
|
break;
|
||||||
|
case '-o':
|
||||||
|
params.output = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.fallback(name, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Main --
|
||||||
|
function mainProgram(nonopt, parsed) {
|
||||||
|
if (nonopt.length > 1) {
|
||||||
|
throw new Error('invalid number of arguments, try --help');
|
||||||
|
}
|
||||||
|
|
||||||
|
// READ INPUT
|
||||||
|
let ifs = new fnio.InputFileStream(nonopt[0]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var font = Font.read(ifs);
|
||||||
|
ifs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXTRA ACTIONS
|
||||||
|
if (parsed.expandX) {
|
||||||
|
font.expandX();
|
||||||
|
}
|
||||||
|
if (parsed.expandY) {
|
||||||
|
font.expandY();
|
||||||
|
}
|
||||||
|
|
||||||
|
// WRITE OUTPUT
|
||||||
|
let ofs = new fnio.OutputFileStream(parsed.output);
|
||||||
|
|
||||||
|
try {
|
||||||
|
font.write(ofs);
|
||||||
|
ofs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ofs.location() + e.message() + ofs.destroy();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
fncli.start('bdfexp.js', new Options(), new Params(), mainProgram);
|
||||||
|
}
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
import fnutil
|
||||||
|
import fncli
|
||||||
|
import fnio
|
||||||
|
import bdf
|
||||||
|
|
||||||
|
# -- Font --
|
||||||
|
class Font(bdf.Font):
|
||||||
|
def __init__(self):
|
||||||
|
bdf.Font.__init__(self)
|
||||||
|
self.min_width = 0 # used in proportional()
|
||||||
|
self.avg_width = 0
|
||||||
|
|
||||||
|
|
||||||
|
def _expand(self, char):
|
||||||
|
if char.dwidth.x >= 0:
|
||||||
|
if char.bbx.xoff >= 0:
|
||||||
|
width = max(char.bbx.xoff + char.bbx.width, char.dwidth.x)
|
||||||
|
dst_xoff = char.bbx.xoff
|
||||||
|
exp_xoff = 0
|
||||||
|
else:
|
||||||
|
width = max(char.bbx.width, char.dwidth.x - char.bbx.xoff)
|
||||||
|
dst_xoff = 0
|
||||||
|
exp_xoff = char.bbx.xoff
|
||||||
|
else:
|
||||||
|
rev_xoff = char.bbx.xoff + char.bbx.width
|
||||||
|
|
||||||
|
if rev_xoff <= 0:
|
||||||
|
width = -min(char.dwidth.x, char.bbx.xoff)
|
||||||
|
dst_xoff = width + char.bbx.xoff
|
||||||
|
exp_xoff = -width
|
||||||
|
else:
|
||||||
|
width = max(char.bbx.width, rev_xoff - char.dwidth.x)
|
||||||
|
dst_xoff = width - char.bbx.width
|
||||||
|
exp_xoff = rev_xoff - width
|
||||||
|
|
||||||
|
height = self.bbx.height
|
||||||
|
|
||||||
|
if width == char.bbx.width and height == char.bbx.height:
|
||||||
|
return
|
||||||
|
|
||||||
|
src_row_size = char.bbx.row_size()
|
||||||
|
dst_row_size = (width + 7) >> 3
|
||||||
|
dst_ymax = self.px_ascender - char.bbx.yoff
|
||||||
|
dst_ymin = dst_ymax - char.bbx.height
|
||||||
|
copy_row = (dst_xoff & 7) == 0
|
||||||
|
dst_data = bytearray(dst_row_size * height)
|
||||||
|
|
||||||
|
for dst_y in range(dst_ymin, dst_ymax):
|
||||||
|
src_byte_no = (dst_y - dst_ymin) * src_row_size
|
||||||
|
dst_byte_no = dst_y * dst_row_size + (dst_xoff >> 3)
|
||||||
|
|
||||||
|
if copy_row:
|
||||||
|
dst_data[dst_byte_no : dst_byte_no + src_row_size] = \
|
||||||
|
char.data[src_byte_no : src_byte_no + src_row_size]
|
||||||
|
else:
|
||||||
|
src_bit_no = 7
|
||||||
|
dst_bit_no = 7 - (dst_xoff & 7)
|
||||||
|
|
||||||
|
for _ in range(0, char.bbx.width):
|
||||||
|
if char.data[src_byte_no] & (1 << src_bit_no):
|
||||||
|
dst_data[dst_byte_no] |= (1 << dst_bit_no)
|
||||||
|
|
||||||
|
if src_bit_no > 0:
|
||||||
|
src_bit_no -= 1
|
||||||
|
else:
|
||||||
|
src_bit_no = 7
|
||||||
|
src_byte_no += 1
|
||||||
|
|
||||||
|
if dst_bit_no > 0:
|
||||||
|
dst_bit_no -= 1
|
||||||
|
else:
|
||||||
|
dst_bit_no = 7
|
||||||
|
dst_byte_no += 1
|
||||||
|
|
||||||
|
char.bbx = bdf.BBX(width, height, exp_xoff, self.bbx.yoff)
|
||||||
|
char.props.set('BBX', char.bbx)
|
||||||
|
char.data = dst_data
|
||||||
|
|
||||||
|
|
||||||
|
def expand(self):
|
||||||
|
# PREXPAND / VERTICAL
|
||||||
|
ascent = self.props.get('FONT_ASCENT')
|
||||||
|
descent = self.props.get('FONT_DESCENT')
|
||||||
|
px_ascent = 0 if ascent is None else fnutil.parse_dec('FONT_ASCENT', ascent, 0, bdf.DPARSE_LIMIT)
|
||||||
|
px_descent = 0 if descent is None else fnutil.parse_dec('FONT_DESCENT', descent, 0, bdf.DPARSE_LIMIT)
|
||||||
|
|
||||||
|
for char in self.chars:
|
||||||
|
px_ascent = max(px_ascent, char.bbx.height + char.bbx.yoff)
|
||||||
|
px_descent = max(px_descent, -char.bbx.yoff)
|
||||||
|
|
||||||
|
self.bbx.height = px_ascent + px_descent
|
||||||
|
self.bbx.yoff = -px_descent
|
||||||
|
|
||||||
|
# EXPAND / HORIZONTAL
|
||||||
|
total_width = 0
|
||||||
|
self.min_width = self.chars[0].bbx.width
|
||||||
|
|
||||||
|
for char in self.chars:
|
||||||
|
self._expand(char)
|
||||||
|
self.min_width = min(self.min_width, char.bbx.width)
|
||||||
|
self.bbx.width = max(self.bbx.width, char.bbx.width)
|
||||||
|
self.bbx.xoff = min(self.bbx.xoff, char.bbx.xoff)
|
||||||
|
total_width += char.bbx.width
|
||||||
|
|
||||||
|
self.avg_width = round(total_width / len(self.chars))
|
||||||
|
self.props.set('FONTBOUNDINGBOX', self.bbx)
|
||||||
|
|
||||||
|
|
||||||
|
def expand_x(self):
|
||||||
|
for char in self.chars:
|
||||||
|
if char.dwidth.x != char.bbx.width:
|
||||||
|
char.swidth.x = round(char.bbx.width * 1000 / self.bbx.height)
|
||||||
|
char.props.set('SWIDTH', char.swidth)
|
||||||
|
char.dwidth.x = char.bbx.width
|
||||||
|
char.props.set('DWIDTH', char.dwidth)
|
||||||
|
|
||||||
|
char.bbx.xoff = 0
|
||||||
|
char.props.set('BBX', char.bbx)
|
||||||
|
|
||||||
|
self.bbx.xoff = 0
|
||||||
|
self.props.set('FONTBOUNDINGBOX', self.bbx)
|
||||||
|
|
||||||
|
|
||||||
|
def expand_y(self):
|
||||||
|
props = OrderedDict((
|
||||||
|
('FONT_ASCENT', self.px_ascender),
|
||||||
|
('FONT_DESCENT', -self.px_descender),
|
||||||
|
('PIXEL_SIZE', self.bbx.height)
|
||||||
|
))
|
||||||
|
|
||||||
|
for [name, value] in props.items():
|
||||||
|
if self.props.get(name) is not None:
|
||||||
|
self.props.set(name, value)
|
||||||
|
|
||||||
|
self.xlfd[bdf.XLFD.PIXEL_SIZE] = bytes(str(self.bbx.height), 'ascii')
|
||||||
|
self.props.set('FONT', b'-'.join(self.xlfd))
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def proportional(self):
|
||||||
|
return self.bbx.width > self.min_width or bdf.Font.proportional.fget(self) # pylint: disable=no-member
|
||||||
|
|
||||||
|
@property
|
||||||
|
def px_ascender(self):
|
||||||
|
return self.bbx.height + self.bbx.yoff
|
||||||
|
|
||||||
|
@property
|
||||||
|
def px_descender(self):
|
||||||
|
return self.bbx.yoff
|
||||||
|
|
||||||
|
|
||||||
|
def _read(self, input):
|
||||||
|
bdf.Font._read(self, input)
|
||||||
|
self.expand()
|
||||||
|
return self
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def read(input):
|
||||||
|
return Font()._read(input) # pylint: disable=protected-access
|
||||||
|
|
||||||
|
|
||||||
|
# -- Params --
|
||||||
|
class Params(fncli.Params):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Params.__init__(self)
|
||||||
|
self.expand_x = False
|
||||||
|
self.expand_y = False
|
||||||
|
self.output_name = None
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options --
|
||||||
|
HELP = ('' +
|
||||||
|
'usage: bdfexp [-X] [-Y] [-o OUTPUT] [INPUT]\n' +
|
||||||
|
'Expand BDF font bitmaps\n' +
|
||||||
|
'\n' +
|
||||||
|
' -X zero xoffs, set character S/DWIDTH.X from the output\n' +
|
||||||
|
' BBX.width if needed\n' +
|
||||||
|
' -Y enlarge FONT_ASCENT, FONT_DESCENT and PIXEL_SIZE to\n' +
|
||||||
|
' cover the font bounding box, if needed\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout)\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input must be a BDF 2.1 font with unicode encoding.\n')
|
||||||
|
|
||||||
|
VERSION = 'bdfexp 1.62, Copyright (C) 2017-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE
|
||||||
|
|
||||||
|
class Options(fncli.Options):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Options.__init__(self, ['-o'], HELP, VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
def parse(self, name, value, params):
|
||||||
|
if name == '-X':
|
||||||
|
params.expand_x = True
|
||||||
|
elif name == '-Y':
|
||||||
|
params.expand_y = True
|
||||||
|
elif name == '-o':
|
||||||
|
params.output_name = value
|
||||||
|
else:
|
||||||
|
self.fallback(name, params)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Main --
|
||||||
|
def main_program(nonopt, parsed):
|
||||||
|
if len(nonopt) > 1:
|
||||||
|
raise Exception('invalid number of arguments, try --help')
|
||||||
|
|
||||||
|
# READ INPUT
|
||||||
|
font = fnio.read_file(nonopt[0] if nonopt else None, Font.read)
|
||||||
|
|
||||||
|
# EXTRA ACTIONS
|
||||||
|
if parsed.expand_x:
|
||||||
|
font.expand_x()
|
||||||
|
|
||||||
|
if parsed.expand_y:
|
||||||
|
font.expand_y()
|
||||||
|
|
||||||
|
# WRITE OUTPUT
|
||||||
|
fnio.write_file(parsed.output_name, lambda ofs: font.write(ofs))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fncli.start('bdfexp.py', Options(), Params(), main_program)
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
const fncli = require('./fncli.js');
|
||||||
|
const fnio = require('./fnio.js');
|
||||||
|
const bdf = require('./bdf.js');
|
||||||
|
const bdfexp = require('./bdfexp.js');
|
||||||
|
|
||||||
|
// -- Params --
|
||||||
|
class Params extends fncli.Params {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.charSet = -1;
|
||||||
|
this.minChar = -1;
|
||||||
|
this.fntFamily = 0;
|
||||||
|
this.output = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Options --
|
||||||
|
const HELP = ('' +
|
||||||
|
'usage: bdftofnt [-c CHARSET] [-m MINCHAR] [-f FAMILY] [-o OUTPUT] [INPUT]\n' +
|
||||||
|
'Convert a BDF font to Windows FNT\n' +
|
||||||
|
'\n' +
|
||||||
|
' -c CHARSET fnt character set (default = 0, see wingdi.h ..._CHARSET)\n' +
|
||||||
|
' -m MINCHAR fnt minimum character code (8-bit CP decimal, not unicode)\n' +
|
||||||
|
' -f FAMILY fnt family: DontCare, Roman, Swiss, Modern or Decorative\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout, may not be a terminal)\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input must be a BDF 2.1 font with unicode encoding.\n');
|
||||||
|
|
||||||
|
const VERSION = 'bdftofnt 1.60, Copyright (C) 2017-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE;
|
||||||
|
|
||||||
|
const FNT_FAMILIES = [ 'DontCare', 'Roman', 'Swiss', 'Modern', 'Decorative' ];
|
||||||
|
|
||||||
|
class Options extends fncli.Options {
|
||||||
|
constructor() {
|
||||||
|
super(['-c', '-m', '-f', '-o'], HELP, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(name, value, params) {
|
||||||
|
switch (name) {
|
||||||
|
case '-c':
|
||||||
|
params.charSet = fnutil.parseDec('CHARSET', value, 0, 255);
|
||||||
|
break;
|
||||||
|
case '-m':
|
||||||
|
params.minChar = fnutil.parseDec('MINCHAR', value, 0, 255);
|
||||||
|
break;
|
||||||
|
case '-f':
|
||||||
|
params.fntFamily = FNT_FAMILIES.indexOf(value);
|
||||||
|
|
||||||
|
if (params.fntFamily === -1) {
|
||||||
|
throw new Error('invalid FAMILY');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '-o':
|
||||||
|
params.output = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.fallback(name, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Main --
|
||||||
|
const FNT_HEADER_SIZE = 118;
|
||||||
|
const FNT_CHARSETS = [238, 204, 0, 161, 162, 177, 178, 186, 163];
|
||||||
|
|
||||||
|
function mainProgram(nonopt, parsed) {
|
||||||
|
if (nonopt.length > 1) {
|
||||||
|
throw new Error('invalid number of arguments, try --help');
|
||||||
|
}
|
||||||
|
|
||||||
|
let charSet = parsed.charSet;
|
||||||
|
let minChar = parsed.minChar;
|
||||||
|
|
||||||
|
// READ INPUT
|
||||||
|
let ifs = new fnio.InputFileStream(nonopt[0]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var font = bdfexp.Font.read(ifs);
|
||||||
|
ifs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// COMPUTE
|
||||||
|
if (charSet === -1) {
|
||||||
|
const encoding = font.xlfd[bdf.XLFD.CHARSET_ENCODING];
|
||||||
|
|
||||||
|
if (encoding.toLowerCase().match(/^(cp)?125[0-8]$/)) {
|
||||||
|
charSet = FNT_CHARSETS[parseInt(encoding.substring(encoding.length - 1), 10)];
|
||||||
|
} else {
|
||||||
|
charSet = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const numChars = font.chars.length;
|
||||||
|
|
||||||
|
if (numChars > 256) {
|
||||||
|
throw new Error('too many characters, the maximum is 256');
|
||||||
|
}
|
||||||
|
if (minChar === -1) {
|
||||||
|
if (numChars === 192 || numChars === 256) {
|
||||||
|
minChar = 256 - numChars;
|
||||||
|
} else {
|
||||||
|
minChar = font.chars[0].code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxChar = minChar + numChars - 1;
|
||||||
|
|
||||||
|
if (maxChar >= 256) {
|
||||||
|
throw new Error('the maximum character code is too big, (re)specify -m');
|
||||||
|
}
|
||||||
|
|
||||||
|
// HEADER
|
||||||
|
var vtell = FNT_HEADER_SIZE + (numChars + 1) * 4;
|
||||||
|
var bitsOffset = vtell;
|
||||||
|
var ctable = [];
|
||||||
|
var widthBytes = 0;
|
||||||
|
|
||||||
|
// CTABLE/GLYPHS
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
const rowSize = char.bbx.rowSize();
|
||||||
|
|
||||||
|
ctable.push(char.bbx.width);
|
||||||
|
ctable.push(vtell);
|
||||||
|
vtell += rowSize * font.bbx.height;
|
||||||
|
widthBytes += rowSize;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (vtell > 0xFFFF) {
|
||||||
|
throw new Error('too much character data');
|
||||||
|
}
|
||||||
|
|
||||||
|
// SENTINEL
|
||||||
|
var sentinel = 2 - widthBytes % 2;
|
||||||
|
|
||||||
|
ctable.push(sentinel * 8);
|
||||||
|
ctable.push(vtell);
|
||||||
|
vtell += sentinel * font.bbx.height;
|
||||||
|
widthBytes += sentinel;
|
||||||
|
|
||||||
|
if (widthBytes > 0xFFFF) {
|
||||||
|
throw new Error('the total character width is too big');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WRITE
|
||||||
|
let ofs = new fnio.OutputFileStream(parsed.output, null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// HEADER
|
||||||
|
const family = font.xlfd[bdf.XLFD.FAMILY_NAME];
|
||||||
|
let copyright = font.props.get('COPYRIGHT');
|
||||||
|
|
||||||
|
copyright = (copyright != null) ? fnutil.unquote(copyright).substring(0, 60) : '';
|
||||||
|
ofs.write16(0x0200); // font version
|
||||||
|
ofs.write32(vtell + family.length + 1); // total size
|
||||||
|
ofs.writeZStr(copyright, 60 - copyright.length);
|
||||||
|
ofs.write16(0); // gdi, device type
|
||||||
|
ofs.write16(fnutil.round(font.bbx.height * 72 / 96));
|
||||||
|
ofs.write16(96); // vertical resolution
|
||||||
|
ofs.write16(96); // horizontal resolution
|
||||||
|
ofs.write16(font.pxAscender); // base line
|
||||||
|
ofs.write16(0); // internal leading
|
||||||
|
ofs.write16(0); // external leading
|
||||||
|
ofs.write8(Number(font.italic));
|
||||||
|
ofs.write8(0); // underline
|
||||||
|
ofs.write8(0); // strikeout
|
||||||
|
ofs.write16(font.bold ? 700 : 400);
|
||||||
|
ofs.write8(charSet);
|
||||||
|
ofs.write16(font.proportional ? 0 : font.bbx.width);
|
||||||
|
ofs.write16(font.bbx.height);
|
||||||
|
ofs.write8((parsed.fntFamily << 4) + Number(font.proportional));
|
||||||
|
ofs.write16(font.avgWidth);
|
||||||
|
ofs.write16(font.bbx.width);
|
||||||
|
ofs.write8(minChar);
|
||||||
|
ofs.write8(maxChar);
|
||||||
|
|
||||||
|
let defaultIndex = maxChar - minChar;
|
||||||
|
let breakIndex = 0;
|
||||||
|
|
||||||
|
if (font.defaultCode !== -1) {
|
||||||
|
defaultIndex = font.chars.findIndex(char => char.code === font.defaultCode);
|
||||||
|
}
|
||||||
|
if (minChar <= 0x20 && maxChar >= 0x20) {
|
||||||
|
breakIndex = 0x20 - minChar;
|
||||||
|
}
|
||||||
|
ofs.write8(defaultIndex);
|
||||||
|
ofs.write8(breakIndex);
|
||||||
|
ofs.write16(widthBytes);
|
||||||
|
ofs.write32(0); // device name
|
||||||
|
ofs.write32(vtell);
|
||||||
|
ofs.write32(0); // gdi bits pointer
|
||||||
|
ofs.write32(bitsOffset);
|
||||||
|
ofs.write8(0); // reserved
|
||||||
|
|
||||||
|
// CTABLE
|
||||||
|
ctable.forEach(value => ofs.write16(value));
|
||||||
|
|
||||||
|
// GLYPHS
|
||||||
|
const data = Buffer.alloc(font.bbx.height * font.bbx.rowSize());
|
||||||
|
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
const rowSize = char.bbx.rowSize();
|
||||||
|
let counter = 0;
|
||||||
|
// MS coordinates
|
||||||
|
for (let n = 0; n < rowSize; n++) {
|
||||||
|
for (let y = 0; y < font.bbx.height; y++) {
|
||||||
|
data[counter++] = char.data[rowSize * y + n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ofs.write(data.slice(0, counter));
|
||||||
|
});
|
||||||
|
ofs.write(Buffer.alloc(sentinel * font.bbx.height));
|
||||||
|
|
||||||
|
// FAMILY
|
||||||
|
ofs.writeZStr(family, 1);
|
||||||
|
ofs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ofs.location() + e.message + ofs.destroy();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
fncli.start('bdftofnt.js', new Options(), new Params(), mainProgram);
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
import fnutil
|
||||||
|
import fncli
|
||||||
|
import fnio
|
||||||
|
import bdf
|
||||||
|
import bdfexp
|
||||||
|
|
||||||
|
# -- Params --
|
||||||
|
class Params(fncli.Params):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Params.__init__(self)
|
||||||
|
self.char_set = -1
|
||||||
|
self.min_char = -1
|
||||||
|
self.fnt_family = 0
|
||||||
|
self.output_name = None
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options --
|
||||||
|
HELP = ('' +
|
||||||
|
'usage: bdftofnt [-c CHARSET] [-m MINCHAR] [-f FAMILY] [-o OUTPUT] [INPUT]\n' +
|
||||||
|
'Convert a BDF font to Windows FNT\n' +
|
||||||
|
'\n' +
|
||||||
|
' -c CHARSET fnt character set (default = 0, see wingdi.h ..._CHARSET)\n' +
|
||||||
|
' -m MINCHAR fnt minimum character code (8-bit CP decimal, not unicode)\n' +
|
||||||
|
' -f FAMILY fnt family: DontCare, Roman, Swiss, Modern or Decorative\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout, may not be a terminal)\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input must be a BDF 2.1 font with unicode encoding.\n')
|
||||||
|
|
||||||
|
VERSION = 'bdftofnt 1.62, Copyright (C) 2017-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE
|
||||||
|
|
||||||
|
FNT_FAMILIES = ['DontCare', 'Roman', 'Swiss', 'Modern', 'Decorative']
|
||||||
|
|
||||||
|
class Options(fncli.Options):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Options.__init__(self, ['-c', '-m', '-f', '-o'], HELP, VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
def parse(self, name, value, params):
|
||||||
|
if name == '-c':
|
||||||
|
params.char_set = fnutil.parse_dec('CHARSET', value, 0, 255)
|
||||||
|
elif name == '-m':
|
||||||
|
params.min_char = fnutil.parse_dec('MINCHAR', value, 0, 255)
|
||||||
|
elif name == '-f':
|
||||||
|
if value in FNT_FAMILIES:
|
||||||
|
params.fnt_family = FNT_FAMILIES.index(value)
|
||||||
|
else:
|
||||||
|
raise Exception('invalid FAMILY')
|
||||||
|
elif name == '-o':
|
||||||
|
params.output_name = value
|
||||||
|
else:
|
||||||
|
self.fallback(name, params)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Main --
|
||||||
|
FNT_HEADER_SIZE = 118
|
||||||
|
FNT_CHARSETS = [238, 204, 0, 161, 162, 177, 178, 186, 163]
|
||||||
|
|
||||||
|
def main_program(nonopt, parsed):
|
||||||
|
if len(nonopt) > 1:
|
||||||
|
raise Exception('invalid number of arguments, try --help')
|
||||||
|
|
||||||
|
char_set = parsed.char_set
|
||||||
|
min_char = parsed.min_char
|
||||||
|
|
||||||
|
# READ INPUT
|
||||||
|
ifs = fnio.InputFileStream(nonopt[0] if nonopt else None)
|
||||||
|
font = ifs.process(bdfexp.Font.read)
|
||||||
|
|
||||||
|
# COMPUTE
|
||||||
|
if char_set == -1:
|
||||||
|
encoding = font.xlfd[bdf.XLFD.CHARSET_ENCODING]
|
||||||
|
|
||||||
|
if re.fullmatch(b'(cp)?125[0-8]', encoding.lower()):
|
||||||
|
char_set = FNT_CHARSETS[int(encoding[-1:])]
|
||||||
|
else:
|
||||||
|
char_set = 255
|
||||||
|
|
||||||
|
try:
|
||||||
|
num_chars = len(font.chars)
|
||||||
|
|
||||||
|
if num_chars > 256:
|
||||||
|
raise Exception('too many characters, the maximum is 256')
|
||||||
|
|
||||||
|
if min_char == -1:
|
||||||
|
if num_chars in [192, 256]:
|
||||||
|
min_char = 256 - num_chars
|
||||||
|
else:
|
||||||
|
min_char = font.chars[0].code
|
||||||
|
|
||||||
|
max_char = min_char + num_chars - 1
|
||||||
|
|
||||||
|
if max_char >= 256:
|
||||||
|
raise Exception('the maximum character code is too big, (re)specify -m')
|
||||||
|
|
||||||
|
# HEADER
|
||||||
|
vtell = FNT_HEADER_SIZE + (num_chars + 1) * 4
|
||||||
|
bits_offset = vtell
|
||||||
|
ctable = []
|
||||||
|
width_bytes = 0
|
||||||
|
|
||||||
|
# CTABLE/GLYPHS
|
||||||
|
for char in font.chars:
|
||||||
|
row_size = char.bbx.row_size()
|
||||||
|
ctable.append(char.bbx.width)
|
||||||
|
ctable.append(vtell)
|
||||||
|
vtell += row_size * font.bbx.height
|
||||||
|
width_bytes += row_size
|
||||||
|
|
||||||
|
if vtell > 0xFFFF:
|
||||||
|
raise Exception('too much character data')
|
||||||
|
|
||||||
|
# SENTINEL
|
||||||
|
sentinel = 2 - width_bytes % 2
|
||||||
|
ctable.append(sentinel * 8)
|
||||||
|
ctable.append(vtell)
|
||||||
|
vtell += sentinel * font.bbx.height
|
||||||
|
width_bytes += sentinel
|
||||||
|
|
||||||
|
if width_bytes > 0xFFFF:
|
||||||
|
raise Exception('the total character width is too big')
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
ex.message = ifs.location() + getattr(ex, 'message', str(ex))
|
||||||
|
raise
|
||||||
|
|
||||||
|
# WRITE
|
||||||
|
def write_fnt(output):
|
||||||
|
# HEADER
|
||||||
|
family = font.xlfd[bdf.XLFD.FAMILY_NAME]
|
||||||
|
copyright = font.props.get('COPYRIGHT')
|
||||||
|
copyright = fnutil.unquote(copyright)[:60] if copyright is not None else b''
|
||||||
|
|
||||||
|
output.write16(0x0200) # font version
|
||||||
|
output.write32(vtell + len(family) + 1) # total size
|
||||||
|
output.write_zstr(copyright, 60 - len(copyright))
|
||||||
|
output.write16(0) # gdi, device type
|
||||||
|
output.write16(round(font.bbx.height * 72 / 96))
|
||||||
|
output.write16(96) # vertical resolution
|
||||||
|
output.write16(96) # horizontal resolution
|
||||||
|
output.write16(font.px_ascender) # base line
|
||||||
|
output.write16(0) # internal leading
|
||||||
|
output.write16(0) # external leading
|
||||||
|
output.write8(int(font.italic))
|
||||||
|
output.write8(0) # underline
|
||||||
|
output.write8(0) # strikeout
|
||||||
|
output.write16(700 if font.bold else 400)
|
||||||
|
output.write8(char_set)
|
||||||
|
output.write16(0 if font.proportional else font.bbx.width)
|
||||||
|
output.write16(font.bbx.height)
|
||||||
|
output.write8((parsed.fnt_family << 4) + int(font.proportional))
|
||||||
|
output.write16(font.avg_width)
|
||||||
|
output.write16(font.bbx.width)
|
||||||
|
output.write8(min_char)
|
||||||
|
output.write8(max_char)
|
||||||
|
|
||||||
|
default_index = max_char - min_char
|
||||||
|
break_index = 0
|
||||||
|
|
||||||
|
if font.default_code != -1:
|
||||||
|
default_index = next(index for index, char in enumerate(font.chars) if char.code == font.default_code)
|
||||||
|
|
||||||
|
if min_char <= 0x20 <= max_char:
|
||||||
|
break_index = 0x20 - min_char
|
||||||
|
|
||||||
|
output.write8(default_index)
|
||||||
|
output.write8(break_index)
|
||||||
|
output.write16(width_bytes)
|
||||||
|
output.write32(0) # device name
|
||||||
|
output.write32(vtell)
|
||||||
|
output.write32(0) # gdi bits pointer
|
||||||
|
output.write32(bits_offset)
|
||||||
|
output.write8(0) # reserved
|
||||||
|
|
||||||
|
# CTABLE
|
||||||
|
for value in ctable:
|
||||||
|
output.write16(value)
|
||||||
|
|
||||||
|
# GLYPHS
|
||||||
|
data = bytearray(font.bbx.height * font.bbx.row_size())
|
||||||
|
|
||||||
|
for char in font.chars:
|
||||||
|
row_size = char.bbx.row_size()
|
||||||
|
counter = 0
|
||||||
|
# MS coordinates
|
||||||
|
for n in range(0, row_size):
|
||||||
|
for y in range(0, font.bbx.height):
|
||||||
|
data[counter] = char.data[row_size * y + n]
|
||||||
|
counter += 1
|
||||||
|
output.write(data[:counter])
|
||||||
|
output.write(bytes(sentinel * font.bbx.height))
|
||||||
|
|
||||||
|
# FAMILY
|
||||||
|
output.write_zstr(family, 1)
|
||||||
|
|
||||||
|
fnio.write_file(parsed.output_name, write_fnt, encoding=None)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fncli.start('bdftofnt.py', Options(), Params(), main_program)
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2019 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
const fncli = require('./fncli.js');
|
||||||
|
const fnio = require('./fnio.js');
|
||||||
|
const bdfexp = require('./bdfexp.js');
|
||||||
|
|
||||||
|
// -- Params --
|
||||||
|
class Params extends fncli.Params {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.version = -1;
|
||||||
|
this.exchange = -1;
|
||||||
|
this.output = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Options --
|
||||||
|
const HELP = ('' +
|
||||||
|
'usage: bdftopsf [-1|-2|-r] [-g|-G] [-o OUTPUT] [INPUT.bdf] [TABLE...]\n' +
|
||||||
|
'Convert a BDF font to PC Screen Font or raw font\n' +
|
||||||
|
'\n' +
|
||||||
|
' -1, -2 write a PSF version 1 or 2 font (default = 1 if possible)\n' +
|
||||||
|
' -r, --raw write a RAW font\n' +
|
||||||
|
' -g, --vga exchange the characters at positions 0...31 with these at\n' +
|
||||||
|
' 192...223 (default for VGA text mode compliant PSF fonts\n' +
|
||||||
|
' with 224 to 512 characters starting with unicode 00A3)\n' +
|
||||||
|
' -G do not exchange characters 0...31 and 192...223\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout, may not be a terminal)\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input must be a monospaced unicode-encoded BDF 2.1 font.\n' +
|
||||||
|
'\n' +
|
||||||
|
'The tables are text files with two or more hexadecimal unicodes per line:\n' +
|
||||||
|
'a character code from the BDF, and extra code(s) for it. All extra codes\n' +
|
||||||
|
'are stored sequentially in the PSF unicode table for their character.\n' +
|
||||||
|
'<ss> is always specified as FFFE, although it is stored as FE in PSF2.\n');
|
||||||
|
|
||||||
|
const VERSION = 'bdftopsf 1.58, Copyright (C) 2017-2019 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_VERSION;
|
||||||
|
|
||||||
|
class Options extends fncli.Options {
|
||||||
|
constructor() {
|
||||||
|
super(['-o'], HELP, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(name, value, params) {
|
||||||
|
switch (name) {
|
||||||
|
case '-1':
|
||||||
|
case '-2':
|
||||||
|
params.version = parseInt(name[1]);
|
||||||
|
break;
|
||||||
|
case '-r':
|
||||||
|
case '--raw':
|
||||||
|
params.version = 0;
|
||||||
|
break;
|
||||||
|
case '-g':
|
||||||
|
case '--vga':
|
||||||
|
params.exchange = true;
|
||||||
|
break;
|
||||||
|
case '-G':
|
||||||
|
params.exchange = false;
|
||||||
|
break;
|
||||||
|
case '-o':
|
||||||
|
params.output = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.fallback(name, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Main --
|
||||||
|
function mainProgram(nonopt, parsed) {
|
||||||
|
const bdfile = nonopt.length > 0 && nonopt[0].toLowerCase().endsWith('.bdf');
|
||||||
|
let version = parsed.version;
|
||||||
|
let exchange = parsed.exchange;
|
||||||
|
let ver1Unicodes = true;
|
||||||
|
|
||||||
|
// READ INPUT
|
||||||
|
let ifs = new fnio.InputFileStream(bdfile ? nonopt[0] : null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var font = bdfexp.Font.read(ifs);
|
||||||
|
|
||||||
|
ifs.close();
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
const prefix = `char ${char.code}: `;
|
||||||
|
|
||||||
|
if (char.bbx.width !== font.bbx.width) {
|
||||||
|
throw new Error(prefix + 'output width not equal to maximum output width');
|
||||||
|
}
|
||||||
|
if (char.code === 65534) {
|
||||||
|
throw new Error(prefix + 'not a character, use 65535 for empty position');
|
||||||
|
}
|
||||||
|
if (char.code >= 65536) {
|
||||||
|
if (version === 1) {
|
||||||
|
throw new Error(prefix + '-1 requires unicodes <= 65535');
|
||||||
|
}
|
||||||
|
ver1Unicodes = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// VERSION
|
||||||
|
var ver1NumChars = (font.chars.length === 256 || font.chars.length === 512);
|
||||||
|
|
||||||
|
if (version === 1) {
|
||||||
|
if (!ver1NumChars) {
|
||||||
|
throw new Error('-1 requires a font with 256 or 512 characters');
|
||||||
|
}
|
||||||
|
if (font.bbx.width !== 8) {
|
||||||
|
throw new Error('-1 requires a font with width 8');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXCHANGE
|
||||||
|
var vgaNumChars = font.chars.length >= 224 && font.chars.length <= 512;
|
||||||
|
var vgaTextSize = font.bbx.width === 8 && [8, 14, 16].indexOf(font.bbx.height) !== -1;
|
||||||
|
|
||||||
|
if (exchange === true) {
|
||||||
|
if (!vgaNumChars) {
|
||||||
|
throw new Error('-g/--vga requires a font with 224...512 characters');
|
||||||
|
}
|
||||||
|
if (!vgaTextSize) {
|
||||||
|
throw new Error('-g/--vga requires an 8x8, 8x14 or 8x16 font');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// READ TABLES
|
||||||
|
let tables = [];
|
||||||
|
|
||||||
|
function loadExtra(line) {
|
||||||
|
const words = line.split(/\s+/);
|
||||||
|
|
||||||
|
if (words.length < 2) {
|
||||||
|
throw new Error('invalid format');
|
||||||
|
}
|
||||||
|
|
||||||
|
const uni = fnutil.parseHex('unicode', words[0]);
|
||||||
|
let table = tables[uni];
|
||||||
|
|
||||||
|
if (uni === 0xFFFE) {
|
||||||
|
throw new Error('FFFE is not a character');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (font.chars.findIndex(char => char.code === uni) !== -1) {
|
||||||
|
if (uni > fnutil.UNICODE_BMP_MAX) {
|
||||||
|
ver1Unicodes = false;
|
||||||
|
}
|
||||||
|
if (table == null) {
|
||||||
|
table = tables[uni] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
words.slice(1).forEach(word => {
|
||||||
|
const dup = fnutil.parseHex('extra code', word);
|
||||||
|
|
||||||
|
if (dup === 0xFFFF) {
|
||||||
|
throw new Error('FFFF is not a character');
|
||||||
|
}
|
||||||
|
if (dup > fnutil.UNICODE_BMP_MAX) {
|
||||||
|
ver1Unicodes = false;
|
||||||
|
}
|
||||||
|
if (table.indexOf(dup) === -1 || table.indexOf(0xFFFE) !== -1) {
|
||||||
|
table.push(dup);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (version === 1 && !ver1Unicodes) {
|
||||||
|
throw new Error('-1 requires unicodes <= ' + fnutil.UNICODE_BMP_MAX.toString(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nonopt.slice(Number(bdfile)).forEach(name => {
|
||||||
|
ifs = new fnio.InputFileStream(name);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ifs.readLines(loadExtra);
|
||||||
|
ifs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// VERSION
|
||||||
|
if (version === -1) {
|
||||||
|
version = ver1NumChars && ver1Unicodes && font.bbx.width === 8 ? 1 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXCHANGE
|
||||||
|
if (exchange === -1) {
|
||||||
|
exchange = vgaTextSize && version >= 1 && vgaNumChars && font.chars[0].code === 0x00A3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exchange) {
|
||||||
|
const control = font.chars.splice(0, 32, ...font.chars.splice(192, 32));
|
||||||
|
font.chars.splice(192, 0, ...control);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WRITE
|
||||||
|
let ofs = new fnio.OutputFileStream(parsed.output, null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// HEADER
|
||||||
|
if (version === 1) {
|
||||||
|
ofs.write8(0x36);
|
||||||
|
ofs.write8(0x04);
|
||||||
|
ofs.write8((font.chars.length >> 8) + 1);
|
||||||
|
ofs.write8(font.bbx.height);
|
||||||
|
} else if (version === 2) {
|
||||||
|
ofs.write32(0x864AB572);
|
||||||
|
ofs.write32(0x00000000);
|
||||||
|
ofs.write32(0x00000020);
|
||||||
|
ofs.write32(0x00000001);
|
||||||
|
ofs.write32(font.chars.length);
|
||||||
|
ofs.write32(font.chars[0].data.length);
|
||||||
|
ofs.write32(font.bbx.height);
|
||||||
|
ofs.write32(font.bbx.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLYPHS
|
||||||
|
font.chars.forEach(char => ofs.write(char.data));
|
||||||
|
|
||||||
|
// UNICODES
|
||||||
|
if (version > 0) {
|
||||||
|
const writeUnicode = function(code) {
|
||||||
|
if (version === 1) {
|
||||||
|
ofs.write16(code);
|
||||||
|
} else if (code <= 0x7F) {
|
||||||
|
ofs.write8(code);
|
||||||
|
} else if (code === 0xFFFE || code === 0xFFFF) {
|
||||||
|
ofs.write8(code & 0xFF);
|
||||||
|
} else {
|
||||||
|
if (code <= 0x7FF) {
|
||||||
|
ofs.write8(0xC0 + (code >> 6));
|
||||||
|
} else {
|
||||||
|
if (code <= 0xFFFF) {
|
||||||
|
ofs.write8(0xE0 + (code >> 12));
|
||||||
|
} else {
|
||||||
|
ofs.write8(0xF0 + (code >> 18));
|
||||||
|
ofs.write8(0x80 + ((code >> 12) & 0x3F));
|
||||||
|
}
|
||||||
|
ofs.write8(0x80 + ((code >> 6) & 0x3F));
|
||||||
|
}
|
||||||
|
ofs.write8(0x80 + (code & 0x3F));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
if (char.code !== 0xFFFF) {
|
||||||
|
writeUnicode(char.code);
|
||||||
|
}
|
||||||
|
if (tables[char.code] != null) {
|
||||||
|
tables[char.code].forEach(extra => writeUnicode(extra));
|
||||||
|
}
|
||||||
|
writeUnicode(0xFFFF);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// FINISH
|
||||||
|
ofs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ofs.location() + e.message + ofs.destroy();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
fncli.start('bdftopsf.js', new Options(), new Params(), mainProgram);
|
||||||
|
}
|
||||||
@@ -0,0 +1,241 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import fnutil
|
||||||
|
import fncli
|
||||||
|
import fnio
|
||||||
|
import bdfexp
|
||||||
|
|
||||||
|
# -- Params --
|
||||||
|
class Params(fncli.Params):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Params.__init__(self)
|
||||||
|
self.version = -1
|
||||||
|
self.exchange = -1
|
||||||
|
self.output_name = None
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options --
|
||||||
|
HELP = ('' +
|
||||||
|
'usage: bdftopsf [-1|-2|-r] [-g|-G] [-o OUTPUT] [INPUT.bdf] [TABLE...]\n' +
|
||||||
|
'Convert a BDF font to PC Screen Font or raw font\n' +
|
||||||
|
'\n' +
|
||||||
|
' -1, -2 write a PSF version 1 or 2 font (default = 1 if possible)\n' +
|
||||||
|
' -r, --raw write a RAW font\n' +
|
||||||
|
' -g, --vga exchange the characters at positions 0...31 with these at\n' +
|
||||||
|
' 192...223 (default for VGA text mode compliant PSF fonts\n' +
|
||||||
|
' with 224 to 512 characters starting with unicode 00A3)\n' +
|
||||||
|
' -G do not exchange characters 0...31 and 192...223\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout, may not be a terminal)\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input must be a monospaced unicode-encoded BDF 2.1 font.\n' +
|
||||||
|
'\n' +
|
||||||
|
'The tables are text files with two or more hexadecimal unicodes per line:\n' +
|
||||||
|
'a character code from the BDF, and extra code(s) for it. All extra codes\n' +
|
||||||
|
'are stored sequentially in the PSF unicode table for their character.\n' +
|
||||||
|
'<ss> is always specified as FFFE, although it is stored as FE in PSF2.\n')
|
||||||
|
|
||||||
|
VERSION = 'bdftopsf 1.62, Copyright (C) 2017-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE
|
||||||
|
|
||||||
|
class Options(fncli.Options):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Options.__init__(self, ['-o'], HELP, VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
def parse(self, name, value, params):
|
||||||
|
if name in ['-1', '-2']:
|
||||||
|
params.version = int(name[1])
|
||||||
|
elif name in ['-r', '--raw']:
|
||||||
|
params.version = 0
|
||||||
|
elif name in ['-g', '--vga']:
|
||||||
|
params.exchange = True
|
||||||
|
elif name == '-G':
|
||||||
|
params.exchange = False
|
||||||
|
elif name == '-o':
|
||||||
|
params.output_name = value
|
||||||
|
else:
|
||||||
|
self.fallback(name, params)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Main --
|
||||||
|
def main_program(nonopt, parsed):
|
||||||
|
version = parsed.version
|
||||||
|
exchange = parsed.exchange
|
||||||
|
bdfile = len(nonopt) > 0 and nonopt[0].lower().endswith('.bdf')
|
||||||
|
ver1_unicodes = True
|
||||||
|
|
||||||
|
# READ INPUT
|
||||||
|
ifs = fnio.InputFileStream(nonopt[0] if bdfile else None)
|
||||||
|
font = ifs.process(bdfexp.Font.read)
|
||||||
|
|
||||||
|
try:
|
||||||
|
for char in font.chars:
|
||||||
|
prefix = 'char %d: ' % char.code
|
||||||
|
|
||||||
|
if char.bbx.width != font.bbx.width:
|
||||||
|
raise Exception(prefix + 'output width not equal to maximum output width')
|
||||||
|
|
||||||
|
if char.code == 65534:
|
||||||
|
raise Exception(prefix + 'not a character, use 65535 for empty position')
|
||||||
|
|
||||||
|
if char.code >= 65536:
|
||||||
|
if version == 1:
|
||||||
|
raise Exception(prefix + '-1 requires unicodes <= 65535')
|
||||||
|
ver1_unicodes = False
|
||||||
|
|
||||||
|
# VERSION
|
||||||
|
ver1_num_chars = len(font.chars) == 256 or len(font.chars) == 512
|
||||||
|
|
||||||
|
if version == 1:
|
||||||
|
if not ver1_num_chars:
|
||||||
|
raise Exception('-1 requires a font with 256 or 512 characters')
|
||||||
|
|
||||||
|
if font.bbx.width != 8:
|
||||||
|
raise Exception('-1 requires a font with width 8')
|
||||||
|
|
||||||
|
# EXCHANGE
|
||||||
|
vga_num_chars = len(font.chars) >= 224 and len(font.chars) <= 512
|
||||||
|
vga_text_size = font.bbx.width == 8 and font.bbx.height in [8, 14, 16]
|
||||||
|
|
||||||
|
if exchange is True:
|
||||||
|
if not vga_num_chars:
|
||||||
|
raise Exception('-g/--vga requires a font with 224...512 characters')
|
||||||
|
|
||||||
|
if not vga_text_size:
|
||||||
|
raise Exception('-g/--vga requires an 8x8, 8x14 or 8x16 font')
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
ex.message = ifs.location() + getattr(ex, 'message', str(ex))
|
||||||
|
raise
|
||||||
|
|
||||||
|
# READ TABLES
|
||||||
|
tables = dict()
|
||||||
|
|
||||||
|
def load_extra(line):
|
||||||
|
nonlocal ver1_unicodes
|
||||||
|
words = line.split()
|
||||||
|
|
||||||
|
if len(words) < 2:
|
||||||
|
raise Exception('invalid format')
|
||||||
|
|
||||||
|
uni = fnutil.parse_hex('unicode', words[0])
|
||||||
|
|
||||||
|
if uni == 0xFFFE:
|
||||||
|
raise Exception('FFFE is not a character')
|
||||||
|
|
||||||
|
if next((char for char in font.chars if char.code == uni), None):
|
||||||
|
if uni > fnutil.UNICODE_BMP_MAX:
|
||||||
|
ver1_unicodes = False
|
||||||
|
|
||||||
|
if uni not in tables:
|
||||||
|
tables[uni] = []
|
||||||
|
|
||||||
|
table = tables[uni]
|
||||||
|
|
||||||
|
for word in words[1:]:
|
||||||
|
dup = fnutil.parse_hex('extra code', word)
|
||||||
|
|
||||||
|
if dup == 0xFFFF:
|
||||||
|
raise Exception('FFFF is not a character')
|
||||||
|
|
||||||
|
if dup > fnutil.UNICODE_BMP_MAX:
|
||||||
|
ver1_unicodes = False
|
||||||
|
|
||||||
|
if not dup in table or 0xFFFE in table:
|
||||||
|
tables[uni].append(dup)
|
||||||
|
|
||||||
|
if version == 1 and not ver1_unicodes:
|
||||||
|
raise Exception('-1 requires unicodes <= %X' % fnutil.UNICODE_BMP_MAX)
|
||||||
|
|
||||||
|
for table_name in nonopt[int(bdfile):]:
|
||||||
|
fnio.read_file(table_name, lambda ifs: ifs.read_lines(load_extra))
|
||||||
|
|
||||||
|
# VERSION
|
||||||
|
if version == -1:
|
||||||
|
version = 1 if ver1_num_chars and ver1_unicodes and font.bbx.width == 8 else 2
|
||||||
|
|
||||||
|
# EXCHANGE
|
||||||
|
if exchange == -1:
|
||||||
|
exchange = vga_text_size and version >= 1 and vga_num_chars and font.chars[0].code == 0x00A3
|
||||||
|
|
||||||
|
if exchange:
|
||||||
|
font.chars = font.chars[192:224] + font.chars[32:192] + font.chars[0:32] + font.chars[224:]
|
||||||
|
|
||||||
|
# WRITE
|
||||||
|
def write_psf(output):
|
||||||
|
# HEADER
|
||||||
|
if version == 1:
|
||||||
|
output.write8(0x36)
|
||||||
|
output.write8(0x04)
|
||||||
|
output.write8((len(font.chars) >> 8) + 1)
|
||||||
|
output.write8(font.bbx.height)
|
||||||
|
elif version == 2:
|
||||||
|
output.write32(0x864AB572)
|
||||||
|
output.write32(0x00000000)
|
||||||
|
output.write32(0x00000020)
|
||||||
|
output.write32(0x00000001)
|
||||||
|
output.write32(len(font.chars))
|
||||||
|
output.write32(len(font.chars[0].data))
|
||||||
|
output.write32(font.bbx.height)
|
||||||
|
output.write32(font.bbx.width)
|
||||||
|
|
||||||
|
# GLYPHS
|
||||||
|
for char in font.chars:
|
||||||
|
output.write(char.data)
|
||||||
|
|
||||||
|
# UNICODES
|
||||||
|
if version > 0:
|
||||||
|
def write_unicode(code):
|
||||||
|
if version == 1:
|
||||||
|
output.write16(code)
|
||||||
|
elif code <= 0x7F:
|
||||||
|
output.write8(code)
|
||||||
|
elif code in [0xFFFE, 0xFFFF]:
|
||||||
|
output.write8(code & 0xFF)
|
||||||
|
else:
|
||||||
|
if code <= 0x7FF:
|
||||||
|
output.write8(0xC0 + (code >> 6))
|
||||||
|
else:
|
||||||
|
if code <= 0xFFFF:
|
||||||
|
output.write8(0xE0 + (code >> 12))
|
||||||
|
else:
|
||||||
|
output.write8(0xF0 + (code >> 18))
|
||||||
|
output.write8(0x80 + ((code >> 12) & 0x3F))
|
||||||
|
|
||||||
|
output.write8(0x80 + ((code >> 6) & 0x3F))
|
||||||
|
|
||||||
|
output.write8(0x80 + (code & 0x3F))
|
||||||
|
|
||||||
|
for char in font.chars:
|
||||||
|
if char.code != 0xFFFF:
|
||||||
|
write_unicode(char.code)
|
||||||
|
|
||||||
|
if char.code in tables:
|
||||||
|
for extra in tables[char.code]:
|
||||||
|
write_unicode(extra)
|
||||||
|
|
||||||
|
write_unicode(0xFFFF)
|
||||||
|
|
||||||
|
fnio.write_file(parsed.output_name, write_psf, encoding=None)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fncli.start('bdftopsf.py', Options(), Params(), main_program)
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2018-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// -- Params --
|
||||||
|
class Params {
|
||||||
|
constructor() {
|
||||||
|
this.excstk = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Options --
|
||||||
|
class Options {
|
||||||
|
constructor(needArgs, helpText, versionText) {
|
||||||
|
needArgs.forEach(name => {
|
||||||
|
if (!name.match(/^(-[^-]|--[^=]+)$/)) {
|
||||||
|
throw new Error(`invalid option name "${name}"`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.needArgs = needArgs;
|
||||||
|
this.helpText = helpText;
|
||||||
|
this.versionText = versionText;
|
||||||
|
}
|
||||||
|
|
||||||
|
posixlyCorrect() { // eslint-disable-line class-methods-use-this
|
||||||
|
return process.env['POSIXLY_CORRECT'] != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
needsArg(name) {
|
||||||
|
return this.needArgs.includes(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback(name, params) {
|
||||||
|
if (name === '--excstk') {
|
||||||
|
params.excstk = true;
|
||||||
|
} else if (name === '--help' && this.helpText != null) {
|
||||||
|
process.stdout.write(this.helpText);
|
||||||
|
process.exit(0);
|
||||||
|
} else if (name === '--version' && this.versionText != null) {
|
||||||
|
process.stdout.write(this.versionText);
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
let suffix = this.needsArg(name) ? ' (taking an argument?)' : '';
|
||||||
|
|
||||||
|
suffix += (this.helpText != null) ? ', try --help' : '';
|
||||||
|
throw new Error(`unknown option "${name}"${suffix}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader(args, skip = 2) {
|
||||||
|
return new Options.Reader(this, args, skip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Options.Reader = class {
|
||||||
|
constructor(options, args, skip) {
|
||||||
|
this.options = options;
|
||||||
|
this.args = args;
|
||||||
|
this.skip = skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
forEach(callback) {
|
||||||
|
let optind;
|
||||||
|
|
||||||
|
for (optind = this.skip; optind < this.args.length; optind++) {
|
||||||
|
let arg = this.args[optind];
|
||||||
|
|
||||||
|
if (arg === '-' || !arg.startsWith('-')) {
|
||||||
|
if (this.options.posixlyCorrect()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
callback(null, arg);
|
||||||
|
} else if (arg === '--') {
|
||||||
|
optind++;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
let name, value;
|
||||||
|
|
||||||
|
if (!arg.startsWith('--')) {
|
||||||
|
for (;;) {
|
||||||
|
name = arg.substring(0, 2);
|
||||||
|
value = (name !== arg) ? arg.substring(2) : null;
|
||||||
|
|
||||||
|
if (this.options.needsArg(name) || value == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
callback(name, null);
|
||||||
|
arg = '-' + value;
|
||||||
|
}
|
||||||
|
} else if (arg.indexOf('=') >= 3) {
|
||||||
|
name = arg.split('=', 1)[0];
|
||||||
|
if (!this.options.needsArg(name)) {
|
||||||
|
throw new Error(`option "${name}" does not take an argument`);
|
||||||
|
}
|
||||||
|
value = arg.substring(name.length + 1);
|
||||||
|
} else {
|
||||||
|
name = arg;
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null && Number(this.options.needsArg(name)) > 0) {
|
||||||
|
if (++optind === this.args.length) {
|
||||||
|
throw new Error(`option "${name}" requires an argument`);
|
||||||
|
}
|
||||||
|
value = this.args[optind];
|
||||||
|
}
|
||||||
|
callback(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.args.slice(optind).forEach(value => callback(null, value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(Options, 'Reader', { 'enumerable': false });
|
||||||
|
Object.defineProperty(Options.Reader, 'name', { value: 'Reader' });
|
||||||
|
|
||||||
|
// -- Main --
|
||||||
|
function start(programName, options, params, mainProgram) { // eslint-disable-line consistent-return
|
||||||
|
const parsed = (params != null) ? params : new Params();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const version = process.version.match(/^v?(\d+)\.(\d+)/);
|
||||||
|
|
||||||
|
if (version.length < 3) {
|
||||||
|
throw new Error('unable to obtain node version');
|
||||||
|
} else if ((parseInt(version[1]) * 1000 + parseInt(version[2])) < 6009) {
|
||||||
|
throw new Error('node version 6.9.0 or later required');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params == null) {
|
||||||
|
return mainProgram(options.reader(process.argv), name => options.fallback(name, parsed));
|
||||||
|
} else {
|
||||||
|
let nonopt = [];
|
||||||
|
|
||||||
|
options.reader(process.argv).forEach((name, value) => {
|
||||||
|
if (name == null) {
|
||||||
|
nonopt.push(value);
|
||||||
|
} else {
|
||||||
|
options.parse(name, value, parsed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return mainProgram(nonopt, parsed);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (parsed.excstk) {
|
||||||
|
if (e.stack != null) {
|
||||||
|
process.stderr.write(e.stack + '\n');
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
process.stderr.write(`${process.argv.length >= 2 ? process.argv[1] : programName}: ${e.message}\n`);
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Exports --
|
||||||
|
module.exports = Object.freeze({
|
||||||
|
Params,
|
||||||
|
Options,
|
||||||
|
start
|
||||||
|
});
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
# -- Params --
|
||||||
|
class Params:
|
||||||
|
def __init__(self):
|
||||||
|
self.excstk = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options --
|
||||||
|
class Options:
|
||||||
|
def __init__(self, need_args, help_text, version_text):
|
||||||
|
for name in need_args:
|
||||||
|
if not re.fullmatch('(-[^-]|--[^=]+)', name):
|
||||||
|
raise Exception('invalid option name "%s"' % name)
|
||||||
|
|
||||||
|
self.need_args = need_args
|
||||||
|
self.help_text = help_text
|
||||||
|
self.version_text = version_text
|
||||||
|
|
||||||
|
|
||||||
|
def posixly_correct(self): # pylint: disable=no-self-use
|
||||||
|
return 'POSIXLY_CORRECT' in os.environ
|
||||||
|
|
||||||
|
|
||||||
|
def needs_arg(self, name):
|
||||||
|
return name in self.need_args
|
||||||
|
|
||||||
|
|
||||||
|
def fallback(self, name, params):
|
||||||
|
if name == '--excstk':
|
||||||
|
params.excstk = True
|
||||||
|
elif name == '--help' and self.help_text is not None:
|
||||||
|
sys.stdout.write(self.help_text)
|
||||||
|
sys.exit(0)
|
||||||
|
elif name == '--version' and self.version_text is not None:
|
||||||
|
sys.stdout.write(self.version_text)
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
suffix = ' (taking an argument?)' if self.needs_arg(name) else ''
|
||||||
|
suffix += ', try --help' if self.help_text is not None else ''
|
||||||
|
raise Exception('unknown option "%s"%s' % (name, suffix))
|
||||||
|
|
||||||
|
|
||||||
|
def reader(self, args, skip_zero=True):
|
||||||
|
return Options.Reader(self, args, skip_zero)
|
||||||
|
|
||||||
|
|
||||||
|
class Reader:
|
||||||
|
def __init__(self, options, args, skip_zero):
|
||||||
|
self.options = options
|
||||||
|
self.args = args
|
||||||
|
self.skip_zero = skip_zero
|
||||||
|
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return Options.Reader.Iterator(self)
|
||||||
|
|
||||||
|
|
||||||
|
class Iterator:
|
||||||
|
def __init__(self, reader):
|
||||||
|
self.options = reader.options
|
||||||
|
self.args = reader.args
|
||||||
|
self.optind = int(reader.skip_zero)
|
||||||
|
self.chrind = 1
|
||||||
|
self.endopt = False
|
||||||
|
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if self.chrind == 0:
|
||||||
|
self.optind += 1
|
||||||
|
self.chrind = 1
|
||||||
|
|
||||||
|
if self.optind == len(self.args):
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
arg = self.args[self.optind]
|
||||||
|
|
||||||
|
if self.endopt or arg == '-' or not arg.startswith('-'):
|
||||||
|
self.endopt = self.options.posixly_correct()
|
||||||
|
name = None
|
||||||
|
value = arg
|
||||||
|
elif arg == '--':
|
||||||
|
self.chrind = 0
|
||||||
|
self.endopt = True
|
||||||
|
return next(self)
|
||||||
|
elif not arg.startswith('--'):
|
||||||
|
name = '-' + arg[self.chrind]
|
||||||
|
self.chrind += 1
|
||||||
|
if self.chrind < len(arg):
|
||||||
|
if not self.options.needs_arg(name):
|
||||||
|
return (name, None)
|
||||||
|
value = arg[self.chrind:]
|
||||||
|
else:
|
||||||
|
value = None
|
||||||
|
elif '=' in arg and arg.index('=') >= 3:
|
||||||
|
name = arg.split('=', 1)[0]
|
||||||
|
if not self.options.needs_arg(name):
|
||||||
|
raise Exception('option "%s" does not take an argument' % name)
|
||||||
|
value = arg[len(name) + 1:]
|
||||||
|
else:
|
||||||
|
name = arg
|
||||||
|
value = None
|
||||||
|
|
||||||
|
if value is None and int(self.options.needs_arg(name)) > 0:
|
||||||
|
self.optind += 1
|
||||||
|
if self.optind == len(self.args):
|
||||||
|
raise Exception('option "%s" requires an argument' % name)
|
||||||
|
value = self.args[self.optind]
|
||||||
|
|
||||||
|
self.chrind = 0
|
||||||
|
return (name, value)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Main --
|
||||||
|
def start(program_name, options, params, main_program):
|
||||||
|
parsed = Params() if params is None else params
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
if sys.hexversion < 0x3050000:
|
||||||
|
raise Exception('python 3.5.0 or later required')
|
||||||
|
|
||||||
|
if params is None:
|
||||||
|
return main_program(options.reader(sys.argv), lambda name: options.fallback(name, parsed))
|
||||||
|
|
||||||
|
nonopt = []
|
||||||
|
|
||||||
|
for [name, value] in options.reader(sys.argv):
|
||||||
|
if name is None:
|
||||||
|
nonopt.append(value)
|
||||||
|
else:
|
||||||
|
options.parse(name, value, parsed)
|
||||||
|
|
||||||
|
return main_program(nonopt, parsed)
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
if parsed.excstk:
|
||||||
|
raise # loses the message information, but preserves the start() caller stack info
|
||||||
|
|
||||||
|
message = getattr(ex, 'message', str(ex))
|
||||||
|
sys.stderr.write('%s: %s\n' % (sys.argv[0] if sys.argv[0] else program_name, message))
|
||||||
|
sys.exit(1)
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const tty = require('tty');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
// -- InputFileStream --
|
||||||
|
const BLOCK_SIZE = 4096;
|
||||||
|
|
||||||
|
class InputFileStream {
|
||||||
|
constructor(fileName, encoding = 'binary') {
|
||||||
|
if (fileName != null) {
|
||||||
|
this.fd = fs.openSync(fileName, 'r');
|
||||||
|
this.stName = fileName;
|
||||||
|
} else {
|
||||||
|
this.fd = process.stdin.fd;
|
||||||
|
this.stName = '<stdin>';
|
||||||
|
}
|
||||||
|
this.encoding = encoding;
|
||||||
|
this.unseek();
|
||||||
|
this.lines = [];
|
||||||
|
this.index = 0;
|
||||||
|
this.buffer = Buffer.alloc(BLOCK_SIZE);
|
||||||
|
this.remainder = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.unseek();
|
||||||
|
fs.closeSync(this.fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
fstat() {
|
||||||
|
return (this.fd === process.stdin.fd || tty.isatty(this.fd)) ? null : fs.fstatSync(this.fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
location() {
|
||||||
|
let location = ' ';
|
||||||
|
|
||||||
|
if (this.eof) {
|
||||||
|
location = 'EOF: ';
|
||||||
|
} else if (this.lineNo > 0) {
|
||||||
|
location = `${this.lineNo}: `;
|
||||||
|
|
||||||
|
}
|
||||||
|
return `${this.stName}:${location}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
_readBlock() {
|
||||||
|
for (;;) {
|
||||||
|
try {
|
||||||
|
return fs.readSync(this.fd, this.buffer, 0, BLOCK_SIZE);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code === 'EOF') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (e.code !== 'EAGAIN') {
|
||||||
|
this.unseek();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readLine() {
|
||||||
|
return this.readLines(line => line);
|
||||||
|
}
|
||||||
|
|
||||||
|
readLines(callback) {
|
||||||
|
let line;
|
||||||
|
|
||||||
|
do {
|
||||||
|
while (this.index < this.lines.length) {
|
||||||
|
this.lineNo++;
|
||||||
|
line = callback(this.lines[this.index++].trimRight());
|
||||||
|
|
||||||
|
if (line != null) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var count = this._readBlock();
|
||||||
|
|
||||||
|
this.index = 0;
|
||||||
|
this.lines = (this.remainder + this.buffer.toString(this.encoding, 0, count)).split('\n');
|
||||||
|
this.remainder = this.lines.pop();
|
||||||
|
this.eof = false;
|
||||||
|
} while (count > 0);
|
||||||
|
|
||||||
|
if (this.remainder.length > 0) {
|
||||||
|
this.lineNo++;
|
||||||
|
line = callback(this.remainder.trimRight());
|
||||||
|
this.remainder = '';
|
||||||
|
} else {
|
||||||
|
this.eof = true;
|
||||||
|
line = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
unseek() {
|
||||||
|
this.lineNo = 0;
|
||||||
|
this.eof = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- OutputFileStream --
|
||||||
|
class OutputFileStream {
|
||||||
|
constructor(fileName, encoding = 'binary') {
|
||||||
|
if (fileName != null) {
|
||||||
|
this.fd = fs.openSync(fileName, 'w');
|
||||||
|
this.stName = fileName;
|
||||||
|
} else {
|
||||||
|
this.fd = process.stdout.fd;
|
||||||
|
this.stName = '<stdout>';
|
||||||
|
}
|
||||||
|
if (encoding == null && tty.isatty(this.fd)) {
|
||||||
|
throw new Error(this.location() + 'binary output may not be send to a terminal');
|
||||||
|
}
|
||||||
|
this.encoding = (encoding == null ? 'binary' : encoding);
|
||||||
|
this.fbbuf = Buffer.alloc(4);
|
||||||
|
this.closeAttempt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.closeAttempt = true;
|
||||||
|
fs.closeSync(this.fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
let errors = '';
|
||||||
|
|
||||||
|
if (this.fd !== process.stdout.fd) {
|
||||||
|
if (!this.closeAttempt) {
|
||||||
|
try {
|
||||||
|
fs.closeSync(this.fd);
|
||||||
|
} catch (e) {
|
||||||
|
errors += `\n${this.stName}: close: ${e.message}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(this.stName);
|
||||||
|
} catch (e) {
|
||||||
|
errors += `\n${this.stName}: unlink: ${e.message}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
location() {
|
||||||
|
return this.stName + ': ';
|
||||||
|
}
|
||||||
|
|
||||||
|
write(buffer) {
|
||||||
|
fs.writeSync(this.fd, buffer, 0, buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
write8(value) {
|
||||||
|
this.fbbuf.writeUInt8(value, 0);
|
||||||
|
fs.writeSync(this.fd, this.fbbuf, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
write16(value) {
|
||||||
|
this.fbbuf.writeUInt16LE(value, 0);
|
||||||
|
fs.writeSync(this.fd, this.fbbuf, 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
write32(value) {
|
||||||
|
this.fbbuf.writeUInt32LE(value, 0);
|
||||||
|
fs.writeSync(this.fd, this.fbbuf, 0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeLine(text) {
|
||||||
|
fs.writeSync(this.fd, text + '\n', null, this.encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeProp(name, value) {
|
||||||
|
this.writeLine((name + ' ' + value).trimRight());
|
||||||
|
}
|
||||||
|
|
||||||
|
writeZStr(bstr, numZeros) {
|
||||||
|
fs.writeSync(this.fd, bstr, null, 'binary');
|
||||||
|
this.write(Buffer.alloc(numZeros));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Export --
|
||||||
|
module.exports = Object.freeze({
|
||||||
|
InputFileStream,
|
||||||
|
OutputFileStream
|
||||||
|
});
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import codecs
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# -- InputFileStream --
|
||||||
|
class InputFileStream:
|
||||||
|
def __init__(self, file_name, encoding='binary'):
|
||||||
|
if file_name is not None:
|
||||||
|
self.file = open(file_name, 'r') if encoding is None else open(file_name, 'rb')
|
||||||
|
self.st_name = file_name
|
||||||
|
else:
|
||||||
|
self.file = sys.stdin if encoding is None else sys.stdin.buffer
|
||||||
|
self.st_name = '<stdin>'
|
||||||
|
|
||||||
|
if encoding not in [None, 'binary']:
|
||||||
|
self.file = codecs.getreader(encoding)(self.file)
|
||||||
|
|
||||||
|
self.line_no = 0
|
||||||
|
self.eof = False
|
||||||
|
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.unseek()
|
||||||
|
self.file.close()
|
||||||
|
|
||||||
|
|
||||||
|
def fstat(self):
|
||||||
|
return None if (self.file == sys.stdin.buffer or self.file.isatty()) else os.fstat(self.file.fileno())
|
||||||
|
|
||||||
|
|
||||||
|
def location(self):
|
||||||
|
return '%s:%s' % (self.st_name, 'EOF: ' if self.eof else '%d: ' % self.line_no if self.line_no > 0 else ' ')
|
||||||
|
|
||||||
|
|
||||||
|
def process(self, callback):
|
||||||
|
try:
|
||||||
|
result = callback(self)
|
||||||
|
self.close()
|
||||||
|
return result
|
||||||
|
except Exception as ex:
|
||||||
|
ex.message = self.location() + getattr(ex, 'message', str(ex))
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def read_line(self):
|
||||||
|
return self.read_lines(lambda line: line)
|
||||||
|
|
||||||
|
|
||||||
|
def read_lines(self, callback):
|
||||||
|
try:
|
||||||
|
for line in self.file:
|
||||||
|
self.line_no += 1
|
||||||
|
self.eof = False
|
||||||
|
line = callback(line.rstrip())
|
||||||
|
if line is not None:
|
||||||
|
return line
|
||||||
|
except OSError:
|
||||||
|
self.unseek()
|
||||||
|
raise
|
||||||
|
|
||||||
|
self.eof = True
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def unseek(self):
|
||||||
|
self.line_no = 0
|
||||||
|
self.eof = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- OutputFileStream --
|
||||||
|
class OutputFileStream:
|
||||||
|
def __init__(self, file_name, encoding='binary'):
|
||||||
|
if file_name is not None:
|
||||||
|
self.file = open(file_name, 'wb')
|
||||||
|
self.st_name = file_name
|
||||||
|
else:
|
||||||
|
self.file = sys.stdout.buffer
|
||||||
|
self.st_name = '<stdout>'
|
||||||
|
|
||||||
|
if encoding is None and self.file.isatty():
|
||||||
|
raise Exception(self.location() + 'binary output may not be send to a terminal')
|
||||||
|
|
||||||
|
self.encoding = (None if encoding == 'binary' else encoding)
|
||||||
|
self.close_attempt = False
|
||||||
|
|
||||||
|
|
||||||
|
def abort(self):
|
||||||
|
errors = ''
|
||||||
|
|
||||||
|
if self.file != sys.stdout.buffer:
|
||||||
|
if not self.close_attempt:
|
||||||
|
try:
|
||||||
|
self.close()
|
||||||
|
except Exception as ex:
|
||||||
|
errors += '\n%sclose: %s' % (self.location(), str(ex))
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.remove(self.st_name)
|
||||||
|
except Exception as ex:
|
||||||
|
errors += '\n%sunlink: %s' % (self.location(), str(ex))
|
||||||
|
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.close_attempt = True
|
||||||
|
self.file.close()
|
||||||
|
|
||||||
|
|
||||||
|
def location(self):
|
||||||
|
return self.st_name + ': '
|
||||||
|
|
||||||
|
|
||||||
|
def process(self, callback):
|
||||||
|
try:
|
||||||
|
callback(self)
|
||||||
|
self.close()
|
||||||
|
except Exception as ex:
|
||||||
|
ex.message = self.location() + getattr(ex, 'message', str(ex)) + self.abort()
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def write(self, data):
|
||||||
|
self.file.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
def write8(self, value):
|
||||||
|
self.write(struct.pack('B', value))
|
||||||
|
|
||||||
|
|
||||||
|
def write16(self, value):
|
||||||
|
self.write(struct.pack('<H', value))
|
||||||
|
|
||||||
|
|
||||||
|
def write32(self, value):
|
||||||
|
self.write(struct.pack('<L', value))
|
||||||
|
|
||||||
|
|
||||||
|
def write_line(self, text):
|
||||||
|
self.write((text if self.encoding is None else bytes(text, self.encoding)) + b'\n')
|
||||||
|
|
||||||
|
|
||||||
|
def write_prop(self, name, value):
|
||||||
|
self.write_line((bytes(name, 'ascii') + b' ' + value).rstrip())
|
||||||
|
|
||||||
|
|
||||||
|
def write_zstr(self, bstr, num_zeros):
|
||||||
|
self.write(bstr + bytes(num_zeros))
|
||||||
|
|
||||||
|
|
||||||
|
# -- read/write file --
|
||||||
|
def read_file(file_name, callback, encoding='binary'):
|
||||||
|
return InputFileStream(file_name, encoding).process(callback)
|
||||||
|
|
||||||
|
|
||||||
|
def write_file(file_name, callback, encoding='binary'):
|
||||||
|
return OutputFileStream(file_name, encoding).process(callback)
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2019 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// -- Various --
|
||||||
|
const UNICODE_MAX = 1114111; // 0x10FFFF
|
||||||
|
const UNICODE_BMP_MAX = 65535; // 0xFFFF
|
||||||
|
|
||||||
|
function parseDec(name, s, minValue = 0, maxValue = UNICODE_MAX) {
|
||||||
|
if (s.match(/^\s*-?\d+\s*$/) == null) {
|
||||||
|
throw new Error(`invalid ${name} format`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = parseInt(s, 10);
|
||||||
|
|
||||||
|
if (minValue != null && value < minValue) {
|
||||||
|
throw new Error(`${name} must be >= ${minValue}`);
|
||||||
|
}
|
||||||
|
if (maxValue != null && value > maxValue) {
|
||||||
|
throw new Error(`${name} must be <= ${maxValue}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseHex(name, s, minValue = 0, maxValue = UNICODE_MAX) {
|
||||||
|
if (s.match(/^\s*(0[xX])?[\dA-Fa-f]+\s*$/) == null) {
|
||||||
|
throw new Error(`invalid ${name} format`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = parseInt(s, 16);
|
||||||
|
|
||||||
|
if (minValue != null && value < minValue) {
|
||||||
|
throw new Error(`${name} must be >= ` + minValue.toString(16).toUpperCase());
|
||||||
|
}
|
||||||
|
if (maxValue != null && value > maxValue) {
|
||||||
|
throw new Error(`${name} must be <= ` + maxValue.toString(16).toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unihex(code) {
|
||||||
|
return ('000' + code.toString(16).toUpperCase()).replace(/0+(?=[\dA-F]{4})/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function round(value) {
|
||||||
|
const esround = Math.round(value);
|
||||||
|
|
||||||
|
return esround - Number(esround % 2 !== 0 && esround - value === 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
function quote(s) {
|
||||||
|
return '"' + s.replace(/"/g, '""') + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
function unquote(s, name) {
|
||||||
|
if (s.length >= 2 && s.startsWith('"') && s.endsWith('"')) {
|
||||||
|
s = s.substring(1, s.length - 1).replace(/""/g, '"');
|
||||||
|
} else if (name != null) {
|
||||||
|
throw new Error(name + ' must be quoted');
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function message(prefix, severity, text) {
|
||||||
|
process.stderr.write(`${prefix}${severity ? severity + ': ' : ''}${text}\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function warning(prefix, text) {
|
||||||
|
message(prefix, 'warning', text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitWords(name, value, count) {
|
||||||
|
const words = value.split(/\s+/, count + 1);
|
||||||
|
|
||||||
|
if (words.length !== count) {
|
||||||
|
throw new Error(`${name} must contain ${count} values`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return words;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GPL2PLUS_LICENSE = ('' +
|
||||||
|
'This program is free software; you can redistribute it and/or modify it\n' +
|
||||||
|
'under the terms of the GNU General Public License as published by the Free\n' +
|
||||||
|
'Software Foundation; either version 2 of the License, or (at your option)\n' +
|
||||||
|
'any later version.\n' +
|
||||||
|
'\n' +
|
||||||
|
'This program is distributed in the hope that it will be useful, but\n' +
|
||||||
|
'WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n' +
|
||||||
|
'or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n' +
|
||||||
|
'for more details.\n' +
|
||||||
|
'\n' +
|
||||||
|
'You should have received a copy of the GNU General Public License along\n' +
|
||||||
|
'with this program; if not, write to the Free Software Foundation, Inc.,\n' +
|
||||||
|
'51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n');
|
||||||
|
|
||||||
|
// -- Exports --
|
||||||
|
module.exports = Object.freeze({
|
||||||
|
UNICODE_MAX,
|
||||||
|
UNICODE_BMP_MAX,
|
||||||
|
parseDec,
|
||||||
|
parseHex,
|
||||||
|
unihex,
|
||||||
|
round,
|
||||||
|
quote,
|
||||||
|
unquote,
|
||||||
|
message,
|
||||||
|
warning,
|
||||||
|
splitWords,
|
||||||
|
GPL2PLUS_LICENSE
|
||||||
|
});
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# -- Various --
|
||||||
|
UNICODE_MAX = 1114111 # 0x10FFFF
|
||||||
|
UNICODE_BMP_MAX = 65535 # 0xFFFF
|
||||||
|
|
||||||
|
def parse_dec(name, s, min_value=0, max_value=UNICODE_MAX):
|
||||||
|
try:
|
||||||
|
value = int(s)
|
||||||
|
except ValueError:
|
||||||
|
raise Exception('invalid %s format' % name)
|
||||||
|
|
||||||
|
if min_value is not None and value < min_value:
|
||||||
|
raise Exception('%s must be >= %d' % (name, min_value))
|
||||||
|
|
||||||
|
if max_value is not None and value > max_value:
|
||||||
|
raise Exception('%s must be <= %d' % (name, max_value))
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def parse_hex(name, s, min_value=0, max_value=UNICODE_MAX):
|
||||||
|
try:
|
||||||
|
value = int(s, 16)
|
||||||
|
except ValueError:
|
||||||
|
raise Exception('invalid %s format' % name)
|
||||||
|
|
||||||
|
if min_value is not None and value < min_value:
|
||||||
|
raise Exception('%s must be >= %X' % (name, min_value))
|
||||||
|
|
||||||
|
if max_value is not None and value > max_value:
|
||||||
|
raise Exception('%s must be <= %X' % (name, max_value))
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def quote(bstr):
|
||||||
|
return b'"%s"' % bstr.replace(b'"', b'""')
|
||||||
|
|
||||||
|
|
||||||
|
def unquote(bstr, name=None):
|
||||||
|
if len(bstr) >= 2 and bstr.startswith(b'"') and bstr.endswith(b'"'):
|
||||||
|
bstr = bstr[1 : len(bstr) - 1].replace(b'""', b'"')
|
||||||
|
elif name is not None:
|
||||||
|
raise Exception(name + ' must be quoted')
|
||||||
|
|
||||||
|
return bstr
|
||||||
|
|
||||||
|
|
||||||
|
def message(prefix, severity, text):
|
||||||
|
sys.stderr.write('%s%s%s\n' % (prefix, severity + ': ' if severity else '', text))
|
||||||
|
|
||||||
|
|
||||||
|
def warning(prefix, text):
|
||||||
|
message(prefix, 'warning', text)
|
||||||
|
|
||||||
|
|
||||||
|
def split_words(name, value, count):
|
||||||
|
words = value.split(None, count)
|
||||||
|
|
||||||
|
if len(words) != count:
|
||||||
|
raise Exception('%s must contain %d values' % (name, count))
|
||||||
|
|
||||||
|
return words
|
||||||
|
|
||||||
|
|
||||||
|
GPL2PLUS_LICENSE = ('' +
|
||||||
|
'This program is free software; you can redistribute it and/or modify it\n' +
|
||||||
|
'under the terms of the GNU General Public License as published by the Free\n' +
|
||||||
|
'Software Foundation; either version 2 of the License, or (at your option)\n' +
|
||||||
|
'any later version.\n' +
|
||||||
|
'\n' +
|
||||||
|
'This program is distributed in the hope that it will be useful, but\n' +
|
||||||
|
'WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n' +
|
||||||
|
'or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n' +
|
||||||
|
'for more details.\n' +
|
||||||
|
'\n' +
|
||||||
|
'You should have received a copy of the GNU General Public License along\n' +
|
||||||
|
'with this program; if not, write to the Free Software Foundation, Inc.,\n' +
|
||||||
|
'51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n')
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2018-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
const fncli = require('./fncli.js');
|
||||||
|
const fnio = require('./fnio.js');
|
||||||
|
const otb1exp = require('./otb1exp.js');
|
||||||
|
|
||||||
|
// -- Params --
|
||||||
|
class Params extends otb1exp.Params {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.output = null;
|
||||||
|
this.encoding = 'utf-8';
|
||||||
|
this.realTime = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Options --
|
||||||
|
const HELP = ('' +
|
||||||
|
'usage: otb1cli [options] [INPUT]\n' +
|
||||||
|
'Convert a BDF font to OTB\n' +
|
||||||
|
'\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout, may not be a terminal)\n' +
|
||||||
|
' -d DIR-HINT set font direction hint (default = 0)\n' +
|
||||||
|
' -e EM-SIZE set em size (default = 1024)\n' +
|
||||||
|
' -g LINE-GAP set line gap (default = 0)\n' +
|
||||||
|
' -l LOW-PPEM set lowest recorded PPEM (default = font height)\n' +
|
||||||
|
' -E ENCODING BDF string properties encoding (default = utf-8)\n' +
|
||||||
|
' -W WLANG-ID set Windows name-s language ID (default = 0x0409)\n' +
|
||||||
|
' -T use the current date and time for created/modified\n' +
|
||||||
|
' (default = get them from INPUT if not stdin/terminal)\n' +
|
||||||
|
' -X set xMaxExtent = 0 (default = max character width)\n' +
|
||||||
|
' -L write a single loca entry (default = CHARS entries)\n' +
|
||||||
|
' -P write PostScript glyph names (default = no names)\n' +
|
||||||
|
'\n' +
|
||||||
|
'Notes:\n' +
|
||||||
|
' The input must be a BDF 2.1 font with unicode encoding.\n' +
|
||||||
|
' All bitmaps are expanded first. Bitmap widths are used.\n' +
|
||||||
|
' Overlapping characters are not supported.\n');
|
||||||
|
|
||||||
|
const VERSION = 'otb1cli 0.22, Copyright (C) 2018-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE;
|
||||||
|
|
||||||
|
class Options extends otb1exp.Options {
|
||||||
|
constructor() {
|
||||||
|
super(['-o', '-E'], HELP, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(name, value, params) {
|
||||||
|
switch (name) {
|
||||||
|
case '-o':
|
||||||
|
params.output = value;
|
||||||
|
break;
|
||||||
|
case '-E':
|
||||||
|
params.encoding = value;
|
||||||
|
break;
|
||||||
|
case '-T':
|
||||||
|
params.realTime = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
super.parse(name, value, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Main --
|
||||||
|
function mainProgram(nonopt, parsed) {
|
||||||
|
if (nonopt.length > 1) {
|
||||||
|
throw new Error('invalid number of arguments, try --help');
|
||||||
|
}
|
||||||
|
|
||||||
|
// READ INPUT
|
||||||
|
let ifs = new fnio.InputFileStream(nonopt[0], parsed.encoding);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (parsed.realTime) {
|
||||||
|
try {
|
||||||
|
const stat = ifs.fstat();
|
||||||
|
|
||||||
|
if (stat != null) {
|
||||||
|
parsed.created = stat.birthtime;
|
||||||
|
parsed.modified = stat.mtime;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
fnutil.warning(ifs.location(), e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var font = otb1exp.Font.read(ifs, parsed);
|
||||||
|
ifs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WRITE OUTPUT
|
||||||
|
let ofs = new fnio.OutputFileStream(parsed.output, null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const table = new otb1exp.SFNT(font);
|
||||||
|
|
||||||
|
ofs.write(table.data.slice(0, table.size));
|
||||||
|
ofs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ofs.location() + e.message + ofs.destroy();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
fncli.start('otb1cli.js', new Options(), new Params(), mainProgram);
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
import fnutil
|
||||||
|
import fncli
|
||||||
|
import fnio
|
||||||
|
import otb1exp
|
||||||
|
|
||||||
|
# -- Params --
|
||||||
|
class Params(otb1exp.Params):
|
||||||
|
def __init__(self):
|
||||||
|
otb1exp.Params.__init__(self)
|
||||||
|
self.output_name = None
|
||||||
|
self.real_time = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options --
|
||||||
|
HELP = ('' +
|
||||||
|
'usage: otb1cli [options] [INPUT]\n' +
|
||||||
|
'Convert a BDF font to OTB\n' +
|
||||||
|
'\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout, may not be a terminal)\n' +
|
||||||
|
' -d DIR-HINT set font direction hint (default = 0)\n' +
|
||||||
|
' -e EM-SIZE set em size (default = 1024)\n' +
|
||||||
|
' -g LINE-GAP set line gap (default = 0)\n' +
|
||||||
|
' -l LOW-PPEM set lowest recorded PPEM (default = font height)\n' +
|
||||||
|
' -E ENCODING BDF string properties encoding (default = utf-8)\n' +
|
||||||
|
' -W WLANG-ID set Windows name-s language ID (default = 0x0409)\n' +
|
||||||
|
' -T use the current date and time for created/modified\n' +
|
||||||
|
' (default = get them from INPUT if not stdin/terminal)\n' +
|
||||||
|
' -X set xMaxExtent = 0 (default = max character width)\n' +
|
||||||
|
' -L write a single loca entry (default = CHARS entries)\n' +
|
||||||
|
' -P write PostScript glyph names (default = no names)\n' +
|
||||||
|
'\n' +
|
||||||
|
'Notes:\n' +
|
||||||
|
' The input must be a BDF 2.1 font with unicode encoding.\n' +
|
||||||
|
' All bitmaps are expanded first. Bitmap widths are used.\n' +
|
||||||
|
' Overlapping characters are not supported.\n')
|
||||||
|
|
||||||
|
VERSION = 'otb1cli 0.24, Copyright (C) 2018-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE
|
||||||
|
|
||||||
|
class Options(otb1exp.Options):
|
||||||
|
def __init__(self):
|
||||||
|
otb1exp.Options.__init__(self, ['-o'], HELP, VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
def parse(self, name, value, params):
|
||||||
|
if name == '-o':
|
||||||
|
params.output_name = value
|
||||||
|
elif name == '-T':
|
||||||
|
params.real_time = False
|
||||||
|
else:
|
||||||
|
otb1exp.Options.parse(self, name, value, params)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Main --
|
||||||
|
def main_program(nonopt, parsed):
|
||||||
|
if len(nonopt) > 1:
|
||||||
|
raise Exception('invalid number of arguments, try --help')
|
||||||
|
|
||||||
|
# READ INPUT
|
||||||
|
def read_otb(ifs):
|
||||||
|
if parsed.real_time:
|
||||||
|
try:
|
||||||
|
stat = ifs.fstat()
|
||||||
|
if stat:
|
||||||
|
parsed.created = datetime.fromtimestamp(stat.st_ctime, timezone.utc)
|
||||||
|
parsed.modified = datetime.fromtimestamp(stat.st_mtime, timezone.utc)
|
||||||
|
except Exception as ex:
|
||||||
|
fnutil.warning(ifs.location(), str(ex))
|
||||||
|
|
||||||
|
return otb1exp.Font.read(ifs, parsed)
|
||||||
|
|
||||||
|
font = fnio.read_file(nonopt[0] if nonopt else None, read_otb)
|
||||||
|
|
||||||
|
# WRITE OUTPUT
|
||||||
|
sfnt = otb1exp.SFNT(font)
|
||||||
|
fnio.write_file(parsed.output_name, lambda ofs: ofs.write(sfnt.data), encoding=None)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fncli.start('otb1cli.py', Options(), Params(), main_program)
|
||||||
@@ -0,0 +1,895 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
const fncli = require('./fncli.js');
|
||||||
|
const bdf = require('./bdf.js');
|
||||||
|
const bdfexp = require('./bdfexp.js');
|
||||||
|
const otb1get = require('./otb1get.js');
|
||||||
|
|
||||||
|
// -- Table --
|
||||||
|
const TS_EMPTY = 0;
|
||||||
|
const TS_SMALL = 64;
|
||||||
|
const TS_LARGE = 1024;
|
||||||
|
|
||||||
|
class Table {
|
||||||
|
constructor(size, name) {
|
||||||
|
this.data = Buffer.alloc(size);
|
||||||
|
this.size = 0;
|
||||||
|
this.tableName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSize(size) {
|
||||||
|
if (size !== this.size) {
|
||||||
|
throw new Error(`internal error: ${this.tableName} size = ${this.size} instead of ${size}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checksum() {
|
||||||
|
let cksum = 0;
|
||||||
|
|
||||||
|
for (let offset = 0; offset < this.size; offset += 4) {
|
||||||
|
cksum += this.data.readUInt32BE(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cksum >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure(count) {
|
||||||
|
if (this.size + count > this.data.length) {
|
||||||
|
let newSize = this.data.length << 1;
|
||||||
|
|
||||||
|
while (this.size + count > newSize) {
|
||||||
|
newSize <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newData = Buffer.alloc(newSize);
|
||||||
|
|
||||||
|
this.data.copy(newData, 0, 0, this.size);
|
||||||
|
this.data = newData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get padding() {
|
||||||
|
return ((this.size + 1) & 3) ^ 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewriteUInt32(value, offset) {
|
||||||
|
this.data.writeUInt32BE(value, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(buffer) {
|
||||||
|
this.ensure(buffer.length);
|
||||||
|
buffer.copy(this.data, this.size);
|
||||||
|
this.size += buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeRC(size, writer, name) {
|
||||||
|
this.ensure(size);
|
||||||
|
try {
|
||||||
|
writer(this.size);
|
||||||
|
} catch (e) {
|
||||||
|
e.message = e.message.replace('"value"', `"${this.tableName}.${name}"`);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
this.size += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeInt8(value, name) {
|
||||||
|
this.writeRC(1, (offset) => this.data.writeInt8(value, offset), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeInt16(value, name) {
|
||||||
|
this.writeRC(2, (offset) => this.data.writeInt16BE(value, offset), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeInt32(value, name) {
|
||||||
|
this.writeRC(4, (offset) => this.data.writeInt32BE(value, offset), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeInt64(value, name) {
|
||||||
|
this.writeRC(8, (offset) => this.data.writeInt64BE(value, offset), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeUInt8(value, name) {
|
||||||
|
this.writeRC(1, (offset) => this.data.writeUInt8(value, offset), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeUInt16(value, name) {
|
||||||
|
this.writeRC(2, (offset) => this.data.writeUInt16BE(value, offset), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeUInt32(value, name) {
|
||||||
|
this.writeRC(4, (offset) => this.data.writeUInt32BE(value, offset), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeUInt48(value, name) {
|
||||||
|
this.writeUInt16(name, 0);
|
||||||
|
this.writeRC(6, (offset) => this.data.writeUIntBE(value, offset, 6), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFixed(value, name) {
|
||||||
|
this.writeRC(4, (offset) => this.data.writeInt32BE(fnutil.round(value * 65536), offset), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeTable(table) {
|
||||||
|
this.write(table.data.slice(0, table.size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Params --
|
||||||
|
const EM_SIZE_MIN = 64;
|
||||||
|
const EM_SIZE_MAX = 16384;
|
||||||
|
const EM_SIZE_DEFAULT = 1024;
|
||||||
|
|
||||||
|
class Params extends fncli.Params {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.created = new Date();
|
||||||
|
this.modified = this.created;
|
||||||
|
this.dirHint = 0;
|
||||||
|
this.emSize = EM_SIZE_DEFAULT;
|
||||||
|
this.lineGap = 0;
|
||||||
|
this.lowPPem = 0;
|
||||||
|
this.wLangId = 0x0409;
|
||||||
|
this.xMaxExtent = true;
|
||||||
|
this.singleLoca = false;
|
||||||
|
this.postNames = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Options --
|
||||||
|
class Options extends fncli.Options {
|
||||||
|
constructor(needArgs, helpText, versionText) {
|
||||||
|
super(needArgs.concat(['-d', '-e', '-g', '-l', '-W']), helpText, versionText);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(name, value, params) {
|
||||||
|
switch (name) {
|
||||||
|
case '-d':
|
||||||
|
params.dirHint = fnutil.parseDec('DIR-HINT', value, -2, 2);
|
||||||
|
break;
|
||||||
|
case '-e':
|
||||||
|
params.emSize = fnutil.parseDec('EM-SIZE', value, EM_SIZE_MIN, EM_SIZE_MAX);
|
||||||
|
break;
|
||||||
|
case '-g':
|
||||||
|
params.lineGap = fnutil.parseDec('LINE-GAP', value, 0, EM_SIZE_MAX << 1);
|
||||||
|
break;
|
||||||
|
case '-l':
|
||||||
|
params.lowPPem = fnutil.parseDec('LOW-PPEM', value, 1, bdf.DPARSE_LIMIT);
|
||||||
|
break;
|
||||||
|
case '-W':
|
||||||
|
params.wLangId = fnutil.parseHex('WLANG-ID', value, 0, 0x7FFF);
|
||||||
|
break;
|
||||||
|
case '-X':
|
||||||
|
params.xMaxExtent = false;
|
||||||
|
break;
|
||||||
|
case '-L':
|
||||||
|
params.singleLoca = true;
|
||||||
|
break;
|
||||||
|
case '-P':
|
||||||
|
params.postNames = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.fallback(name, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Font --
|
||||||
|
class Font extends bdfexp.Font {
|
||||||
|
constructor(params) {
|
||||||
|
super();
|
||||||
|
this.params = params;
|
||||||
|
this.emAscender = 0;
|
||||||
|
this.emDescender = 0;
|
||||||
|
this.emMaxWidth = 0;
|
||||||
|
this.macStyle = 0;
|
||||||
|
this.lineSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get bmpOnly() {
|
||||||
|
return this.maxCode <= fnutil.UNICODE_BMP_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
get created() {
|
||||||
|
return Font.sfntime(this.params.created);
|
||||||
|
}
|
||||||
|
|
||||||
|
emScale(value, divisor) {
|
||||||
|
return fnutil.round(value * this.params.emSize / (divisor || this.bbx.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
get italicAngle() {
|
||||||
|
const value = this.props.get('ITALIC_ANGLE'); // must be integer
|
||||||
|
return value != null ? fnutil.parseDec('ITALIC_ANGLE', value, -45, 45) : this.italic ? -11.5 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get maxCode() {
|
||||||
|
return this.chars.slice(-1)[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
|
get minCode() {
|
||||||
|
return this.chars[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
|
get modified() {
|
||||||
|
return Font.sfntime(this.params.modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare() {
|
||||||
|
this.chars.sort((c1, c2) => c1.code - c2.code);
|
||||||
|
this.chars = this.chars.filter((c, index, array) => index === 0 || c.code !== array[index - 1].code);
|
||||||
|
this.props.set('CHARS', this.chars.length);
|
||||||
|
this.emAscender = this.emScale(this.pxAscender);
|
||||||
|
this.emDescender = this.emAscender - this.params.emSize;
|
||||||
|
this.emMaxWidth = this.emScaleWidth(this);
|
||||||
|
this.macStyle = Number(this.bold) + (Number(this.italic) << 1);
|
||||||
|
this.lineSize = this.emScale(fnutil.round(this.bbx.height / 17) || 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
_read(input) {
|
||||||
|
super._read(input);
|
||||||
|
this.prepare();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static read(input, params) {
|
||||||
|
return (new Font(params))._read(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
emScaleWidth(base) {
|
||||||
|
return this.emScale(base.bbx.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
static sfntime(stamp) {
|
||||||
|
return Math.floor((stamp - Date.UTC(1904, 0, 1)) / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
get underlinePosition() {
|
||||||
|
return fnutil.round((this.emDescender + this.lineSize) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
get xMaxExtent() {
|
||||||
|
return this.params.xMaxExtent ? this.emMaxWidth : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- BDAT --
|
||||||
|
const BDAT_HEADER_SIZE = 4;
|
||||||
|
const BDAT_METRIC_SIZE = 5;
|
||||||
|
|
||||||
|
class BDAT extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_LARGE, 'EBDT');
|
||||||
|
// header
|
||||||
|
this.writeFixed(2, 'version');
|
||||||
|
// format 1 data
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
this.writeUInt8(font.bbx.height, 'height');
|
||||||
|
this.writeUInt8(char.bbx.width, 'width');
|
||||||
|
this.writeInt8(0, 'bearingX');
|
||||||
|
this.writeInt8(font.pxAscender, 'bearingY');
|
||||||
|
this.writeUInt8(char.bbx.width, 'advance');
|
||||||
|
this.write(char.data); // imageData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static getCharSize(char) {
|
||||||
|
return BDAT_METRIC_SIZE + char.data.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- BLOC --
|
||||||
|
const BLOC_TABLE_SIZE_OFFSET = 12;
|
||||||
|
const BLOC_PREFIX_SIZE = 0x38; // header 0x08 + 1 bitmapSizeTable * 0x30
|
||||||
|
const BLOC_INDEX_ARRAY_SIZE = 8; // 1 index record * 0x08
|
||||||
|
|
||||||
|
class BLOC extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_SMALL, 'EBLC');
|
||||||
|
// header
|
||||||
|
this.writeFixed(2, 'version');
|
||||||
|
this.writeUInt32(1, 'numSizes');
|
||||||
|
// bitmapSizeTable
|
||||||
|
this.writeUInt32(BLOC_PREFIX_SIZE, 'indexSubTableArrayOffset');
|
||||||
|
this.writeUInt32(0, 'indexTableSize'); // adjusted later
|
||||||
|
this.writeUInt32(1, 'numberOfIndexSubTables');
|
||||||
|
this.writeUInt32(0, 'colorRef');
|
||||||
|
// hori
|
||||||
|
this.writeInt8(font.pxAscender, 'hori ascender');
|
||||||
|
this.writeInt8(font.pxDescender, 'hori descender');
|
||||||
|
this.writeUInt8(font.bbx.width, 'hori widthMax');
|
||||||
|
this.writeInt8(1, 'hori caretSlopeNumerator');
|
||||||
|
this.writeInt8(0, 'hori caretSlopeDenominator');
|
||||||
|
this.writeInt8(0, 'hori caretOffset');
|
||||||
|
this.writeInt8(0, 'hori minOriginSB');
|
||||||
|
this.writeInt8(0, 'hori minAdvanceSB');
|
||||||
|
this.writeInt8(font.pxAscender, 'hori maxBeforeBL');
|
||||||
|
this.writeInt8(font.pxDescender, 'hori minAfterBL');
|
||||||
|
this.writeInt16(0, 'hori padd');
|
||||||
|
// vert
|
||||||
|
this.writeInt8(0, 'vert ascender');
|
||||||
|
this.writeInt8(0, 'vert descender');
|
||||||
|
this.writeUInt8(0, 'vert widthMax');
|
||||||
|
this.writeInt8(0, 'vert caretSlopeNumerator');
|
||||||
|
this.writeInt8(0, 'vert caretSlopeDenominator');
|
||||||
|
this.writeInt8(0, 'vert caretOffset');
|
||||||
|
this.writeInt8(0, 'vert minOriginSB');
|
||||||
|
this.writeInt8(0, 'vert minAdvanceSB');
|
||||||
|
this.writeInt8(0, 'vert maxBeforeBL');
|
||||||
|
this.writeInt8(0, 'vert minAfterBL');
|
||||||
|
this.writeInt16(0, 'vert padd');
|
||||||
|
// (bitmapSizeTable)
|
||||||
|
this.writeUInt16(0, 'startGlyphIndex');
|
||||||
|
this.writeUInt16(font.chars.length - 1, 'endGlyphIndex');
|
||||||
|
this.writeUInt8(font.bbx.height, 'ppemX');
|
||||||
|
this.writeUInt8(font.bbx.height, 'ppemY');
|
||||||
|
this.writeUInt8(1, 'bitDepth');
|
||||||
|
this.writeUInt8(1, 'flags'); // small metrics are horizontal
|
||||||
|
// indexSubTableArray
|
||||||
|
this.writeUInt16(0, 'firstGlyphIndex');
|
||||||
|
this.writeUInt16(font.chars.length - 1, 'lastGlyphIndex');
|
||||||
|
this.writeUInt32(BLOC_INDEX_ARRAY_SIZE, 'additionalOffsetToIndexSubtable');
|
||||||
|
// indexSubtableHeader
|
||||||
|
this.writeUInt16(font.proportional ? 1 : 2, 'indexFormat');
|
||||||
|
this.writeUInt16(1, 'imageFormat'); // BDAT -> small metrics, byte-aligned
|
||||||
|
this.writeUInt32(BDAT_HEADER_SIZE, 'imageDataOffset');
|
||||||
|
// indexSubtable data
|
||||||
|
if (font.proportional) {
|
||||||
|
let offset = 0;
|
||||||
|
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
this.writeUInt32(offset, 'offsetArray[]');
|
||||||
|
offset += BDAT.getCharSize(char);
|
||||||
|
});
|
||||||
|
this.writeUInt32(offset, 'offsetArray[]');
|
||||||
|
} else {
|
||||||
|
this.writeUInt32(BDAT.getCharSize(font.chars[0]), 'imageSize');
|
||||||
|
this.writeUInt8(font.bbx.height, 'height');
|
||||||
|
this.writeUInt8(font.bbx.width, 'width');
|
||||||
|
this.writeInt8(0, 'horiBearingX');
|
||||||
|
this.writeInt8(font.pxAscender, 'horiBearingY');
|
||||||
|
this.writeUInt8(font.bbx.width, 'horiAdvance');
|
||||||
|
this.writeInt8(-(font.bbx.width >> 1), 'vertBearingX');
|
||||||
|
this.writeInt8(0, 'vertBearingY');
|
||||||
|
this.writeUInt8(font.bbx.height, 'vertAdvance');
|
||||||
|
}
|
||||||
|
// adjust
|
||||||
|
this.rewriteUInt32(this.size - BLOC_PREFIX_SIZE, BLOC_TABLE_SIZE_OFFSET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- OS/2 --
|
||||||
|
const OS_2_TABLE_SIZE = 96;
|
||||||
|
|
||||||
|
class OS_2 extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_SMALL, 'OS/2');
|
||||||
|
// Version 4
|
||||||
|
const xAvgCharWidth = font.emScale(font.avgWidth); // otb1get.xAvgCharWidth(font);
|
||||||
|
const ulCharRanges = otb1get.ulCharRanges(font);
|
||||||
|
const ulCodePages = font.bmpOnly ? otb1get.ulCodePages(font) : [0, 0];
|
||||||
|
// mostly from FontForge
|
||||||
|
const scriptXSize = font.emScale(30, 100);
|
||||||
|
const scriptYSize = font.emScale(40, 100);
|
||||||
|
const subscriptYOff = scriptYSize >> 1;
|
||||||
|
const xfactor = Math.tan(font.italicAngle * Math.PI / 180);
|
||||||
|
const subscriptXOff = 0; // stub, no overlapping characters yet
|
||||||
|
const superscriptYOff = font.emAscender - scriptYSize;
|
||||||
|
const superscriptXOff = -fnutil.round(xfactor * superscriptYOff);
|
||||||
|
// write
|
||||||
|
this.writeUInt16(4, 'version');
|
||||||
|
this.writeInt16(xAvgCharWidth, 'xAvgCharWidth');
|
||||||
|
this.writeUInt16(font.bold ? 700 : 400, 'usWeightClass');
|
||||||
|
this.writeUInt16(5, 'usWidthClass'); // medium
|
||||||
|
this.writeInt16(0, 'fsType');
|
||||||
|
this.writeInt16(scriptXSize, 'ySubscriptXSize');
|
||||||
|
this.writeInt16(scriptYSize, 'ySubscriptYSize');
|
||||||
|
this.writeInt16(subscriptXOff, 'ySubscriptXOffset');
|
||||||
|
this.writeInt16(subscriptYOff, 'ySubscriptYOffset');
|
||||||
|
this.writeInt16(scriptXSize, 'ySuperscriptXSize');
|
||||||
|
this.writeInt16(scriptYSize, 'ySuperscriptYSize');
|
||||||
|
this.writeInt16(superscriptXOff, 'ySuperscriptXOffset');
|
||||||
|
this.writeInt16(superscriptYOff, 'ySuperscriptYOffset');
|
||||||
|
this.writeInt16(font.lineSize, 'yStrikeoutSize');
|
||||||
|
this.writeInt16(font.emScale(25, 100), 'yStrikeoutPosition');
|
||||||
|
this.writeInt16(0, 'sFamilyClass'); // no classification
|
||||||
|
this.writeUInt8(2, 'bFamilyType'); // text and display
|
||||||
|
this.writeUInt8(0, 'bSerifStyle'); // any
|
||||||
|
this.writeUInt8(font.bold ? 8 : 6, 'bWeight');
|
||||||
|
this.writeUInt8(font.proportional ? 3 : 9, 'bProportion');
|
||||||
|
this.writeUInt8(0, 'bContrast');
|
||||||
|
this.writeUInt8(0, 'bStrokeVariation');
|
||||||
|
this.writeUInt8(0, 'bArmStyle');
|
||||||
|
this.writeUInt8(0, 'bLetterform');
|
||||||
|
this.writeUInt8(0, 'bMidline');
|
||||||
|
this.writeUInt8(0, 'bXHeight');
|
||||||
|
this.writeUInt32(ulCharRanges[0], 'ulCharRange1');
|
||||||
|
this.writeUInt32(ulCharRanges[1], 'ulCharRange2');
|
||||||
|
this.writeUInt32(ulCharRanges[2], 'ulCharRange3');
|
||||||
|
this.writeUInt32(ulCharRanges[3], 'ulCharRange4');
|
||||||
|
this.writeUInt32(0x586F7334, 'achVendID'); // 'Xos4'
|
||||||
|
this.writeUInt16(OS_2.fsSelection(font), 'fsSelection');
|
||||||
|
this.writeUInt16(Math.min(font.minCode, fnutil.UNICODE_BMP_MAX), 'firstChar');
|
||||||
|
this.writeUInt16(Math.min(font.maxCode, fnutil.UNICODE_BMP_MAX), 'lastChar');
|
||||||
|
this.writeInt16(font.emAscender, 'sTypoAscender');
|
||||||
|
this.writeInt16(font.emDescender, 'sTypoDescender');
|
||||||
|
this.writeInt16(font.params.lineGap, 'sTypoLineGap');
|
||||||
|
this.writeUInt16(font.emAscender, 'usWinAscent');
|
||||||
|
this.writeUInt16(-font.emDescender, 'usWinDescent');
|
||||||
|
this.writeUInt32(ulCodePages[0], 'ulCodePageRange1');
|
||||||
|
this.writeUInt32(ulCodePages[1], 'ulCodePageRange2');
|
||||||
|
this.writeInt16(font.emScale(font.pxAscender * 0.6), 'sxHeight'); // stub
|
||||||
|
this.writeInt16(font.emScale(font.pxAscender * 0.8), 'sCapHeight'); // stub
|
||||||
|
this.writeUInt16(OS_2.defaultChar(font), 'usDefaultChar');
|
||||||
|
this.writeUInt16(OS_2.breakChar(font), 'usBreakChar');
|
||||||
|
this.writeUInt16(1, 'usMaxContext');
|
||||||
|
// check
|
||||||
|
this.checkSize(OS_2_TABLE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static breakChar(font) {
|
||||||
|
return font.chars.findIndex(char => char.code === 0x20) !== -1 ? 0x20 : font.minCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultChar(font) {
|
||||||
|
if (font.defaultCode !== -1 && font.defaultCode <= fnutil.UNICODE_BMP_MAX) {
|
||||||
|
return font.defaultCode;
|
||||||
|
}
|
||||||
|
return font.minCode && font.maxCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fsSelection(font) {
|
||||||
|
const fsSelection = Number(font.bold) * 5 + Number(font.italic);
|
||||||
|
return fsSelection || (font.xlfd[bdf.XLFD.SLANT] === 'R' ? 0x40 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- cmap --
|
||||||
|
const CMAP_4_PREFIX_SIZE = 12;
|
||||||
|
const CMAP_4_FORMAT_SIZE = 16;
|
||||||
|
const CMAP_4_SEGMENT_SIZE = 8;
|
||||||
|
|
||||||
|
const CMAP_12_PREFIX_SIZE = 20;
|
||||||
|
const CMAP_12_FORMAT_SIZE = 16;
|
||||||
|
const CMAP_12_GROUP_SIZE = 12;
|
||||||
|
|
||||||
|
class CMapRange {
|
||||||
|
constructor(glyphIndex = 0, startCode = 0, finalCode = -2) {
|
||||||
|
this.glyphIndex = glyphIndex;
|
||||||
|
this.startCode = startCode;
|
||||||
|
this.finalCode = finalCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
get idDelta() {
|
||||||
|
return (this.glyphIndex - this.startCode) & 0xFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CMAP extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_LARGE, 'cmap');
|
||||||
|
// make ranges
|
||||||
|
let ranges = [];
|
||||||
|
let range = new CMapRange();
|
||||||
|
|
||||||
|
for (let index = 0; index < font.chars.length; index++) {
|
||||||
|
let code = font.chars[index].code;
|
||||||
|
|
||||||
|
if (code === range.finalCode + 1) {
|
||||||
|
range.finalCode++;
|
||||||
|
} else {
|
||||||
|
range = new CMapRange(index, code, code);
|
||||||
|
ranges.push(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// write
|
||||||
|
if (font.bmpOnly) {
|
||||||
|
if (font.maxCode < 0xFFFF) {
|
||||||
|
ranges.push(new CMapRange(0, 0xFFFF, 0xFFFF));
|
||||||
|
}
|
||||||
|
this.writeFormat4(ranges);
|
||||||
|
} else {
|
||||||
|
this.writeFormat12(ranges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFormat4(ranges) {
|
||||||
|
// index
|
||||||
|
this.writeUInt16(0, 'version');
|
||||||
|
this.writeUInt16(1, 'numberSubtables');
|
||||||
|
// encoding subtables index
|
||||||
|
this.writeUInt16(3, 'platformID'); // Microsoft
|
||||||
|
this.writeUInt16(1, 'platformSpecificID'); // Unicode BMP (UCS-2)
|
||||||
|
this.writeUInt32(CMAP_4_PREFIX_SIZE, 'offset'); // for Unicode BMP (UCS-2)
|
||||||
|
// cmap format 4
|
||||||
|
const segCount = ranges.length;
|
||||||
|
const subtableSize = CMAP_4_FORMAT_SIZE + segCount * CMAP_4_SEGMENT_SIZE;
|
||||||
|
const searchRange = 2 << Math.floor(Math.log2(segCount));
|
||||||
|
|
||||||
|
this.writeUInt16(4, 'format');
|
||||||
|
this.writeUInt16(subtableSize, 'length');
|
||||||
|
this.writeUInt16(0, 'language'); // none/independent
|
||||||
|
this.writeUInt16(segCount * 2, 'segCountX2');
|
||||||
|
this.writeUInt16(searchRange, 'searchRange');
|
||||||
|
this.writeUInt16(Math.log2(searchRange / 2), 'entrySelector');
|
||||||
|
this.writeUInt16((segCount * 2) - searchRange, 'rangeShift');
|
||||||
|
ranges.forEach(range => {
|
||||||
|
this.writeUInt16(range.finalCode, 'endCode');
|
||||||
|
});
|
||||||
|
this.writeUInt16(0, 'reservedPad');
|
||||||
|
ranges.forEach(range => {
|
||||||
|
this.writeUInt16(range.startCode, 'startCode');
|
||||||
|
});
|
||||||
|
ranges.forEach(range => {
|
||||||
|
this.writeUInt16(range.idDelta, 'idDelta');
|
||||||
|
});
|
||||||
|
ranges.forEach(() => this.writeUInt16(0), 'idRangeOffset');
|
||||||
|
// check
|
||||||
|
this.checkSize(CMAP_4_PREFIX_SIZE + subtableSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFormat12(ranges) {
|
||||||
|
// index
|
||||||
|
this.writeUInt16(0, 'version');
|
||||||
|
this.writeUInt16(2, 'numberSubtables');
|
||||||
|
// encoding subtables
|
||||||
|
this.writeUInt16(0, 'platformID'); // Unicode
|
||||||
|
this.writeUInt16(4, 'platformSpecificID'); // Unicode 2.0+ full range
|
||||||
|
this.writeUInt32(CMAP_12_PREFIX_SIZE, 'offset'); // for Unicode 2.0+ full range
|
||||||
|
this.writeUInt16(3, 'platformID'); // Microsoft
|
||||||
|
this.writeUInt16(10, 'platformSpecificID'); // Unicode UCS-4
|
||||||
|
this.writeUInt32(CMAP_12_PREFIX_SIZE, 'offset'); // for Unicode UCS-4
|
||||||
|
// cmap format 12
|
||||||
|
const subtableSize = CMAP_12_FORMAT_SIZE + ranges.length * CMAP_12_GROUP_SIZE;
|
||||||
|
|
||||||
|
this.writeFixed(12, 'format');
|
||||||
|
this.writeUInt32(subtableSize, 'length');
|
||||||
|
this.writeUInt32(0, 'language'); // none/independent
|
||||||
|
this.writeUInt32(ranges.length, 'nGroups');
|
||||||
|
this.ranges.forEach(range => {
|
||||||
|
this.writeUInt32(range.startCode, 'startCharCode');
|
||||||
|
this.writeUInt32(range.finalCode, 'endCharCode');
|
||||||
|
this.writeUInt32(range.glyphIndex, 'startGlyphID');
|
||||||
|
});
|
||||||
|
// check
|
||||||
|
this.checkSize(CMAP_12_PREFIX_SIZE + subtableSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- glyf --
|
||||||
|
class GLYF extends Table {
|
||||||
|
constructor() {
|
||||||
|
super(TS_EMPTY, 'glyf');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- head --
|
||||||
|
const HEAD_TABLE_SIZE = 54;
|
||||||
|
const HEAD_CHECKSUM_OFFSET = 8;
|
||||||
|
|
||||||
|
class HEAD extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_SMALL, 'head');
|
||||||
|
this.writeFixed(1, 'version');
|
||||||
|
this.writeFixed(1, 'fontRevision');
|
||||||
|
this.writeUInt32(0, 'checksumAdjustment'); // adjusted later
|
||||||
|
this.writeUInt32(0x5F0F3CF5, 'magicNumber');
|
||||||
|
this.writeUInt16(HEAD.flags(font), 'flags');
|
||||||
|
this.writeUInt16(font.params.emSize, 'unitsPerEm');
|
||||||
|
this.writeUInt48(font.created, 'created');
|
||||||
|
this.writeUInt48(font.modified, 'modified');
|
||||||
|
this.writeInt16(0, 'xMin');
|
||||||
|
this.writeInt16(font.emDescender, 'yMin');
|
||||||
|
this.writeInt16(font.emMaxWidth, 'xMax');
|
||||||
|
this.writeInt16(font.emAscender, 'yMax');
|
||||||
|
this.writeUInt16(font.macStyle, 'macStyle');
|
||||||
|
this.writeUInt16(font.params.lowPPem || font.bbx.height, 'lowestRecPPEM');
|
||||||
|
this.writeInt16(font.params.dirHint, 'fontDirectionHint');
|
||||||
|
this.writeInt16(0, 'indexToLocFormat'); // short
|
||||||
|
this.writeInt16(0, 'glyphDataFormat'); // current
|
||||||
|
// check
|
||||||
|
this.checkSize(HEAD_TABLE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static flags(font) {
|
||||||
|
return otb1get.containsRTL(font) ? 0x020B : 0x0B; // y0 base, x0 lsb, scale int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- hhea --
|
||||||
|
const HHEA_TABLE_SIZE = 36;
|
||||||
|
|
||||||
|
class HHEA extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_SMALL, 'hhea');
|
||||||
|
this.writeFixed(1, 'version');
|
||||||
|
this.writeInt16(font.emAscender, 'ascender');
|
||||||
|
this.writeInt16(font.emDescender, 'descender');
|
||||||
|
this.writeInt16(font.params.lineGap, 'lineGap');
|
||||||
|
this.writeUInt16(font.emMaxWidth, 'advanceWidthMax');
|
||||||
|
this.writeInt16(0, 'minLeftSideBearing');
|
||||||
|
this.writeInt16(0, 'minRightSideBearing');
|
||||||
|
this.writeInt16(font.xMaxExtent, 'xMaxExtent');
|
||||||
|
this.writeInt16(font.italic ? 100 : 1, 'caretSlopeRise');
|
||||||
|
this.writeInt16(font.italic ? 20 : 0, 'caretSlopeRun');
|
||||||
|
this.writeInt16(0, 'caretOffset');
|
||||||
|
this.writeInt16(0, 'reserved');
|
||||||
|
this.writeInt16(0, 'reserved');
|
||||||
|
this.writeInt16(0, 'reserved');
|
||||||
|
this.writeInt16(0, 'reserved');
|
||||||
|
this.writeInt16(0, 'metricDataFormat'); // current
|
||||||
|
this.writeUInt16(font.chars.length, 'numOfLongHorMetrics');
|
||||||
|
// check
|
||||||
|
this.checkSize(HHEA_TABLE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- hmtx --
|
||||||
|
class HMTX extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_LARGE, 'hmtx');
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
this.writeUInt16(font.emScaleWidth(char), 'advanceWidth');
|
||||||
|
this.writeInt16(0, 'leftSideBearing');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- loca --
|
||||||
|
class LOCA extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_SMALL, 'loca');
|
||||||
|
if (!font.params.singleLoca) {
|
||||||
|
font.chars.forEach(() => this.writeUInt16(0, 'offset'));
|
||||||
|
}
|
||||||
|
this.writeUInt16(0, 'offset');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- maxp --
|
||||||
|
const MAXP_TABLE_SIZE = 32;
|
||||||
|
|
||||||
|
class MAXP extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_SMALL, 'maxp');
|
||||||
|
this.writeFixed(1, 'version');
|
||||||
|
this.writeUInt16(font.chars.length, 'numGlyphs');
|
||||||
|
this.writeUInt16(0, 'maxPoints');
|
||||||
|
this.writeUInt16(0, 'maxContours');
|
||||||
|
this.writeUInt16(0, 'maxComponentPoints');
|
||||||
|
this.writeUInt16(0, 'maxComponentContours');
|
||||||
|
this.writeUInt16(2, 'maxZones');
|
||||||
|
this.writeUInt16(0, 'maxTwilightPoints');
|
||||||
|
this.writeUInt16(1, 'maxStorage');
|
||||||
|
this.writeUInt16(1, 'maxFunctionDefs');
|
||||||
|
this.writeUInt16(0, 'maxInstructionDefs');
|
||||||
|
this.writeUInt16(64, 'maxStackElements');
|
||||||
|
this.writeUInt16(0, 'maxSizeOfInstructions');
|
||||||
|
this.writeUInt16(0, 'maxComponentElements');
|
||||||
|
this.writeUInt16(0, 'maxComponentDepth');
|
||||||
|
// check
|
||||||
|
this.checkSize(MAXP_TABLE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- name --
|
||||||
|
const NAME_ID = {
|
||||||
|
COPYRIGHT: 0,
|
||||||
|
FONT_FAMILY: 1,
|
||||||
|
FONT_SUBFAMILY: 2,
|
||||||
|
UNIQUE_SUBFAMILY: 3,
|
||||||
|
FULL_FONT_NAME: 4,
|
||||||
|
LICENSE: 14
|
||||||
|
};
|
||||||
|
|
||||||
|
const NAME_HEADER_SIZE = 6;
|
||||||
|
const NAME_RECORD_SIZE = 12;
|
||||||
|
|
||||||
|
class NAME extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_LARGE, 'name');
|
||||||
|
// compute names
|
||||||
|
let names = new Map();
|
||||||
|
const copyright = font.props.get('COPYRIGHT');
|
||||||
|
|
||||||
|
if (copyright != null) {
|
||||||
|
names.set(NAME_ID.COPYRIGHT, fnutil.unquote(copyright));
|
||||||
|
}
|
||||||
|
|
||||||
|
const family = font.xlfd[bdf.XLFD.FAMILY_NAME];
|
||||||
|
const style = ['Regular', 'Bold', 'Italic', 'Bold Italic'][font.macStyle];
|
||||||
|
|
||||||
|
names.set(NAME_ID.FONT_FAMILY, family);
|
||||||
|
names.set(NAME_ID.FONT_SUBFAMILY, style);
|
||||||
|
names.set(NAME_ID.UNIQUE_SUBFAMILY, `${family} ${style} bitmap height ${font.bbx.height}`);
|
||||||
|
names.set(NAME_ID.FULL_FONT_NAME, `${family} ${style}`);
|
||||||
|
|
||||||
|
let license = font.props.get('LICENSE');
|
||||||
|
const notice = font.props.get('NOTICE');
|
||||||
|
|
||||||
|
if (license == null && notice != null && notice.toLowerCase().includes('license')) {
|
||||||
|
license = notice;
|
||||||
|
}
|
||||||
|
if (license != null) {
|
||||||
|
names.set(NAME_ID.LICENSE, fnutil.unquote(license));
|
||||||
|
}
|
||||||
|
// header
|
||||||
|
const count = names.size * (1 + 1); // Unicode + Microsoft
|
||||||
|
const stringOffset = NAME_HEADER_SIZE + NAME_RECORD_SIZE * count;
|
||||||
|
|
||||||
|
this.writeUInt16(0, 'format');
|
||||||
|
this.writeUInt16(count, 'count');
|
||||||
|
this.writeUInt16(stringOffset, 'stringOffset');
|
||||||
|
// name records / create values
|
||||||
|
let values = new Table(TS_LARGE, 'name');
|
||||||
|
|
||||||
|
names.forEach((str, nameID) => {
|
||||||
|
const value = Buffer.from(str, 'utf16le').swap16();
|
||||||
|
const bmp = font.bmpOnly && value.length === str.length * 2;
|
||||||
|
// Unicode
|
||||||
|
this.writeUInt16(0, 'platformID'); // Unicode
|
||||||
|
this.writeUInt16(bmp ? 3 : 4, 'platformSpecificID');
|
||||||
|
this.writeUInt16(0, 'languageID');
|
||||||
|
this.writeUInt16(nameID, 'nameID');
|
||||||
|
this.writeUInt16(value.length, 'length'); // in bytes
|
||||||
|
this.writeUInt16(values.size, 'offset');
|
||||||
|
// Windows
|
||||||
|
this.writeUInt16(3, 'platformID'); // Microsoft
|
||||||
|
this.writeUInt16(bmp ? 1 : 10, 'platformSpecificID');
|
||||||
|
this.writeUInt16(font.params.wLangId, 'languageID');
|
||||||
|
this.writeUInt16(nameID, 'nameID');
|
||||||
|
this.writeUInt16(value.length, 'length'); // in bytes
|
||||||
|
this.writeUInt16(values.size, 'offset');
|
||||||
|
// value
|
||||||
|
values.write(value);
|
||||||
|
});
|
||||||
|
// write values
|
||||||
|
this.writeTable(values);
|
||||||
|
// check
|
||||||
|
this.checkSize(stringOffset + values.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- post --
|
||||||
|
const POST_TABLE_SIZE = 32;
|
||||||
|
|
||||||
|
class POST extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_SMALL, 'post');
|
||||||
|
this.writeFixed(font.params.postNames ? 2 : 3, 'format');
|
||||||
|
this.writeFixed(font.italicAngle, 'italicAngle');
|
||||||
|
this.writeInt16(font.underlinePosition, 'underlinePosition');
|
||||||
|
this.writeInt16(font.lineSize, 'underlineThickness');
|
||||||
|
this.writeUInt32(font.proportional ? 0 : 1, 'isFixedPitch');
|
||||||
|
this.writeUInt32(0, 'minMemType42');
|
||||||
|
this.writeUInt32(0, 'maxMemType42');
|
||||||
|
this.writeUInt32(0, 'minMemType1');
|
||||||
|
this.writeUInt32(0, 'maxMemType1');
|
||||||
|
// names
|
||||||
|
if (font.params.postNames) {
|
||||||
|
let postNames = otb1get.postMacNames();
|
||||||
|
const postMacCount = postNames.length;
|
||||||
|
|
||||||
|
this.writeUInt16(font.chars.length, 'numberOfGlyphs');
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
const name = char.props.get('STARTCHAR');
|
||||||
|
const index = postNames.indexOf(name);
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
this.writeUInt16(index, 'glyphNameIndex');
|
||||||
|
} else {
|
||||||
|
this.writeUInt16(postNames.length, 'glyphNameIndex');
|
||||||
|
postNames.push(name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
postNames.slice(postMacCount).forEach(name => {
|
||||||
|
this.writeUInt8(name.length, 'glyphNameLength');
|
||||||
|
this.write(Buffer.from(name, 'binary'));
|
||||||
|
});
|
||||||
|
// check
|
||||||
|
} else {
|
||||||
|
this.checkSize(POST_TABLE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- SFNT --
|
||||||
|
const SFNT_HEADER_SIZE = 12;
|
||||||
|
const SFNT_RECORD_SIZE = 16;
|
||||||
|
const SFNT_SUBTABLES = [ BDAT, BLOC, OS_2, CMAP, GLYF, HEAD, HHEA, HMTX, LOCA, MAXP, NAME, POST ];
|
||||||
|
|
||||||
|
class SFNT extends Table {
|
||||||
|
constructor(font) {
|
||||||
|
super(TS_LARGE, 'SFNT');
|
||||||
|
// create tables
|
||||||
|
let tables = [];
|
||||||
|
|
||||||
|
SFNT_SUBTABLES.forEach(Ctor => {
|
||||||
|
tables.push(new Ctor(font));
|
||||||
|
});
|
||||||
|
// header
|
||||||
|
const numTables = tables.length;
|
||||||
|
const entrySelector = Math.floor(Math.log2(numTables));
|
||||||
|
const searchRange = 16 << entrySelector;
|
||||||
|
const contentOffset = SFNT_HEADER_SIZE + numTables * SFNT_RECORD_SIZE;
|
||||||
|
let offset = contentOffset;
|
||||||
|
let content = new Table(TS_LARGE, 'SFNT');
|
||||||
|
let headChecksumOffset = -1;
|
||||||
|
|
||||||
|
this.writeFixed(1, 'sfntVersion');
|
||||||
|
this.writeUInt16(numTables, 'numTables');
|
||||||
|
this.writeUInt16(searchRange, 'searchRange');
|
||||||
|
this.writeUInt16(entrySelector, 'entrySelector');
|
||||||
|
this.writeUInt16(numTables * 16 - searchRange, 'rangeShift');
|
||||||
|
// table records / create content
|
||||||
|
tables.forEach(table => {
|
||||||
|
this.write(Buffer.from(table.tableName, 'binary'));
|
||||||
|
this.writeUInt32(table.checksum(), 'checkSum');
|
||||||
|
this.writeUInt32(offset, 'offset');
|
||||||
|
this.writeUInt32(table.size, 'length');
|
||||||
|
// create content
|
||||||
|
if (table.tableName === 'head') {
|
||||||
|
headChecksumOffset = offset + HEAD_CHECKSUM_OFFSET;
|
||||||
|
}
|
||||||
|
const paddedSize = table.size + table.padding;
|
||||||
|
|
||||||
|
content.write(table.data.slice(0, paddedSize));
|
||||||
|
offset += paddedSize;
|
||||||
|
});
|
||||||
|
// write content
|
||||||
|
this.writeTable(content);
|
||||||
|
// check
|
||||||
|
this.checkSize(contentOffset + content.size);
|
||||||
|
// adjust
|
||||||
|
if (headChecksumOffset !== -1) {
|
||||||
|
this.rewriteUInt32((0xB1B0AFBA - this.checksum()) >>> 0, headChecksumOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Export --
|
||||||
|
module.exports = Object.freeze({
|
||||||
|
TS_EMPTY,
|
||||||
|
TS_SMALL,
|
||||||
|
TS_LARGE,
|
||||||
|
Table,
|
||||||
|
EM_SIZE_MIN,
|
||||||
|
EM_SIZE_MAX,
|
||||||
|
EM_SIZE_DEFAULT,
|
||||||
|
Params,
|
||||||
|
Options,
|
||||||
|
Font,
|
||||||
|
BDAT,
|
||||||
|
BLOC,
|
||||||
|
OS_2,
|
||||||
|
CMAP,
|
||||||
|
GLYF,
|
||||||
|
HEAD,
|
||||||
|
HHEA,
|
||||||
|
HMTX,
|
||||||
|
LOCA,
|
||||||
|
MAXP,
|
||||||
|
NAME,
|
||||||
|
POST,
|
||||||
|
SFNT
|
||||||
|
});
|
||||||
@@ -0,0 +1,808 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import struct
|
||||||
|
import codecs
|
||||||
|
import math
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
from itertools import groupby
|
||||||
|
from enum import IntEnum, unique
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
import fnutil
|
||||||
|
import fncli
|
||||||
|
import bdf
|
||||||
|
import bdfexp
|
||||||
|
import otb1get
|
||||||
|
|
||||||
|
# -- Table --
|
||||||
|
class Table:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.data = bytearray(0)
|
||||||
|
self.table_name = name
|
||||||
|
|
||||||
|
|
||||||
|
def check_size(self, size):
|
||||||
|
if size != self.size:
|
||||||
|
raise Exception('internal error: %s size = %d instead of %d' % (self.table_name, self.size, size))
|
||||||
|
|
||||||
|
|
||||||
|
def checksum(self):
|
||||||
|
cksum = 0
|
||||||
|
data = self.data + self.padding
|
||||||
|
|
||||||
|
for offset in range(0, self.size, 4):
|
||||||
|
cksum += struct.unpack('>L', data[offset : offset + 4])[0]
|
||||||
|
|
||||||
|
return cksum & 0xFFFFFFFF
|
||||||
|
|
||||||
|
|
||||||
|
def pack(self, format, value, name):
|
||||||
|
try:
|
||||||
|
return struct.pack(format, value)
|
||||||
|
except struct.error as ex:
|
||||||
|
raise Exception('%s.%s: %s' % (self.table_name, name, str(ex)))
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
return len(self.data)
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def padding(self):
|
||||||
|
return bytes(((self.size + 1) & 3) ^ 1)
|
||||||
|
|
||||||
|
|
||||||
|
def rewrite_uint32(self, value, offset):
|
||||||
|
self.data[offset : offset + 4] = struct.pack('>L', value)
|
||||||
|
|
||||||
|
|
||||||
|
def write(self, data):
|
||||||
|
self.data += data
|
||||||
|
|
||||||
|
|
||||||
|
def write_int8(self, value, name):
|
||||||
|
self.data += self.pack('b', value, name)
|
||||||
|
|
||||||
|
|
||||||
|
def write_uint8(self, value, name):
|
||||||
|
self.data += self.pack('B', value, name)
|
||||||
|
|
||||||
|
|
||||||
|
def write_int16(self, value, name):
|
||||||
|
self.data += self.pack('>h', value, name)
|
||||||
|
|
||||||
|
|
||||||
|
def write_uint16(self, value, name):
|
||||||
|
self.data += self.pack('>H', value, name)
|
||||||
|
|
||||||
|
|
||||||
|
def write_uint32(self, value, name):
|
||||||
|
self.data += self.pack('>L', value, name)
|
||||||
|
|
||||||
|
|
||||||
|
def write_uint64(self, value, name):
|
||||||
|
self.data += self.pack('>Q', value, name)
|
||||||
|
|
||||||
|
|
||||||
|
def write_fixed(self, value, name):
|
||||||
|
self.data += self.pack('>l', round(value * 65536), name)
|
||||||
|
|
||||||
|
|
||||||
|
def write_table(self, table):
|
||||||
|
self.data += table.data
|
||||||
|
|
||||||
|
|
||||||
|
# -- Params --
|
||||||
|
EM_SIZE_MIN = 64
|
||||||
|
EM_SIZE_MAX = 16384
|
||||||
|
EM_SIZE_DEFAULT = 1024
|
||||||
|
|
||||||
|
class Params(fncli.Params): # pylint: disable=too-many-instance-attributes
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Params.__init__(self)
|
||||||
|
self.created = datetime.now(timezone.utc)
|
||||||
|
self.modified = self.created
|
||||||
|
self.dir_hint = 0
|
||||||
|
self.em_size = EM_SIZE_DEFAULT
|
||||||
|
self.line_gap = 0
|
||||||
|
self.low_ppem = 0
|
||||||
|
self.encoding = 'utf_8'
|
||||||
|
self.w_lang_id = 0x0409
|
||||||
|
self.x_max_extent = True
|
||||||
|
self.single_loca = False
|
||||||
|
self.post_names = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options --
|
||||||
|
class Options(fncli.Options):
|
||||||
|
def __init__(self, need_args, help_text, version_text):
|
||||||
|
fncli.Options.__init__(self, need_args + ['-d', '-e', '-g', '-l', '-E', '-W'], help_text, version_text)
|
||||||
|
|
||||||
|
|
||||||
|
def parse(self, name, value, params):
|
||||||
|
if name == '-d':
|
||||||
|
params.dir_hint = fnutil.parse_dec('DIR-HINT', value, -2, 2)
|
||||||
|
elif name == '-e':
|
||||||
|
params.em_size = fnutil.parse_dec('EM-SIZE', value, EM_SIZE_MIN, EM_SIZE_MAX)
|
||||||
|
elif name == '-g':
|
||||||
|
params.line_gap = fnutil.parse_dec('LINE-GAP', value, 0, EM_SIZE_MAX << 1)
|
||||||
|
elif name == '-l':
|
||||||
|
params.low_ppem = fnutil.parse_dec('LOW-PPEM', value, 1, bdf.DPARSE_LIMIT)
|
||||||
|
elif name == '-E':
|
||||||
|
params.encoding = value
|
||||||
|
elif name == '-W':
|
||||||
|
params.w_lang_id = fnutil.parse_hex('WLANG-ID', value, 0, 0x7FFF)
|
||||||
|
elif name == '-X':
|
||||||
|
params.x_max_extent = False
|
||||||
|
elif name == '-L':
|
||||||
|
params.single_loca = True
|
||||||
|
elif name == '-P':
|
||||||
|
params.post_names = True
|
||||||
|
else:
|
||||||
|
self.fallback(name, params)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Font --
|
||||||
|
class Font(bdfexp.Font):
|
||||||
|
def __init__(self, params):
|
||||||
|
bdfexp.Font.__init__(self)
|
||||||
|
self.params = params
|
||||||
|
self.em_ascender = 0
|
||||||
|
self.em_descender = 0
|
||||||
|
self.em_max_width = 0
|
||||||
|
self.mac_style = 0
|
||||||
|
self.line_size = 0
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bmp_only(self):
|
||||||
|
return self.max_code <= fnutil.UNICODE_BMP_MAX
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created(self):
|
||||||
|
return Font.sfntime(self.params.created)
|
||||||
|
|
||||||
|
def decode(self, data):
|
||||||
|
return codecs.decode(data, self.params.encoding)
|
||||||
|
|
||||||
|
def em_scale(self, value, divisor=0):
|
||||||
|
return round(value * self.params.em_size / (divisor or self.bbx.height))
|
||||||
|
|
||||||
|
def em_scale_width(self, base):
|
||||||
|
return self.em_scale(base.bbx.width)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def italic_angle(self):
|
||||||
|
value = self.props.get('ITALIC_ANGLE') # must be integer
|
||||||
|
return fnutil.parse_dec('ITALIC_ANGLE', value, -45, 45) if value else -11.5 if self.italic else 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_code(self):
|
||||||
|
return self.chars[-1].code
|
||||||
|
|
||||||
|
@property
|
||||||
|
def min_code(self):
|
||||||
|
return self.chars[0].code
|
||||||
|
|
||||||
|
@property
|
||||||
|
def modified(self):
|
||||||
|
return Font.sfntime(self.params.modified)
|
||||||
|
|
||||||
|
|
||||||
|
def prepare(self):
|
||||||
|
self.chars.sort(key=lambda c: c.code)
|
||||||
|
self.chars = [next(elem[1]) for elem in groupby(self.chars, key=lambda c: c.code)]
|
||||||
|
self.props.set('CHARS', len(self.chars))
|
||||||
|
self.em_ascender = self.em_scale(self.px_ascender)
|
||||||
|
self.em_descender = self.em_ascender - self.params.em_size
|
||||||
|
self.em_max_width = self.em_scale_width(self)
|
||||||
|
self.mac_style = int(self.bold) + (int(self.italic) << 1)
|
||||||
|
self.line_size = self.em_scale(round(self.bbx.height / 17) or 1)
|
||||||
|
|
||||||
|
|
||||||
|
def _read(self, input):
|
||||||
|
bdfexp.Font._read(self, input)
|
||||||
|
self.prepare()
|
||||||
|
return self
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def read(input, params): # pylint: disable=arguments-differ
|
||||||
|
return Font(params)._read(input) # pylint: disable=protected-access
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def sfntime(stamp):
|
||||||
|
return math.floor((stamp - datetime(1904, 1, 1, tzinfo=timezone.utc)).total_seconds())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def underline_position(self):
|
||||||
|
return round((self.em_descender + self.line_size) / 2)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def x_max_extent(self):
|
||||||
|
return self.em_max_width if self.params.x_max_extent else 0
|
||||||
|
|
||||||
|
|
||||||
|
# -- BDAT --
|
||||||
|
BDAT_HEADER_SIZE = 4
|
||||||
|
BDAT_METRIC_SIZE = 5
|
||||||
|
|
||||||
|
class BDAT(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'EBDT')
|
||||||
|
# header
|
||||||
|
self.write_fixed(2, 'version')
|
||||||
|
# format 1 data
|
||||||
|
for char in font.chars:
|
||||||
|
self.write_uint8(font.bbx.height, 'height')
|
||||||
|
self.write_uint8(char.bbx.width, 'width')
|
||||||
|
self.write_int8(0, 'bearingX')
|
||||||
|
self.write_int8(font.px_ascender, 'bearingY')
|
||||||
|
self.write_uint8(char.bbx.width, 'advance')
|
||||||
|
self.write(char.data) # imageData
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_char_size(char):
|
||||||
|
return BDAT_METRIC_SIZE + len(char.data)
|
||||||
|
|
||||||
|
|
||||||
|
# -- BLOC --
|
||||||
|
BLOC_TABLE_SIZE_OFFSET = 12
|
||||||
|
BLOC_PREFIX_SIZE = 0x38 # header 0x08 + 1 bitmapSizeTable * 0x30
|
||||||
|
BLOC_INDEX_ARRAY_SIZE = 8 # 1 index record * 0x08
|
||||||
|
|
||||||
|
class BLOC(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'EBLC')
|
||||||
|
# header
|
||||||
|
self.write_fixed(2, 'version')
|
||||||
|
self.write_uint32(1, 'numSizes')
|
||||||
|
# bitmapSizeTable
|
||||||
|
self.write_uint32(BLOC_PREFIX_SIZE, 'indexSubTableArrayOffset')
|
||||||
|
self.write_uint32(0, 'indexTableSize') # adjusted later
|
||||||
|
self.write_uint32(1, 'numberOfIndexSubTables')
|
||||||
|
self.write_uint32(0, 'colorRef')
|
||||||
|
# hori
|
||||||
|
self.write_int8(font.px_ascender, 'hori ascender')
|
||||||
|
self.write_int8(font.px_descender, 'hori descender')
|
||||||
|
self.write_uint8(font.bbx.width, 'hori widthMax')
|
||||||
|
self.write_int8(1, 'hori caretSlopeNumerator')
|
||||||
|
self.write_int8(0, 'hori caretSlopeDenominator')
|
||||||
|
self.write_int8(0, 'hori caretOffset')
|
||||||
|
self.write_int8(0, 'hori minOriginSB')
|
||||||
|
self.write_int8(0, 'hori minAdvanceSB')
|
||||||
|
self.write_int8(font.px_ascender, 'hori maxBeforeBL')
|
||||||
|
self.write_int8(font.px_descender, 'hori minAfterBL')
|
||||||
|
self.write_int16(0, 'hori padd')
|
||||||
|
# vert
|
||||||
|
self.write_int8(0, 'vert ascender')
|
||||||
|
self.write_int8(0, 'vert descender')
|
||||||
|
self.write_uint8(0, 'vert widthMax')
|
||||||
|
self.write_int8(0, 'vert caretSlopeNumerator')
|
||||||
|
self.write_int8(0, 'vert caretSlopeDenominator')
|
||||||
|
self.write_int8(0, 'vert caretOffset')
|
||||||
|
self.write_int8(0, 'vert minOriginSB')
|
||||||
|
self.write_int8(0, 'vert minAdvanceSB')
|
||||||
|
self.write_int8(0, 'vert maxBeforeBL')
|
||||||
|
self.write_int8(0, 'vert minAfterBL')
|
||||||
|
self.write_int16(0, 'vert padd')
|
||||||
|
# (bitmapSizeTable)
|
||||||
|
self.write_uint16(0, 'startGlyphIndex')
|
||||||
|
self.write_uint16(len(font.chars) - 1, 'endGlyphIndex')
|
||||||
|
self.write_uint8(font.bbx.height, 'ppemX')
|
||||||
|
self.write_uint8(font.bbx.height, 'ppemY')
|
||||||
|
self.write_uint8(1, 'bitDepth')
|
||||||
|
self.write_uint8(1, 'flags') # small metrics are horizontal
|
||||||
|
# indexSubTableArray
|
||||||
|
self.write_uint16(0, 'firstGlyphIndex')
|
||||||
|
self.write_uint16(len(font.chars) - 1, 'lastGlyphIndex')
|
||||||
|
self.write_uint32(BLOC_INDEX_ARRAY_SIZE, 'additionalOffsetToIndexSubtable')
|
||||||
|
# indexSubtableHeader
|
||||||
|
self.write_uint16(1 if font.proportional else 2, 'indexFormat')
|
||||||
|
self.write_uint16(1, 'imageFormat') # BDAT -> small metrics, byte-aligned
|
||||||
|
self.write_uint32(BDAT_HEADER_SIZE, 'imageDataOffset')
|
||||||
|
# indexSubtable data
|
||||||
|
if font.proportional:
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
for char in font.chars:
|
||||||
|
self.write_uint32(offset, 'offsetArray[]')
|
||||||
|
offset += BDAT.get_char_size(char)
|
||||||
|
|
||||||
|
self.write_uint32(offset, 'offsetArray[]')
|
||||||
|
else:
|
||||||
|
self.write_uint32(BDAT.get_char_size(font.chars[0]), 'imageSize')
|
||||||
|
self.write_uint8(font.bbx.height, 'height')
|
||||||
|
self.write_uint8(font.bbx.width, 'width')
|
||||||
|
self.write_int8(0, 'horiBearingX')
|
||||||
|
self.write_int8(font.px_ascender, 'horiBearingY')
|
||||||
|
self.write_uint8(font.bbx.width, 'horiAdvance')
|
||||||
|
self.write_int8(-(font.bbx.width >> 1), 'vertBearingX')
|
||||||
|
self.write_int8(0, 'vertBearingY')
|
||||||
|
self.write_uint8(font.bbx.height, 'vertAdvance')
|
||||||
|
# adjust
|
||||||
|
self.rewrite_uint32(self.size - BLOC_PREFIX_SIZE, BLOC_TABLE_SIZE_OFFSET)
|
||||||
|
|
||||||
|
|
||||||
|
# -- OS/2 --
|
||||||
|
OS_2_TABLE_SIZE = 96
|
||||||
|
|
||||||
|
class OS_2(Table): # pylint: disable=invalid-name
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'OS/2')
|
||||||
|
# Version 4
|
||||||
|
x_avg_char_width = font.em_scale(font.avg_width) # otb1get.x_avg_char_width(font)
|
||||||
|
ul_char_ranges = otb1get.ul_char_ranges(font)
|
||||||
|
ul_code_pages = otb1get.ul_code_pages(font) if font.bmp_only else [0, 0]
|
||||||
|
# mostly from FontForge
|
||||||
|
script_xsize = font.em_scale(30, 100)
|
||||||
|
script_ysize = font.em_scale(40, 100)
|
||||||
|
subscript_yoff = script_ysize >> 1
|
||||||
|
xfactor = math.tan(font.italic_angle * math.pi / 180)
|
||||||
|
subscript_xoff = 0 # stub, no overlapping characters yet
|
||||||
|
superscript_yoff = font.em_ascender - script_ysize
|
||||||
|
superscript_xoff = -round(xfactor * superscript_yoff)
|
||||||
|
# write
|
||||||
|
self.write_uint16(4, 'version')
|
||||||
|
self.write_int16(x_avg_char_width, 'xAvgCharWidth')
|
||||||
|
self.write_uint16(700 if font.bold else 400, 'usWeightClass')
|
||||||
|
self.write_uint16(5, 'usWidthClass') # medium
|
||||||
|
self.write_int16(0, 'fsType')
|
||||||
|
self.write_int16(script_xsize, 'ySubscriptXSize')
|
||||||
|
self.write_int16(script_ysize, 'ySubscriptYSize')
|
||||||
|
self.write_int16(subscript_xoff, 'ySubscriptXOffset')
|
||||||
|
self.write_int16(subscript_yoff, 'ySubscriptYOffset')
|
||||||
|
self.write_int16(script_xsize, 'ySuperscriptXSize')
|
||||||
|
self.write_int16(script_ysize, 'ySuperscriptYSize')
|
||||||
|
self.write_int16(superscript_xoff, 'ySuperscriptXOffset')
|
||||||
|
self.write_int16(superscript_yoff, 'ySuperscriptYOffset')
|
||||||
|
self.write_int16(font.line_size, 'yStrikeoutSize')
|
||||||
|
self.write_int16(font.em_scale(25, 100), 'yStrikeoutPosition')
|
||||||
|
self.write_int16(0, 'sFamilyClass') # no classification
|
||||||
|
self.write_uint8(2, 'bFamilyType') # text and display
|
||||||
|
self.write_uint8(0, 'bSerifStyle') # any
|
||||||
|
self.write_uint8(8 if font.bold else 6, 'bWeight')
|
||||||
|
self.write_uint8(3 if font.proportional else 9, 'bProportion')
|
||||||
|
self.write_uint8(0, 'bContrast')
|
||||||
|
self.write_uint8(0, 'bStrokeVariation')
|
||||||
|
self.write_uint8(0, 'bArmStyle')
|
||||||
|
self.write_uint8(0, 'bLetterform')
|
||||||
|
self.write_uint8(0, 'bMidline')
|
||||||
|
self.write_uint8(0, 'bXHeight')
|
||||||
|
self.write_uint32(ul_char_ranges[0], 'ulCharRange1')
|
||||||
|
self.write_uint32(ul_char_ranges[1], 'ulCharRange2')
|
||||||
|
self.write_uint32(ul_char_ranges[2], 'ulCharRange3')
|
||||||
|
self.write_uint32(ul_char_ranges[3], 'ulCharRange4')
|
||||||
|
self.write_uint32(0x586F7334, 'achVendID') # 'Xos4'
|
||||||
|
self.write_uint16(OS_2.fs_selection(font), 'fsSelection')
|
||||||
|
self.write_uint16(min(font.min_code, fnutil.UNICODE_BMP_MAX), 'firstChar')
|
||||||
|
self.write_uint16(min(font.max_code, fnutil.UNICODE_BMP_MAX), 'lastChar')
|
||||||
|
self.write_int16(font.em_ascender, 'sTypoAscender')
|
||||||
|
self.write_int16(font.em_descender, 'sTypoDescender')
|
||||||
|
self.write_int16(font.params.line_gap, 'sTypoLineGap')
|
||||||
|
self.write_uint16(font.em_ascender, 'usWinAscent')
|
||||||
|
self.write_uint16(-font.em_descender, 'usWinDescent')
|
||||||
|
self.write_uint32(ul_code_pages[0], 'ulCodePageRange1')
|
||||||
|
self.write_uint32(ul_code_pages[1], 'ulCodePageRange2')
|
||||||
|
self.write_int16(font.em_scale(font.px_ascender * 0.6), 'sxHeight') # stub
|
||||||
|
self.write_int16(font.em_scale(font.px_ascender * 0.8), 'sCapHeight') # stub
|
||||||
|
self.write_uint16(OS_2.default_char(font), 'usDefaultChar')
|
||||||
|
self.write_uint16(OS_2.break_char(font), 'usBreakChar')
|
||||||
|
self.write_uint16(1, 'usMaxContext')
|
||||||
|
# check
|
||||||
|
self.check_size(OS_2_TABLE_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def break_char(font):
|
||||||
|
return 0x20 if next((char for char in font.chars if char.code == 0x20), None) else font.min_code
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def default_char(font):
|
||||||
|
if font.default_code != -1 and font.default_code <= fnutil.UNICODE_BMP_MAX:
|
||||||
|
return font.default_code
|
||||||
|
|
||||||
|
return 0 if font.min_code == 0 else font.max_code
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fs_selection(font):
|
||||||
|
fs_selection = int(font.bold) * 5 + int(font.italic)
|
||||||
|
return fs_selection if fs_selection != 0 else 0x40 if font.xlfd[bdf.XLFD.SLANT] == 'R' else 0
|
||||||
|
|
||||||
|
|
||||||
|
# -- cmap --
|
||||||
|
CMAP_4_PREFIX_SIZE = 12
|
||||||
|
CMAP_4_FORMAT_SIZE = 16
|
||||||
|
CMAP_4_SEGMENT_SIZE = 8
|
||||||
|
|
||||||
|
CMAP_12_PREFIX_SIZE = 20
|
||||||
|
CMAP_12_FORMAT_SIZE = 16
|
||||||
|
CMAP_12_GROUP_SIZE = 12
|
||||||
|
|
||||||
|
class CMapRange:
|
||||||
|
def __init__(self, glyph_index=0, start_code=0, final_code=-2):
|
||||||
|
self.glyph_index = glyph_index
|
||||||
|
self.start_code = start_code
|
||||||
|
self.final_code = final_code
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id_delta(self):
|
||||||
|
return (self.glyph_index - self.start_code) & 0xFFFF
|
||||||
|
|
||||||
|
|
||||||
|
class CMAP(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'cmap')
|
||||||
|
# make ranges
|
||||||
|
ranges = []
|
||||||
|
range = CMapRange()
|
||||||
|
index = -1
|
||||||
|
|
||||||
|
for char in font.chars:
|
||||||
|
index += 1
|
||||||
|
code = char.code
|
||||||
|
|
||||||
|
if code == range.final_code + 1:
|
||||||
|
range.final_code += 1
|
||||||
|
else:
|
||||||
|
range = CMapRange(index, code, code)
|
||||||
|
ranges.append(range)
|
||||||
|
# write
|
||||||
|
if font.bmp_only:
|
||||||
|
if font.max_code < 0xFFFF:
|
||||||
|
ranges.append(CMapRange(0, 0xFFFF, 0xFFFF))
|
||||||
|
|
||||||
|
self.write_format_4(ranges)
|
||||||
|
else:
|
||||||
|
self.write_format_12(ranges)
|
||||||
|
|
||||||
|
|
||||||
|
def write_format_4(self, ranges):
|
||||||
|
# index
|
||||||
|
self.write_uint16(0, 'version')
|
||||||
|
self.write_uint16(1, 'numberSubtables')
|
||||||
|
# encoding subtables index
|
||||||
|
self.write_uint16(3, 'platformID') # Microsoft
|
||||||
|
self.write_uint16(1, 'platformSpecificID') # Unicode BMP (UCS-2)
|
||||||
|
self.write_uint32(CMAP_4_PREFIX_SIZE, 'offset') # for Unicode BMP (UCS-2)
|
||||||
|
# cmap format 4
|
||||||
|
seg_count = len(ranges)
|
||||||
|
subtable_size = CMAP_4_FORMAT_SIZE + seg_count * CMAP_4_SEGMENT_SIZE
|
||||||
|
search_range = 2 << math.floor(math.log2(seg_count))
|
||||||
|
|
||||||
|
self.write_uint16(4, 'format')
|
||||||
|
self.write_uint16(subtable_size, 'length')
|
||||||
|
self.write_uint16(0, 'language') # none/independent
|
||||||
|
self.write_uint16(seg_count * 2, 'segCountX2')
|
||||||
|
self.write_uint16(search_range, 'searchRange')
|
||||||
|
self.write_uint16(int(math.log2(search_range / 2)), 'entrySelector')
|
||||||
|
self.write_uint16((seg_count * 2) - search_range, 'rangeShift')
|
||||||
|
for range in ranges:
|
||||||
|
self.write_uint16(range.final_code, 'endCode')
|
||||||
|
self.write_uint16(0, 'reservedPad')
|
||||||
|
for range in ranges:
|
||||||
|
self.write_uint16(range.start_code, 'startCode')
|
||||||
|
for range in ranges:
|
||||||
|
self.write_uint16(range.id_delta, 'idDelta')
|
||||||
|
for _ in ranges:
|
||||||
|
self.write_uint16(0, 'idRangeOffset')
|
||||||
|
# check
|
||||||
|
self.check_size(CMAP_4_PREFIX_SIZE + subtable_size)
|
||||||
|
|
||||||
|
|
||||||
|
def write_format_12(self, ranges):
|
||||||
|
# index
|
||||||
|
self.write_uint16(0, 'version')
|
||||||
|
self.write_uint16(2, 'numberSubtables')
|
||||||
|
# encoding subtables
|
||||||
|
self.write_uint16(0, 'platformID') # Unicode
|
||||||
|
self.write_uint16(4, 'platformSpecificID') # Unicode 2.0+ full range
|
||||||
|
self.write_uint32(CMAP_12_PREFIX_SIZE, 'offset') # for Unicode 2.0+ full range
|
||||||
|
self.write_uint16(3, 'platformID') # Microsoft
|
||||||
|
self.write_uint16(10, 'platformSpecificID') # Unicode UCS-4
|
||||||
|
self.write_uint32(CMAP_12_PREFIX_SIZE, 'offset') # for Unicode UCS-4
|
||||||
|
# cmap format 12
|
||||||
|
subtable_size = CMAP_12_FORMAT_SIZE + len(ranges) * CMAP_12_GROUP_SIZE
|
||||||
|
|
||||||
|
self.write_fixed(12, 'format')
|
||||||
|
self.write_uint32(subtable_size, 'length')
|
||||||
|
self.write_uint32(0, 'language') # none/independent
|
||||||
|
self.write_uint32(len(ranges), 'nGroups')
|
||||||
|
for range in ranges:
|
||||||
|
self.write_uint32(range.start_code, 'startCharCode')
|
||||||
|
self.write_uint32(range.final_code, 'endCharCode')
|
||||||
|
self.write_uint32(range.glyph_index, 'startGlyphID')
|
||||||
|
# check
|
||||||
|
self.check_size(CMAP_12_PREFIX_SIZE + subtable_size)
|
||||||
|
|
||||||
|
|
||||||
|
# -- glyf --
|
||||||
|
class GLYF(Table):
|
||||||
|
def __init__(self, _font):
|
||||||
|
Table.__init__(self, 'glyf')
|
||||||
|
|
||||||
|
|
||||||
|
# -- head --
|
||||||
|
HEAD_TABLE_SIZE = 54
|
||||||
|
HEAD_CHECKSUM_OFFSET = 8
|
||||||
|
|
||||||
|
class HEAD(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'head')
|
||||||
|
self.write_fixed(1, 'version')
|
||||||
|
self.write_fixed(1, 'fontRevision')
|
||||||
|
self.write_uint32(0, 'checksumAdjustment') # adjusted later
|
||||||
|
self.write_uint32(0x5F0F3CF5, 'magicNumber')
|
||||||
|
self.write_uint16(HEAD.flags(font), 'flags')
|
||||||
|
self.write_uint16(font.params.em_size, 'unitsPerEm')
|
||||||
|
self.write_uint64(font.created, 'created')
|
||||||
|
self.write_uint64(font.modified, 'modified')
|
||||||
|
self.write_int16(0, 'xMin')
|
||||||
|
self.write_int16(font.em_descender, 'yMin')
|
||||||
|
self.write_int16(font.em_max_width, 'xMax')
|
||||||
|
self.write_int16(font.em_ascender, 'yMax')
|
||||||
|
self.write_uint16(font.mac_style, 'macStyle')
|
||||||
|
self.write_uint16(font.params.low_ppem or font.bbx.height, 'lowestRecPPEM')
|
||||||
|
self.write_int16(font.params.dir_hint, 'fontDirectionHint')
|
||||||
|
self.write_int16(0, 'indexToLocFormat') # short
|
||||||
|
self.write_int16(0, 'glyphDataFormat') # current
|
||||||
|
# check
|
||||||
|
self.check_size(HEAD_TABLE_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def flags(font):
|
||||||
|
return 0x20B if otb1get.contains_rtl(font) else 0x0B # y0 base, x0 lsb, scale int
|
||||||
|
|
||||||
|
|
||||||
|
# -- hhea --
|
||||||
|
HHEA_TABLE_SIZE = 36
|
||||||
|
|
||||||
|
class HHEA(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'hhea')
|
||||||
|
self.write_fixed(1, 'version')
|
||||||
|
self.write_int16(font.em_ascender, 'ascender')
|
||||||
|
self.write_int16(font.em_descender, 'descender')
|
||||||
|
self.write_int16(font.params.line_gap, 'lineGap')
|
||||||
|
self.write_uint16(font.em_max_width, 'advanceWidthMax')
|
||||||
|
self.write_int16(0, 'minLeftSideBearing')
|
||||||
|
self.write_int16(0, 'minRightSideBearing')
|
||||||
|
self.write_int16(font.x_max_extent, 'xMaxExtent')
|
||||||
|
self.write_int16(100 if font.italic else 1, 'caretSlopeRise')
|
||||||
|
self.write_int16(20 if font.italic else 0, 'caretSlopeRun')
|
||||||
|
self.write_int16(0, 'caretOffset')
|
||||||
|
self.write_int16(0, 'reserved')
|
||||||
|
self.write_int16(0, 'reserved')
|
||||||
|
self.write_int16(0, 'reserved')
|
||||||
|
self.write_int16(0, 'reserved')
|
||||||
|
self.write_int16(0, 'metricDataFormat') # current
|
||||||
|
self.write_uint16(len(font.chars), 'numOfLongHorMetrics')
|
||||||
|
# check
|
||||||
|
self.check_size(HHEA_TABLE_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
# -- hmtx --
|
||||||
|
class HMTX(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'hmtx')
|
||||||
|
for char in font.chars:
|
||||||
|
self.write_uint16(font.em_scale_width(char), 'advanceWidth')
|
||||||
|
self.write_int16(0, 'leftSideBearing')
|
||||||
|
|
||||||
|
|
||||||
|
# -- loca --
|
||||||
|
class LOCA(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'loca')
|
||||||
|
if not font.params.single_loca:
|
||||||
|
for _ in font.chars:
|
||||||
|
self.write_uint16(0, 'offset')
|
||||||
|
self.write_uint16(0, 'offset')
|
||||||
|
|
||||||
|
|
||||||
|
# -- maxp --
|
||||||
|
MAXP_TABLE_SIZE = 32
|
||||||
|
|
||||||
|
class MAXP(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'maxp')
|
||||||
|
self.write_fixed(1, 'version')
|
||||||
|
self.write_uint16(len(font.chars), 'numGlyphs')
|
||||||
|
self.write_uint16(0, 'maxPoints')
|
||||||
|
self.write_uint16(0, 'maxContours')
|
||||||
|
self.write_uint16(0, 'maxComponentPoints')
|
||||||
|
self.write_uint16(0, 'maxComponentContours')
|
||||||
|
self.write_uint16(2, 'maxZones')
|
||||||
|
self.write_uint16(0, 'maxTwilightPoints')
|
||||||
|
self.write_uint16(1, 'maxStorage')
|
||||||
|
self.write_uint16(1, 'maxFunctionDefs')
|
||||||
|
self.write_uint16(0, 'maxInstructionDefs')
|
||||||
|
self.write_uint16(64, 'maxStackElements')
|
||||||
|
self.write_uint16(0, 'maxSizeOfInstructions')
|
||||||
|
self.write_uint16(0, 'maxComponentElements')
|
||||||
|
self.write_uint16(0, 'maxComponentDepth')
|
||||||
|
# check
|
||||||
|
self.check_size(MAXP_TABLE_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
# -- name --
|
||||||
|
@unique # pylint: disable=invalid-name
|
||||||
|
class NAME_ID(IntEnum): # pylint: disable=invalid-name
|
||||||
|
COPYRIGHT = 0
|
||||||
|
FONT_FAMILY = 1
|
||||||
|
FONT_SUBFAMILY = 2
|
||||||
|
UNIQUE_SUBFAMILY = 3
|
||||||
|
FULL_FONT_NAME = 4
|
||||||
|
LICENSE = 14
|
||||||
|
|
||||||
|
NAME_HEADER_SIZE = 6
|
||||||
|
NAME_RECORD_SIZE = 12
|
||||||
|
|
||||||
|
class NAME(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'name')
|
||||||
|
# compute names
|
||||||
|
names = OrderedDict()
|
||||||
|
copyright = font.props.get('COPYRIGHT')
|
||||||
|
|
||||||
|
if copyright is not None:
|
||||||
|
names[NAME_ID.COPYRIGHT] = fnutil.unquote(copyright)
|
||||||
|
|
||||||
|
family = font.xlfd[bdf.XLFD.FAMILY_NAME]
|
||||||
|
style = [b'Regular', b'Bold', b'Italic', b'Bold Italic'][font.mac_style]
|
||||||
|
|
||||||
|
names[NAME_ID.FONT_FAMILY] = family
|
||||||
|
names[NAME_ID.FONT_SUBFAMILY] = style
|
||||||
|
names[NAME_ID.UNIQUE_SUBFAMILY] = b'%s %s bitmap height %d' % (family, style, font.bbx.height)
|
||||||
|
names[NAME_ID.FULL_FONT_NAME] = b'%s %s' % (family, style)
|
||||||
|
|
||||||
|
license = font.props.get('LICENSE')
|
||||||
|
notice = font.props.get('NOTICE')
|
||||||
|
|
||||||
|
if license is None and notice is not None and b'license' in notice.lower():
|
||||||
|
license = notice
|
||||||
|
|
||||||
|
if license is not None:
|
||||||
|
names[NAME_ID.LICENSE] = fnutil.unquote(license)
|
||||||
|
|
||||||
|
# header
|
||||||
|
count = len(names) * (1 + 1) # Unicode + Microsoft
|
||||||
|
string_offset = NAME_HEADER_SIZE + NAME_RECORD_SIZE * count
|
||||||
|
|
||||||
|
self.write_uint16(0, 'format')
|
||||||
|
self.write_uint16(count, 'count')
|
||||||
|
self.write_uint16(string_offset, 'stringOffset')
|
||||||
|
# name records / create values
|
||||||
|
values = Table('name')
|
||||||
|
|
||||||
|
for [name_id, bstr] in names.items():
|
||||||
|
s = font.decode(bstr)
|
||||||
|
value = codecs.encode(s, 'utf_16_be')
|
||||||
|
bmp = font.bmp_only and len(value) == len(s) * 2
|
||||||
|
# Unicode
|
||||||
|
self.write_uint16(0, 'platformID') # Unicode
|
||||||
|
self.write_uint16(3 if bmp else 4, 'platformSpecificID')
|
||||||
|
self.write_uint16(0, 'languageID') # none
|
||||||
|
self.write_uint16(name_id, 'nameID')
|
||||||
|
self.write_uint16(len(value), 'length') # in bytes
|
||||||
|
self.write_uint16(values.size, 'offset')
|
||||||
|
# Microsoft
|
||||||
|
self.write_uint16(3, 'platformID') # Microsoft
|
||||||
|
self.write_uint16(1 if bmp else 10, 'platformSpecificID')
|
||||||
|
self.write_uint16(font.params.w_lang_id, 'languageID')
|
||||||
|
self.write_uint16(name_id, 'nameID')
|
||||||
|
self.write_uint16(len(value), 'length') # in bytes
|
||||||
|
self.write_uint16(values.size, 'offset')
|
||||||
|
# value
|
||||||
|
values.write(value)
|
||||||
|
|
||||||
|
# write values
|
||||||
|
self.write_table(values)
|
||||||
|
# check
|
||||||
|
self.check_size(string_offset + values.size)
|
||||||
|
|
||||||
|
|
||||||
|
# -- post --
|
||||||
|
POST_TABLE_SIZE = 32
|
||||||
|
|
||||||
|
class POST(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'post')
|
||||||
|
self.write_fixed(2 if font.params.post_names else 3, 'format')
|
||||||
|
self.write_fixed(font.italic_angle, 'italicAngle')
|
||||||
|
self.write_int16(font.underline_position, 'underlinePosition')
|
||||||
|
self.write_int16(font.line_size, 'underlineThickness')
|
||||||
|
self.write_uint32(0 if font.proportional else 1, 'isFixedPitch')
|
||||||
|
self.write_uint32(0, 'minMemType42')
|
||||||
|
self.write_uint32(0, 'maxMemType42')
|
||||||
|
self.write_uint32(0, 'minMemType1')
|
||||||
|
self.write_uint32(0, 'maxMemType1')
|
||||||
|
# names
|
||||||
|
if font.params.post_names:
|
||||||
|
self.write_uint16(len(font.chars), 'numberOfGlyphs')
|
||||||
|
post_names = otb1get.post_mac_names()
|
||||||
|
post_mac_count = len(post_names)
|
||||||
|
|
||||||
|
for name in [char.props['STARTCHAR'] for char in font.chars]:
|
||||||
|
if name in post_names:
|
||||||
|
self.write_uint16(post_names.index(name), 'glyphNameIndex')
|
||||||
|
else:
|
||||||
|
self.write_uint16(len(post_names), 'glyphNameIndex')
|
||||||
|
post_names.append(name)
|
||||||
|
|
||||||
|
for name in post_names[post_mac_count:]:
|
||||||
|
self.write_uint8(len(name), 'glyphNameLength')
|
||||||
|
self.write(name)
|
||||||
|
# check
|
||||||
|
else:
|
||||||
|
self.check_size(POST_TABLE_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
# -- SFNT --
|
||||||
|
SFNT_HEADER_SIZE = 12
|
||||||
|
SFNT_RECORD_SIZE = 16
|
||||||
|
SFNT_SUBTABLES = (BDAT, BLOC, OS_2, CMAP, GLYF, HEAD, HHEA, HMTX, LOCA, MAXP, NAME, POST)
|
||||||
|
|
||||||
|
class SFNT(Table):
|
||||||
|
def __init__(self, font):
|
||||||
|
Table.__init__(self, 'SFNT')
|
||||||
|
# create tables
|
||||||
|
tables = []
|
||||||
|
for ctor in SFNT_SUBTABLES:
|
||||||
|
tables.append(ctor(font))
|
||||||
|
# header
|
||||||
|
num_tables = len(tables)
|
||||||
|
entry_selector = math.floor(math.log2(num_tables))
|
||||||
|
search_range = 16 << entry_selector
|
||||||
|
content_offset = SFNT_HEADER_SIZE + num_tables * SFNT_RECORD_SIZE
|
||||||
|
offset = content_offset
|
||||||
|
content = Table('SFNT')
|
||||||
|
head_checksum_offset = -1
|
||||||
|
|
||||||
|
self.write_fixed(1, 'sfntVersion')
|
||||||
|
self.write_uint16(num_tables, 'numTables')
|
||||||
|
self.write_uint16(search_range, 'searchRange')
|
||||||
|
self.write_uint16(entry_selector, 'entrySelector')
|
||||||
|
self.write_uint16(num_tables * 16 - search_range, 'rangeShift')
|
||||||
|
# table records / create content
|
||||||
|
for table in tables:
|
||||||
|
self.write(bytes(table.table_name, 'ascii'))
|
||||||
|
self.write_uint32(table.checksum(), 'checkSum')
|
||||||
|
self.write_uint32(offset, 'offset')
|
||||||
|
self.write_uint32(len(table.data), 'length')
|
||||||
|
# create content
|
||||||
|
if table.table_name == 'head':
|
||||||
|
head_checksum_offset = offset + HEAD_CHECKSUM_OFFSET
|
||||||
|
|
||||||
|
padded_data = table.data + table.padding
|
||||||
|
content.write(padded_data)
|
||||||
|
offset += len(padded_data)
|
||||||
|
# write content
|
||||||
|
self.write_table(content)
|
||||||
|
# check
|
||||||
|
self.check_size(content_offset + len(content.data))
|
||||||
|
# adjust
|
||||||
|
if head_checksum_offset != -1:
|
||||||
|
self.rewrite_uint32((0xB1B0AFBA - self.checksum()) & 0xFFFFFFFF, head_checksum_offset)
|
||||||
@@ -0,0 +1,706 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2018-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
|
||||||
|
// -- xAvgCharWidth --
|
||||||
|
const WEIGHT_FACTORS = [
|
||||||
|
[ 'a', 64 ],
|
||||||
|
[ 'b', 14 ],
|
||||||
|
[ 'c', 27 ],
|
||||||
|
[ 'd', 35 ],
|
||||||
|
[ 'e', 100 ],
|
||||||
|
[ 'f', 20 ],
|
||||||
|
[ 'g', 14 ],
|
||||||
|
[ 'h', 42 ],
|
||||||
|
[ 'i', 63 ],
|
||||||
|
[ 'j', 3 ],
|
||||||
|
[ 'k', 6 ],
|
||||||
|
[ 'l', 35 ],
|
||||||
|
[ 'm', 20 ],
|
||||||
|
[ 'n', 56 ],
|
||||||
|
[ 'o', 56 ],
|
||||||
|
[ 'p', 17 ],
|
||||||
|
[ 'q', 4 ],
|
||||||
|
[ 'r', 49 ],
|
||||||
|
[ 's', 56 ],
|
||||||
|
[ 't', 71 ],
|
||||||
|
[ 'u', 31 ],
|
||||||
|
[ 'v', 10 ],
|
||||||
|
[ 'w', 18 ],
|
||||||
|
[ 'x', 3 ],
|
||||||
|
[ 'y', 18 ],
|
||||||
|
[ 'z', 2 ],
|
||||||
|
[ ' ', 166 ]
|
||||||
|
];
|
||||||
|
|
||||||
|
function xAvgCharWidth(font) {
|
||||||
|
let xAvgTotalWidth = 0;
|
||||||
|
|
||||||
|
for (let factor of WEIGHT_FACTORS) {
|
||||||
|
const char = font.chars.find(_char => _char.code === factor[0].charCodeAt(0));
|
||||||
|
|
||||||
|
if (char == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
xAvgTotalWidth += font.scaleWidth(char) * factor[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return fnutil.round(xAvgTotalWidth / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- ulCharRanges --
|
||||||
|
const CHAR_RANGES = [
|
||||||
|
[ 0, 0x0000, 0x007F ],
|
||||||
|
[ 1, 0x0080, 0x00FF ],
|
||||||
|
[ 2, 0x0100, 0x017F ],
|
||||||
|
[ 3, 0x0180, 0x024F ],
|
||||||
|
[ 4, 0x0250, 0x02AF ],
|
||||||
|
[ 4, 0x1D00, 0x1D7F ],
|
||||||
|
[ 4, 0x1D80, 0x1DBF ],
|
||||||
|
[ 5, 0x02B0, 0x02FF ],
|
||||||
|
[ 5, 0xA700, 0xA71F ],
|
||||||
|
[ 6, 0x0300, 0x036F ],
|
||||||
|
[ 6, 0x1DC0, 0x1DFF ],
|
||||||
|
[ 7, 0x0370, 0x03FF ],
|
||||||
|
[ 8, 0x2C80, 0x2CFF ],
|
||||||
|
[ 9, 0x0400, 0x04FF ],
|
||||||
|
[ 9, 0x0500, 0x052F ],
|
||||||
|
[ 9, 0x2DE0, 0x2DFF ],
|
||||||
|
[ 9, 0xA640, 0xA69F ],
|
||||||
|
[ 10, 0x0530, 0x058F ],
|
||||||
|
[ 11, 0x0590, 0x05FF ],
|
||||||
|
[ 12, 0xA500, 0xA63F ],
|
||||||
|
[ 13, 0x0600, 0x06FF ],
|
||||||
|
[ 13, 0x0750, 0x077F ],
|
||||||
|
[ 14, 0x07C0, 0x07FF ],
|
||||||
|
[ 15, 0x0900, 0x097F ],
|
||||||
|
[ 16, 0x0980, 0x09FF ],
|
||||||
|
[ 17, 0x0A00, 0x0A7F ],
|
||||||
|
[ 18, 0x0A80, 0x0AFF ],
|
||||||
|
[ 19, 0x0B00, 0x0B7F ],
|
||||||
|
[ 20, 0x0B80, 0x0BFF ],
|
||||||
|
[ 21, 0x0C00, 0x0C7F ],
|
||||||
|
[ 22, 0x0C80, 0x0CFF ],
|
||||||
|
[ 23, 0x0D00, 0x0D7F ],
|
||||||
|
[ 24, 0x0E00, 0x0E7F ],
|
||||||
|
[ 25, 0x0E80, 0x0EFF ],
|
||||||
|
[ 26, 0x10A0, 0x10FF ],
|
||||||
|
[ 26, 0x2D00, 0x2D2F ],
|
||||||
|
[ 27, 0x1B00, 0x1B7F ],
|
||||||
|
[ 28, 0x1100, 0x11FF ],
|
||||||
|
[ 29, 0x1E00, 0x1EFF ],
|
||||||
|
[ 29, 0x2C60, 0x2C7F ],
|
||||||
|
[ 29, 0xA720, 0xA7FF ],
|
||||||
|
[ 30, 0x1F00, 0x1FFF ],
|
||||||
|
[ 31, 0x2000, 0x206F ],
|
||||||
|
[ 31, 0x2E00, 0x2E7F ],
|
||||||
|
[ 32, 0x2070, 0x209F ],
|
||||||
|
[ 33, 0x20A0, 0x20CF ],
|
||||||
|
[ 34, 0x20D0, 0x20FF ],
|
||||||
|
[ 35, 0x2100, 0x214F ],
|
||||||
|
[ 36, 0x2150, 0x218F ],
|
||||||
|
[ 37, 0x2190, 0x21FF ],
|
||||||
|
[ 37, 0x27F0, 0x27FF ],
|
||||||
|
[ 37, 0x2900, 0x297F ],
|
||||||
|
[ 37, 0x2B00, 0x2BFF ],
|
||||||
|
[ 38, 0x2200, 0x22FF ],
|
||||||
|
[ 38, 0x2A00, 0x2AFF ],
|
||||||
|
[ 38, 0x27C0, 0x27EF ],
|
||||||
|
[ 38, 0x2980, 0x29FF ],
|
||||||
|
[ 39, 0x2300, 0x23FF ],
|
||||||
|
[ 40, 0x2400, 0x243F ],
|
||||||
|
[ 41, 0x2440, 0x245F ],
|
||||||
|
[ 42, 0x2460, 0x24FF ],
|
||||||
|
[ 43, 0x2500, 0x257F ],
|
||||||
|
[ 44, 0x2580, 0x259F ],
|
||||||
|
[ 45, 0x25A0, 0x25FF ],
|
||||||
|
[ 46, 0x2600, 0x26FF ],
|
||||||
|
[ 47, 0x2700, 0x27BF ],
|
||||||
|
[ 48, 0x3000, 0x303F ],
|
||||||
|
[ 49, 0x3040, 0x309F ],
|
||||||
|
[ 50, 0x30A0, 0x30FF ],
|
||||||
|
[ 50, 0x31F0, 0x31FF ],
|
||||||
|
[ 51, 0x3100, 0x312F ],
|
||||||
|
[ 51, 0x31A0, 0x31BF ],
|
||||||
|
[ 52, 0x3130, 0x318F ],
|
||||||
|
[ 53, 0xA840, 0xA87F ],
|
||||||
|
[ 54, 0x3200, 0x32FF ],
|
||||||
|
[ 55, 0x3300, 0x33FF ],
|
||||||
|
[ 56, 0xAC00, 0xD7AF ],
|
||||||
|
[ 57, 0xD800, 0xDFFF ],
|
||||||
|
[ 58, 0x10900, 0x1091F ],
|
||||||
|
[ 59, 0x4E00, 0x9FFF ],
|
||||||
|
[ 59, 0x2E80, 0x2EFF ],
|
||||||
|
[ 59, 0x2F00, 0x2FDF ],
|
||||||
|
[ 59, 0x2FF0, 0x2FFF ],
|
||||||
|
[ 59, 0x3400, 0x4DBF ],
|
||||||
|
[ 59, 0x20000, 0x2A6DF ],
|
||||||
|
[ 59, 0x3190, 0x319F ],
|
||||||
|
[ 60, 0xE000, 0xF8FF ],
|
||||||
|
[ 61, 0x31C0, 0x31EF ],
|
||||||
|
[ 61, 0xF900, 0xFAFF ],
|
||||||
|
[ 61, 0x2F800, 0x2FA1F ],
|
||||||
|
[ 62, 0xFB00, 0xFB4F ],
|
||||||
|
[ 63, 0xFB50, 0xFDFF ],
|
||||||
|
[ 64, 0xFE20, 0xFE2F ],
|
||||||
|
[ 65, 0xFE10, 0xFE1F ],
|
||||||
|
[ 65, 0xFE30, 0xFE4F ],
|
||||||
|
[ 66, 0xFE50, 0xFE6F ],
|
||||||
|
[ 67, 0xFE70, 0xFEFF ],
|
||||||
|
[ 68, 0xFF00, 0xFFEF ],
|
||||||
|
[ 69, 0xFFF0, 0xFFFF ],
|
||||||
|
[ 70, 0x0F00, 0x0FFF ],
|
||||||
|
[ 71, 0x0700, 0x074F ],
|
||||||
|
[ 72, 0x0780, 0x07BF ],
|
||||||
|
[ 73, 0x0D80, 0x0DFF ],
|
||||||
|
[ 74, 0x1000, 0x109F ],
|
||||||
|
[ 75, 0x1200, 0x137F ],
|
||||||
|
[ 75, 0x1380, 0x139F ],
|
||||||
|
[ 75, 0x2D80, 0x2DDF ],
|
||||||
|
[ 76, 0x13A0, 0x13FF ],
|
||||||
|
[ 77, 0x1400, 0x167F ],
|
||||||
|
[ 78, 0x1680, 0x169F ],
|
||||||
|
[ 79, 0x16A0, 0x16FF ],
|
||||||
|
[ 80, 0x1780, 0x17FF ],
|
||||||
|
[ 80, 0x19E0, 0x19FF ],
|
||||||
|
[ 81, 0x1800, 0x18AF ],
|
||||||
|
[ 82, 0x2800, 0x28FF ],
|
||||||
|
[ 83, 0xA000, 0xA48F ],
|
||||||
|
[ 83, 0xA490, 0xA4CF ],
|
||||||
|
[ 84, 0x1700, 0x171F ],
|
||||||
|
[ 84, 0x1720, 0x173F ],
|
||||||
|
[ 84, 0x1740, 0x175F ],
|
||||||
|
[ 84, 0x1760, 0x177F ],
|
||||||
|
[ 85, 0x10300, 0x1032F ],
|
||||||
|
[ 86, 0x10330, 0x1034F ],
|
||||||
|
[ 87, 0x10400, 0x1044F ],
|
||||||
|
[ 88, 0x1D000, 0x1D0FF ],
|
||||||
|
[ 88, 0x1D100, 0x1D1FF ],
|
||||||
|
[ 88, 0x1D200, 0x1D24F ],
|
||||||
|
[ 89, 0x1D400, 0x1D7FF ],
|
||||||
|
[ 90, 0xF0000, 0xFFFFD ],
|
||||||
|
[ 90, 0x100000, 0x10FFFD ],
|
||||||
|
[ 91, 0xFE00, 0xFE0F ],
|
||||||
|
[ 91, 0xE0100, 0xE01EF ],
|
||||||
|
[ 92, 0xE0000, 0xE007F ],
|
||||||
|
[ 93, 0x1900, 0x194F ],
|
||||||
|
[ 94, 0x1950, 0x197F ],
|
||||||
|
[ 95, 0x1980, 0x19DF ],
|
||||||
|
[ 96, 0x1A00, 0x1A1F ],
|
||||||
|
[ 97, 0x2C00, 0x2C5F ],
|
||||||
|
[ 98, 0x2D30, 0x2D7F ],
|
||||||
|
[ 99, 0x4DC0, 0x4DFF ],
|
||||||
|
[ 100, 0xA800, 0xA82F ],
|
||||||
|
[ 101, 0x10000, 0x1007F ],
|
||||||
|
[ 101, 0x10080, 0x100FF ],
|
||||||
|
[ 101, 0x10100, 0x1013F ],
|
||||||
|
[ 102, 0x10140, 0x1018F ],
|
||||||
|
[ 103, 0x10380, 0x1039F ],
|
||||||
|
[ 104, 0x103A0, 0x103DF ],
|
||||||
|
[ 105, 0x10450, 0x1047F ],
|
||||||
|
[ 106, 0x10480, 0x104AF ],
|
||||||
|
[ 107, 0x10800, 0x1083F ],
|
||||||
|
[ 108, 0x10A00, 0x10A5F ],
|
||||||
|
[ 109, 0x1D300, 0x1D35F ],
|
||||||
|
[ 110, 0x12000, 0x123FF ],
|
||||||
|
[ 110, 0x12400, 0x1247F ],
|
||||||
|
[ 111, 0x1D360, 0x1D37F ],
|
||||||
|
[ 112, 0x1B80, 0x1BBF ],
|
||||||
|
[ 113, 0x1C00, 0x1C4F ],
|
||||||
|
[ 114, 0x1C50, 0x1C7F ],
|
||||||
|
[ 115, 0xA880, 0xA8DF ],
|
||||||
|
[ 116, 0xA900, 0xA92F ],
|
||||||
|
[ 117, 0xA930, 0xA95F ],
|
||||||
|
[ 118, 0xAA00, 0xAA5F ],
|
||||||
|
[ 119, 0x10190, 0x101CF ],
|
||||||
|
[ 120, 0x101D0, 0x101FF ],
|
||||||
|
[ 121, 0x102A0, 0x102DF ],
|
||||||
|
[ 121, 0x10280, 0x1029F ],
|
||||||
|
[ 121, 0x10920, 0x1093F ],
|
||||||
|
[ 122, 0x1F030, 0x1F09F ],
|
||||||
|
[ 122, 0x1F000, 0x1F02F ]
|
||||||
|
];
|
||||||
|
|
||||||
|
function ulCharRanges(font) {
|
||||||
|
let charRanges = [0, 0, 0, 0];
|
||||||
|
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
const unicode = char.code;
|
||||||
|
const range = CHAR_RANGES.find(_range => unicode >= _range[1] && unicode <= _range[2]);
|
||||||
|
|
||||||
|
if (range != null) {
|
||||||
|
charRanges[range[0] >> 5] |= 1 << (range[0] & 0x1F);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (font.maxCode >= 0x10000) {
|
||||||
|
charRanges[57 >> 5] |= 1 << (57 & 0x1F);
|
||||||
|
}
|
||||||
|
return [ charRanges[0] >>> 0, charRanges[1] >>> 0, charRanges[2] >>> 0, charRanges[3] >>> 0 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- ulCodePages --
|
||||||
|
function ulCodePages(font) {
|
||||||
|
const spaceIndex = font.chars.findIndex(char => char.code === 0x20);
|
||||||
|
const ascii = Number(spaceIndex !== -1 && font.chars[spaceIndex + 0x5E].code === 0x7E);
|
||||||
|
const findf = (unicode) => Number(font.chars.findIndex(char => char.code === unicode) !== -1);
|
||||||
|
const graph = findf(0x2524);
|
||||||
|
const radic = findf(0x221A);
|
||||||
|
let codePages = [0, 0];
|
||||||
|
|
||||||
|
// conditions from FontForge
|
||||||
|
font.chars.forEach(char => {
|
||||||
|
switch (char.code) {
|
||||||
|
case 0x00DE:
|
||||||
|
codePages[0] |= (ascii) << 0; // 1252 Latin1
|
||||||
|
break;
|
||||||
|
case 0x255A:
|
||||||
|
codePages[1] |= (ascii) << 30; // 850 WE/Latin1
|
||||||
|
codePages[1] |= (ascii) << 31; // 437 US
|
||||||
|
break;
|
||||||
|
case 0x013D:
|
||||||
|
codePages[0] |= (ascii) << 1; // 1250 Latin 2: Eastern Europe
|
||||||
|
codePages[1] |= (ascii & graph) << 26; // 852 Latin 2
|
||||||
|
break;
|
||||||
|
case 0x0411:
|
||||||
|
codePages[0] |= 1 << 2; // 1251 Cyrillic
|
||||||
|
codePages[1] |= (findf(0x255C) & graph) << 17; // 866 MS-DOS Russian
|
||||||
|
codePages[1] |= (findf(0x0405) & graph) << 25; // 855 IBM Cyrillic
|
||||||
|
break;
|
||||||
|
case 0x0386:
|
||||||
|
codePages[0] |= 1 << 3; // 1253 Greek
|
||||||
|
codePages[1] |= (findf(0x00BD) & graph) << 16; // 869 IBM Greek
|
||||||
|
codePages[1] |= (graph & radic) << 28; // 737 Greek; former 437 G
|
||||||
|
break;
|
||||||
|
case 0x0130:
|
||||||
|
codePages[0] |= (ascii) << 4; // 1254 Turkish
|
||||||
|
codePages[1] |= (ascii & graph) << 24; // 857 IBM Turkish
|
||||||
|
break;
|
||||||
|
case 0x05D0:
|
||||||
|
codePages[0] |= 1 << 5; // 1255 Hebrew
|
||||||
|
codePages[1] |= (graph & radic) << 21; // 862 Hebrew
|
||||||
|
break;
|
||||||
|
case 0x0631:
|
||||||
|
codePages[0] |= 1 << 6; // 1256 Arabic
|
||||||
|
codePages[1] |= (radic) << 19; // 864 Arabic
|
||||||
|
codePages[1] |= (graph) << 29; // 708 Arabic; ASMO 708
|
||||||
|
break;
|
||||||
|
case 0x0157:
|
||||||
|
codePages[0] |= (ascii) << 7; // 1257 Windows Baltic
|
||||||
|
codePages[1] |= (ascii & graph) << 27; // 775 MS-DOS Baltic
|
||||||
|
break;
|
||||||
|
case 0x20AB:
|
||||||
|
codePages[0] |= 1 << 8; // 1258 Vietnamese
|
||||||
|
break;
|
||||||
|
case 0x0E45:
|
||||||
|
codePages[0] |= 1 << 16; // 874 Thai
|
||||||
|
break;
|
||||||
|
case 0x30A8:
|
||||||
|
codePages[0] |= 1 << 17; // 932 JIS/Japan
|
||||||
|
break;
|
||||||
|
case 0x3105:
|
||||||
|
codePages[0] |= 1 << 18; // 936 Chinese: Simplified chars
|
||||||
|
break;
|
||||||
|
case 0x3131:
|
||||||
|
codePages[0] |= 1 << 19; // 949 Korean Wansung
|
||||||
|
break;
|
||||||
|
case 0x592E:
|
||||||
|
codePages[0] |= 1 << 20; // 950 Chinese: Traditional chars
|
||||||
|
break;
|
||||||
|
case 0xACF4:
|
||||||
|
codePages[0] |= 1 << 21; // 1361 Korean Johab
|
||||||
|
break;
|
||||||
|
case 0x2030:
|
||||||
|
codePages[0] |= (findf(0x2211) & ascii) << 29; // Macintosh Character Set (Roman)
|
||||||
|
break;
|
||||||
|
case 0x2665:
|
||||||
|
codePages[0] |= (ascii) << 30; // OEM Character Set
|
||||||
|
break;
|
||||||
|
case 0x00C5:
|
||||||
|
codePages[1] |= (ascii & graph & radic) << 18; // 865 MS-DOS Nordic
|
||||||
|
break;
|
||||||
|
case 0x00E9:
|
||||||
|
codePages[1] |= (ascii & graph & radic) << 20; // 863 MS-DOS Canadian French
|
||||||
|
break;
|
||||||
|
case 0x00F5:
|
||||||
|
codePages[1] |= (ascii & graph & radic) << 23; // 860 MS-DOS Portuguese
|
||||||
|
break;
|
||||||
|
case 0x00FE:
|
||||||
|
codePages[1] |= (ascii & graph) << 22; // 861 MS-DOS Icelandic
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
if (char.code >= 0xF000 && char.code <= 0xF0FF) {
|
||||||
|
codePages[0] |= 1 << 31; // Symbol Character Set
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return [ codePages[0] >>> 0, codePages[1] >>> 0 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- containsRTL --
|
||||||
|
const RTL_RANGES = [
|
||||||
|
[ 0x05BE, 0x05BE ],
|
||||||
|
[ 0x05C0, 0x05C0 ],
|
||||||
|
[ 0x05C3, 0x05C3 ],
|
||||||
|
[ 0x05C6, 0x05C6 ],
|
||||||
|
[ 0x05D0, 0x05EA ],
|
||||||
|
[ 0x05EF, 0x05F4 ],
|
||||||
|
[ 0x0608, 0x0608 ],
|
||||||
|
[ 0x060B, 0x060B ],
|
||||||
|
[ 0x060D, 0x060D ],
|
||||||
|
[ 0x061B, 0x061C ],
|
||||||
|
[ 0x061E, 0x064A ],
|
||||||
|
[ 0x066D, 0x066F ],
|
||||||
|
[ 0x0671, 0x06D5 ],
|
||||||
|
[ 0x06E5, 0x06E6 ],
|
||||||
|
[ 0x06EE, 0x06EF ],
|
||||||
|
[ 0x06FA, 0x070D ],
|
||||||
|
[ 0x070F, 0x0710 ],
|
||||||
|
[ 0x0712, 0x072F ],
|
||||||
|
[ 0x074D, 0x07A5 ],
|
||||||
|
[ 0x07B1, 0x07B1 ],
|
||||||
|
[ 0x07C0, 0x07EA ],
|
||||||
|
[ 0x07F4, 0x07F5 ],
|
||||||
|
[ 0x07FA, 0x07FA ],
|
||||||
|
[ 0x07FE, 0x0815 ],
|
||||||
|
[ 0x081A, 0x081A ],
|
||||||
|
[ 0x0824, 0x0824 ],
|
||||||
|
[ 0x0828, 0x0828 ],
|
||||||
|
[ 0x0830, 0x083E ],
|
||||||
|
[ 0x0840, 0x0858 ],
|
||||||
|
[ 0x085E, 0x085E ],
|
||||||
|
[ 0x0860, 0x086A ],
|
||||||
|
[ 0x08A0, 0x08B4 ],
|
||||||
|
[ 0x08B6, 0x08BD ],
|
||||||
|
[ 0x200F, 0x200F ],
|
||||||
|
[ 0x202B, 0x202B ],
|
||||||
|
[ 0x202E, 0x202E ],
|
||||||
|
[ 0xFB1D, 0xFB1D ],
|
||||||
|
[ 0xFB1F, 0xFB28 ],
|
||||||
|
[ 0xFB2A, 0xFB36 ],
|
||||||
|
[ 0xFB38, 0xFB3C ],
|
||||||
|
[ 0xFB3E, 0xFB3E ],
|
||||||
|
[ 0xFB40, 0xFB41 ],
|
||||||
|
[ 0xFB43, 0xFB44 ],
|
||||||
|
[ 0xFB46, 0xFBC1 ],
|
||||||
|
[ 0xFBD3, 0xFD3D ],
|
||||||
|
[ 0xFD50, 0xFD8F ],
|
||||||
|
[ 0xFD92, 0xFDC7 ],
|
||||||
|
[ 0xFDF0, 0xFDFC ],
|
||||||
|
[ 0xFE70, 0xFE74 ],
|
||||||
|
[ 0xFE76, 0xFEFC ],
|
||||||
|
[ 0x10800, 0x10FFF ],
|
||||||
|
[ 0x1E800, 0x1EFFF ],
|
||||||
|
[ -1, 0 ]
|
||||||
|
];
|
||||||
|
|
||||||
|
function containsRTL(font) {
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
for (let char of font.chars) {
|
||||||
|
while (char.code > RTL_RANGES[index][1]) {
|
||||||
|
if (RTL_RANGES[++index][0] === -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (char.code >= RTL_RANGES[index][0]) {
|
||||||
|
return 0x200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0x000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- postMacIndex --
|
||||||
|
const POST_MAC_NAMES = [
|
||||||
|
'.notdef',
|
||||||
|
'.null',
|
||||||
|
'nonmarkingreturn',
|
||||||
|
'space',
|
||||||
|
'exclam',
|
||||||
|
'quotedbl',
|
||||||
|
'numbersign',
|
||||||
|
'dollar',
|
||||||
|
'percent',
|
||||||
|
'ampersand',
|
||||||
|
'quotesingle',
|
||||||
|
'parenleft',
|
||||||
|
'parenright',
|
||||||
|
'asterisk',
|
||||||
|
'plus',
|
||||||
|
'comma',
|
||||||
|
'hyphen',
|
||||||
|
'period',
|
||||||
|
'slash',
|
||||||
|
'zero',
|
||||||
|
'one',
|
||||||
|
'two',
|
||||||
|
'three',
|
||||||
|
'four',
|
||||||
|
'five',
|
||||||
|
'six',
|
||||||
|
'seven',
|
||||||
|
'eight',
|
||||||
|
'nine',
|
||||||
|
'colon',
|
||||||
|
'semicolon',
|
||||||
|
'less',
|
||||||
|
'equal',
|
||||||
|
'greater',
|
||||||
|
'question',
|
||||||
|
'at',
|
||||||
|
'A',
|
||||||
|
'B',
|
||||||
|
'C',
|
||||||
|
'D',
|
||||||
|
'E',
|
||||||
|
'F',
|
||||||
|
'G',
|
||||||
|
'H',
|
||||||
|
'I',
|
||||||
|
'J',
|
||||||
|
'K',
|
||||||
|
'L',
|
||||||
|
'M',
|
||||||
|
'N',
|
||||||
|
'O',
|
||||||
|
'P',
|
||||||
|
'Q',
|
||||||
|
'R',
|
||||||
|
'S',
|
||||||
|
'T',
|
||||||
|
'U',
|
||||||
|
'V',
|
||||||
|
'W',
|
||||||
|
'X',
|
||||||
|
'Y',
|
||||||
|
'Z',
|
||||||
|
'bracketleft',
|
||||||
|
'backslash',
|
||||||
|
'bracketright',
|
||||||
|
'asciicircum',
|
||||||
|
'underscore',
|
||||||
|
'grave',
|
||||||
|
'a',
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
'd',
|
||||||
|
'e',
|
||||||
|
'f',
|
||||||
|
'g',
|
||||||
|
'h',
|
||||||
|
'i',
|
||||||
|
'j',
|
||||||
|
'k',
|
||||||
|
'l',
|
||||||
|
'm',
|
||||||
|
'n',
|
||||||
|
'o',
|
||||||
|
'p',
|
||||||
|
'q',
|
||||||
|
'r',
|
||||||
|
's',
|
||||||
|
't',
|
||||||
|
'u',
|
||||||
|
'v',
|
||||||
|
'w',
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
'z',
|
||||||
|
'braceleft',
|
||||||
|
'bar',
|
||||||
|
'braceright',
|
||||||
|
'asciitilde',
|
||||||
|
'Adieresis',
|
||||||
|
'Aring',
|
||||||
|
'Ccedilla',
|
||||||
|
'Eacute',
|
||||||
|
'Ntilde',
|
||||||
|
'Odieresis',
|
||||||
|
'Udieresis',
|
||||||
|
'aacute',
|
||||||
|
'agrave',
|
||||||
|
'acircumflex',
|
||||||
|
'adieresis',
|
||||||
|
'atilde',
|
||||||
|
'aring',
|
||||||
|
'ccedilla',
|
||||||
|
'eacute',
|
||||||
|
'egrave',
|
||||||
|
'ecircumflex',
|
||||||
|
'edieresis',
|
||||||
|
'iacute',
|
||||||
|
'igrave',
|
||||||
|
'icircumflex',
|
||||||
|
'idieresis',
|
||||||
|
'ntilde',
|
||||||
|
'oacute',
|
||||||
|
'ograve',
|
||||||
|
'ocircumflex',
|
||||||
|
'odieresis',
|
||||||
|
'otilde',
|
||||||
|
'uacute',
|
||||||
|
'ugrave',
|
||||||
|
'ucircumflex',
|
||||||
|
'udieresis',
|
||||||
|
'dagger',
|
||||||
|
'degree',
|
||||||
|
'cent',
|
||||||
|
'sterling',
|
||||||
|
'section',
|
||||||
|
'bullet',
|
||||||
|
'paragraph',
|
||||||
|
'germandbls',
|
||||||
|
'registered',
|
||||||
|
'copyright',
|
||||||
|
'trademark',
|
||||||
|
'acute',
|
||||||
|
'dieresis',
|
||||||
|
'notequal',
|
||||||
|
'AE',
|
||||||
|
'Oslash',
|
||||||
|
'infinity',
|
||||||
|
'plusminus',
|
||||||
|
'lessequal',
|
||||||
|
'greaterequal',
|
||||||
|
'yen',
|
||||||
|
'mu',
|
||||||
|
'partialdiff',
|
||||||
|
'summation',
|
||||||
|
'product',
|
||||||
|
'pi',
|
||||||
|
'integral',
|
||||||
|
'ordfeminine',
|
||||||
|
'ordmasculine',
|
||||||
|
'Omega',
|
||||||
|
'ae',
|
||||||
|
'oslash',
|
||||||
|
'questiondown',
|
||||||
|
'exclamdown',
|
||||||
|
'logicalnot',
|
||||||
|
'radical',
|
||||||
|
'florin',
|
||||||
|
'approxequal',
|
||||||
|
'Delta',
|
||||||
|
'guillemotleft',
|
||||||
|
'guillemotright',
|
||||||
|
'ellipsis',
|
||||||
|
'nonbreakingspace',
|
||||||
|
'Agrave',
|
||||||
|
'Atilde',
|
||||||
|
'Otilde',
|
||||||
|
'OE',
|
||||||
|
'oe',
|
||||||
|
'endash',
|
||||||
|
'emdash',
|
||||||
|
'quotedblleft',
|
||||||
|
'quotedblright',
|
||||||
|
'quoteleft',
|
||||||
|
'quoteright',
|
||||||
|
'divide',
|
||||||
|
'lozenge',
|
||||||
|
'ydieresis',
|
||||||
|
'Ydieresis',
|
||||||
|
'fraction',
|
||||||
|
'currency',
|
||||||
|
'guilsinglleft',
|
||||||
|
'guilsinglright',
|
||||||
|
'fi',
|
||||||
|
'fl',
|
||||||
|
'daggerdbl',
|
||||||
|
'periodcentered',
|
||||||
|
'quotesinglbase',
|
||||||
|
'quotedblbase',
|
||||||
|
'perthousand',
|
||||||
|
'Acircumflex',
|
||||||
|
'Ecircumflex',
|
||||||
|
'Aacute',
|
||||||
|
'Edieresis',
|
||||||
|
'Egrave',
|
||||||
|
'Iacute',
|
||||||
|
'Icircumflex',
|
||||||
|
'Idieresis',
|
||||||
|
'Igrave',
|
||||||
|
'Oacute',
|
||||||
|
'Ocircumflex',
|
||||||
|
'apple',
|
||||||
|
'Ograve',
|
||||||
|
'Uacute',
|
||||||
|
'Ucircumflex',
|
||||||
|
'Ugrave',
|
||||||
|
'dotlessi',
|
||||||
|
'circumflex',
|
||||||
|
'tilde',
|
||||||
|
'macron',
|
||||||
|
'breve',
|
||||||
|
'dotaccent',
|
||||||
|
'ring',
|
||||||
|
'cedilla',
|
||||||
|
'hungarumlaut',
|
||||||
|
'ogonek',
|
||||||
|
'caron',
|
||||||
|
'Lslash',
|
||||||
|
'lslash',
|
||||||
|
'Scaron',
|
||||||
|
'scaron',
|
||||||
|
'Zcaron',
|
||||||
|
'zcaron',
|
||||||
|
'brokenbar',
|
||||||
|
'Eth',
|
||||||
|
'eth',
|
||||||
|
'Yacute',
|
||||||
|
'yacute',
|
||||||
|
'Thorn',
|
||||||
|
'thorn',
|
||||||
|
'minus',
|
||||||
|
'multiply',
|
||||||
|
'onesuperior',
|
||||||
|
'twosuperior',
|
||||||
|
'threesuperior',
|
||||||
|
'onehalf',
|
||||||
|
'onequarter',
|
||||||
|
'threequarters',
|
||||||
|
'franc',
|
||||||
|
'Gbreve',
|
||||||
|
'gbreve',
|
||||||
|
'Idotaccent',
|
||||||
|
'Scedilla',
|
||||||
|
'scedilla',
|
||||||
|
'Cacute',
|
||||||
|
'cacute',
|
||||||
|
'Ccaron',
|
||||||
|
'ccaron',
|
||||||
|
'dcroat'
|
||||||
|
];
|
||||||
|
|
||||||
|
function postMacNames() {
|
||||||
|
return POST_MAC_NAMES.slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Export --
|
||||||
|
module.exports = Object.freeze({
|
||||||
|
xAvgCharWidth,
|
||||||
|
ulCharRanges,
|
||||||
|
ulCodePages,
|
||||||
|
containsRTL,
|
||||||
|
postMacNames
|
||||||
|
});
|
||||||
@@ -0,0 +1,663 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
# pylint: disable=bad-whitespace
|
||||||
|
|
||||||
|
# -- x_avg_char_width --
|
||||||
|
WEIGHT_FACTORS = (
|
||||||
|
( 'a', 64 ),
|
||||||
|
( 'b', 14 ),
|
||||||
|
( 'c', 27 ),
|
||||||
|
( 'd', 35 ),
|
||||||
|
( 'e', 100 ),
|
||||||
|
( 'f', 20 ),
|
||||||
|
( 'g', 14 ),
|
||||||
|
( 'h', 42 ),
|
||||||
|
( 'i', 63 ),
|
||||||
|
( 'j', 3 ),
|
||||||
|
( 'k', 6 ),
|
||||||
|
( 'l', 35 ),
|
||||||
|
( 'm', 20 ),
|
||||||
|
( 'n', 56 ),
|
||||||
|
( 'o', 56 ),
|
||||||
|
( 'p', 17 ),
|
||||||
|
( 'q', 4 ),
|
||||||
|
( 'r', 49 ),
|
||||||
|
( 's', 56 ),
|
||||||
|
( 't', 71 ),
|
||||||
|
( 'u', 31 ),
|
||||||
|
( 'v', 10 ),
|
||||||
|
( 'w', 18 ),
|
||||||
|
( 'x', 3 ),
|
||||||
|
( 'y', 18 ),
|
||||||
|
( 'z', 2 ),
|
||||||
|
( ' ', 166 )
|
||||||
|
)
|
||||||
|
|
||||||
|
def x_avg_char_width(font):
|
||||||
|
x_avg_total_width = 0
|
||||||
|
|
||||||
|
for factor in WEIGHT_FACTORS:
|
||||||
|
char = next((char for char in font.chars if char.code == ord(factor[0])), None)
|
||||||
|
|
||||||
|
if char is None:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
x_avg_total_width += font.scaleWidth(char) * factor[1]
|
||||||
|
|
||||||
|
return round(x_avg_total_width / 1000)
|
||||||
|
|
||||||
|
|
||||||
|
# -- ul_char_ranges --
|
||||||
|
CHAR_RANGES = (
|
||||||
|
( 0, 0x0000, 0x007F ),
|
||||||
|
( 1, 0x0080, 0x00FF ),
|
||||||
|
( 2, 0x0100, 0x017F ),
|
||||||
|
( 3, 0x0180, 0x024F ),
|
||||||
|
( 4, 0x0250, 0x02AF ),
|
||||||
|
( 4, 0x1D00, 0x1D7F ),
|
||||||
|
( 4, 0x1D80, 0x1DBF ),
|
||||||
|
( 5, 0x02B0, 0x02FF ),
|
||||||
|
( 5, 0xA700, 0xA71F ),
|
||||||
|
( 6, 0x0300, 0x036F ),
|
||||||
|
( 6, 0x1DC0, 0x1DFF ),
|
||||||
|
( 7, 0x0370, 0x03FF ),
|
||||||
|
( 8, 0x2C80, 0x2CFF ),
|
||||||
|
( 9, 0x0400, 0x04FF ),
|
||||||
|
( 9, 0x0500, 0x052F ),
|
||||||
|
( 9, 0x2DE0, 0x2DFF ),
|
||||||
|
( 9, 0xA640, 0xA69F ),
|
||||||
|
( 10, 0x0530, 0x058F ),
|
||||||
|
( 11, 0x0590, 0x05FF ),
|
||||||
|
( 12, 0xA500, 0xA63F ),
|
||||||
|
( 13, 0x0600, 0x06FF ),
|
||||||
|
( 13, 0x0750, 0x077F ),
|
||||||
|
( 14, 0x07C0, 0x07FF ),
|
||||||
|
( 15, 0x0900, 0x097F ),
|
||||||
|
( 16, 0x0980, 0x09FF ),
|
||||||
|
( 17, 0x0A00, 0x0A7F ),
|
||||||
|
( 18, 0x0A80, 0x0AFF ),
|
||||||
|
( 19, 0x0B00, 0x0B7F ),
|
||||||
|
( 20, 0x0B80, 0x0BFF ),
|
||||||
|
( 21, 0x0C00, 0x0C7F ),
|
||||||
|
( 22, 0x0C80, 0x0CFF ),
|
||||||
|
( 23, 0x0D00, 0x0D7F ),
|
||||||
|
( 24, 0x0E00, 0x0E7F ),
|
||||||
|
( 25, 0x0E80, 0x0EFF ),
|
||||||
|
( 26, 0x10A0, 0x10FF ),
|
||||||
|
( 26, 0x2D00, 0x2D2F ),
|
||||||
|
( 27, 0x1B00, 0x1B7F ),
|
||||||
|
( 28, 0x1100, 0x11FF ),
|
||||||
|
( 29, 0x1E00, 0x1EFF ),
|
||||||
|
( 29, 0x2C60, 0x2C7F ),
|
||||||
|
( 29, 0xA720, 0xA7FF ),
|
||||||
|
( 30, 0x1F00, 0x1FFF ),
|
||||||
|
( 31, 0x2000, 0x206F ),
|
||||||
|
( 31, 0x2E00, 0x2E7F ),
|
||||||
|
( 32, 0x2070, 0x209F ),
|
||||||
|
( 33, 0x20A0, 0x20CF ),
|
||||||
|
( 34, 0x20D0, 0x20FF ),
|
||||||
|
( 35, 0x2100, 0x214F ),
|
||||||
|
( 36, 0x2150, 0x218F ),
|
||||||
|
( 37, 0x2190, 0x21FF ),
|
||||||
|
( 37, 0x27F0, 0x27FF ),
|
||||||
|
( 37, 0x2900, 0x297F ),
|
||||||
|
( 37, 0x2B00, 0x2BFF ),
|
||||||
|
( 38, 0x2200, 0x22FF ),
|
||||||
|
( 38, 0x2A00, 0x2AFF ),
|
||||||
|
( 38, 0x27C0, 0x27EF ),
|
||||||
|
( 38, 0x2980, 0x29FF ),
|
||||||
|
( 39, 0x2300, 0x23FF ),
|
||||||
|
( 40, 0x2400, 0x243F ),
|
||||||
|
( 41, 0x2440, 0x245F ),
|
||||||
|
( 42, 0x2460, 0x24FF ),
|
||||||
|
( 43, 0x2500, 0x257F ),
|
||||||
|
( 44, 0x2580, 0x259F ),
|
||||||
|
( 45, 0x25A0, 0x25FF ),
|
||||||
|
( 46, 0x2600, 0x26FF ),
|
||||||
|
( 47, 0x2700, 0x27BF ),
|
||||||
|
( 48, 0x3000, 0x303F ),
|
||||||
|
( 49, 0x3040, 0x309F ),
|
||||||
|
( 50, 0x30A0, 0x30FF ),
|
||||||
|
( 50, 0x31F0, 0x31FF ),
|
||||||
|
( 51, 0x3100, 0x312F ),
|
||||||
|
( 51, 0x31A0, 0x31BF ),
|
||||||
|
( 52, 0x3130, 0x318F ),
|
||||||
|
( 53, 0xA840, 0xA87F ),
|
||||||
|
( 54, 0x3200, 0x32FF ),
|
||||||
|
( 55, 0x3300, 0x33FF ),
|
||||||
|
( 56, 0xAC00, 0xD7AF ),
|
||||||
|
( 57, 0xD800, 0xDFFF ),
|
||||||
|
( 58, 0x10900, 0x1091F ),
|
||||||
|
( 59, 0x4E00, 0x9FFF ),
|
||||||
|
( 59, 0x2E80, 0x2EFF ),
|
||||||
|
( 59, 0x2F00, 0x2FDF ),
|
||||||
|
( 59, 0x2FF0, 0x2FFF ),
|
||||||
|
( 59, 0x3400, 0x4DBF ),
|
||||||
|
( 59, 0x20000, 0x2A6DF ),
|
||||||
|
( 59, 0x3190, 0x319F ),
|
||||||
|
( 60, 0xE000, 0xF8FF ),
|
||||||
|
( 61, 0x31C0, 0x31EF ),
|
||||||
|
( 61, 0xF900, 0xFAFF ),
|
||||||
|
( 61, 0x2F800, 0x2FA1F ),
|
||||||
|
( 62, 0xFB00, 0xFB4F ),
|
||||||
|
( 63, 0xFB50, 0xFDFF ),
|
||||||
|
( 64, 0xFE20, 0xFE2F ),
|
||||||
|
( 65, 0xFE10, 0xFE1F ),
|
||||||
|
( 65, 0xFE30, 0xFE4F ),
|
||||||
|
( 66, 0xFE50, 0xFE6F ),
|
||||||
|
( 67, 0xFE70, 0xFEFF ),
|
||||||
|
( 68, 0xFF00, 0xFFEF ),
|
||||||
|
( 69, 0xFFF0, 0xFFFF ),
|
||||||
|
( 70, 0x0F00, 0x0FFF ),
|
||||||
|
( 71, 0x0700, 0x074F ),
|
||||||
|
( 72, 0x0780, 0x07BF ),
|
||||||
|
( 73, 0x0D80, 0x0DFF ),
|
||||||
|
( 74, 0x1000, 0x109F ),
|
||||||
|
( 75, 0x1200, 0x137F ),
|
||||||
|
( 75, 0x1380, 0x139F ),
|
||||||
|
( 75, 0x2D80, 0x2DDF ),
|
||||||
|
( 76, 0x13A0, 0x13FF ),
|
||||||
|
( 77, 0x1400, 0x167F ),
|
||||||
|
( 78, 0x1680, 0x169F ),
|
||||||
|
( 79, 0x16A0, 0x16FF ),
|
||||||
|
( 80, 0x1780, 0x17FF ),
|
||||||
|
( 80, 0x19E0, 0x19FF ),
|
||||||
|
( 81, 0x1800, 0x18AF ),
|
||||||
|
( 82, 0x2800, 0x28FF ),
|
||||||
|
( 83, 0xA000, 0xA48F ),
|
||||||
|
( 83, 0xA490, 0xA4CF ),
|
||||||
|
( 84, 0x1700, 0x171F ),
|
||||||
|
( 84, 0x1720, 0x173F ),
|
||||||
|
( 84, 0x1740, 0x175F ),
|
||||||
|
( 84, 0x1760, 0x177F ),
|
||||||
|
( 85, 0x10300, 0x1032F ),
|
||||||
|
( 86, 0x10330, 0x1034F ),
|
||||||
|
( 87, 0x10400, 0x1044F ),
|
||||||
|
( 88, 0x1D000, 0x1D0FF ),
|
||||||
|
( 88, 0x1D100, 0x1D1FF ),
|
||||||
|
( 88, 0x1D200, 0x1D24F ),
|
||||||
|
( 89, 0x1D400, 0x1D7FF ),
|
||||||
|
( 90, 0xF0000, 0xFFFFD ),
|
||||||
|
( 90, 0x100000, 0x10FFFD ),
|
||||||
|
( 91, 0xFE00, 0xFE0F ),
|
||||||
|
( 91, 0xE0100, 0xE01EF ),
|
||||||
|
( 92, 0xE0000, 0xE007F ),
|
||||||
|
( 93, 0x1900, 0x194F ),
|
||||||
|
( 94, 0x1950, 0x197F ),
|
||||||
|
( 95, 0x1980, 0x19DF ),
|
||||||
|
( 96, 0x1A00, 0x1A1F ),
|
||||||
|
( 97, 0x2C00, 0x2C5F ),
|
||||||
|
( 98, 0x2D30, 0x2D7F ),
|
||||||
|
( 99, 0x4DC0, 0x4DFF ),
|
||||||
|
( 100, 0xA800, 0xA82F ),
|
||||||
|
( 101, 0x10000, 0x1007F ),
|
||||||
|
( 101, 0x10080, 0x100FF ),
|
||||||
|
( 101, 0x10100, 0x1013F ),
|
||||||
|
( 102, 0x10140, 0x1018F ),
|
||||||
|
( 103, 0x10380, 0x1039F ),
|
||||||
|
( 104, 0x103A0, 0x103DF ),
|
||||||
|
( 105, 0x10450, 0x1047F ),
|
||||||
|
( 106, 0x10480, 0x104AF ),
|
||||||
|
( 107, 0x10800, 0x1083F ),
|
||||||
|
( 108, 0x10A00, 0x10A5F ),
|
||||||
|
( 109, 0x1D300, 0x1D35F ),
|
||||||
|
( 110, 0x12000, 0x123FF ),
|
||||||
|
( 110, 0x12400, 0x1247F ),
|
||||||
|
( 111, 0x1D360, 0x1D37F ),
|
||||||
|
( 112, 0x1B80, 0x1BBF ),
|
||||||
|
( 113, 0x1C00, 0x1C4F ),
|
||||||
|
( 114, 0x1C50, 0x1C7F ),
|
||||||
|
( 115, 0xA880, 0xA8DF ),
|
||||||
|
( 116, 0xA900, 0xA92F ),
|
||||||
|
( 117, 0xA930, 0xA95F ),
|
||||||
|
( 118, 0xAA00, 0xAA5F ),
|
||||||
|
( 119, 0x10190, 0x101CF ),
|
||||||
|
( 120, 0x101D0, 0x101FF ),
|
||||||
|
( 121, 0x102A0, 0x102DF ),
|
||||||
|
( 121, 0x10280, 0x1029F ),
|
||||||
|
( 121, 0x10920, 0x1093F ),
|
||||||
|
( 122, 0x1F030, 0x1F09F ),
|
||||||
|
( 122, 0x1F000, 0x1F02F )
|
||||||
|
)
|
||||||
|
|
||||||
|
def ul_char_ranges(font):
|
||||||
|
char_ranges = [0, 0, 0, 0]
|
||||||
|
|
||||||
|
for char in font.chars:
|
||||||
|
range = next((range for range in CHAR_RANGES if range[1] <= char.code <= range[2]), None)
|
||||||
|
|
||||||
|
if range is not None:
|
||||||
|
char_ranges[range[0] >> 5] |= 1 << (range[0] & 0x1F)
|
||||||
|
|
||||||
|
if font.max_code >= 0x10000:
|
||||||
|
char_ranges[57 >> 5] |= 1 << (57 & 0x1F)
|
||||||
|
|
||||||
|
return char_ranges
|
||||||
|
|
||||||
|
|
||||||
|
# -- ul_code_pages --
|
||||||
|
def ul_code_pages(font):
|
||||||
|
space_index = next((index for index, char in enumerate(font.chars) if char.code == 0x20), len(font.chars))
|
||||||
|
ascii = int(len(font.chars) >= space_index + 0x5F and font.chars[space_index + 0x5E].code == 0x7E)
|
||||||
|
findf = lambda unicode: int(next((char for char in font.chars if char.code == unicode), None) is not None)
|
||||||
|
graph = findf(0x2524)
|
||||||
|
radic = findf(0x221A)
|
||||||
|
code_pages = [0, 0]
|
||||||
|
|
||||||
|
# conditions from FontForge
|
||||||
|
for char in font.chars:
|
||||||
|
unicode = char.code
|
||||||
|
|
||||||
|
if unicode == 0x00DE:
|
||||||
|
code_pages[0] |= (ascii) << 0 # 1252 Latin1
|
||||||
|
elif unicode == 0x255A:
|
||||||
|
code_pages[1] |= (ascii) << 30 # 850 WE/Latin1
|
||||||
|
code_pages[1] |= (ascii) << 31 # 437 US
|
||||||
|
elif unicode == 0x013D:
|
||||||
|
code_pages[0] |= (ascii) << 1 # 1250 Latin 2: Eastern Europe
|
||||||
|
code_pages[1] |= (ascii & graph) << 26 # 852 Latin 2
|
||||||
|
elif unicode == 0x0411:
|
||||||
|
code_pages[0] |= 1 << 2 # 1251 Cyrillic
|
||||||
|
code_pages[1] |= (findf(0x255C) & graph) << 17 # 866 MS-DOS Russian
|
||||||
|
code_pages[1] |= (findf(0x0405) & graph) << 25 # 855 IBM Cyrillic
|
||||||
|
elif unicode == 0x0386:
|
||||||
|
code_pages[0] |= 1 << 3 # 1253 Greek
|
||||||
|
code_pages[1] |= (findf(0x00BD) & graph) << 16 # 869 IBM Greek
|
||||||
|
code_pages[1] |= (graph & radic) << 28 # 737 Greek; former 437 G
|
||||||
|
elif unicode == 0x0130:
|
||||||
|
code_pages[0] |= (ascii) << 4 # 1254 Turkish
|
||||||
|
code_pages[1] |= (ascii & graph) << 24 # 857 IBM Turkish
|
||||||
|
elif unicode == 0x05D0:
|
||||||
|
code_pages[0] |= 1 << 5 # 1255 Hebrew
|
||||||
|
code_pages[1] |= (graph & radic) << 21 # 862 Hebrew
|
||||||
|
elif unicode == 0x0631:
|
||||||
|
code_pages[0] |= 1 << 6 # 1256 Arabic
|
||||||
|
code_pages[1] |= (radic) << 19 # 864 Arabic
|
||||||
|
code_pages[1] |= (graph) << 29 # 708 Arabic; ASMO 708
|
||||||
|
elif unicode == 0x0157:
|
||||||
|
code_pages[0] |= (ascii) << 7 # 1257 Windows Baltic
|
||||||
|
code_pages[1] |= (ascii & graph) << 27 # 775 MS-DOS Baltic
|
||||||
|
elif unicode == 0x20AB:
|
||||||
|
code_pages[0] |= 1 << 8 # 1258 Vietnamese
|
||||||
|
elif unicode == 0x0E45:
|
||||||
|
code_pages[0] |= 1 << 16 # 874 Thai
|
||||||
|
elif unicode == 0x30A8:
|
||||||
|
code_pages[0] |= 1 << 17 # 932 JIS/Japan
|
||||||
|
elif unicode == 0x3105:
|
||||||
|
code_pages[0] |= 1 << 18 # 936 Chinese: Simplified chars
|
||||||
|
elif unicode == 0x3131:
|
||||||
|
code_pages[0] |= 1 << 19 # 949 Korean Wansung
|
||||||
|
elif unicode == 0x592E:
|
||||||
|
code_pages[0] |= 1 << 20 # 950 Chinese: Traditional chars
|
||||||
|
elif unicode == 0xACF4:
|
||||||
|
code_pages[0] |= 1 << 21 # 1361 Korean Johab
|
||||||
|
elif unicode == 0x2030:
|
||||||
|
code_pages[0] |= (findf(0x2211) & ascii) << 29 # Macintosh Character Set (Roman)
|
||||||
|
elif unicode == 0x2665:
|
||||||
|
code_pages[0] |= (ascii) << 30 # OEM Character Set
|
||||||
|
elif unicode == 0x00C5:
|
||||||
|
code_pages[1] |= (ascii & graph & radic) << 18 # 865 MS-DOS Nordic
|
||||||
|
elif unicode == 0x00E9:
|
||||||
|
code_pages[1] |= (ascii & graph & radic) << 20 # 863 MS-DOS Canadian French
|
||||||
|
elif unicode == 0x00F5:
|
||||||
|
code_pages[1] |= (ascii & graph & radic) << 23 # 860 MS-DOS Portuguese
|
||||||
|
elif unicode == 0x00FE:
|
||||||
|
code_pages[1] |= (ascii & graph) << 22 # 861 MS-DOS Icelandic
|
||||||
|
elif 0xF000 <= unicode <= 0xF0FF:
|
||||||
|
code_pages[0] |= 1 << 31 # Symbol Character Set
|
||||||
|
|
||||||
|
return code_pages
|
||||||
|
|
||||||
|
|
||||||
|
# -- strong_rtl_flag --
|
||||||
|
RTL_RANGES = (
|
||||||
|
( 0x05BE, 0x05BE ),
|
||||||
|
( 0x05C0, 0x05C0 ),
|
||||||
|
( 0x05C3, 0x05C3 ),
|
||||||
|
( 0x05C6, 0x05C6 ),
|
||||||
|
( 0x05D0, 0x05EA ),
|
||||||
|
( 0x05EF, 0x05F4 ),
|
||||||
|
( 0x0608, 0x0608 ),
|
||||||
|
( 0x060B, 0x060B ),
|
||||||
|
( 0x060D, 0x060D ),
|
||||||
|
( 0x061B, 0x061C ),
|
||||||
|
( 0x061E, 0x064A ),
|
||||||
|
( 0x066D, 0x066F ),
|
||||||
|
( 0x0671, 0x06D5 ),
|
||||||
|
( 0x06E5, 0x06E6 ),
|
||||||
|
( 0x06EE, 0x06EF ),
|
||||||
|
( 0x06FA, 0x070D ),
|
||||||
|
( 0x070F, 0x0710 ),
|
||||||
|
( 0x0712, 0x072F ),
|
||||||
|
( 0x074D, 0x07A5 ),
|
||||||
|
( 0x07B1, 0x07B1 ),
|
||||||
|
( 0x07C0, 0x07EA ),
|
||||||
|
( 0x07F4, 0x07F5 ),
|
||||||
|
( 0x07FA, 0x07FA ),
|
||||||
|
( 0x07FE, 0x0815 ),
|
||||||
|
( 0x081A, 0x081A ),
|
||||||
|
( 0x0824, 0x0824 ),
|
||||||
|
( 0x0828, 0x0828 ),
|
||||||
|
( 0x0830, 0x083E ),
|
||||||
|
( 0x0840, 0x0858 ),
|
||||||
|
( 0x085E, 0x085E ),
|
||||||
|
( 0x0860, 0x086A ),
|
||||||
|
( 0x08A0, 0x08B4 ),
|
||||||
|
( 0x08B6, 0x08BD ),
|
||||||
|
( 0x200F, 0x200F ),
|
||||||
|
( 0x202B, 0x202B ),
|
||||||
|
( 0x202E, 0x202E ),
|
||||||
|
( 0xFB1D, 0xFB1D ),
|
||||||
|
( 0xFB1F, 0xFB28 ),
|
||||||
|
( 0xFB2A, 0xFB36 ),
|
||||||
|
( 0xFB38, 0xFB3C ),
|
||||||
|
( 0xFB3E, 0xFB3E ),
|
||||||
|
( 0xFB40, 0xFB41 ),
|
||||||
|
( 0xFB43, 0xFB44 ),
|
||||||
|
( 0xFB46, 0xFBC1 ),
|
||||||
|
( 0xFBD3, 0xFD3D ),
|
||||||
|
( 0xFD50, 0xFD8F ),
|
||||||
|
( 0xFD92, 0xFDC7 ),
|
||||||
|
( 0xFDF0, 0xFDFC ),
|
||||||
|
( 0xFE70, 0xFE74 ),
|
||||||
|
( 0xFE76, 0xFEFC ),
|
||||||
|
( 0x10800, 0x10FFF ),
|
||||||
|
( 0x1E800, 0x1EFFF ),
|
||||||
|
(-1, 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
def contains_rtl(font):
|
||||||
|
index = 0
|
||||||
|
|
||||||
|
for char in font.chars:
|
||||||
|
while char.code > RTL_RANGES[index][1]:
|
||||||
|
index += 1
|
||||||
|
if RTL_RANGES[index][0] == -1:
|
||||||
|
break
|
||||||
|
|
||||||
|
if char.code >= RTL_RANGES[index][0]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# -- post_mac_names --
|
||||||
|
POST_MAC_NAMES = (
|
||||||
|
b'.notdef',
|
||||||
|
b'.null',
|
||||||
|
b'nonmarkingreturn',
|
||||||
|
b'space',
|
||||||
|
b'exclam',
|
||||||
|
b'quotedbl',
|
||||||
|
b'numbersign',
|
||||||
|
b'dollar',
|
||||||
|
b'percent',
|
||||||
|
b'ampersand',
|
||||||
|
b'quotesingle',
|
||||||
|
b'parenleft',
|
||||||
|
b'parenright',
|
||||||
|
b'asterisk',
|
||||||
|
b'plus',
|
||||||
|
b'comma',
|
||||||
|
b'hyphen',
|
||||||
|
b'period',
|
||||||
|
b'slash',
|
||||||
|
b'zero',
|
||||||
|
b'one',
|
||||||
|
b'two',
|
||||||
|
b'three',
|
||||||
|
b'four',
|
||||||
|
b'five',
|
||||||
|
b'six',
|
||||||
|
b'seven',
|
||||||
|
b'eight',
|
||||||
|
b'nine',
|
||||||
|
b'colon',
|
||||||
|
b'semicolon',
|
||||||
|
b'less',
|
||||||
|
b'equal',
|
||||||
|
b'greater',
|
||||||
|
b'question',
|
||||||
|
b'at',
|
||||||
|
b'A',
|
||||||
|
b'B',
|
||||||
|
b'C',
|
||||||
|
b'D',
|
||||||
|
b'E',
|
||||||
|
b'F',
|
||||||
|
b'G',
|
||||||
|
b'H',
|
||||||
|
b'I',
|
||||||
|
b'J',
|
||||||
|
b'K',
|
||||||
|
b'L',
|
||||||
|
b'M',
|
||||||
|
b'N',
|
||||||
|
b'O',
|
||||||
|
b'P',
|
||||||
|
b'Q',
|
||||||
|
b'R',
|
||||||
|
b'S',
|
||||||
|
b'T',
|
||||||
|
b'U',
|
||||||
|
b'V',
|
||||||
|
b'W',
|
||||||
|
b'X',
|
||||||
|
b'Y',
|
||||||
|
b'Z',
|
||||||
|
b'bracketleft',
|
||||||
|
b'backslash',
|
||||||
|
b'bracketright',
|
||||||
|
b'asciicircum',
|
||||||
|
b'underscore',
|
||||||
|
b'grave',
|
||||||
|
b'a',
|
||||||
|
b'b',
|
||||||
|
b'c',
|
||||||
|
b'd',
|
||||||
|
b'e',
|
||||||
|
b'f',
|
||||||
|
b'g',
|
||||||
|
b'h',
|
||||||
|
b'i',
|
||||||
|
b'j',
|
||||||
|
b'k',
|
||||||
|
b'l',
|
||||||
|
b'm',
|
||||||
|
b'n',
|
||||||
|
b'o',
|
||||||
|
b'p',
|
||||||
|
b'q',
|
||||||
|
b'r',
|
||||||
|
b's',
|
||||||
|
b't',
|
||||||
|
b'u',
|
||||||
|
b'v',
|
||||||
|
b'w',
|
||||||
|
b'x',
|
||||||
|
b'y',
|
||||||
|
b'z',
|
||||||
|
b'braceleft',
|
||||||
|
b'bar',
|
||||||
|
b'braceright',
|
||||||
|
b'asciitilde',
|
||||||
|
b'Adieresis',
|
||||||
|
b'Aring',
|
||||||
|
b'Ccedilla',
|
||||||
|
b'Eacute',
|
||||||
|
b'Ntilde',
|
||||||
|
b'Odieresis',
|
||||||
|
b'Udieresis',
|
||||||
|
b'aacute',
|
||||||
|
b'agrave',
|
||||||
|
b'acircumflex',
|
||||||
|
b'adieresis',
|
||||||
|
b'atilde',
|
||||||
|
b'aring',
|
||||||
|
b'ccedilla',
|
||||||
|
b'eacute',
|
||||||
|
b'egrave',
|
||||||
|
b'ecircumflex',
|
||||||
|
b'edieresis',
|
||||||
|
b'iacute',
|
||||||
|
b'igrave',
|
||||||
|
b'icircumflex',
|
||||||
|
b'idieresis',
|
||||||
|
b'ntilde',
|
||||||
|
b'oacute',
|
||||||
|
b'ograve',
|
||||||
|
b'ocircumflex',
|
||||||
|
b'odieresis',
|
||||||
|
b'otilde',
|
||||||
|
b'uacute',
|
||||||
|
b'ugrave',
|
||||||
|
b'ucircumflex',
|
||||||
|
b'udieresis',
|
||||||
|
b'dagger',
|
||||||
|
b'degree',
|
||||||
|
b'cent',
|
||||||
|
b'sterling',
|
||||||
|
b'section',
|
||||||
|
b'bullet',
|
||||||
|
b'paragraph',
|
||||||
|
b'germandbls',
|
||||||
|
b'registered',
|
||||||
|
b'copyright',
|
||||||
|
b'trademark',
|
||||||
|
b'acute',
|
||||||
|
b'dieresis',
|
||||||
|
b'notequal',
|
||||||
|
b'AE',
|
||||||
|
b'Oslash',
|
||||||
|
b'infinity',
|
||||||
|
b'plusminus',
|
||||||
|
b'lessequal',
|
||||||
|
b'greaterequal',
|
||||||
|
b'yen',
|
||||||
|
b'mu',
|
||||||
|
b'partialdiff',
|
||||||
|
b'summation',
|
||||||
|
b'product',
|
||||||
|
b'pi',
|
||||||
|
b'integral',
|
||||||
|
b'ordfeminine',
|
||||||
|
b'ordmasculine',
|
||||||
|
b'Omega',
|
||||||
|
b'ae',
|
||||||
|
b'oslash',
|
||||||
|
b'questiondown',
|
||||||
|
b'exclamdown',
|
||||||
|
b'logicalnot',
|
||||||
|
b'radical',
|
||||||
|
b'florin',
|
||||||
|
b'approxequal',
|
||||||
|
b'Delta',
|
||||||
|
b'guillemotleft',
|
||||||
|
b'guillemotright',
|
||||||
|
b'ellipsis',
|
||||||
|
b'nonbreakingspace',
|
||||||
|
b'Agrave',
|
||||||
|
b'Atilde',
|
||||||
|
b'Otilde',
|
||||||
|
b'OE',
|
||||||
|
b'oe',
|
||||||
|
b'endash',
|
||||||
|
b'emdash',
|
||||||
|
b'quotedblleft',
|
||||||
|
b'quotedblright',
|
||||||
|
b'quoteleft',
|
||||||
|
b'quoteright',
|
||||||
|
b'divide',
|
||||||
|
b'lozenge',
|
||||||
|
b'ydieresis',
|
||||||
|
b'Ydieresis',
|
||||||
|
b'fraction',
|
||||||
|
b'currency',
|
||||||
|
b'guilsinglleft',
|
||||||
|
b'guilsinglright',
|
||||||
|
b'fi',
|
||||||
|
b'fl',
|
||||||
|
b'daggerdbl',
|
||||||
|
b'periodcentered',
|
||||||
|
b'quotesinglbase',
|
||||||
|
b'quotedblbase',
|
||||||
|
b'perthousand',
|
||||||
|
b'Acircumflex',
|
||||||
|
b'Ecircumflex',
|
||||||
|
b'Aacute',
|
||||||
|
b'Edieresis',
|
||||||
|
b'Egrave',
|
||||||
|
b'Iacute',
|
||||||
|
b'Icircumflex',
|
||||||
|
b'Idieresis',
|
||||||
|
b'Igrave',
|
||||||
|
b'Oacute',
|
||||||
|
b'Ocircumflex',
|
||||||
|
b'apple',
|
||||||
|
b'Ograve',
|
||||||
|
b'Uacute',
|
||||||
|
b'Ucircumflex',
|
||||||
|
b'Ugrave',
|
||||||
|
b'dotlessi',
|
||||||
|
b'circumflex',
|
||||||
|
b'tilde',
|
||||||
|
b'macron',
|
||||||
|
b'breve',
|
||||||
|
b'dotaccent',
|
||||||
|
b'ring',
|
||||||
|
b'cedilla',
|
||||||
|
b'hungarumlaut',
|
||||||
|
b'ogonek',
|
||||||
|
b'caron',
|
||||||
|
b'Lslash',
|
||||||
|
b'lslash',
|
||||||
|
b'Scaron',
|
||||||
|
b'scaron',
|
||||||
|
b'Zcaron',
|
||||||
|
b'zcaron',
|
||||||
|
b'brokenbar',
|
||||||
|
b'Eth',
|
||||||
|
b'eth',
|
||||||
|
b'Yacute',
|
||||||
|
b'yacute',
|
||||||
|
b'Thorn',
|
||||||
|
b'thorn',
|
||||||
|
b'minus',
|
||||||
|
b'multiply',
|
||||||
|
b'onesuperior',
|
||||||
|
b'twosuperior',
|
||||||
|
b'threesuperior',
|
||||||
|
b'onehalf',
|
||||||
|
b'onequarter',
|
||||||
|
b'threequarters',
|
||||||
|
b'franc',
|
||||||
|
b'Gbreve',
|
||||||
|
b'gbreve',
|
||||||
|
b'Idotaccent',
|
||||||
|
b'Scedilla',
|
||||||
|
b'scedilla',
|
||||||
|
b'Cacute',
|
||||||
|
b'cacute',
|
||||||
|
b'Ccaron',
|
||||||
|
b'ccaron',
|
||||||
|
b'dcroat'
|
||||||
|
)
|
||||||
|
|
||||||
|
def post_mac_names():
|
||||||
|
return list(POST_MAC_NAMES)
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2017-2019 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fnutil = require('./fnutil.js');
|
||||||
|
const fncli = require('./fncli.js');
|
||||||
|
const fnio = require('./fnio.js');
|
||||||
|
const bdf = require('./bdf.js');
|
||||||
|
|
||||||
|
// -- Params --
|
||||||
|
class Params extends fncli.Params {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.filter = false;
|
||||||
|
this.family = null;
|
||||||
|
this.output = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Options --
|
||||||
|
const HELP = ('' +
|
||||||
|
'usage: ucstoany [-f] [-F FAMILY] [-o OUTPUT] INPUT REGISTRY ENCODING TABLE...\n' +
|
||||||
|
'Generate a BDF font subset.\n' +
|
||||||
|
'\n' +
|
||||||
|
' -f, --filter Discard characters with unicode FFFF; with registry ISO10646,\n' +
|
||||||
|
' encode the first 32 characters with their indexes; with other\n' +
|
||||||
|
' registries, encode all characters with indexes\n' +
|
||||||
|
' -F FAMILY output font family name (default = input)\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout)\n' +
|
||||||
|
' TABLE text file, one hexadecimal unicode per line\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input must be a BDF 2.1 font with unicode encoding.\n' +
|
||||||
|
'Unlike ucs2any, all TABLE-s form a single subset of the input font.\n');
|
||||||
|
|
||||||
|
const VERSION = 'ucstoany 1.55, Copyright (C) 2019 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE;
|
||||||
|
|
||||||
|
class Options extends fncli.Options {
|
||||||
|
constructor() {
|
||||||
|
super(['-F', '-o'], HELP, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(name, value, params) {
|
||||||
|
switch (name) {
|
||||||
|
case '-f':
|
||||||
|
case '--filter':
|
||||||
|
params.filter = true;
|
||||||
|
break;
|
||||||
|
case '-F':
|
||||||
|
if (value.includes('-')) {
|
||||||
|
throw new Error('FAMILY may not contain "-"');
|
||||||
|
}
|
||||||
|
params.family = value;
|
||||||
|
break;
|
||||||
|
case '-o':
|
||||||
|
params.output = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.fallback(name, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Main --
|
||||||
|
function mainProgram(nonopt, parsed) {
|
||||||
|
if (nonopt.length < 4) {
|
||||||
|
throw new Error('invalid number of arguments, try --help');
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = nonopt[0];
|
||||||
|
const registry = nonopt[1];
|
||||||
|
const encoding = nonopt[2];
|
||||||
|
let newCodes = [];
|
||||||
|
|
||||||
|
if (!registry.match(/^[A-Za-z][\w.:()]*$/) || !encoding.match(/^[\w.:()]+$/)) {
|
||||||
|
throw new Error('invalid registry or encoding');
|
||||||
|
}
|
||||||
|
|
||||||
|
// READ INPUT
|
||||||
|
let ifs = new fnio.InputFileStream(input);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var oldFont = bdf.Font.read(ifs);
|
||||||
|
ifs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// READ TABLES
|
||||||
|
nonopt.slice(3).forEach(name => {
|
||||||
|
ifs = new fnio.InputFileStream(name);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ifs.readLines(line => {
|
||||||
|
newCodes.push(fnutil.parseHex('unicode', line));
|
||||||
|
});
|
||||||
|
ifs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ifs.location() + e.message;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (newCodes.length === 0) {
|
||||||
|
throw new Error('no characters in the output font');
|
||||||
|
}
|
||||||
|
|
||||||
|
// CREATE GLYPHS
|
||||||
|
const newFont = new bdf.Font();
|
||||||
|
const charMap = [];
|
||||||
|
let index = 0;
|
||||||
|
let unstart = 0;
|
||||||
|
|
||||||
|
if (parsed.filter) {
|
||||||
|
unstart = (registry === 'ISO10646') ? 32 : bdf.CHARS_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// faster than Map() for <= 4K chars
|
||||||
|
oldFont.chars.forEach(char => (charMap[char.code] = char));
|
||||||
|
|
||||||
|
newCodes.forEach(code => {
|
||||||
|
let oldChar = charMap[code];
|
||||||
|
const uniFFFF = (oldChar == null);
|
||||||
|
|
||||||
|
if (code === 0xFFFF && parsed.filter) {
|
||||||
|
index++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uniFFFF) {
|
||||||
|
if (code !== 0xFFFF) {
|
||||||
|
throw new Error(`${input} does not contain U+${fnutil.unihex(code)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldFont.defaultCode !== -1) {
|
||||||
|
oldChar = charMap[oldFont.defaultCode];
|
||||||
|
} else {
|
||||||
|
oldChar = charMap[0xFFFD];
|
||||||
|
|
||||||
|
if (oldChar == null) {
|
||||||
|
throw new Error(`${input} does not contain U+FFFF, and no replacement found`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newChar = Object.assign(new bdf.Char(), oldChar);
|
||||||
|
|
||||||
|
newChar.code = index >= unstart ? code : index;
|
||||||
|
index++;
|
||||||
|
newChar.props = new bdf.Props();
|
||||||
|
oldChar.props.forEach((name, value) => newChar.props.set(name, value));
|
||||||
|
newChar.props.set('ENCODING', newChar.code);
|
||||||
|
newFont.chars.push(newChar);
|
||||||
|
|
||||||
|
if (uniFFFF) {
|
||||||
|
newChar.props.set('STARTCHAR', 'uniFFFF');
|
||||||
|
} else if (oldChar.code === oldFont.defaultCode || (oldChar.code === 0xFFFD && newFont.defaultCode === -1)) {
|
||||||
|
newFont.defaultCode = newChar.code;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// CREATE HEADER
|
||||||
|
let numProps;
|
||||||
|
const family = (parsed.family != null) ? parsed.family : oldFont.xlfd[bdf.XLFD.FAMILY_NAME];
|
||||||
|
|
||||||
|
oldFont.props.forEach((name, value) => {
|
||||||
|
switch (name) {
|
||||||
|
case 'FONT':
|
||||||
|
newFont.xlfd = oldFont.xlfd.slice();
|
||||||
|
newFont.xlfd[bdf.XLFD.FAMILY_NAME] = family;
|
||||||
|
newFont.xlfd[bdf.XLFD.CHARSET_REGISTRY] = registry;
|
||||||
|
newFont.xlfd[bdf.XLFD.CHARSET_ENCODING] = encoding;
|
||||||
|
value = newFont.xlfd.join('-');
|
||||||
|
break;
|
||||||
|
case 'STARTPROPERTIES':
|
||||||
|
numProps = fnutil.parseDec(name, value, 1);
|
||||||
|
break;
|
||||||
|
case 'FAMILY_NAME':
|
||||||
|
value = fnutil.quote(family);
|
||||||
|
break;
|
||||||
|
case 'CHARSET_REGISTRY':
|
||||||
|
value = fnutil.quote(registry);
|
||||||
|
break;
|
||||||
|
case 'CHARSET_ENCODING':
|
||||||
|
value = fnutil.quote(encoding);
|
||||||
|
break;
|
||||||
|
case 'DEFAULT_CHAR':
|
||||||
|
if (newFont.defaultCode !== -1) {
|
||||||
|
value = newFont.defaultCode;
|
||||||
|
} else {
|
||||||
|
numProps -= 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'ENDPROPERTIES':
|
||||||
|
if (newFont.defaultCode !== -1 && newFont.props.get('DEFAULT_CHAR') == null) {
|
||||||
|
newFont.props.set('DEFAULT_CHAR', newFont.defaultCode);
|
||||||
|
numProps += 1;
|
||||||
|
}
|
||||||
|
newFont.props.set('STARTPROPERTIES', numProps);
|
||||||
|
break;
|
||||||
|
case 'CHARS':
|
||||||
|
value = newFont.chars.length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
newFont.props.set(name, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// COPY FIELDS
|
||||||
|
newFont.bbx = oldFont.bbx;
|
||||||
|
|
||||||
|
// WRITE OUTPUT
|
||||||
|
let ofs = new fnio.OutputFileStream(parsed.output);
|
||||||
|
|
||||||
|
try {
|
||||||
|
newFont.write(ofs);
|
||||||
|
ofs.close();
|
||||||
|
} catch (e) {
|
||||||
|
e.message = ofs.location() + e.message + ofs.destroy();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
fncli.start('ucstoany.js', new Options(), new Params(), mainProgram);
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2017-2020 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
import re
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import fnutil
|
||||||
|
import fncli
|
||||||
|
import fnio
|
||||||
|
import bdf
|
||||||
|
|
||||||
|
# -- Params --
|
||||||
|
class Params(fncli.Params):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Params.__init__(self)
|
||||||
|
self.filter_ffff = False
|
||||||
|
self.family_name = None
|
||||||
|
self.output_name = None
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options --
|
||||||
|
HELP = ('' +
|
||||||
|
'usage: ucstoany [-f] [-F FAMILY] [-o OUTPUT] INPUT REGISTRY ENCODING TABLE...\n' +
|
||||||
|
'Generate a BDF font subset.\n' +
|
||||||
|
'\n' +
|
||||||
|
' -f, --filter Discard characters with unicode FFFF; with registry ISO10646,\n' +
|
||||||
|
' encode the first 32 characters with their indexes; with other\n' +
|
||||||
|
' registries, encode all characters with indexes\n' +
|
||||||
|
' -F FAMILY output font family name (default = input)\n' +
|
||||||
|
' -o OUTPUT output file (default = stdout)\n' +
|
||||||
|
' TABLE text file, one hexadecimal unicode per line\n' +
|
||||||
|
' --help display this help and exit\n' +
|
||||||
|
' --version display the program version and license, and exit\n' +
|
||||||
|
' --excstk display the exception stack on error\n' +
|
||||||
|
'\n' +
|
||||||
|
'The input must be a BDF 2.1 font with unicode encoding.\n' +
|
||||||
|
'Unlike ucs2any, all TABLE-s form a single subset of the input font.\n')
|
||||||
|
|
||||||
|
VERSION = 'ucstoany 1.62, Copyright (C) 2017-2020 Dimitar Toshkov Zhekov\n\n' + fnutil.GPL2PLUS_LICENSE
|
||||||
|
|
||||||
|
class Options(fncli.Options):
|
||||||
|
def __init__(self):
|
||||||
|
fncli.Options.__init__(self, ['-F', '-o'], HELP, VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
def parse(self, name, value, params):
|
||||||
|
if name in ['-f', '--filter']:
|
||||||
|
params.filter_ffff = True
|
||||||
|
elif name == '-F':
|
||||||
|
params.family_name = bytes(value, 'ascii')
|
||||||
|
if '-' in value:
|
||||||
|
raise Exception('FAMILY may not contain "-"')
|
||||||
|
elif name == '-o':
|
||||||
|
params.output_name = value
|
||||||
|
else:
|
||||||
|
self.fallback(name, params)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Main --
|
||||||
|
def main_program(nonopt, parsed):
|
||||||
|
# NON-OPTIONS
|
||||||
|
if len(nonopt) < 4:
|
||||||
|
raise Exception('invalid number of arguments, try --help')
|
||||||
|
|
||||||
|
input_name = nonopt[0]
|
||||||
|
registry = nonopt[1]
|
||||||
|
encoding = nonopt[2]
|
||||||
|
new_codes = []
|
||||||
|
|
||||||
|
if not re.fullmatch(r'[A-Za-z][\w.:()]*', registry) or not re.fullmatch(r'[\w.:()]+', encoding):
|
||||||
|
raise Exception('invalid registry or encoding')
|
||||||
|
|
||||||
|
# READ INPUT
|
||||||
|
old_font = fnio.read_file(input_name, bdf.Font.read)
|
||||||
|
|
||||||
|
# READ TABLES
|
||||||
|
def load_code(line):
|
||||||
|
new_codes.append(fnutil.parse_hex('unicode', line))
|
||||||
|
|
||||||
|
for table_name in nonopt[3:]:
|
||||||
|
fnio.read_file(table_name, lambda ifs: ifs.read_lines(load_code))
|
||||||
|
|
||||||
|
if not new_codes:
|
||||||
|
raise Exception('no characters in the output font')
|
||||||
|
|
||||||
|
# CREATE GLYPHS
|
||||||
|
new_font = bdf.Font()
|
||||||
|
charmap = {char.code:char for char in old_font.chars}
|
||||||
|
index = 0
|
||||||
|
unstart = 0
|
||||||
|
family = parsed.family_name if parsed.family_name is not None else old_font.xlfd[bdf.XLFD.FAMILY_NAME]
|
||||||
|
|
||||||
|
if parsed.filter_ffff:
|
||||||
|
unstart = 32 if registry == 'ISO10646' else bdf.CHARS_MAX
|
||||||
|
|
||||||
|
for code in new_codes:
|
||||||
|
if code == 0xFFFF and parsed.filter_ffff:
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if code in charmap:
|
||||||
|
old_char = charmap[code]
|
||||||
|
uni_ffff = False
|
||||||
|
else:
|
||||||
|
uni_ffff = True
|
||||||
|
|
||||||
|
if code != 0xFFFF:
|
||||||
|
raise Exception('%s does not contain U+%04X' % (input, code))
|
||||||
|
|
||||||
|
if old_font.default_code != -1:
|
||||||
|
old_char = charmap[old_font.default_code]
|
||||||
|
elif 0xFFFD in charmap:
|
||||||
|
old_char = charmap[0xFFFD]
|
||||||
|
else:
|
||||||
|
raise Exception('%s does not contain U+FFFF, and no replacement found' % input)
|
||||||
|
|
||||||
|
new_char = copy.copy(old_char)
|
||||||
|
new_char.code = code if index >= unstart else index
|
||||||
|
index += 1
|
||||||
|
new_char.props = copy.copy(old_char.props)
|
||||||
|
new_char.props.set('ENCODING', new_char.code)
|
||||||
|
new_font.chars.append(new_char)
|
||||||
|
|
||||||
|
if uni_ffff:
|
||||||
|
new_char.props.set('STARTCHAR', b'uniFFFF')
|
||||||
|
elif old_char.code == old_font.default_code or (old_char.code == 0xFFFD and new_font.default_code == -1):
|
||||||
|
new_font.default_code = new_char.code
|
||||||
|
|
||||||
|
# CREATE HEADER
|
||||||
|
registry = bytes(registry, 'ascii')
|
||||||
|
encoding = bytes(encoding, 'ascii')
|
||||||
|
|
||||||
|
for [name, value] in old_font.props:
|
||||||
|
if name == 'FONT':
|
||||||
|
new_font.xlfd = old_font.xlfd[:]
|
||||||
|
new_font.xlfd[bdf.XLFD.FAMILY_NAME] = family
|
||||||
|
new_font.xlfd[bdf.XLFD.CHARSET_REGISTRY] = registry
|
||||||
|
new_font.xlfd[bdf.XLFD.CHARSET_ENCODING] = encoding
|
||||||
|
value = b'-'.join(new_font.xlfd)
|
||||||
|
elif name == 'STARTPROPERTIES':
|
||||||
|
num_props = fnutil.parse_dec(name, value, 1)
|
||||||
|
elif name == 'FAMILY_NAME':
|
||||||
|
value = fnutil.quote(family)
|
||||||
|
elif name == 'CHARSET_REGISTRY':
|
||||||
|
value = fnutil.quote(registry)
|
||||||
|
elif name == 'CHARSET_ENCODING':
|
||||||
|
value = fnutil.quote(encoding)
|
||||||
|
elif name == 'DEFAULT_CHAR':
|
||||||
|
if new_font.default_code != -1:
|
||||||
|
value = new_font.default_code
|
||||||
|
else:
|
||||||
|
num_props -= 1
|
||||||
|
continue
|
||||||
|
elif name == 'ENDPROPERTIES':
|
||||||
|
if new_font.default_code != -1 and new_font.props.get('DEFAULT_CHAR') is None:
|
||||||
|
new_font.props.set('DEFAULT_CHAR', new_font.default_code)
|
||||||
|
num_props += 1
|
||||||
|
|
||||||
|
new_font.props.set('STARTPROPERTIES', num_props)
|
||||||
|
elif name == 'CHARS':
|
||||||
|
value = len(new_font.chars)
|
||||||
|
|
||||||
|
new_font.props.set(name, value)
|
||||||
|
|
||||||
|
# COPY FIELDS
|
||||||
|
new_font.bbx = old_font.bbx
|
||||||
|
|
||||||
|
# WRITE OUTPUT
|
||||||
|
fnio.write_file(parsed.output_name, lambda ofs: new_font.write(ofs))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fncli.start('ucstoany.py', Options(), Params(), main_program)
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if test "$1" = "--help" ; then
|
||||||
|
echo usage: $0 [--var=VALUE] [VAR=VALUE] ...
|
||||||
|
echo
|
||||||
|
cat configure.help 2> /dev/null && echo
|
||||||
|
echo "Any variables not explicitly set are reset to their defaults"
|
||||||
|
elif test "$1" = "--version" ; then
|
||||||
|
cat << EOT
|
||||||
|
micro configure 0.21, Copyright (C) 2015 Dimitar Toshkov Zhekov
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
EOT
|
||||||
|
elif test -z `printf "\r"` ; then
|
||||||
|
echo "$0: printf failure"
|
||||||
|
false
|
||||||
|
elif test -f Makefile ; then
|
||||||
|
if test -f Makefile.in ; then
|
||||||
|
cp -fp Makefile.in Makefile
|
||||||
|
else
|
||||||
|
cp -p Makefile Makefile.in
|
||||||
|
fi
|
||||||
|
w=`printf "[\t ]*"`
|
||||||
|
r=`printf "\r"`
|
||||||
|
l="[a-z][a-z0-9-]*[^-]"
|
||||||
|
for i do
|
||||||
|
if test "$i" != "`echo "$i" | sed -e 1q`" ; then
|
||||||
|
echo "$0: `echo "$i" | sed -e "s/$r/^M/" -e 1q`^J...: contains line feed" 1>&2
|
||||||
|
elif echo "$i" | grep "$r" > /dev/null ; then
|
||||||
|
echo "$0: `echo "$i" | sed -e "s/$r.*//"`^M...: contains carriage return" 1>&2
|
||||||
|
elif test -n "$i" ; then
|
||||||
|
if echo "$i" | grep -E "^--$l=|^[A-Z][A-Z0-9_]*[^_]=" > /dev/null ; then
|
||||||
|
n=`echo "$i" | sed -e "s$r^-*$r$r" -e "s$r=.*$r$r" | sed -e "s/-/_/g"`
|
||||||
|
if grep -E "^$n$w:?=" Makefile > /dev/null ; then
|
||||||
|
cp -f Makefile Makefile.$$
|
||||||
|
sed -e "s$r^\($n$w:*=$w\).*$r\1`echo "$i" | sed -e "s$r^[^=]*=$r$r"`$r" Makefile.$$ > Makefile
|
||||||
|
grep -E "^$n$w:?=" Makefile /dev/null
|
||||||
|
else
|
||||||
|
echo "$0: $n: not found in Makefile" 1>&2
|
||||||
|
fi
|
||||||
|
unset n
|
||||||
|
else
|
||||||
|
echo "$0: $i: not recognized" 1>&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
unset i l r w
|
||||||
|
if test -f Makefile.$$ ; then
|
||||||
|
rm -f Makefile.$$
|
||||||
|
else
|
||||||
|
rm -f Makefile.in
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$0: Makefile: not found" 1>&2
|
||||||
|
false
|
||||||
|
fi
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
To assign environment variables (e.g., CC, CFLAGS...), specify them as
|
||||||
|
NAME=VALUE. See README for a description of all options and targets.
|
||||||
|
|
||||||
|
The default values are specified in brackets.
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
--help display this help and exit
|
||||||
|
--version display version information and exit
|
||||||
|
|
||||||
|
Installation directories:
|
||||||
|
--prefix=PREFIX prefix for all directories [/usr/local]
|
||||||
|
--psfdir=DIR PC screen fonts directory [PREFIX/share/consolefonts]
|
||||||
|
--x11dir=DIR X11 fonts directory [PREFIX/share/fonts/terminus]
|
||||||
|
--otbdir=DIR TrueType/OTB fonts directory [PREFIX/share/fonts/terminus]
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
0020 0000
|
||||||
|
2302 007F
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
25B6 25BA
|
||||||
|
25C0 25C4
|
||||||
|
2666 25C6
|
||||||
|
266B 266C
|
||||||
|
FFFD 0000
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
00B5 03BC
|
||||||
|
03A3 2211
|
||||||
|
03A9 2126
|
||||||
|
03B2 00DF
|
||||||
|
220A 03B5
|
||||||
|
220A 2208
|
||||||
|
2205 03C6
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0138 043A
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
006B 043A
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
043F 03C0
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
2191 25B2
|
||||||
|
2193 25BC
|
||||||
|
25B6 2192
|
||||||
|
25B6 25BA
|
||||||
|
25A0 FFFD
|
||||||
|
25C0 2190
|
||||||
|
25C0 25C4
|
||||||
|
2666 25C6
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
0020 0000
|
||||||
|
0020 00A0
|
||||||
|
0020 2000
|
||||||
|
0020 2001
|
||||||
|
0020 2002
|
||||||
|
0020 2003
|
||||||
|
0020 2004
|
||||||
|
0020 2005
|
||||||
|
0020 2006
|
||||||
|
0020 2007
|
||||||
|
0020 2008
|
||||||
|
0020 2009
|
||||||
|
0020 200A
|
||||||
|
0020 202F
|
||||||
|
002D 2012
|
||||||
|
002D 2013
|
||||||
|
002D 2212
|
||||||
|
0033 0417
|
||||||
|
0041 0391
|
||||||
|
0041 0410
|
||||||
|
0042 0392
|
||||||
|
0042 0412
|
||||||
|
0043 0421
|
||||||
|
0045 0395
|
||||||
|
0045 0415
|
||||||
|
0048 0397
|
||||||
|
0048 041D
|
||||||
|
0049 0399
|
||||||
|
0049 0406
|
||||||
|
0049 04C0
|
||||||
|
004A 0408
|
||||||
|
004B 039A
|
||||||
|
004B 041A
|
||||||
|
004D 039C
|
||||||
|
004D 041C
|
||||||
|
004E 039D
|
||||||
|
004F 039F
|
||||||
|
004F 041E
|
||||||
|
0050 03A1
|
||||||
|
0050 0420
|
||||||
|
0053 0405
|
||||||
|
0054 03A4
|
||||||
|
0054 0422
|
||||||
|
0058 03A7
|
||||||
|
0058 0425
|
||||||
|
0059 03A5
|
||||||
|
0059 04AE
|
||||||
|
005A 0396
|
||||||
|
0061 0430
|
||||||
|
0063 03F2
|
||||||
|
0063 0441
|
||||||
|
0065 0435
|
||||||
|
0068 210E
|
||||||
|
0069 0456
|
||||||
|
006A 03F3
|
||||||
|
006A 0458
|
||||||
|
006C 04CF
|
||||||
|
006F 03BF
|
||||||
|
006F 043E
|
||||||
|
0070 0440
|
||||||
|
0073 0455
|
||||||
|
0076 03BD
|
||||||
|
0078 0445
|
||||||
|
0079 0443
|
||||||
|
00AD 2010
|
||||||
|
00AD 2011
|
||||||
|
00B4 0301
|
||||||
|
00B5 03BC
|
||||||
|
00C4 04D2
|
||||||
|
00C6 04D4
|
||||||
|
00C8 0400
|
||||||
|
00CB 0401
|
||||||
|
00CF 03AA
|
||||||
|
00CF 0407
|
||||||
|
00D0 0110
|
||||||
|
00D6 04E6
|
||||||
|
00E4 04D3
|
||||||
|
00E6 04D5
|
||||||
|
00E8 0450
|
||||||
|
00EB 0451
|
||||||
|
00EF 0457
|
||||||
|
00F3 03CC
|
||||||
|
00F6 04E7
|
||||||
|
0102 04D0
|
||||||
|
0103 04D1
|
||||||
|
0138 03BA
|
||||||
|
0178 03AB
|
||||||
|
02C6 0302
|
||||||
|
02C7 030C
|
||||||
|
02D8 0306
|
||||||
|
02DC 0303
|
||||||
|
0393 0413
|
||||||
|
03A9 2126
|
||||||
|
03B5 2208
|
||||||
|
03B5 220A
|
||||||
|
03C0 043F
|
||||||
|
03C6 2205
|
||||||
|
041F 03A0
|
||||||
|
045B 0127
|
||||||
|
045B 210F
|
||||||
|
04AF 03B3
|
||||||
|
04D8 018F
|
||||||
|
04D9 0259
|
||||||
|
04E8 03F4
|
||||||
|
2014 2015
|
||||||
|
2206 0394
|
||||||
|
0138 043A
|
||||||