114 lines
3.1 KiB
JavaScript
114 lines
3.1 KiB
JavaScript
"use strict";
|
|
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
const argv = require("yargs").argv;
|
|
const buildGlyphs = require("./build-glyphs.js");
|
|
const parameters = require("../support/parameters");
|
|
const formVariantData = require("../support/variant-data");
|
|
const regulateGlyphs = require("../support/regulate-glyph");
|
|
const toml = require("toml");
|
|
|
|
function objHashNonEmpty(obj) {
|
|
if (!obj) return false;
|
|
for (let k in obj) if (obj[k]) return true;
|
|
return false;
|
|
}
|
|
|
|
const PARAMETERS_TOML = path.resolve(__dirname, "../parameters.toml");
|
|
const PRIVATE_TOML = path.resolve(__dirname, "../private.toml");
|
|
const VARIANTS_TOML = path.resolve(__dirname, "../variants.toml");
|
|
const EMPTY_FONT_TOML = path.resolve(__dirname, "../empty-font.toml");
|
|
|
|
function tryParseToml(str) {
|
|
try {
|
|
return toml.parse(fs.readFileSync(str, "utf-8"));
|
|
} catch (e) {
|
|
throw new Error(
|
|
`Failed to parse configuration file ${str}.\nPlease validate whether there's syntax error.\n${e}`
|
|
);
|
|
}
|
|
}
|
|
|
|
function getParameters(argv) {
|
|
const parametersData = Object.assign(
|
|
{},
|
|
tryParseToml(PARAMETERS_TOML),
|
|
fs.existsSync(PRIVATE_TOML) ? tryParseToml(PRIVATE_TOML) : []
|
|
);
|
|
const variantData = tryParseToml(VARIANTS_TOML);
|
|
|
|
const para = parameters.build(parametersData, argv._, { "shape-weight": argv["shape-weight"] });
|
|
const variantsData = formVariantData(variantData, para);
|
|
para.variants = variantsData;
|
|
para.variantSelector = parameters.build(variantsData, ["default", ...argv._]);
|
|
para.defaultVariant = variantsData.default;
|
|
|
|
para.naming = {
|
|
family: argv.family,
|
|
version: argv.ver,
|
|
weight: argv["menu-weight"] - 0,
|
|
width: argv["menu-width"] - 0,
|
|
slant: argv["menu-slant"]
|
|
};
|
|
|
|
return para;
|
|
}
|
|
|
|
// Font building
|
|
const font = (function() {
|
|
const emptyFont = tryParseToml(EMPTY_FONT_TOML);
|
|
const para = getParameters(argv);
|
|
const font = buildGlyphs.build.call(emptyFont, para);
|
|
font.parameters = para;
|
|
return font;
|
|
})();
|
|
|
|
if (argv.charmap) {
|
|
const charmap = font.glyf.map(function(glyph) {
|
|
const isSpace = glyph.contours && glyph.contours.length ? 2 : 0;
|
|
return [
|
|
glyph.name,
|
|
glyph.unicode,
|
|
glyph.advanceWidth === 0 ? (objHashNonEmpty(glyph.anchors) ? 1 : isSpace ? 2 : 0) : 0
|
|
];
|
|
});
|
|
fs.writeFileSync(argv.charmap, JSON.stringify(charmap), "utf8");
|
|
}
|
|
|
|
if (argv.o) {
|
|
const skew = Math.tan(((font.post.italicAngle || 0) / 180) * Math.PI);
|
|
|
|
regulateGlyphs(font, skew);
|
|
|
|
// finalize
|
|
const excludedCodePoints = new Set();
|
|
if (font.parameters.excludedCodePointRanges) {
|
|
for (const [start, end] of font.parameters.excludedCodePointRanges) {
|
|
for (let p = start; p <= end; p++) excludedCodePoints.add(p);
|
|
}
|
|
}
|
|
|
|
const o_glyf = {};
|
|
const o_cmap = {};
|
|
for (let g of font.glyf) {
|
|
o_glyf[g.name] = g;
|
|
|
|
if (!g.unicode) continue;
|
|
for (let u of g.unicode) {
|
|
if (!excludedCodePoints.has(u - 0)) o_cmap[u] = g.name;
|
|
}
|
|
}
|
|
|
|
// Prepare OTD
|
|
const otd = Object.assign({}, font);
|
|
otd.glyf = o_glyf;
|
|
otd.cmap = o_cmap;
|
|
otd.glyfMap = null;
|
|
if (argv.o === "|") {
|
|
process.stdout.write(JSON.stringify(otd));
|
|
} else {
|
|
fs.writeFileSync(argv.o, JSON.stringify(otd, null, " "));
|
|
}
|
|
}
|