From 4b456ea906dcb9b1e725986ae52c6c2370be3cae Mon Sep 17 00:00:00 2001 From: be5invis Date: Fri, 1 Nov 2019 19:14:55 -0700 Subject: [PATCH 1/3] I did not realize that 0.10 is already released. Strange --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f51eb4a1..d9666c93f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sarasa-gothic", - "version": "0.9.2", + "version": "0.10.1", "main": "./run", "dependencies": { "@chlorophytum/cli": "^0.3.0", From 899a6a51ffde3d3bbdc7f8301d1d0b7b6ec17c1c Mon Sep 17 00:00:00 2001 From: be5invis Date: Fri, 1 Nov 2019 20:27:35 -0700 Subject: [PATCH 2/3] Implement continuous dash. Fixes #84. --- make/punct/as.js | 10 ++++- make/punct/common.js | 96 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- verdafile.js | 11 +++-- 4 files changed, 111 insertions(+), 8 deletions(-) diff --git a/make/punct/as.js b/make/punct/as.js index 4cc9317b6..ba9eb56d1 100644 --- a/make/punct/as.js +++ b/make/punct/as.js @@ -8,7 +8,13 @@ const { isKorean, filterUnicodeRange } = require("../common/unicode-kind"); -const { sanitizeSymbols, removeUnusedFeatures, toPWID } = require("./common"); +const { + sanitizeSymbols, + removeUnusedFeatures, + toPWID, + removeDashCcmp, + buildNexusDash +} = require("./common"); module.exports = async function makeFont(ctx, config, argv) { const a = await ctx.run(introduce, "a", { @@ -31,6 +37,8 @@ module.exports = async function makeFont(ctx, config, argv) { } if (argv.mono) { await ctx.run(manip.glyph, "a", sanitizeSymbols, argv.type); + removeDashCcmp(ctx.items.a, argv.mono); + await ctx.run(manip.glyph, "a", buildNexusDash); } removeUnusedFeatures(ctx.items.a, argv.mono); await ctx.run(gc, "a", { ignoreAltSub: true }); diff --git a/make/punct/common.js b/make/punct/common.js index 340857b4c..a7ff10299 100644 --- a/make/punct/common.js +++ b/make/punct/common.js @@ -98,6 +98,70 @@ exports.sanitizeSymbols = async function sanitizeSymbols(isType) { } }; +exports.buildNexusDash = async function() { + let gidCovered = new Set(); + for (const u of [0x2013, 0x2014, 0x2015]) { + const gn = this.find.gname.unicode(u); + if (gn) gidCovered.add(gn); + } + + const nexusLookupName = "ccmp__nexusDash"; + let nexusLookupSubst = {}; + const nexusLookup = { type: "gsub_single", subtables: [nexusLookupSubst] }; + const nexusChainingLookupName = "ccmp__nexusDash_chaining"; + let nexusChainingRules = []; + const nexusChainingLookup = { type: "gsub_chaining", subtables: nexusChainingRules }; + + for (const originalGid of gidCovered) { + const glyph = createNexusGlyph(this.find.glyph$(originalGid)); + const nexusGid = originalGid + ".nexus"; + await this.save.to(nexusGid, null, glyph); + nexusLookupSubst[originalGid] = nexusGid; + nexusChainingRules.push({ + match: [[originalGid, nexusGid], [originalGid]], + apply: [{ lookup: nexusLookupName, at: 1 }], + inputBegins: 1, + inputEnds: 2 + }); + } + + if (this.font.GSUB) { + this.font.GSUB.lookups[nexusLookupName] = nexusLookup; + this.font.GSUB.lookups[nexusChainingLookupName] = nexusChainingLookup; + + for (const fid in this.font.GSUB.features) { + if (fid.slice(0, 4) !== "ccmp") continue; + const feature = this.font.GSUB.features[fid]; + if (!feature) continue; + feature.push(nexusChainingLookupName); + } + } +}; + +function createNexusGlyph(glyph) { + let xMax = -0xffff, + xMin = 0xffff; + if (glyph.contours) { + for (let c of glyph.contours) { + for (let z of c) { + if (z.x > xMax) xMax = z.x; + if (z.x < xMin) xMin = z.x; + } + } + } + const rsb = glyph.advanceWidth - xMax; + const negMin = rsb * 1.5; + const scaling = (xMax + rsb * 1.5) / (xMax - xMin); + if (glyph.contours) { + for (let c of glyph.contours) { + for (let z of c) { + z.x = (z.x - xMin) * scaling - negMin; + } + } + } + return glyph; +} + function removeUnusedFeature(table, tag) { if (!table) return; for (let f in table.features) { @@ -124,6 +188,38 @@ exports.removeUnusedFeatures = function(a, mono) { } }; +exports.removeDashCcmp = function(a, mono) { + if (!a.GSUB || !a.GSUB.features || !a.GSUB.lookups) return; + + let affectedLookups = new Set(); + for (const fid in a.GSUB.features) { + if (fid.slice(0, 4) === "ccmp") { + const feature = a.GSUB.features[fid]; + if (!feature) continue; + for (const lid of feature) affectedLookups.add(lid); + } + } + + for (const lid of affectedLookups) { + const lookup = a.GSUB.lookups[lid]; + removeDashCcmpLookup(lookup, a.cmap); + } +}; +function removeDashCcmpLookup(lookup, cmap) { + if (!lookup || lookup.type !== "gsub_ligature") return; + for (const st of lookup.subtables) { + let st1 = []; + for (const subst of st.substitutions) { + let valid = true; + for (const gid of subst.from) { + if (cmap[0x2014] === gid || cmap[0x2015] === gid) valid = false; + } + if (valid) st1.push(subst); + } + st.substitutions = st1; + } +} + exports.toPWID = async function() { const font = this.font; for (let c in font.cmap) { diff --git a/package.json b/package.json index d9666c93f..fd5edfc9f 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "yargs": "^9.0.0" }, "engines": { - "node": ">=8.5.0" + "node": ">=12.13.0" }, "scripts": { "install": "node checkenv", diff --git a/verdafile.js b/verdafile.js index 09185337d..598b57ef0 100644 --- a/verdafile.js +++ b/verdafile.js @@ -142,6 +142,10 @@ const AS0 = file.make( } ); +task("as-mono-sc-regular", async $ => { + await $.need(AS0("mono", "sc", "regular")); +}); + const Pass1 = file.make( (family, region, style) => `${BUILD}/pass1/${family}-${region}-${style}.ttf`, async (t, { full, dir, name }, family, region, style) => { @@ -220,12 +224,7 @@ const Prod = file.make( /////////////////////////////////////////////////////////////////////////////////////////////////// // HINTING -const Chlorophytum = [ - NODEJS, - `--experimental-worker`, - `--max-old-space-size=8192`, - `./node_modules/@chlorophytum/cli/lib/index.js` -]; +const Chlorophytum = [NODEJS, `./node_modules/@chlorophytum/cli/lib/index.js`]; const HintDirPrefix = `${BUILD}/hf`; const HintDirOutPrefix = `${BUILD}/hfo`; From 8509372224871fcd433735406ed2703d2c3f758c Mon Sep 17 00:00:00 2001 From: be5invis Date: Fri, 1 Nov 2019 23:23:01 -0700 Subject: [PATCH 3/3] Add a intermediate pass to make building faster --- make/non-kanji/build.js | 27 +++++++++++++++++++++++++++ package.json | 4 ++-- verdafile.js | 27 ++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 make/non-kanji/build.js diff --git a/make/non-kanji/build.js b/make/non-kanji/build.js new file mode 100644 index 000000000..e5eaa4ff4 --- /dev/null +++ b/make/non-kanji/build.js @@ -0,0 +1,27 @@ +"use strict"; + +const { introduce, build, gc } = require("megaminx"); +const { isIdeograph, isKorean, filterUnicodeRange } = require("../common/unicode-kind"); + +async function pass(ctx, config, argv) { + const a = await ctx.run(introduce, "a", { + from: argv.main, + prefix: "a", + ignoreHints: true + }); + filterUnicodeRange(a, c => !isIdeograph(c) && !isKorean(c)); + a.cvt_ = []; + a.fpgm = []; + a.prep = []; + if (!config.loclFeature) { + a.GSUB = null; + a.GPOS = null; + } + await ctx.run(gc, "a"); + await ctx.run(build, "a", { to: config.o, optimize: true }); + ctx.remove("a"); +} + +module.exports = async function makeFont(ctx, config, argv) { + await pass(ctx, { o: argv.o }, argv); +}; diff --git a/package.json b/package.json index fd5edfc9f..18dc400a7 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.10.1", "main": "./run", "dependencies": { - "@chlorophytum/cli": "^0.3.0", + "@chlorophytum/cli": "^0.3.5", "@chlorophytum/final-hint-format-hltt": "^0.3.0", "@chlorophytum/font-format-otd": "^0.3.0", "@chlorophytum/hint-store-provider-file": "^0.3.0", @@ -17,7 +17,7 @@ "yargs": "^9.0.0" }, "engines": { - "node": ">=12.13.0" + "node": ">=12.0.0" }, "scripts": { "install": "node checkenv", diff --git a/verdafile.js b/verdafile.js index 598b57ef0..35b535903 100644 --- a/verdafile.js +++ b/verdafile.js @@ -26,6 +26,10 @@ const OTFCCDUMP = `otfccdump`; const OTFCCBUILD = `otfccbuild`; const OTF2TTF = `otf2ttf`; +const NPX_SUFFIX = os.platform() === "win32" ? ".cmd" : ""; +const TTCIZE = "node_modules/.bin/otfcc-ttcize" + NPX_SUFFIX; +const Chlorophytum = [NODEJS, `./node_modules/@chlorophytum/cli/bin/_startup`]; + /////////////////////////////////////////////////////////////////////////////////////////////////// // Entrypoint const Start = phony("all", async t => { @@ -106,11 +110,25 @@ const ShsOtd = file.make( } ); +const NonKanji = file.make( + (region, style) => `${BUILD}/non-kanji0/${region}-${style}.ttf`, + async (t, { full, dir, name }, region, style) => { + await t.need(Config, Scripts); + const [$1] = await t.need(ShsOtd(region, style), de(dir)); + const tmpOTD = `${dir}/${name}.otd`; + await RunFontBuildTask("make/non-kanji/build.js", { + main: $1.full, + o: tmpOTD + }); + await OtfccBuildAsIs(tmpOTD, full); + } +); + const WS0 = file.make( (family, region, style) => `${BUILD}/ws0/${family}-${region}-${style}.ttf`, async (t, { full, dir, name }, family, region, style) => { const [config] = await t.need(Config, Scripts); - const [, $1] = await t.need(de(dir), ShsOtd(region, style)); + const [, $1] = await t.need(de(dir), NonKanji(region, style)); const tmpOTD = `${dir}/${name}.otd`; await RunFontBuildTask("make/punct/ws.js", { main: $1.full, @@ -128,7 +146,7 @@ const AS0 = file.make( (family, region, style) => `${BUILD}/as0/${family}-${region}-${style}.ttf`, async (t, { full, dir, name }, family, region, style) => { const [config] = await t.need(Config, Scripts); - const [, $1] = await t.need(de(dir), ShsOtd(region, style)); + const [, $1] = await t.need(de(dir), NonKanji(region, style)); const tmpOTD = `${dir}/${name}.otd`; await RunFontBuildTask("make/punct/as.js", { main: $1.full, @@ -224,7 +242,7 @@ const Prod = file.make( /////////////////////////////////////////////////////////////////////////////////////////////////// // HINTING -const Chlorophytum = [NODEJS, `./node_modules/@chlorophytum/cli/lib/index.js`]; + const HintDirPrefix = `${BUILD}/hf`; const HintDirOutPrefix = `${BUILD}/hfo`; @@ -384,9 +402,8 @@ const TTCFile = file.make( } const [$$] = await t.need(requirements.map(t => t.from)); - const ttcize = "node_modules/.bin/otfcc-ttcize" + (os.platform() === "win32" ? ".cmd" : ""); await run( - ttcize, + TTCIZE, ["-x", "--common-width", 1000, "--common-height", 1000], ["-o", full], [...$$.map(t => t.full)]