Files
jameswitzeman.net/fonts/terminus-font/bin/otb1get.js
T
2026-05-29 11:30:10 -07:00

707 lines
14 KiB
JavaScript

/*
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
});