137 lines
4 KiB
JavaScript
137 lines
4 KiB
JavaScript
"use strict";
|
|
|
|
const monotonicInterpolate = require("./monotonic-interpolate");
|
|
|
|
exports.init = initPara;
|
|
function initPara(data, argv) {
|
|
let para = {};
|
|
apply(para, data, ["iosevka"]);
|
|
if (argv.shape.serifs) apply(para, data, ["serifs-" + argv.shape.serifs]);
|
|
if (argv.shape.spacing) apply(para, data, ["spacing-" + argv.shape.spacing]);
|
|
apply(para, data, ["shapeWeight"], { shapeWeight: argv.shape.weight });
|
|
apply(para, data, ["shapeWidth"], { shapeWidth: argv.shape.width });
|
|
apply(para, data, [`s-${argv.shape.slope}`]);
|
|
apply(para, data, [`diversity-${argv.shape.quasiProportionalDiversity}`]);
|
|
para.quasiProportionalDiversity = argv.shape.quasiProportionalDiversity || 0;
|
|
if (argv.featureControl.noCvSs) para.enableCvSs = false;
|
|
if (argv.featureControl.noLigation) para.enableLigation = false;
|
|
return para;
|
|
}
|
|
|
|
exports.apply = apply;
|
|
function apply(sink, parametersData, styles, blendArgs) {
|
|
if (!styles) return;
|
|
for (const item of styles) intro(parametersData, item, blendArgs, sink);
|
|
}
|
|
|
|
// eslint-disable-next-line complexity
|
|
function intro(source, style, blendArgs, sink) {
|
|
let hive = source[style];
|
|
if (!hive) return;
|
|
hive = { ...hive };
|
|
|
|
if (hive.inherits) {
|
|
for (const hn of hive.inherits) intro(source, hn, blendArgs, sink);
|
|
delete hive.inherits;
|
|
}
|
|
if (hive.multiplies) {
|
|
const mu = hiveBlend(hive.multiplies, getBlendArg(blendArgs, style), sink);
|
|
for (const k in mu) sink[k] = (sink[k] || 0) * mu[k];
|
|
delete hive.multiplies;
|
|
}
|
|
if (hive.adds) {
|
|
const mu = hiveBlend(hive.adds, getBlendArg(blendArgs, style), sink);
|
|
for (const k in mu) sink[k] = (sink[k] || 0) + mu[k];
|
|
delete hive.adds;
|
|
}
|
|
if (hive.appends) {
|
|
const mu = hive.appends;
|
|
for (const k in mu) sink[k] = [...(sink[k] || []), ...mu[k]];
|
|
delete hive.appends;
|
|
}
|
|
if (hive.removes) {
|
|
const mu = hive.removes;
|
|
for (const k in mu) {
|
|
const s = new Set(mu[k]);
|
|
sink[k] = [...(sink[k] || [])].filter(x => !s.has(x));
|
|
}
|
|
delete hive.removes;
|
|
}
|
|
|
|
hive = hiveBlend(hive, getBlendArg(blendArgs, style));
|
|
for (const k in hive) sink[k] = hive[k];
|
|
}
|
|
|
|
function getBlendArg(blendArgs, style) {
|
|
if (!blendArgs) return undefined;
|
|
return blendArgs[style];
|
|
}
|
|
|
|
function hiveBlend(hive, value) {
|
|
if (!hive || !hive.blend || value == null) return hive;
|
|
|
|
const generatedHive = {};
|
|
const block = hive.blend;
|
|
let keys = new Set();
|
|
for (const grade in block) {
|
|
if (!isFinite(parseFloat(grade))) continue;
|
|
for (const key in block[grade]) {
|
|
if (block[grade][key] == null) continue;
|
|
keys.add(key);
|
|
}
|
|
}
|
|
|
|
for (const key of keys) {
|
|
let xs = [],
|
|
ys = [];
|
|
for (const grade in block) {
|
|
if (!isFinite(parseFloat(grade))) continue;
|
|
if (block[grade][key] == null) continue;
|
|
xs.push(grade);
|
|
ys.push(block[grade][key]);
|
|
}
|
|
generatedHive[key] = monotonicInterpolate(xs, ys)(value);
|
|
}
|
|
return generatedHive;
|
|
}
|
|
|
|
exports.applyMetricOverride = applyMetricOverride;
|
|
function applyMetricOverride(para, mo) {
|
|
const overrideObj = { metricOverride: {} };
|
|
createMetricDataSet(overrideObj.metricOverride, mo);
|
|
apply(para, overrideObj, ["metricOverride"]);
|
|
}
|
|
|
|
function createMetricDataSet(sink, mo) {
|
|
for (const key in mo) {
|
|
if (metricOverrideHandlers[key]) {
|
|
metricOverrideHandlers[key](sink, key, mo[key]);
|
|
} else {
|
|
console.error(`Metric override key ${key} is not supported. Skipping it.`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function numericFieldHandler(sink, key, x) {
|
|
if (x != null && isFinite(x)) sink[key] = x;
|
|
}
|
|
function subObjectHandler(sink, key, obj) {
|
|
sink[key] = {};
|
|
createMetricDataSet(sink[key], obj);
|
|
}
|
|
const metricOverrideHandlers = {
|
|
cap: numericFieldHandler,
|
|
xheight: numericFieldHandler,
|
|
sb: numericFieldHandler,
|
|
leading: numericFieldHandler,
|
|
winMetricAscenderPad: numericFieldHandler,
|
|
winMetricDescenderPad: numericFieldHandler,
|
|
symbolMid: numericFieldHandler,
|
|
parenSize: numericFieldHandler,
|
|
powerlineScaleY: numericFieldHandler,
|
|
powerlineScaleX: numericFieldHandler,
|
|
powerlineShiftY: numericFieldHandler,
|
|
powerlineShiftX: numericFieldHandler,
|
|
multiplies: subObjectHandler,
|
|
adds: subObjectHandler
|
|
};
|