Implement caching when performing outline conversion
This commit is contained in:
parent
b16dfb91db
commit
e28ce0fd68
6 changed files with 82 additions and 14 deletions
|
@ -9,7 +9,7 @@ const { buildOtl } = require("../otl/index");
|
||||||
const { assignFontNames } = require("../meta/naming");
|
const { assignFontNames } = require("../meta/naming");
|
||||||
const { copyFontMetrics } = require("../meta/aesthetics");
|
const { copyFontMetrics } = require("../meta/aesthetics");
|
||||||
|
|
||||||
module.exports = function (para) {
|
module.exports = async function (argv, para, ptCache) {
|
||||||
const otd = EmptyFont();
|
const otd = EmptyFont();
|
||||||
const gs = buildGlyphs(para);
|
const gs = buildGlyphs(para);
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ module.exports = function (para) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalGs = finalizeFont(para, gs.glyphStore, excludeChars, otd);
|
const finalGs = finalizeFont(para, gs.glyphStore, excludeChars, otd, ptCache);
|
||||||
const font = convertOtd(otd, finalGs);
|
const font = convertOtd(otd, finalGs);
|
||||||
return { font, glyphStore: finalGs };
|
return { font, glyphStore: finalGs };
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,15 +6,15 @@ const CurveUtil = require("../../support/curve-util");
|
||||||
const util = require("util");
|
const util = require("util");
|
||||||
|
|
||||||
module.exports = finalizeGlyphs;
|
module.exports = finalizeGlyphs;
|
||||||
function finalizeGlyphs(para, glyphStore) {
|
function finalizeGlyphs(para, glyphStore, ptCache) {
|
||||||
const skew = Math.tan(((para.slopeAngle || 0) / 180) * Math.PI);
|
const skew = Math.tan(((para.slopeAngle || 0) / 180) * Math.PI);
|
||||||
regulateGlyphStore(skew, glyphStore);
|
regulateGlyphStore(skew, glyphStore, ptCache);
|
||||||
return glyphStore;
|
return glyphStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function regulateGlyphStore(skew, glyphStore) {
|
function regulateGlyphStore(skew, glyphStore, ptCache) {
|
||||||
for (const g of glyphStore.glyphs()) {
|
for (const g of glyphStore.glyphs()) {
|
||||||
if (g.geometry.isEmpty()) continue;
|
if (g.geometry.isEmpty()) continue;
|
||||||
if (!regulateCompositeGlyph(glyphStore, g)) {
|
if (!regulateCompositeGlyph(glyphStore, g)) {
|
||||||
|
@ -24,7 +24,7 @@ function regulateGlyphStore(skew, glyphStore) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const g of glyphStore.glyphs()) {
|
for (const g of glyphStore.glyphs()) {
|
||||||
if (!g.geometry.asReferences()) regulateSimpleGlyph(g, skew);
|
if (!g.geometry.asReferences()) regulateSimpleGlyph(g, skew, ptCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,10 +40,10 @@ function regulateCompositeGlyph(glyphStore, g) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function regulateSimpleGlyph(g, skew) {
|
function regulateSimpleGlyph(g, skew, ptCache) {
|
||||||
let cs = g.geometry.asContours();
|
let cs = g.geometry.asContours();
|
||||||
for (const contour of cs) for (const z of contour) z.x -= z.y * skew;
|
for (const contour of cs) for (const z of contour) z.x -= z.y * skew;
|
||||||
cs = simplifyContours(cs);
|
cs = simplifyContours(cs, ptCache);
|
||||||
for (const contour of cs) for (const z of contour) z.x += z.y * skew;
|
for (const contour of cs) for (const z of contour) z.x += z.y * skew;
|
||||||
|
|
||||||
g.clearGeometry();
|
g.clearGeometry();
|
||||||
|
@ -52,7 +52,13 @@ function regulateSimpleGlyph(g, skew) {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function simplifyContours(source) {
|
function simplifyContours(source, ptCache) {
|
||||||
|
const ck = CurveUtil.hashShape(source);
|
||||||
|
if (ptCache.source[ck]) {
|
||||||
|
ptCache.sink[ck] = ptCache.source[ck];
|
||||||
|
return CurveUtil.repToShape(ptCache.source[ck]);
|
||||||
|
}
|
||||||
|
|
||||||
const sink = new FairizedShapeSink();
|
const sink = new FairizedShapeSink();
|
||||||
TypoGeom.ShapeConv.transferGenericShape(
|
TypoGeom.ShapeConv.transferGenericShape(
|
||||||
TypoGeom.Fairize.fairizeBezierShape(
|
TypoGeom.Fairize.fairizeBezierShape(
|
||||||
|
@ -66,6 +72,7 @@ function simplifyContours(source) {
|
||||||
CurveUtil.GEOMETRY_PRECISION
|
CurveUtil.GEOMETRY_PRECISION
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ptCache.sink[ck] = CurveUtil.shapeToRep(sink.contours);
|
||||||
return sink.contours;
|
return sink.contours;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
const finalizeGlyphs = require("./glyphs");
|
const finalizeGlyphs = require("./glyphs");
|
||||||
const gcFont = require("./gc");
|
const gcFont = require("./gc");
|
||||||
|
|
||||||
module.exports = function finalizeFont(para, glyphStore, excludedCodePoints, restFont) {
|
module.exports = function finalizeFont(para, glyphStore, excludedCodePoints, restFont, ptCache) {
|
||||||
glyphStore = gcFont(glyphStore, excludedCodePoints, restFont, {});
|
glyphStore = gcFont(glyphStore, excludedCodePoints, restFont, {});
|
||||||
glyphStore = finalizeGlyphs(para, glyphStore);
|
glyphStore = finalizeGlyphs(para, glyphStore, ptCache);
|
||||||
validateMonospace(para, glyphStore);
|
validateMonospace(para, glyphStore);
|
||||||
return glyphStore;
|
return glyphStore;
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,11 +15,27 @@ const { createGrDisplaySheet } = require("./support/gr");
|
||||||
|
|
||||||
module.exports = async function main(argv) {
|
module.exports = async function main(argv) {
|
||||||
const paraT = await getParameters();
|
const paraT = await getParameters();
|
||||||
const { font, glyphStore } = BuildFont(paraT(argv));
|
|
||||||
|
const ptCache = await loadPTCache(argv);
|
||||||
|
|
||||||
|
const { font, glyphStore } = await BuildFont(argv, paraT(argv), ptCache);
|
||||||
if (argv.oCharMap) await saveCharMap(argv, glyphStore);
|
if (argv.oCharMap) await saveCharMap(argv, glyphStore);
|
||||||
if (argv.o) await saveTTF(argv, font);
|
if (argv.o) await saveTTF(argv, font);
|
||||||
|
|
||||||
|
await savePTCache(argv, ptCache);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function loadPTCache(argv) {
|
||||||
|
let ptCache = { source: {}, sink: {} };
|
||||||
|
if (argv.ptCache && fs.existsSync(argv.ptCache)) {
|
||||||
|
ptCache.source = unzip(await fs.readFile(argv.ptCache));
|
||||||
|
}
|
||||||
|
return ptCache;
|
||||||
|
}
|
||||||
|
async function savePTCache(argv, ptCache) {
|
||||||
|
if (argv.ptCache) await fs.writeFile(argv.ptCache, zip(ptCache.sink));
|
||||||
|
}
|
||||||
|
|
||||||
// Parameter preparation
|
// Parameter preparation
|
||||||
async function getParameters() {
|
async function getParameters() {
|
||||||
const PARAMETERS_TOML = path.resolve(__dirname, "../params/parameters.toml");
|
const PARAMETERS_TOML = path.resolve(__dirname, "../params/parameters.toml");
|
||||||
|
@ -97,5 +113,12 @@ async function saveCharMap(argv, glyphStore) {
|
||||||
...createGrDisplaySheet(glyphStore, gn)
|
...createGrDisplaySheet(glyphStore, gn)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
await fs.writeFile(argv.oCharMap, zlib.gzipSync(Buffer.from(JSON.stringify(charMap), "utf-8")));
|
await fs.writeFile(argv.oCharMap, zip(charMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
function unzip(buf) {
|
||||||
|
return JSON.parse(zlib.gunzipSync(buf));
|
||||||
|
}
|
||||||
|
function zip(obj) {
|
||||||
|
return zlib.gzipSync(Buffer.from(JSON.stringify(obj), "utf-8"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const crypto = require("crypto");
|
||||||
|
|
||||||
const TypoGeom = require("typo-geom");
|
const TypoGeom = require("typo-geom");
|
||||||
const Point = require("./point");
|
const Point = require("./point");
|
||||||
const Transform = require("./transform");
|
const Transform = require("./transform");
|
||||||
|
@ -51,6 +53,36 @@ exports.convertShapeToArcs = function convertShapeToArcs(shape) {
|
||||||
return shape.map(convertContourToArcs);
|
return shape.map(convertContourToArcs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.hashShape = function (shape) {
|
||||||
|
let s = "";
|
||||||
|
for (const c of shape) {
|
||||||
|
s += "[";
|
||||||
|
for (const z of c) {
|
||||||
|
s += `[${z.type};${Math.round(z.x * 0x10000)};${Math.round(z.y * 0x10000)}]`;
|
||||||
|
}
|
||||||
|
s += "]";
|
||||||
|
}
|
||||||
|
return crypto.createHash("sha256").update(s).digest();
|
||||||
|
};
|
||||||
|
|
||||||
|
function contourToRep(contour) {
|
||||||
|
let c = [];
|
||||||
|
for (const z of contour) c.push({ type: z.type, x: z.x, y: z.y });
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
exports.shapeToRep = function (shape) {
|
||||||
|
return shape.map(contourToRep);
|
||||||
|
};
|
||||||
|
|
||||||
|
function repToContour(contourRep) {
|
||||||
|
let c = [];
|
||||||
|
for (const z of contourRep) c.push(Point.fromXY(z.type, z.x, z.y));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
exports.repToShape = function (shapeRep) {
|
||||||
|
return shapeRep.map(repToContour);
|
||||||
|
};
|
||||||
|
|
||||||
function convertContourToArcs(contour) {
|
function convertContourToArcs(contour) {
|
||||||
if (!contour || !contour.length) return [];
|
if (!contour || !contour.length) return [];
|
||||||
|
|
||||||
|
|
|
@ -277,9 +277,15 @@ const DistUnhintedTTF = file.make(
|
||||||
await target.need(Scripts, Parameters, Dependencies);
|
await target.need(Scripts, Parameters, Dependencies);
|
||||||
const charMapDir = `${BUILD}/ttf/${gr}`;
|
const charMapDir = `${BUILD}/ttf/${gr}`;
|
||||||
const charMapPath = `${charMapDir}/${fn}.cm.gz`;
|
const charMapPath = `${charMapDir}/${fn}.cm.gz`;
|
||||||
|
const ptCachePath = `${charMapDir}/${fn}.ptCache.gz`;
|
||||||
const [fi] = await target.need(FontInfoOf(fn), de(out.dir), de(charMapDir));
|
const [fi] = await target.need(FontInfoOf(fn), de(out.dir), de(charMapDir));
|
||||||
echo.action(echo.hl.command(`Create TTF`), fn, echo.hl.operator("->"), out.full);
|
echo.action(echo.hl.command(`Create TTF`), fn, echo.hl.operator("->"), out.full);
|
||||||
await silently.node("font-src/index", { o: out.full, oCharMap: charMapPath, ...fi });
|
await silently.node("font-src/index", {
|
||||||
|
o: out.full,
|
||||||
|
oCharMap: charMapPath,
|
||||||
|
ptCache: ptCachePath,
|
||||||
|
...fi
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue