Caching improvement: now caching works across families
This commit is contained in:
parent
de458c9fce
commit
04a6a29238
7 changed files with 122 additions and 34 deletions
|
@ -27,10 +27,13 @@ exports.buildFont = async function buildFont(argv, para) {
|
|||
}
|
||||
}
|
||||
|
||||
const cache = await Caching.load(argv);
|
||||
// Finalize (like geometry conversion)
|
||||
const cache = await Caching.load(argv.iCache, argv.menu.version, argv.cacheFreshAgeKey);
|
||||
const finalGs = finalizeFont(cache, para, gs.glyphStore, excludeChars, otl);
|
||||
await Caching.save(argv, cache);
|
||||
if (cache.isUpdated()) {
|
||||
await Caching.save(argv.oCache, argv.menu.version, cache, true);
|
||||
}
|
||||
|
||||
const font = convertOtd(baseFont, otl, finalGs);
|
||||
return { font, glyphStore: finalGs };
|
||||
return { font, glyphStore: finalGs, cacheUpdated: cache.isUpdated() };
|
||||
};
|
||||
|
|
|
@ -4,8 +4,8 @@ const fs = require("fs-extra");
|
|||
const zlib = require("zlib");
|
||||
const { encode, decode } = require("@msgpack/msgpack");
|
||||
|
||||
const Edition = 14;
|
||||
const MAX_AGE = 5;
|
||||
const Edition = 20;
|
||||
const MAX_AGE = 16;
|
||||
|
||||
class GfEntry {
|
||||
constructor(age, value) {
|
||||
|
@ -15,21 +15,44 @@ class GfEntry {
|
|||
}
|
||||
|
||||
class Cache {
|
||||
constructor() {
|
||||
constructor(freshAgeKey) {
|
||||
this.freshAgeKey = freshAgeKey;
|
||||
this.historyAgeKeys = [];
|
||||
this.gf = new Map();
|
||||
this.diff = new Set();
|
||||
}
|
||||
loadRep(version, rep) {
|
||||
if (!rep || rep.version !== version + "@" + Edition) return;
|
||||
this.historyAgeKeys = rep.ageKeys.slice(0, MAX_AGE);
|
||||
const ageKeySet = new Set(this.historyAgeKeys);
|
||||
for (const [k, e] of Object.entries(rep.gf)) {
|
||||
this.gf.set(k, new GfEntry((e.age || 0) + 1, e.value));
|
||||
if (ageKeySet.has(e.age)) this.gf.set(k, new GfEntry(e.age, e.value));
|
||||
}
|
||||
}
|
||||
toRep(version) {
|
||||
toRep(version, diffOnly) {
|
||||
let gfRep = {};
|
||||
for (const [k, e] of this.gf) {
|
||||
if (e.age < MAX_AGE) gfRep[k] = { age: e.age, value: e.value };
|
||||
if (!diffOnly || this.diff.has(k)) {
|
||||
gfRep[k] = { age: e.age, value: e.value };
|
||||
}
|
||||
return { version: version + "@" + Edition, gf: gfRep };
|
||||
}
|
||||
const mergedAgeKeys =
|
||||
this.historyAgeKeys[0] === this.freshAgeKey
|
||||
? this.historyAgeKeys
|
||||
: [this.freshAgeKey, ...this.historyAgeKeys];
|
||||
|
||||
return {
|
||||
version: version + "@" + Edition,
|
||||
ageKeys: mergedAgeKeys,
|
||||
gf: gfRep
|
||||
};
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return this.gf.size == 0;
|
||||
}
|
||||
isUpdated() {
|
||||
return this.diff.size != 0;
|
||||
}
|
||||
|
||||
// Geometry flattening conversion cache
|
||||
|
@ -41,26 +64,45 @@ class Cache {
|
|||
refreshGF(k) {
|
||||
const entry = this.gf.get(k);
|
||||
if (!entry) return;
|
||||
entry.age = 0;
|
||||
if (entry.age != this.freshAgeKey) {
|
||||
this.diff.add(k);
|
||||
entry.age = this.freshAgeKey;
|
||||
}
|
||||
}
|
||||
saveGF(k, v) {
|
||||
this.gf.set(k, new GfEntry(0, v));
|
||||
this.gf.set(k, new GfEntry(this.freshAgeKey, v));
|
||||
this.diff.add(k);
|
||||
}
|
||||
merge(other) {
|
||||
for (const [k, e] of other.gf) {
|
||||
this.gf.set(k, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.load = async function (argv) {
|
||||
let cache = new Cache();
|
||||
if (argv.oCache && fs.existsSync(argv.oCache)) {
|
||||
const buf = zlib.gunzipSync(await fs.readFile(argv.oCache));
|
||||
cache.loadRep(argv.menu.version, decode(buf));
|
||||
exports.load = async function (path, version, freshAgeKey) {
|
||||
let cache = new Cache(freshAgeKey);
|
||||
if (path && fs.existsSync(path)) {
|
||||
const buf = zlib.gunzipSync(await fs.readFile(path));
|
||||
cache.loadRep(version, decode(buf));
|
||||
}
|
||||
return cache;
|
||||
};
|
||||
|
||||
exports.save = async function savePTCache(argv, cache) {
|
||||
if (argv.oCache) {
|
||||
const buf = encode(cache.toRep(argv.menu.version));
|
||||
exports.save = async function savePTCache(path, version, cache, diffOnly) {
|
||||
if (path) {
|
||||
const buf = encode(cache.toRep(version, diffOnly));
|
||||
const bufZip = zlib.gzipSync(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength));
|
||||
await fs.writeFile(argv.oCache, bufZip);
|
||||
await fs.writeFile(path, bufZip);
|
||||
}
|
||||
};
|
||||
|
||||
exports.merge = async function (base, diff, version, freshAgeKey) {
|
||||
const cacheDiff = await exports.load(diff, version, freshAgeKey);
|
||||
if (!cacheDiff.isEmpty()) {
|
||||
const cacheBase = await exports.load(base, version, freshAgeKey);
|
||||
cacheBase.merge(cacheDiff);
|
||||
await exports.save(base, version, cacheBase, false);
|
||||
}
|
||||
if (fs.existsSync(diff)) await fs.rm(diff);
|
||||
};
|
||||
|
|
|
@ -17,9 +17,10 @@ const { createGrDisplaySheet } = require("./support/gr");
|
|||
|
||||
module.exports = async function main(argv) {
|
||||
const paraT = await getParameters();
|
||||
const { font, glyphStore } = await buildFont(argv, paraT(argv));
|
||||
const { font, glyphStore, cacheUpdated } = await buildFont(argv, paraT(argv));
|
||||
if (argv.oCharMap) await saveCharMap(argv, glyphStore);
|
||||
if (argv.o) await saveTTF(argv, font);
|
||||
return { cacheUpdated };
|
||||
};
|
||||
|
||||
// Parameter preparation
|
||||
|
|
7
font-src/merge-cache.js
Normal file
7
font-src/merge-cache.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
const Caching = require("./gen/caching/index");
|
||||
|
||||
module.exports = async function main(argv) {
|
||||
await Caching.merge(argv.base, argv.diff, argv.version, argv.freshAgeKey);
|
||||
};
|
28
package-lock.json
generated
28
package-lock.json
generated
|
@ -20,7 +20,8 @@
|
|||
"spiro": "^3.0.0",
|
||||
"toposort": "^2.0.2",
|
||||
"typo-geom": "^0.12.1",
|
||||
"verda": "^1.5.0",
|
||||
"uuid": "^8.3.2",
|
||||
"verda": "^1.6.0",
|
||||
"wawoff2": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -2258,6 +2259,14 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/v8-compile-cache": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
|
||||
|
@ -2265,9 +2274,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/verda": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/verda/-/verda-1.5.0.tgz",
|
||||
"integrity": "sha512-TjZ0q140lfBcKp4QzODbOeZS2rJVRhKl+5AxMEuJ//4uMXQzoLQbZic4fkR011d3GWfKk+m7/3IsviWg2vn9sQ==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/verda/-/verda-1.6.0.tgz",
|
||||
"integrity": "sha512-r7YP2FG7AbV/BjnvIqpHZRokkZlWzP6SCJNh0Oq9LsMzEBM9Vx3HqUz2gTV49LKY6/e7yCWAA/aDgWgFkKXdbA==",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"cli-cursor": "^3.1.0",
|
||||
|
@ -4225,6 +4234,11 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
},
|
||||
"v8-compile-cache": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
|
||||
|
@ -4232,9 +4246,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"verda": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/verda/-/verda-1.5.0.tgz",
|
||||
"integrity": "sha512-TjZ0q140lfBcKp4QzODbOeZS2rJVRhKl+5AxMEuJ//4uMXQzoLQbZic4fkR011d3GWfKk+m7/3IsviWg2vn9sQ==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/verda/-/verda-1.6.0.tgz",
|
||||
"integrity": "sha512-r7YP2FG7AbV/BjnvIqpHZRokkZlWzP6SCJNh0Oq9LsMzEBM9Vx3HqUz2gTV49LKY6/e7yCWAA/aDgWgFkKXdbA==",
|
||||
"requires": {
|
||||
"chalk": "^4.1.2",
|
||||
"cli-cursor": "^3.1.0",
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
"spiro": "^3.0.0",
|
||||
"toposort": "^2.0.2",
|
||||
"typo-geom": "^0.12.1",
|
||||
"verda": "^1.5.0",
|
||||
"uuid": "^8.3.2",
|
||||
"verda": "^1.6.0",
|
||||
"wawoff2": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
28
verdafile.js
28
verdafile.js
|
@ -6,6 +6,7 @@ const which = require("which");
|
|||
const Path = require("path");
|
||||
const toml = require("@iarna/toml");
|
||||
const semver = require("semver");
|
||||
const uuid = require("uuid");
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -312,24 +313,43 @@ function whyBuildPlanIsnNotThere(gid) {
|
|||
////// Font Building //////
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
const ageKey = uuid.v4();
|
||||
const DistUnhintedTTF = file.make(
|
||||
(gr, fn) => `${DIST}/${gr}/ttf-unhinted/${fn}.ttf`,
|
||||
async (target, out, gr, fn) => {
|
||||
await target.need(Scripts, Parameters, Dependencies);
|
||||
await target.need(Scripts, Parameters, Dependencies, de(`${BUILD}/caches`));
|
||||
const [compositesFromBuildPlan] = await target.need(CompositesFromBuildPlan);
|
||||
const charMapDir = `${BUILD}/ttf/${gr}`;
|
||||
const charMapPath = `${charMapDir}/${fn}.charmap.mpz`;
|
||||
const cachePath = `${charMapDir}/${fn}.cache.mpz`;
|
||||
|
||||
const [fi] = await target.need(FontInfoOf(fn), de(out.dir), de(charMapDir));
|
||||
const cacheFileName =
|
||||
`${Math.round(1000 * fi.shape.weight)}-${Math.round(1000 * fi.shape.width)}-` +
|
||||
`${Math.round(3600 * fi.shape.slopeAngle)}-${fi.shape.slope}`;
|
||||
const cachePath = `${BUILD}/caches/${cacheFileName}.mpz`;
|
||||
const cacheDiffPath = `${charMapDir}/${fn}.cache.mpz`;
|
||||
|
||||
echo.action(echo.hl.command(`Create TTF`), fn, echo.hl.operator("->"), out.full);
|
||||
await silently.node("font-src/index", {
|
||||
const { cacheUpdated } = await silently.node("font-src/index", {
|
||||
o: out.full,
|
||||
oCharMap: charMapPath,
|
||||
oCache: cachePath,
|
||||
cacheFreshAgeKey: ageKey,
|
||||
iCache: cachePath,
|
||||
oCache: cacheDiffPath,
|
||||
compositesFromBuildPlan,
|
||||
...fi
|
||||
});
|
||||
if (cacheUpdated) {
|
||||
const lock = build.locks.alloc(cacheFileName);
|
||||
await lock.acquire();
|
||||
await silently.node(`font-src/merge-cache`, {
|
||||
base: cachePath,
|
||||
diff: cacheDiffPath,
|
||||
version: fi.menu.version,
|
||||
freshAgeKey: ageKey
|
||||
});
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue