Iosevka/font-src/index.js
2020-09-30 20:25:39 -07:00

121 lines
4.2 KiB
JavaScript

"use strict";
const fs = require("fs-extra");
const path = require("path");
const child_process = require("child_process");
const Toml = require("@iarna/toml");
const which = require("which");
const BuildFont = require("./gen/build-font.js");
const Parameters = require("./support/parameters");
const FormVariantData = require("./support/variant-data");
const FormLigationData = require("./support/ligation-data");
const { createGrDisplaySheet } = require("./support/gr");
module.exports = async function main(argv) {
const para = await getParameters(argv);
const { font, glyphStore } = BuildFont(para);
if (argv.oCharMap) await saveCharMap(argv, glyphStore);
if (argv.o) await saveTTF(argv, font);
};
// Parameter preparation
async function getParameters(argv) {
const PARAMETERS_TOML = path.resolve(__dirname, "../params/parameters.toml");
const WEIGHTS_TOML = path.resolve(__dirname, "../params/shape-weight.toml");
const WIDTHS_TOML = path.resolve(__dirname, "../params/shape-width.toml");
const PRIVATE_TOML = path.resolve(__dirname, "../params/private-parameters.toml");
const VARIANTS_TOML = path.resolve(__dirname, "../params/variants.toml");
const LIGATIONS_TOML = path.resolve(__dirname, "../params/ligation-set.toml");
const parametersData = Object.assign(
{},
await tryParseToml(PARAMETERS_TOML),
await tryParseToml(WEIGHTS_TOML),
await tryParseToml(WIDTHS_TOML),
fs.existsSync(PRIVATE_TOML) ? await tryParseToml(PRIVATE_TOML) : {}
);
const rawVariantsData = await tryParseToml(VARIANTS_TOML);
const rawLigationData = await tryParseToml(LIGATIONS_TOML);
let para = {};
Parameters.apply(para, parametersData, ["iosevka"]);
Parameters.apply(para, parametersData, argv.preHives);
Parameters.apply(para, parametersData, ["shapeWeight"], { shapeWeight: argv.shape.weight });
Parameters.apply(para, parametersData, ["shapeWidth"], { shapeWidth: argv.shape.width });
Parameters.apply(para, parametersData, [`s-${argv.shape.slope}`]);
Parameters.apply(para, parametersData, [`diversity-${argv.shape.quasiProportionalDiversity}`]);
const variantsData = FormVariantData(rawVariantsData, para);
para.variants = variantsData;
para.variantSelector = {};
Parameters.apply(para.variantSelector, variantsData, ["default", ...argv.preHives]);
para.defaultVariant = variantsData.default;
const ligationData = FormLigationData(rawLigationData, para);
para.defaultBuildup = { ...ligationData.defaultBuildup };
para.ligation = {};
Parameters.apply(para.ligation, ligationData.hives, ["default", ...argv.preHives]);
if (argv.excludedCharRanges) para.excludedCharRanges = argv.excludedCharRanges;
if (argv.compatibilityLigatures) para.compLig = argv.compatibilityLigatures;
if (argv.metricOverride) Parameters.applyMetricOverride(para, argv.metricOverride);
para.naming = {
...para.naming,
family: argv.menu.family,
version: argv.menu.version,
weight: argv.menu.weight - 0,
width: argv.menu.width - 0,
slope: argv.menu.slope
};
return para;
}
async function tryParseToml(str) {
try {
return Toml.parse(await fs.readFile(str, "utf-8"));
} catch (e) {
throw new Error(
`Failed to parse configuration file ${str}.\nPlease validate whether there's syntax error.\n${e}`
);
}
}
// Save TTF
async function saveTTF(argv, font) {
await otfccBuild(argv.o, JSON.stringify(font));
}
function otfccBuild(argvO, fontJson) {
const otfccOptions = ["-O3", "--keep-average-char-width", "-q"];
return new Promise((resolve, reject) => {
const otfccBuild = which.sync("otfccbuild");
const cp = child_process.spawn(otfccBuild, ["-o", argvO, ...otfccOptions]);
cp.stdout.on("data", data => {
console.log(`stdout: ${data}`);
});
cp.stderr.on("data", data => {
console.error(`stderr: ${data}`);
});
cp.on("close", code => {
if (code) reject(new Error("OTFCC returned with: " + code));
else resolve(0);
});
cp.stdin.write(fontJson);
cp.stdin.end();
});
}
// Save character map file
async function saveCharMap(argv, glyphStore) {
let charMap = [];
for (const [gn] of glyphStore.namedEntries()) {
charMap.push([
gn,
Array.from(glyphStore.queryUnicodeOfName(gn) || []),
...createGrDisplaySheet(glyphStore, gn)
]);
}
await fs.writeFile(argv.oCharMap, JSON.stringify(charMap), "utf8");
}