diff --git a/font-src/derive-spacing.mjs b/font-src/derive-spacing.mjs index 770f4c003..b8be486d0 100644 --- a/font-src/derive-spacing.mjs +++ b/font-src/derive-spacing.mjs @@ -3,15 +3,16 @@ import path from "path"; import url from "url"; import * as Toml from "@iarna/toml"; -import { FontIo, Ot, CliProc } from "ot-builder"; +import { CliProc, Ot } from "ot-builder"; import { assignFontNames, createNamingDictFromArgv } from "./gen/meta/naming.mjs"; +import { readTTF, saveTTF } from "./support/font-io/font-io.mjs"; const __dirname = url.fileURLToPath(new URL(".", import.meta.url)); export default main; async function main(argv) { - const font = await readTTF(argv); + const font = await readTTF(argv.i); const naming = createNamingDictFromArgv(argv); assignFontNames(font, naming, false); @@ -24,17 +25,26 @@ async function main(argv) { await deriveTerm(font); await deriveFixed_DropWideChars(font); await deriveFixed_DropFeatures(font, false); - CliProc.gcFont(font, Ot.ListGlyphStoreFactory); break; case "fixed": await deriveTerm(font); await deriveFixed_DropWideChars(font); await deriveFixed_DropFeatures(font, true); - CliProc.gcFont(font, Ot.ListGlyphStoreFactory); break; } - await saveTTF(argv, font); + await saveTTF(argv.oNoGc, font); + + switch (argv.shape.spacing) { + case "fontconfig-mono": + case "fixed": + CliProc.gcFont(font, Ot.ListGlyphStoreFactory); + await saveTTF(argv.o, font); + break; + default: + await fs.promises.copyFile(argv.oNoGc, argv.o); + break; + } } // To derive -Term variants, simply apply NWID @@ -98,18 +108,3 @@ async function deriveFixed_DropFeatures(font, fFixed) { } } } - -async function readTTF(argv) { - const buf = await fs.promises.readFile(argv.i); - const sfnt = FontIo.readSfntOtf(buf); - const font = FontIo.readFont(sfnt, Ot.ListGlyphStoreFactory); - return font; -} -async function saveTTF(argv, font) { - const sfnt = FontIo.writeFont(font, { - glyphStore: { statOs2XAvgCharWidth: false }, - generateDummyDigitalSignature: true - }); - const buf = FontIo.writeSfntOtf(sfnt); - await fs.promises.writeFile(argv.o, buf); -} diff --git a/font-src/index.mjs b/font-src/index.mjs index c2e204e53..661ad6ec2 100644 --- a/font-src/index.mjs +++ b/font-src/index.mjs @@ -5,10 +5,10 @@ import zlib from "zlib"; import * as Toml from "@iarna/toml"; import { encode } from "@msgpack/msgpack"; -import { FontIo } from "ot-builder"; import { buildFont } from "./gen/build-font.mjs"; import { createNamingDictFromArgv } from "./gen/meta/naming.mjs"; +import { saveTTF } from "./support/font-io/font-io.mjs"; import { createGrDisplaySheet } from "./support/gr.mjs"; import { applyLigationData } from "./support/ligation-data.mjs"; import { applyMetricOverride } from "./support/metric-override.mjs"; @@ -17,6 +17,17 @@ import * as VariantData from "./support/variant-data.mjs"; const __dirname = url.fileURLToPath(new URL(".", import.meta.url)); +export default main; +async function main(argv) { + const paraT = await getParameters(); + const { font, glyphStore, cacheUpdated } = await buildFont(argv, paraT(argv)); + if (argv.oCharMap) await saveCharMap(argv, glyphStore); + if (argv.o) await saveTTF(argv.o, font); + return { cacheUpdated }; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + // Parameter preparation async function getParameters() { const PARAMETERS_TOML = path.resolve(__dirname, "../params/parameters.toml"); @@ -72,15 +83,7 @@ async function tryParseToml(str) { function deepClone(pod) { return JSON.parse(JSON.stringify(pod)); } -// Save TTF -async function saveTTF(argv, font) { - const sfnt = FontIo.writeFont(font, { - glyphStore: { statOs2XAvgCharWidth: false }, - generateDummyDigitalSignature: true - }); - const buf = FontIo.writeSfntOtf(sfnt); - await fs.promises.writeFile(argv.o, buf); -} + // Save character map file async function saveCharMap(argv, glyphStore) { let charMap = []; @@ -93,10 +96,3 @@ async function saveCharMap(argv, glyphStore) { } await fs.promises.writeFile(argv.oCharMap, zlib.gzipSync(encode(charMap))); } -export default (async function main(argv) { - const paraT = await getParameters(); - 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 }; -}); diff --git a/font-src/support/font-io/font-io.mjs b/font-src/support/font-io/font-io.mjs new file mode 100644 index 000000000..2d867325b --- /dev/null +++ b/font-src/support/font-io/font-io.mjs @@ -0,0 +1,19 @@ +import fs from "fs"; + +import { FontIo, Ot } from "ot-builder"; + +export async function readTTF(input) { + const buf = await fs.promises.readFile(input); + const sfnt = FontIo.readSfntOtf(buf); + const font = FontIo.readFont(sfnt, Ot.ListGlyphStoreFactory); + return font; +} + +export async function saveTTF(output, font) { + const sfnt = FontIo.writeFont(font, { + glyphStore: { statOs2XAvgCharWidth: false }, + generateDummyDigitalSignature: true + }); + const buf = FontIo.writeSfntOtf(sfnt); + await fs.promises.writeFile(output, buf); +} diff --git a/verdafile.mjs b/verdafile.mjs index 977f443aa..b3f0be380 100644 --- a/verdafile.mjs +++ b/verdafile.mjs @@ -373,23 +373,28 @@ const DistUnhintedTTF = file.make( await target.need(Scripts, Parameters, Dependencies, de(out.dir)); const [fi] = await target.need(FontInfoOf(fn)); + const charMapDir = `${BUILD}/ttf/${gr}`; + const charMapPath = `${charMapDir}/${fn}.charmap.mpz`; + const noGcTtfPath = `${charMapDir}/${fn}.no-gc.ttf`; + if (fi.spacingDerive) { // The font is a spacing variant, and is derivable form an existing // normally-spaced variant. const spD = fi.spacingDerive; - const [deriveFrom] = await target.need(DistUnhintedTTF(spD.prefix, spD.fileName)); + const [deriveFrom] = await target.need( + DistUnhintedTTF(spD.prefix, spD.fileName), + de(charMapDir) + ); echo.action(echo.hl.command(`Create TTF`), out.full); await silently.node(`font-src/derive-spacing.mjs`, { i: deriveFrom.full, + oNoGc: noGcTtfPath, o: out.full, ...fi }); } else { // Ab-initio build - const charMapDir = `${BUILD}/ttf/${gr}`; - const charMapPath = `${charMapDir}/${fn}.charmap.mpz`; - const cacheFileName = `${Math.round(1000 * fi.shape.weight)}-${Math.round(1000 * fi.shape.width)}-` + `${Math.round(3600 * fi.shape.slopeAngle)}-${fi.shape.slope}`; @@ -428,6 +433,27 @@ const DistUnhintedTTF = file.make( } ); +const BuildNoGcTtfImpl = file.make( + (gr, f) => `${BUILD}/ttf/${gr}/${f}.no-gc.ttf`, + async (target, output, gr, f) => { + await target.need(DistUnhintedTTF(gr, f)); + } +); + +const BuildNoGcTtf = task.make( + (gr, fn) => `BuildNoGcTtf::${gr}/${fn}`, + async (target, gr, fn) => { + const [fi] = await target.need(FontInfoOf(fn)); + if (fi.spacingDerive) { + const [noGc] = await target.need(BuildNoGcTtfImpl(gr, fn)); + return noGc; + } else { + const [distUnhinted] = await target.need(DistUnhintedTTF(gr, fn)); + return distUnhinted; + } + } +); + const BuildCM = file.make( (gr, f) => `${BUILD}/ttf/${gr}/${f}.charmap.mpz`, async (target, output, gr, f) => { @@ -678,9 +704,10 @@ async function buildCompositeTtc(out, inputs) { echo.action(echo.hl.command(`Create TTC`), out.full, echo.hl.operator("<-"), inputPaths); await absolutelySilently.run(TTCIZE, ["-o", out.full], inputPaths); } + async function buildGlyphSharingTtc(target, parts, out) { await target.need(de`${out.dir}`); - const [ttfInputs] = await target.need(parts.map(part => DistUnhintedTTF(part.dir, part.file))); + const [ttfInputs] = await target.need(parts.map(part => BuildNoGcTtf(part.dir, part.file))); const tmpTtc = `${out.dir}/${out.name}.unhinted.ttc`; const ttfInputPaths = ttfInputs.map(p => p.full); echo.action(echo.hl.command(`Create TTC`), out.full, echo.hl.operator("<-"), ttfInputPaths);