Cleanup deps and GC/Quadify code
This commit is contained in:
parent
fbb977c16f
commit
866dc4daae
19 changed files with 493 additions and 222 deletions
|
@ -11,7 +11,7 @@
|
||||||
"experimentalObjectRestSpread": true
|
"experimentalObjectRestSpread": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"indent": ["error", "tab", { "SwitchCase": 1 }],
|
"indent": ["error", "tab", { "SwitchCase": 1 }],
|
||||||
"quotes": ["error", "double", { "allowTemplateLiterals": true }],
|
"quotes": ["error", "double", { "allowTemplateLiterals": true }],
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const EmptyFont = require("./empty-font.js");
|
const EmptyFont = require("./empty-font.js");
|
||||||
const buildGlyphs = require("./build-glyphs.js");
|
const buildGlyphs = require("./build-glyphs.js");
|
||||||
|
|
||||||
|
@ -6,6 +8,7 @@ const { assignFontNames } = require("../meta/naming");
|
||||||
const { setFontMetrics } = require("../meta/aesthetics");
|
const { setFontMetrics } = require("../meta/aesthetics");
|
||||||
|
|
||||||
const regulateGlyphs = require("../support/regulate-glyph");
|
const regulateGlyphs = require("../support/regulate-glyph");
|
||||||
|
const gcFont = require("./gc");
|
||||||
|
|
||||||
module.exports = function(para) {
|
module.exports = function(para) {
|
||||||
const font = EmptyFont();
|
const font = EmptyFont();
|
||||||
|
@ -39,6 +42,8 @@ module.exports = function(para) {
|
||||||
font.glyf = glyf;
|
font.glyf = glyf;
|
||||||
font.cmap = cmap;
|
font.cmap = cmap;
|
||||||
|
|
||||||
|
gcFont(font);
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
return {
|
return {
|
||||||
head: {
|
head: {
|
||||||
|
|
93
gen/gc.js
93
gen/gc.js
|
@ -1,18 +1,83 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { Workflow, introduce, build, gc } = require("megaminx");
|
module.exports = function gcFont(font) {
|
||||||
const argv = require("yargs").argv;
|
let sink = new Set();
|
||||||
|
let glyphCount = 0;
|
||||||
|
|
||||||
async function recipe(ctx, config, argv) {
|
sink.add(".notdef", ".null");
|
||||||
const a = await ctx.run(introduce, "a", { from: argv.i });
|
|
||||||
await ctx.run(gc, "a");
|
if (font.cmap) {
|
||||||
await ctx.run(build, "a", { to: argv.o, optimize: true });
|
for (const k in font.cmap) {
|
||||||
|
if (font.cmap[k]) sink.add(font.cmap[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (font.cmap_uvs) {
|
||||||
|
for (const k in font.cmap_uvs) {
|
||||||
|
if (font.cmap_uvs[k]) sink.add(font.cmap_uvs[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
glyphCount = sink.size;
|
||||||
|
|
||||||
|
if (font.GSUB) {
|
||||||
|
for (const l in font.GSUB.lookups) {
|
||||||
|
const lookup = font.GSUB.lookups[l];
|
||||||
|
if (!lookup || !lookup.subtables) continue;
|
||||||
|
if (lookup && lookup.subtables) {
|
||||||
|
for (let st of lookup.subtables) {
|
||||||
|
markSubtable(sink, lookup.type, st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (font.glyf) {
|
||||||
|
for (const g in font.glyf) {
|
||||||
|
const glyph = font.glyf[g];
|
||||||
|
if (!glyph || !glyph.references) continue;
|
||||||
|
for (const ref of glyph.references) if (ref && ref.glyph) sink.add(ref.glyph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let glyphCount1 = sink.size;
|
||||||
|
if (glyphCount1 === glyphCount) break;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
if (font.glyf) {
|
||||||
|
const filteredGlyf = {};
|
||||||
|
for (const key in font.glyf) {
|
||||||
|
if (sink.has(key)) filteredGlyf[key] = font.glyf[key];
|
||||||
|
}
|
||||||
|
font.glyf = filteredGlyf;
|
||||||
|
} else {
|
||||||
|
font.glyf = {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function markSubtable(sink, type, st) {
|
||||||
|
switch (type) {
|
||||||
|
case "gsub_single":
|
||||||
|
case "gsub_multi":
|
||||||
|
case "gsub_alternate":
|
||||||
|
for (const k in st) if (sink.has(k) && st[k]) sink.add(st[k]);
|
||||||
|
break;
|
||||||
|
case "gsub_ligature":
|
||||||
|
for (const sub of st.substitutions) {
|
||||||
|
let check = true;
|
||||||
|
for (const g of sub.from) if (!sink.has(g)) check = false;
|
||||||
|
if (check && sub.to) sink.add(sub.to);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "gsub_chaining":
|
||||||
|
break;
|
||||||
|
case "gsub_reverse":
|
||||||
|
if (st.match && st.to) {
|
||||||
|
const matchCoverage = st.match[st.inputIndex];
|
||||||
|
for (let j = 0; j < matchCoverage.length; j++) {
|
||||||
|
if (sink.has(matchCoverage[j]) && st.to[j]) sink.add(st.to[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const config = {};
|
|
||||||
const flow = new Workflow(config);
|
|
||||||
await flow.run(recipe, config, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import '../support/transform' as : Transform && [object [transformPoint tp]]
|
||||||
import [curveToContour OffsetCurve] from '../support/curve-util'
|
import [curveToContour OffsetCurve] from '../support/curve-util'
|
||||||
import [mix linreg clamp fallback] from '../support/utils'
|
import [mix linreg clamp fallback] from '../support/utils'
|
||||||
import [designParameters] from '../meta/aesthetics'
|
import [designParameters] from '../meta/aesthetics'
|
||||||
import [CubicBezierCurve autoQuadify] from "primitive-quadify-off-curves"
|
import [Curve Quadify] from "typo-geom"
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ glyph-block Overmarks : begin
|
||||||
define z2 : tp currentGlyph.gizmo : object [x : mix leftEnd rightEnd tildeWaveX] [y : mix tbot ttop tildeWave]
|
define z2 : tp currentGlyph.gizmo : object [x : mix leftEnd rightEnd tildeWaveX] [y : mix tbot ttop tildeWave]
|
||||||
define z3 : tp currentGlyph.gizmo : object [x : mix leftEnd rightEnd (1 - tildeWaveX)] [y : mix tbot ttop (1 - tildeWave)]
|
define z3 : tp currentGlyph.gizmo : object [x : mix leftEnd rightEnd (1 - tildeWaveX)] [y : mix tbot ttop (1 - tildeWave)]
|
||||||
define z4 : tp currentGlyph.gizmo : object [x rightEnd] [y ttop]
|
define z4 : tp currentGlyph.gizmo : object [x rightEnd] [y ttop]
|
||||||
define bone : new CubicBezierCurve z1 z2 z3 z4
|
define bone : new Curve.Bez3 z1 z2 z3 z4
|
||||||
|
|
||||||
define inner : curveToContour [new OffsetCurve bone (+hs) HVCONTRAST] (1 / 256)
|
define inner : curveToContour [new OffsetCurve bone (+hs) HVCONTRAST] (1 / 256)
|
||||||
define outer : curveToContour [new OffsetCurve bone (-hs) HVCONTRAST] (1 / 256)
|
define outer : curveToContour [new OffsetCurve bone (-hs) HVCONTRAST] (1 / 256)
|
||||||
|
|
|
@ -36,13 +36,13 @@ export : define [buildCCMP sink glyphs markGlyphs] : begin
|
||||||
|
|
||||||
define lookupCcmp2 : add-lookup sink : object
|
define lookupCcmp2 : add-lookup sink : object
|
||||||
.type 'gsub_ligature'
|
.type 'gsub_ligature'
|
||||||
.subtables : list : object
|
.subtables : list : object : substitutions : list
|
||||||
psilivaria {'commaAbove' 'graveAbove'}
|
object [from {'commaAbove' 'graveAbove'}] [to 'psilivaria']
|
||||||
psilioxia {'commaAbove' 'acuteAbove'}
|
object [from {'commaAbove' 'acuteAbove'}] [to 'psilioxia']
|
||||||
psiliperispomeni {'commaAbove' 'perispomeniAbove'}
|
object [from {'commaAbove' 'perispomeniAbove'}] [to 'psiliperispomeni']
|
||||||
dasiavaria {'revCommaAbove' 'graveAbove'}
|
object [from {'revCommaAbove' 'graveAbove'}] [to 'dasiavaria']
|
||||||
dasiaoxia {'revCommaAbove' 'acuteAbove'}
|
object [from {'revCommaAbove' 'acuteAbove'}] [to 'dasiaoxia']
|
||||||
dasiaperispomeni {'revCommaAbove' 'perispomeniAbove'}
|
object [from {'revCommaAbove' 'perispomeniAbove'}] [to 'dasiaperispomeni']
|
||||||
|
|
||||||
ccmp.lookups.push lookupCcmp1 lookupCcmp2
|
ccmp.lookups.push lookupCcmp1 lookupCcmp2
|
||||||
add-common-feature sink ccmp
|
add-common-feature sink ccmp
|
||||||
|
|
21
package.json
21
package.json
|
@ -12,28 +12,27 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caryll-shapeops": "^0.3.1",
|
"caryll-shapeops": "^0.3.1",
|
||||||
"megaminx": "^0.9.0",
|
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
"otfcc-ttcize": "^0.9.6",
|
"otfcc-ttcize": "^0.9.6",
|
||||||
"primitive-quadify-off-curves": "^0.6.3",
|
"typo-geom": "0.5.1",
|
||||||
"spiro": "^1.1.0",
|
"spiro": "^1.1.0",
|
||||||
"toml": "^3.0.0",
|
"toml": "^3.0.0",
|
||||||
"topsort": "0.0.2",
|
"topsort": "^0.0.2",
|
||||||
"ttf2woff": "^2.0.1",
|
"ttf2woff": "^2.0.1",
|
||||||
"ttf2woff2": "^3.0.0",
|
"ttf2woff2": "^3.0.0",
|
||||||
"unorm": "^1.6.0",
|
"unorm": "^1.6.0",
|
||||||
"verda": "^1.0.0-12",
|
"verda": "^1.0.0",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^9.0.0",
|
||||||
"yargs": "^15.1.0"
|
"yargs": "^15.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cldr": "^5.5.4",
|
"cldr": "^5.5.4",
|
||||||
"colors": "^1.3.3",
|
"colors": "^1.4.0",
|
||||||
"ejs": "^3.0.1",
|
"ejs": "^3.0.1",
|
||||||
"eslint": "^5.2.0",
|
"eslint": "^6.8.0",
|
||||||
|
"eslint-config-prettier": "^6.10.0",
|
||||||
"patel": "^0.33.1",
|
"patel": "^0.33.1",
|
||||||
"patrisika-scopes": "^0.11.1",
|
"semver": "^7.1.3",
|
||||||
"semver": "^7.1.1",
|
"stylus": "^0.54.7"
|
||||||
"stylus": "^0.54.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const quadify = require("primitive-quadify-off-curves");
|
const typoGeom = require("typo-geom");
|
||||||
|
const Point = require("./point");
|
||||||
|
const { mix } = require("./utils");
|
||||||
|
|
||||||
exports.OffsetCurve = class OffsetCurve {
|
exports.OffsetCurve = class OffsetCurve {
|
||||||
constructor(bone, offset, contrast) {
|
constructor(bone, offset, contrast) {
|
||||||
|
@ -38,7 +40,7 @@ exports.curveToContour = function(curve, err) {
|
||||||
cubic: false,
|
cubic: false,
|
||||||
on: true
|
on: true
|
||||||
});
|
});
|
||||||
const offPoints = quadify.autoQuadify(curve, err || 1);
|
const offPoints = typoGeom.Quadify.auto(curve, err || 1);
|
||||||
for (let k = 0; k < offPoints.length; k++) {
|
for (let k = 0; k < offPoints.length; k++) {
|
||||||
const z = offPoints[k];
|
const z = offPoints[k];
|
||||||
if (k > 0) {
|
if (k > 0) {
|
||||||
|
@ -64,3 +66,211 @@ exports.curveToContour = function(curve, err) {
|
||||||
});
|
});
|
||||||
return exitPoints;
|
return exitPoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function removeMids(contour) {
|
||||||
|
for (let rounds = 0; rounds < 255; rounds++) {
|
||||||
|
const n0 = contour.length;
|
||||||
|
let last = contour.length - 1;
|
||||||
|
for (let j = 0; j < contour.length - 1; j++) {
|
||||||
|
if (
|
||||||
|
Math.abs(contour[j].x - contour[j + 1].x) < 1 &&
|
||||||
|
Math.abs(contour[j].y - contour[j + 1].y) < 1
|
||||||
|
) {
|
||||||
|
contour[j + 1].rem = true;
|
||||||
|
contour[j].on = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (
|
||||||
|
last > 0 &&
|
||||||
|
Math.abs(contour[0].x - contour[last].x) < 1 &&
|
||||||
|
Math.abs(contour[0].y - contour[last].y) < 1
|
||||||
|
) {
|
||||||
|
contour[last].rem = true;
|
||||||
|
contour[0].on = true;
|
||||||
|
last -= 1;
|
||||||
|
}
|
||||||
|
contour = contour.filter(x => !x.rem);
|
||||||
|
|
||||||
|
last = contour.length - 1;
|
||||||
|
for (let j = 1; j < contour.length - 1; j++) {
|
||||||
|
if (!contour[j - 1].on && contour[j].on && !contour[j + 1].on) {
|
||||||
|
const mx = contour[j - 1].x + contour[j + 1].x;
|
||||||
|
const my = contour[j - 1].y + contour[j + 1].y;
|
||||||
|
const dy = contour[j - 1].y - contour[j + 1].y;
|
||||||
|
if (
|
||||||
|
Math.abs(dy) >= 1 &&
|
||||||
|
Math.abs(contour[j].x * 2 - mx) < 1 &&
|
||||||
|
Math.abs(contour[j].y * 2 - my) < 1
|
||||||
|
) {
|
||||||
|
contour[j].rem = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!contour[last].rem && !contour[last].on && contour[0].on && !contour[1].on) {
|
||||||
|
const mx = contour[last].x + contour[1].x;
|
||||||
|
const my = contour[last].y + contour[1].y;
|
||||||
|
if (Math.abs(contour[0].x * 2 - mx) < 1 && Math.abs(contour[0].y * 2 - my) < 1) {
|
||||||
|
contour[0].rem = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contour = contour.filter(x => !x.rem);
|
||||||
|
const n = contour.length;
|
||||||
|
if (n >= n0) break;
|
||||||
|
}
|
||||||
|
return contour;
|
||||||
|
}
|
||||||
|
function extPrior(a, b) {
|
||||||
|
return a.y < b.y || (a.y === b.y && ((a.on && !b.on) || (a.on === b.on && a.x < b.x)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function canonicalStart(_points) {
|
||||||
|
const points = _points.reverse().map(z => {
|
||||||
|
z.x = Math.round(z.x * 1024) / 1024;
|
||||||
|
z.y = Math.round(z.y * 1024) / 1024;
|
||||||
|
return z;
|
||||||
|
});
|
||||||
|
let jm = 0;
|
||||||
|
for (var j = 0; j < points.length * 2; j++) {
|
||||||
|
if (extPrior(points[j % points.length], points[jm])) {
|
||||||
|
jm = j % points.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return points.slice(jm).concat(points.slice(0, jm));
|
||||||
|
}
|
||||||
|
|
||||||
|
function colinear(x1, y1, x2, y2, x3, y3, err) {
|
||||||
|
const det = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2);
|
||||||
|
return det <= err && det >= -err;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inspan(a, b, c) {
|
||||||
|
if (a > c) return inspan(c, b, a);
|
||||||
|
return a <= b && b <= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle(z1, z2, z3, z4, err) {
|
||||||
|
if (
|
||||||
|
colinear(z1.x, z1.y, z2.x, z2.y, z4.x, z4.y, err) &&
|
||||||
|
colinear(z1.x, z1.y, z3.x, z3.y, z4.x, z4.y, err) &&
|
||||||
|
inspan(z1.x, z2.x, z4.x) &&
|
||||||
|
inspan(z1.y, z2.y, z4.y) &&
|
||||||
|
inspan(z1.x, z3.x, z4.x) &&
|
||||||
|
inspan(z1.y, z3.y, z4.y)
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const curve = new typoGeom.Curve.Bez3(z1, z2, z3, z4);
|
||||||
|
const offPoints = typoGeom.Quadify.auto(curve, err);
|
||||||
|
const ans = [];
|
||||||
|
for (const z of offPoints) {
|
||||||
|
ans.push(Point.offFrom(z));
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertContourToTt(contour, err) {
|
||||||
|
if (contour.length === 0) return [];
|
||||||
|
if (contour.length === 1) return [contour[0]];
|
||||||
|
err = err || 1 / 4;
|
||||||
|
|
||||||
|
const newContour = [];
|
||||||
|
let z0 = contour[0];
|
||||||
|
newContour.push(Point.cornerFrom(z0));
|
||||||
|
|
||||||
|
for (let j = 1; j < contour.length; j++) {
|
||||||
|
const z = contour[j];
|
||||||
|
if (z.on) {
|
||||||
|
newContour.push(Point.cornerFrom(z));
|
||||||
|
z0 = z;
|
||||||
|
} else if (z.cubic) {
|
||||||
|
const z1 = z;
|
||||||
|
const z2 = contour[j + 1];
|
||||||
|
const z3 = contour[j + 2];
|
||||||
|
const quadZs = handle(z0, z1, z2, z3, err);
|
||||||
|
for (const z of quadZs) newContour.push(z);
|
||||||
|
newContour.push(Point.cornerFrom(z3));
|
||||||
|
z0 = z3;
|
||||||
|
j += 2;
|
||||||
|
} else {
|
||||||
|
const zc = z;
|
||||||
|
let zf = contour[j + 1] ? contour[j + 1] : contour[0];
|
||||||
|
if (!zf.on) {
|
||||||
|
zf = Point.cornerFromXY(mix(zc.x, zf.x, 0.5), mix(zc.y, zf.y, 0.5));
|
||||||
|
}
|
||||||
|
newContour.push(Point.offFrom(zc));
|
||||||
|
newContour.push(Point.cornerFrom(zf));
|
||||||
|
z0 = zf;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newContour;
|
||||||
|
}
|
||||||
|
|
||||||
|
function byFirstPointCoord(a, b) {
|
||||||
|
if (!a.length) return -1;
|
||||||
|
if (!b.length) return 1;
|
||||||
|
let z1 = a[0];
|
||||||
|
let z2 = b[0];
|
||||||
|
return z1.y !== z2.y
|
||||||
|
? z1.y - z2.y
|
||||||
|
: z1.x !== z2.x
|
||||||
|
? z1.x - z2.x
|
||||||
|
: byFirstPointCoord(a.slice(1), b.slice(1));
|
||||||
|
}
|
||||||
|
function convertContourListToTt(contours, err) {
|
||||||
|
err = err || 1 / 4;
|
||||||
|
let ans = [];
|
||||||
|
for (let c of contours) {
|
||||||
|
ans.push(canonicalStart(removeMids(convertContourToTt(c, err))));
|
||||||
|
}
|
||||||
|
return ans.sort(byFirstPointCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertContourToCubic(contour) {
|
||||||
|
if (!contour || !contour.length) return [];
|
||||||
|
|
||||||
|
const newContour = [];
|
||||||
|
let z0 = contour[0];
|
||||||
|
newContour.push(Point.cornerFrom(z0));
|
||||||
|
|
||||||
|
for (let j = 1; j < contour.length; j++) {
|
||||||
|
const z = contour[j];
|
||||||
|
if (z.on) {
|
||||||
|
newContour.push(Point.cornerFrom(z));
|
||||||
|
z0 = z;
|
||||||
|
} else if (z.cubic) {
|
||||||
|
const z1 = z;
|
||||||
|
const z2 = contour[j + 1];
|
||||||
|
const z3 = contour[j + 2];
|
||||||
|
newContour.push(Point.cubicOffFrom(z1));
|
||||||
|
newContour.push(Point.cubicOffFrom(z2));
|
||||||
|
newContour.push(Point.cornerFrom(z3));
|
||||||
|
z0 = z3;
|
||||||
|
j += 2;
|
||||||
|
} else {
|
||||||
|
const zc = z;
|
||||||
|
let zf = contour[j + 1] ? contour[j + 1] : contour[0];
|
||||||
|
if (!zf.on) {
|
||||||
|
zf = Point.cornerFromXY(mix(zc.x, zf.x, 0.5), mix(zc.y, zf.y, 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
const x1 = mix(z0.x, zc.x, 2 / 3);
|
||||||
|
const y1 = mix(z0.y, zc.y, 2 / 3);
|
||||||
|
const x2 = mix(zf.x, zc.x, 2 / 3);
|
||||||
|
const y2 = mix(zf.y, zc.y, 2 / 3);
|
||||||
|
|
||||||
|
newContour.push(Point.cubicOffFromXY(x1, y1));
|
||||||
|
newContour.push(Point.cubicOffFromXY(x2, y2));
|
||||||
|
newContour.push(Point.cornerFrom(zf));
|
||||||
|
z0 = zf;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newContour;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.convertContourToTt = convertContourToTt;
|
||||||
|
exports.convertContourToCubic = convertContourToCubic;
|
||||||
|
exports.convertContourListToTt = convertContourListToTt;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Transform = require("./transform.js");
|
const Transform = require("./transform.js");
|
||||||
const quadify = require("primitive-quadify-off-curves");
|
const typoGeom = require("typo-geom");
|
||||||
|
|
||||||
const SMALL = 1e-4;
|
const SMALL = 1e-4;
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ class BezierCurveCluster {
|
||||||
z4 = zs[j];
|
z4 = zs[j];
|
||||||
const z2 = mix(z1, z4, 1 / 3);
|
const z2 = mix(z1, z4, 1 / 3);
|
||||||
const z3 = mix(z1, z4, 2 / 3);
|
const z3 = mix(z1, z4, 2 / 3);
|
||||||
const seg = new quadify.CubicBezierCurve(z1, z2, z3, z4);
|
const seg = new typoGeom.Curve.Bez3(z1, z2, z3, z4);
|
||||||
segments.push(seg);
|
segments.push(seg);
|
||||||
lengths.push(this.measureLength(seg));
|
lengths.push(this.measureLength(seg));
|
||||||
last = z4;
|
last = z4;
|
||||||
|
@ -206,7 +206,7 @@ class BezierCurveCluster {
|
||||||
z2 = zs[j],
|
z2 = zs[j],
|
||||||
z3 = zs[j + 1],
|
z3 = zs[j + 1],
|
||||||
z4 = zs[j + 2];
|
z4 = zs[j + 2];
|
||||||
const seg = new quadify.CubicBezierCurve(z1, z2, z3, z4);
|
const seg = new typoGeom.Curve.Bez3(z1, z2, z3, z4);
|
||||||
segments.push(seg);
|
segments.push(seg);
|
||||||
lengths.push(this.measureLength(seg));
|
lengths.push(this.measureLength(seg));
|
||||||
last = z4;
|
last = z4;
|
||||||
|
@ -217,7 +217,7 @@ class BezierCurveCluster {
|
||||||
z4 = zs[j + 1];
|
z4 = zs[j + 1];
|
||||||
const z2 = mix(zm, z1, 1 / 3);
|
const z2 = mix(zm, z1, 1 / 3);
|
||||||
const z3 = mix(zm, z4, 1 / 3);
|
const z3 = mix(zm, z4, 1 / 3);
|
||||||
const seg = new quadify.CubicBezierCurve(z1, z2, z3, z4);
|
const seg = new typoGeom.Curve.Bez3(z1, z2, z3, z4);
|
||||||
segments.push(seg);
|
segments.push(seg);
|
||||||
lengths.push(this.measureLength(seg));
|
lengths.push(this.measureLength(seg));
|
||||||
last = z4;
|
last = z4;
|
||||||
|
@ -307,7 +307,7 @@ function buildCurve(curve) {
|
||||||
if (nPtsOffPoints > 0) {
|
if (nPtsOffPoints > 0) {
|
||||||
const curve = new BezierCurveCluster(pts);
|
const curve = new BezierCurveCluster(pts);
|
||||||
if (curve.isAlmostLinear(1)) continue;
|
if (curve.isAlmostLinear(1)) continue;
|
||||||
const offPoints = quadify.autoQuadify(curve, 1 / 4);
|
const offPoints = typoGeom.Quadify.auto(curve, 1 / 4);
|
||||||
if (!offPoints) continue;
|
if (!offPoints) continue;
|
||||||
for (let k = 0; k < offPoints.length; k++) {
|
for (let k = 0; k < offPoints.length; k++) {
|
||||||
const z = offPoints[k];
|
const z = offPoints[k];
|
||||||
|
|
|
@ -177,38 +177,3 @@ export all : class Glyph
|
||||||
this.start-from x y
|
this.start-from x y
|
||||||
this.start-from mbx mby
|
this.start-from mbx mby
|
||||||
return this
|
return this
|
||||||
|
|
||||||
static [contourToStandardCubic contour] : begin
|
|
||||||
local c {}
|
|
||||||
if (!contour || !contour.length) : return c
|
|
||||||
|
|
||||||
local z0 contour.0
|
|
||||||
c.push : new Point z0.x z0.y true false false
|
|
||||||
for [local j 1] (j < contour.length) [inc j] : begin
|
|
||||||
local point contour.(j)
|
|
||||||
piecewise
|
|
||||||
point.on : begin
|
|
||||||
c.push : new Point point.x point.y true false false
|
|
||||||
set z0 point
|
|
||||||
point.cubic : begin
|
|
||||||
local z1 point
|
|
||||||
local z2 contour.(j + 1)
|
|
||||||
local z3 contour.(j + 2)
|
|
||||||
c.push : new Point z1.x z1.y false true false
|
|
||||||
c.push : new Point z2.x z2.y false true false
|
|
||||||
c.push : new Point z3.x z3.y true false false
|
|
||||||
set z0 z3
|
|
||||||
set j : j + 2
|
|
||||||
true : begin
|
|
||||||
local zc point
|
|
||||||
local zf : if contour.(j + 1) contour.(j + 1) contour.0
|
|
||||||
local x1 : mix z0.x zc.x (2 / 3)
|
|
||||||
local y1 : mix z0.y zc.y (2 / 3)
|
|
||||||
local x2 : mix zf.x zc.x (2 / 3)
|
|
||||||
local y2 : mix zf.y zc.y (2 / 3)
|
|
||||||
c.push : new Point x1 y1 false true false
|
|
||||||
c.push : new Point x2 y2 false true false
|
|
||||||
c.push : new Point zf.x zf.y true false false
|
|
||||||
set z0 zf
|
|
||||||
inc j
|
|
||||||
return c
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
module.exports = function formVariantData(data, para) {
|
module.exports = function formVariantData(data, para) {
|
||||||
const defaultBuildup = {};
|
const defaultBuildup = {};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
function maskBit(x, y) {
|
"use strict";
|
||||||
return x & (1 << y);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = maskBit;
|
module.exports = function maskBit(x, y) {
|
||||||
|
return x & (1 << y);
|
||||||
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
module.exports = function(xs, ys) {
|
module.exports = function(xs, ys) {
|
||||||
let i,
|
let i,
|
||||||
length = xs.length;
|
length = xs.length;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const blend = require("./monotonic-interpolate");
|
const blend = require("./monotonic-interpolate");
|
||||||
|
|
||||||
module.exports = function(aspect, hive, params, sink) {
|
module.exports = function(aspect, hive, params, sink) {
|
||||||
|
|
|
@ -3,8 +3,22 @@ export all : class Point
|
||||||
this.x = x
|
this.x = x
|
||||||
this.y = y
|
this.y = y
|
||||||
this.on = on || false
|
this.on = on || false
|
||||||
this.subdivided = subdivided || false
|
|
||||||
this.cubic = cubic || false
|
this.cubic = cubic || false
|
||||||
|
this.subdivided = subdivided || false
|
||||||
|
|
||||||
|
static [from z on cubic subdivided] : new Point
|
||||||
|
* z.x
|
||||||
|
* z.y
|
||||||
|
* on
|
||||||
|
* cubic
|
||||||
|
* subdivided
|
||||||
|
|
||||||
|
static [cornerFrom z] : new Point z.x z.y true false false
|
||||||
|
static [offFrom z] : new Point z.x z.y false false false
|
||||||
|
static [cubicOffFrom z] : new Point z.x z.y false true false
|
||||||
|
static [cornerFromXY x y] : new Point x y true false false
|
||||||
|
static [offFromXY x y] : new Point x y false false false
|
||||||
|
static [cubicOffFromXY x y] : new Point x y false true false
|
||||||
|
|
||||||
static [transformed tfm x y on cubic subdivided] : new Point
|
static [transformed tfm x y on cubic subdivided] : new Point
|
||||||
* x * tfm.xx + y * tfm.yx + tfm.x
|
* x * tfm.xx + y * tfm.yx + tfm.x
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const Glyph = require("./glyph");
|
const Glyph = require("./glyph");
|
||||||
const autoRef = require("./autoref");
|
const autoRef = require("./autoref");
|
||||||
const caryllShapeOps = require("caryll-shapeops");
|
const caryllShapeOps = require("caryll-shapeops");
|
||||||
const c2q = require("megaminx").geometry.c2q;
|
const curveUtil = require("./curve-util");
|
||||||
|
|
||||||
function regulateGlyph(g, skew) {
|
function regulateGlyph(g, skew) {
|
||||||
if (!g.contours) return;
|
if (!g.contours) return;
|
||||||
|
@ -47,9 +49,11 @@ function regulateGlyph(g, skew) {
|
||||||
function simplifyContours(contours) {
|
function simplifyContours(contours) {
|
||||||
const source = [];
|
const source = [];
|
||||||
for (const contour of contours) {
|
for (const contour of contours) {
|
||||||
if (contour.length > 2) source.push(Glyph.contourToStandardCubic(contour));
|
if (contour.length > 2) source.push(curveUtil.convertContourToCubic(contour));
|
||||||
}
|
}
|
||||||
const simplified = c2q.contours(caryllShapeOps.removeOverlap(source, 1, 1 << 17, true));
|
const simplified = curveUtil.convertContourListToTt(
|
||||||
|
caryllShapeOps.removeOverlap(source, 1, 1 << 17, true)
|
||||||
|
);
|
||||||
const result = [];
|
const result = [];
|
||||||
for (const contour of simplified) {
|
for (const contour of simplified) {
|
||||||
if (contour.length > 2) result.push(contour);
|
if (contour.length > 2) result.push(contour);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'spiro' as SpiroJs
|
||||||
import './spiroexpand' as SpiroExpansionContext
|
import './spiroexpand' as SpiroExpansionContext
|
||||||
import './fairify' as fairify
|
import './fairify' as fairify
|
||||||
import 'caryll-shapeops' as ShapeOps
|
import 'caryll-shapeops' as ShapeOps
|
||||||
|
import './curve-util' as CurveUtil
|
||||||
|
|
||||||
import './transform' as Transform
|
import './transform' as Transform
|
||||||
|
|
||||||
|
@ -213,14 +214,14 @@ export : define [SetupBuilders args] : begin
|
||||||
if (k.length == 0) : return g
|
if (k.length == 0) : return g
|
||||||
|
|
||||||
g.include k.0
|
g.include k.0
|
||||||
set g.contours : g.contours.map Glyph.contourToStandardCubic
|
set g.contours : g.contours.map CurveUtil.convertContourToCubic
|
||||||
foreach [item : items-of : k.slice 1] : begin
|
foreach [item : items-of : k.slice 1] : begin
|
||||||
local g1 : new Glyph
|
local g1 : new Glyph
|
||||||
set g1.gizmo : this.gizmo || globalTransform
|
set g1.gizmo : this.gizmo || globalTransform
|
||||||
g1.include item
|
g1.include item
|
||||||
set g1.contours : g1.contours.map Glyph.contourToStandardCubic
|
set g1.contours : g1.contours.map CurveUtil.convertContourToCubic
|
||||||
local c1 : ShapeOps.boole operator g.contours g1.contours ShapeOps.fillRules.nonzero ShapeOps.fillRules.nonzero 16384
|
local c1 : ShapeOps.boole operator g.contours g1.contours ShapeOps.fillRules.nonzero ShapeOps.fillRules.nonzero 16384
|
||||||
set g.contours : c1.map : lambda [c] : [Glyph.contourToStandardCubic c].reverse
|
set g.contours : c1.map : lambda [c] : [CurveUtil.convertContourToCubic c].reverse
|
||||||
if [not dontinc] : this.include g
|
if [not dontinc] : this.include g
|
||||||
return g
|
return g
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const objectAssign = require("object-assign");
|
const objectAssign = require("object-assign");
|
||||||
|
|
||||||
function mergeVSHive(_target, source) {
|
function mergeVSHive(_target, source) {
|
||||||
|
|
14
verdafile.js
14
verdafile.js
|
@ -21,7 +21,6 @@ const OTF2OTC = "otf2otc";
|
||||||
const PATEL_C = ["node", "./node_modules/patel/bin/patel-c"];
|
const PATEL_C = ["node", "./node_modules/patel/bin/patel-c"];
|
||||||
const TTCIZE = ["node", "./node_modules/otfcc-ttcize/bin/_startup"];
|
const TTCIZE = ["node", "./node_modules/otfcc-ttcize/bin/_startup"];
|
||||||
const GENERATE = ["node", "gen/generator"];
|
const GENERATE = ["node", "gen/generator"];
|
||||||
const GC = ["node", "gen/gc"];
|
|
||||||
const webfontFormats = [
|
const webfontFormats = [
|
||||||
["woff2", "woff2"],
|
["woff2", "woff2"],
|
||||||
["woff", "woff"],
|
["woff", "woff"],
|
||||||
|
@ -319,8 +318,6 @@ const BuildTTF = file.make(
|
||||||
{ hives, family, shapeWeight, menuWeight, menuStyle, menuWidth },
|
{ hives, family, shapeWeight, menuWeight, menuStyle, menuWidth },
|
||||||
version
|
version
|
||||||
] = await target.need(HivesOf(fn), Version);
|
] = await target.need(HivesOf(fn), Version);
|
||||||
const otd = output.dir + "/" + output.name + ".otd";
|
|
||||||
const ttfTmp = output.dir + "/" + output.name + ".tmp.ttf";
|
|
||||||
const otdTmp = output.dir + "/" + output.name + ".tmp.otd";
|
const otdTmp = output.dir + "/" + output.name + ".tmp.otd";
|
||||||
const charmap = output.dir + "/" + output.name + ".charmap";
|
const charmap = output.dir + "/" + output.name + ".charmap";
|
||||||
await target.need(Scripts, fu`parameters.toml`, de`${output.dir}`);
|
await target.need(Scripts, fu`parameters.toml`, de`${output.dir}`);
|
||||||
|
@ -336,12 +333,13 @@ const BuildTTF = file.make(
|
||||||
["--menu-width", menuWidth],
|
["--menu-width", menuWidth],
|
||||||
hives
|
hives
|
||||||
);
|
);
|
||||||
await run("otfccbuild", otdTmp, "-o", ttfTmp, "-O3", "--keep-average-char-width");
|
await run(
|
||||||
await run(GC, ["-i", ttfTmp], ["-o", otd]);
|
"otfccbuild",
|
||||||
await run("otfccbuild", otd, "-o", output.full, "-O3", "--keep-average-char-width", "-q");
|
otdTmp,
|
||||||
|
["-o", output.full],
|
||||||
|
["-O3", "--keep-average-char-width", "-q"]
|
||||||
|
);
|
||||||
await rm(otdTmp);
|
await rm(otdTmp);
|
||||||
await rm(ttfTmp);
|
|
||||||
await rm(otd);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const BuildCM = file.make(
|
const BuildCM = file.make(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue