Remember, no more FontForge

This commit is contained in:
be5invis 2017-01-24 06:24:08 +08:00
parent a6128aab7a
commit 749cfeed65
14 changed files with 779 additions and 51 deletions

461
.esformatter Normal file
View File

@ -0,0 +1,461 @@
{
"indent" : {
"ReturnStatement": ">=1",
"value": "\t",
"alignComments": true,
"ArrayExpression": 1,
"ArrayPattern": 1,
"ArrowFunctionExpression": 1,
"AssignmentExpression": 1,
"AssignmentExpression.BinaryExpression": 1,
"AssignmentExpression.LogicalExpression": 1,
"AssignmentExpression.UnaryExpression": 1,
"CallExpression": 1,
"CallExpression.BinaryExpression": 1,
"CallExpression.LogicalExpression": 1,
"CallExpression.UnaryExpression": 1,
"CatchClause": 1,
"ConditionalExpression": 1,
"CommentInsideEmptyBlock": 1,
"ClassDeclaration": 1,
"DoWhileStatement": 1,
"ForInStatement": 1,
"ForOfStatement": 1,
"ForStatement": 1,
"FunctionDeclaration": 1,
"FunctionExpression": 1,
"IfStatement": 1,
"MemberExpression": 1,
"MultipleVariableDeclaration": 1,
"NewExpression": 1,
"ObjectExpression": 1,
"ObjectExpression.BinaryExpression": 1,
"ObjectExpression.LogicalExpression": 1,
"ObjectExpression.UnaryExpression": 1,
"ObjectPattern": 1,
"ParameterList": 1,
"SingleVariableDeclaration": 0,
"SwitchCase": 1,
"SwitchStatement": 1,
"TopLevelFunctionBlock": 1,
"TryStatement": 1,
"VariableDeclaration.BinaryExpression": 1,
"VariableDeclaration.LogicalExpression": 1,
"VariableDeclaration.UnaryExpression": 1,
"WhileStatement": 1
},
"lineBreak" : {
"value" : "\n",
"before" : {
"AssignmentExpression" : -1,
"AssignmentOperator": -1,
"AssignmentPattern" : 0,
"ArrayPatternOpening": 0,
"ArrayPatternClosing": 0,
"ArrayPatternComma": 0,
"ArrowFunctionExpressionArrow": 0,
"ArrowFunctionExpressionOpeningBrace": 0,
"ArrowFunctionExpressionClosingBrace": "<=1",
"BlockStatement" : -1,
"BreakKeyword": ">=1",
"CallExpression" : -1,
"CallExpressionOpeningParentheses" : 0,
"CallExpressionClosingParentheses" : -1,
"ClassDeclaration" : ">=1",
"ClassDeclarationOpeningBrace" : 0,
"ClassDeclarationClosingBrace" : "<=1",
"ConditionalExpression" : ">=1",
"CatchOpeningBrace" : 0,
"CatchClosingBrace" : "<=1",
"CatchKeyword": 0,
"DeleteOperator" : -1,
"DoWhileStatement" : -1,
"DoWhileStatementOpeningBrace" : 0,
"DoWhileStatementClosingBrace" : "<=1",
"EndOfFile" : 1,
"EmptyStatement" : -1,
"FinallyKeyword" : -1,
"FinallyOpeningBrace" : 0,
"FinallyClosingBrace" : "<=1",
"ForInStatement" : -1,
"ForInStatementExpressionOpening" : -1,
"ForInStatementExpressionClosing" : -1,
"ForInStatementOpeningBrace" : 0,
"ForInStatementClosingBrace" : "<=1",
"ForOfStatement" : ">=1",
"ForOfStatementExpressionOpening" : 0,
"ForOfStatementExpressionClosing" : 0,
"ForOfStatementOpeningBrace" : 0,
"ForOfStatementClosingBrace" : "<=1",
"ForStatement" : -1,
"ForStatementExpressionOpening" : -1,
"ForStatementExpressionClosing" : -1,
"ForStatementOpeningBrace" : 0,
"ForStatementClosingBrace" : "<=1",
"FunctionExpression" : -1,
"FunctionExpressionOpeningBrace" : 0,
"FunctionExpressionClosingBrace" : "<=1",
"FunctionDeclaration" : -1,
"FunctionDeclarationOpeningBrace" : 0,
"FunctionDeclarationClosingBrace" : "<=1",
"IIFEClosingParentheses" : 0,
"IfStatement" : -1,
"IfStatementOpeningBrace" : 0,
"IfStatementClosingBrace" : "<=1",
"ElseIfStatement" : -1,
"ElseIfStatementOpeningBrace" : 0,
"ElseIfStatementClosingBrace" : "<=1",
"ElseStatement" : 0,
"ElseStatementOpeningBrace" : 0,
"ElseStatementClosingBrace" : "<=1",
"LogicalExpression" : -1,
"MethodDefinition": ">=1",
"MemberExpressionOpening": 0,
"MemberExpressionClosing": 0,
"MemberExpressionPeriod": -1,
"ObjectExpressionClosingBrace" : -1,
"ObjectPatternOpeningBrace": 0,
"ObjectPatternClosingBrace": 0,
"ObjectPatternComma": 0,
"Property" : -1,
"PropertyValue" : 0,
"ReturnStatement" : -1,
"SwitchOpeningBrace" : 0,
"SwitchClosingBrace" : -1,
"ThisExpression" : -1,
"ThrowStatement" : -1,
"TryKeyword": -1,
"TryOpeningBrace" : 0,
"TryClosingBrace" : "<=1",
"VariableName" : -1,
"VariableValue" : -1,
"VariableDeclaration" : -1,
"VariableDeclarationSemiColon": -1,
"VariableDeclarationWithoutInit" : -1,
"WhileStatement" : -1,
"WhileStatementOpeningBrace" : 0,
"WhileStatementClosingBrace" : "<=1"
},
"after" : {
"AssignmentExpression" : -1,
"AssignmentOperator" : -1,
"AssignmentPattern" : 0,
"ArrayPatternOpening": 0,
"ArrayPatternClosing": 0,
"ArrayPatternComma": 0,
"ArrowFunctionExpressionArrow": 0,
"ArrowFunctionExpressionOpeningBrace": ">=1",
"ArrowFunctionExpressionClosingBrace": -1,
"BlockStatement" : -1,
"BreakKeyword": -1,
"CallExpression" : -1,
"CallExpressionOpeningParentheses" : -1,
"CallExpressionClosingParentheses" : -1,
"ClassDeclaration" : ">=1",
"ClassDeclarationOpeningBrace" : ">=1",
"ClassDeclarationClosingBrace" : ">=1",
"CatchOpeningBrace" : "<=1",
"CatchClosingBrace" : -1,
"CatchKeyword": 0,
"ConditionalExpression" : -1,
"DeleteOperator" : -1,
"DoWhileStatement" : -1,
"DoWhileStatementOpeningBrace" : "<=1",
"DoWhileStatementClosingBrace" : -1,
"EmptyStatement" : 1,
"FinallyKeyword" : -1,
"FinallyOpeningBrace" : "<=2",
"FinallyClosingBrace" : -1,
"ForInStatement" : -1,
"ForInStatementExpressionOpening" : -1,
"ForInStatementExpressionClosing" : -1,
"ForInStatementOpeningBrace" : "<=1",
"ForInStatementClosingBrace" : -1,
"ForOfStatement" : -1,
"ForOfStatementExpressionOpening" : "<2",
"ForOfStatementExpressionClosing" : -1,
"ForOfStatementOpeningBrace" : ">=1",
"ForOfStatementClosingBrace" : ">=1",
"ForStatement" : -1,
"ForStatementExpressionOpening" : -1,
"ForStatementExpressionClosing" : -1,
"ForStatementOpeningBrace" : "<=1",
"ForStatementClosingBrace" : -1,
"FunctionExpression" : -1,
"FunctionExpressionOpeningBrace" : "<=1",
"FunctionExpressionClosingBrace" : -1,
"FunctionDeclaration" : -1,
"FunctionDeclarationOpeningBrace" : "<=1",
"FunctionDeclarationClosingBrace" : -1,
"IIFEOpeningParentheses" : 0,
"IfStatement" : -1,
"IfStatementOpeningBrace" : "<=1",
"IfStatementClosingBrace" : -1,
"ElseIfStatement" : -1,
"ElseIfStatementOpeningBrace" : "<=1",
"ElseIfStatementClosingBrace" : -1,
"ElseStatement" : -1,
"ElseStatementOpeningBrace" : "<=1",
"ElseStatementClosingBrace" : -1,
"LogicalExpression" : -1,
"MethodDefinition": ">=1",
"MemberExpressionOpening": 0,
"MemberExpressionClosing" : ">=0",
"MemberExpressionPeriod": 0,
"ObjectExpressionOpeningBrace" : "<=1",
"ObjectPatternOpeningBrace": 0,
"ObjectPatternClosingBrace": 0,
"ObjectPatternComma": 0,
"Property" : -1,
"PropertyName" : 0,
"ReturnStatement" : -1,
"SwitchOpeningBrace" : "<=1",
"SwitchClosingBrace" : -1,
"SwitchCaseColon": ">=1",
"ThisExpression" : -1,
"ThrowStatement" : -1,
"TryKeyword": -1,
"TryOpeningBrace" : "<=1",
"TryClosingBrace" : -1,
"VariableValue" : -1,
"VariableDeclaration" : -1,
"VariableDeclarationSemiColon" : ">=1",
"WhileStatement" : -1,
"WhileStatementOpeningBrace" : "<=1",
"WhileStatementClosingBrace" : -1
}
},
"whiteSpace" : {
"value" : " ",
"removeTrailing" : 1,
"before" : {
"AssignmentPattern" : 1,
"ArrayExpressionOpening" : -1,
"ArrayExpressionClosing" : -1,
"ArrayExpressionComma" : -1,
"ArrayPatternOpening": 1,
"ArrayPatternClosing": 0,
"ArrayPatternComma": 0,
"ArrowFunctionExpressionArrow": 1,
"ArrowFunctionExpressionOpeningBrace": 1,
"ArrowFunctionExpressionClosingBrace": 0,
"ArgumentComma" : -1,
"ArgumentList" : 0,
"AssignmentOperator" : 1,
"BinaryExpression": -1,
"BinaryExpressionOperator" : 1,
"BlockComment" : 1,
"CallExpression" : -1,
"CallExpressionOpeningParentheses" : 0,
"CallExpressionClosingParentheses" : -1,
"CatchParameterList" : 0,
"CatchOpeningBrace" : 1,
"CatchClosingBrace" : 1,
"CatchKeyword" : 1,
"CommaOperator" : 0,
"ClassDeclarationOpeningBrace" : 1,
"ClassDeclarationClosingBrace" : 1,
"ConditionalExpressionConsequent" : 1,
"ConditionalExpressionAlternate" : 1,
"DoWhileStatementOpeningBrace" : 1,
"DoWhileStatementClosingBrace" : 1,
"DoWhileStatementConditional" : 1,
"EmptyStatement" : 0,
"ExpressionClosingParentheses": 0,
"FinallyKeyword" : -1,
"FinallyOpeningBrace" : 1,
"FinallyClosingBrace" : 1,
"ForInStatement" : 1,
"ForInStatementExpressionOpening" : 1,
"ForInStatementExpressionClosing" : 0,
"ForInStatementOpeningBrace" : 1,
"ForInStatementClosingBrace" : 1,
"ForOfStatement" : 1,
"ForOfStatementExpressionOpening" : 1,
"ForOfStatementExpressionClosing" : 0,
"ForOfStatementOpeningBrace" : 1,
"ForOfStatementClosingBrace" : 1,
"ForStatement" : 1,
"ForStatementExpressionOpening" : 1,
"ForStatementExpressionClosing" : 0,
"ForStatementOpeningBrace" : 1,
"ForStatementClosingBrace" : -1,
"ForStatementSemicolon" : 0,
"FunctionDeclarationOpeningBrace" : 1,
"FunctionDeclarationClosingBrace" : 1,
"FunctionExpressionOpeningBrace" : 1,
"FunctionExpressionClosingBrace" : 1,
"FunctionGeneratorAsterisk": 1,
"FunctionName" : 1,
"IIFEClosingParentheses" : 0,
"IfStatementConditionalOpening" : 1,
"IfStatementConditionalClosing" : 0,
"IfStatementOpeningBrace" : 1,
"IfStatementClosingBrace" : -1,
"ModuleSpecifierClosingBrace": 1,
"ElseStatementOpeningBrace" : 1,
"ElseStatementClosingBrace" : -1,
"ElseIfStatementOpeningBrace" : 1,
"ElseIfStatementClosingBrace" : -1,
"LineComment" : 1,
"LogicalExpressionOperator" : 1,
"MemberExpressionOpening": 0,
"MemberExpressionClosing" : -1,
"MemberExpressionPeriod": 0,
"ObjectExpressionOpeningBrace": -1,
"ObjectExpressionClosingBrace": -1,
"ObjectPatternOpeningBrace": -1,
"ObjectPatternClosingBrace": -1,
"ObjectPatternComma": 0,
"Property" : -1,
"PropertyValue" : 1,
"ParameterComma" : -1,
"ParameterList" : 0,
"SwitchDiscriminantOpening" : 1,
"SwitchDiscriminantClosing" : -1,
"SwitchCaseColon": 0,
"ThrowKeyword": -1,
"TryKeyword": -1,
"TryOpeningBrace" : 1,
"TryClosingBrace" : -1,
"UnaryExpressionOperator": -1,
"VariableName" : -1,
"VariableValue" : 1,
"VariableDeclarationSemiColon" : 0,
"WhileStatementConditionalOpening" : -1,
"WhileStatementConditionalClosing" : -1,
"WhileStatementOpeningBrace" : -1,
"WhileStatementClosingBrace" : -1
},
"after" : {
"AssignmentPattern" : 1,
"ArrayExpressionOpening" : -1,
"ArrayExpressionClosing" : -1,
"ArrayExpressionComma" : 1,
"ArrayPatternOpening": 0,
"ArrayPatternClosing": 1,
"ArrayPatternComma": 1,
"ArrowFunctionExpressionArrow": 1,
"ArrowFunctionExpressionOpeningBrace": 0,
"ArrowFunctionExpressionClosingBrace": 0,
"ArgumentComma" : 1,
"ArgumentList" : 0,
"AssignmentOperator" : 1,
"BinaryExpression": -1,
"BinaryExpressionOperator" : 1,
"BlockComment" : -1,
"CallExpression" : -1,
"CallExpressionOpeningParentheses" : -1,
"CallExpressionClosingParentheses" : -1,
"CatchParameterList" : -1,
"CatchOpeningBrace" : -1,
"CatchClosingBrace" : -1,
"CatchKeyword" : -1,
"ClassDeclarationOpeningBrace" : 1,
"ClassDeclarationClosingBrace" : 1,
"CommaOperator" : 1,
"ConditionalExpressionConsequent" : 1,
"ConditionalExpressionTest" : 1,
"DoWhileStatementOpeningBrace" : -1,
"DoWhileStatementClosingBrace" : -1,
"DoWhileStatementBody" : -1,
"EmptyStatement" : -1,
"ExpressionOpeningParentheses" : 0,
"FinallyKeyword" : -1,
"FinallyOpeningBrace" : -1,
"FinallyClosingBrace" : -1,
"ForInStatement" : -1,
"ForInStatementExpressionOpening" : -1,
"ForInStatementExpressionClosing" : -1,
"ForInStatementOpeningBrace" : -1,
"ForInStatementClosingBrace" : -1,
"ForStatement" : -1,
"ForStatementExpressionOpening" : -1,
"ForStatementExpressionClosing" : -1,
"ForStatementClosingBrace" : -1,
"ForStatementOpeningBrace" : -1,
"ForStatementSemicolon" : -1,
"FunctionReservedWord": 1,
"FunctionName" : 0,
"FunctionExpressionOpeningBrace" : 1,
"FunctionExpressionClosingBrace" : -1,
"FunctionDeclarationOpeningBrace" : 1,
"FunctionDeclarationClosingBrace" : -1,
"IIFEOpeningParentheses" : 0,
"IfStatementConditionalOpening" : 0,
"IfStatementConditionalClosing" : -1,
"IfStatementOpeningBrace" : -1,
"IfStatementClosingBrace" : 1,
"ModuleSpecifierOpeningBrace": 1,
"ElseStatementOpeningBrace" : -1,
"ElseStatementClosingBrace" : -1,
"ElseIfStatementOpeningBrace" : -1,
"ElseIfStatementClosingBrace" : -1,
"MemberExpressionOpening" : -1,
"MemberExpressionClosing": 0,
"MemberExpressionPeriod": 0,
"MethodDefinitionName" : 0,
"LogicalExpressionOperator" : 1,
"ObjectExpressionOpeningBrace": -1,
"ObjectExpressionClosingBrace": -1,
"ObjectPatternOpeningBrace": -1,
"ObjectPatternClosingBrace": -1,
"ObjectPatternComma": 1,
"PropertyName" : 0,
"PropertyValue" : -1,
"ParameterComma" : 1,
"ParameterList" : 0,
"SwitchDiscriminantOpening" : -1,
"SwitchDiscriminantClosing" : 1,
"ThrowKeyword": -1,
"TryKeyword": -1,
"TryOpeningBrace" : -1,
"TryClosingBrace" : -1,
"UnaryExpressionOperator": -1,
"VariableName" : 1,
"VariableValue" : 0,
"VariableDeclarationSemiColon": -1,
"WhileStatementConditionalOpening" : -1,
"WhileStatementConditionalClosing" : -1,
"WhileStatementOpeningBrace" : -1,
"WhileStatementClosingBrace" : -1
}
},
"jsx": {
"formatJSX": true,
"attrsOnSameLineAsTag": false,
"maxAttrsOnTag": 3,
"firstAttributeOnSameLine": false,
"alignWithFirstAttribute": false,
"spaceInJSXExpressionContainers": "",
"htmlOptions": {
"brace_style": "collapse",
"indent_char": " ",
"indent_size": 2,
"max_preserve_newlines": 2,
"preserve_newlines": true
}
},
"plugins": [
"esformatter-quotes",
"esformatter-literal-notation",
"esformatter-spaced-lined-comment",
"esformatter-semicolons",
"esformatter-semicolon-first",
"esformatter-jsx"
],
"quotes": {
"type": "double",
"avoidEscape": true
}
}

View File

@ -38,7 +38,7 @@ Iosevkas default ligation set is assigned to `calt` feature, though not all o
To build Iosevka you should:
1. Ensure that [`node`](http://nodejs.org) (≥ 6.0), [`FontForge`](http://fontforge.org) (with Python scripting support, ≥ Aug. 2015 release), [`ttfautohint`](http://www.freetype.org/ttfautohint/), [`otfcc`](https://github.com/caryll/otfcc) (≥ 0.4.4) and `make` are runnable in your terminal.
1. Ensure that [`node`](http://nodejs.org) (≥ 6.0), [`ttfautohint`](http://www.freetype.org/ttfautohint/), [`otfcc`](https://github.com/caryll/otfcc) (≥ 0.4.4) and `make` are runnable in your terminal.
- Windows users may need to install MinGW and make \*nix utilities accessible (`mkdir.exe`, `cp.exe`, `cat.exe` and `rm.exe`, in particular) from Command Prompt. Utilities provided by [Git for Windows](https://git-for-windows.github.io/) works fine.
2. Install necessary libs by `npm install`. If youve installed them, upgrade to the latest.
3. `make`.

View File

@ -8,10 +8,15 @@ var parameters = require("./parameters");
var toml = require("toml");
var Glyph = require("./support/glyph");
var autoref = require("./support/autoref");
var caryllShapeOps = require("caryll-shapeops");
var c2q = require("otfcc-c2q");
function hasv(obj) {
if (!obj) return false;
for (var k in obj) if (obj[k]) return true;
for (var k in obj)
if (obj[k]) return true;
return false;
}
@ -29,7 +34,13 @@ var font = function () {
font.glyf = font.glyf.sort(function (a, b) {
var pri1 = a.cmpPriority || 0;
var pri2 = b.cmpPriority || 0;
return (pri2 !== pri1 ? pri2 - pri1 : a.contours.length !== b.contours.length ? a.contours.length - b.contours.length : (a.unicode && b.unicode && a.unicode[0] !== b.unicode[0]) ? a.unicode[0] - b.unicode[0] : (a.name < b.name) ? (-1) : (a.name > b.name) ? 1 : 0);
if (a.contours && b.contours && a.contours.length < b.contours.length) return 1;
if (a.contours && b.contours && a.contours.length > b.contours.length) return (-1);
if (a.unicode && a.unicode[0] && !b.unicode || !b.unicode[0]) return (-1);
if (b.unicode && b.unicode[0] && !a.unicode || !a.unicode[0]) return (+1);
if (a.unicode && a.unicode[0] && b.unicode && b.unicode[0] && a.unicode[0] < b.unicode[0]) return (-1);
if (a.unicode && a.unicode[0] && b.unicode && b.unicode[0] && a.unicode[0] > b.unicode[0]) return (+1);
return (a.name < b.name) ? (-1) : (a.name > b.name) ? 1 : 0;
});
return font;
}();
@ -41,7 +52,7 @@ if (argv.charmap) {
return [
glyph.name,
glyph.unicode,
glyph.advanceWidth === 0 ? hasv(glyph.anchors) ? 1 : (glyph.contours && glyph.contours.length) ? 2 : 0 : 0
glyph.advanceWidth === 0 ? (hasv(glyph.anchors) ? 1 : (glyph.contours && glyph.contours.length) ? 2 : 0) : 0
];
})), "utf8");
})();
@ -53,13 +64,16 @@ if (argv.svg) {
var foundNaN = false;
var glyfname = "";
function mix(a, b, p) { return a + (b - a) * p; }
function mix(a, b, p) {
return a + (b - a) * p;
}
function toSVGPath(glyph) {
var buf = "";
foundNaN = false;
glyfname = glyph.name;
if (glyph.contours) for (var j = 0; j < glyph.contours.length; j++) {
if (glyph.contours)
for (var j = 0; j < glyph.contours.length; j++) {
buf += Glyph.contourToSVGPath(glyph.contours[j], false);
}
return buf;
@ -103,6 +117,110 @@ if (argv.svg) {
})();
}
var StatusBar = function (message, n) {
this.message = message;
this.total = n;
this.progress = 0;
this.lastUpdate = new Date();
};
StatusBar.prototype.update = function (j) {
var j0 = this.progress;
var LEN = 25;
this.progress = j;
if (Math.round(this.progress / this.total * LEN) !== Math.round(j0 / this.total * LEN)) {
var filled = Math.round(this.progress / this.total * LEN);
var remain = LEN - filled;
var pg = Array(filled + 1).join("#") + Array(remain + 1).join(" ");
var d = new Date();
if (!remain || d - this.lastUpdate > 500) {
process.stderr.write(" [" + pg + "] " + this.message + "\n");
this.lastUpdate = d;
}
}
};
StatusBar.each = function (message, a, f) {
var bar = new StatusBar(message, a.length);
a.forEach(function (x, j) {
var r = f.apply(this, arguments);
bar.update(j + 1);
return r;
});
};
if (argv.o) {
console.log(" Writing output -> " + argv.o);
var o_glyf = {};
var cmap = {};
var skew = (argv.uprightify ? 1 : 0) * Math.tan((font.post.italicAngle || 0) / 180 * Math.PI);
// autoref
autoref(font.glyf);
// regulate
StatusBar.each("Regulate", font.glyf, (g) => {
if (g.contours) {
for (var k = 0; k < g.contours.length; k++) {
var contour = g.contours[k];
for (var p = 0; p < contour.length; p++) {
contour[p].x += contour[p].y * skew;
if (contour[p].on) {
contour[p].x = Math.round(contour[p].x);
}
}
var offJ = null, mx = null;
for (var p = 0; p < contour.length; p++) {
if (contour[p].on) {
if (offJ) {
var origx = contour[p].x;
var rx = Math.round(contour[p].x * 4) / 4;
var origx0 = mx;
var rx0 = contour[offJ - 1].x;
if (origx != origx0) {
for (var poff = offJ; poff < p; poff++) {
contour[poff].x = (contour[poff].x - origx0) / (origx - origx0) * (rx - rx0) + rx0;
}
}
}
mx = contour[p].x;
contour[p].x = Math.round(contour[p].x * 4) / 4;
offJ = p + 1;
}
}
}
var c1 = [];
for (var k = 0; k < g.contours.length; k++) {
c1.push(Glyph.contourToStandardCubic(g.contours[k]));
}
g.contours = c1;
}
});
StatusBar.each("Remove Overlap", font.glyf, (g) => {
if (g.contours) {
g.contours = caryllShapeOps.removeOverlap(g.contours, 1, 2048, true);
}
});
StatusBar.each("Finalize", font.glyf, (g) => {
if (g.contours) {
Glyph.prototype.cleanup.call(g, 0.25);
g.contours = c2q.contours(g.contours);
for (var k = 0; k < g.contours.length; k++) {
var contour = g.contours[k];
for (var p = 0; p < contour.length; p++) {
contour[p].x -= contour[p].y * skew;
}
}
}
o_glyf[g.name] = g;
if (g.unicode && g.unicode.length) {
cmap[g.unicode[0]] = g.name;
}
});
font.glyf = o_glyf;
font.cmap = cmap;
font.glyfMap = null;
fs.writeFileSync(argv.o, JSON.stringify(font));
}
if (argv.meta) {
(function () {
console.log(" Writing metadata as JSON -> " + argv.meta);

View File

@ -193,10 +193,7 @@ export : define [apply] : begin
local mt : [mix left RIGHTSB 0.5] + (st - CORRECTION_OMIDX) * STROKE
local mb : [mix left RIGHTSB 0.5] + (sb + CORRECTION_OMIDX) * STROKE
include : dispiro
widths.lhs
g4 (mt) (top - O) [heading {.y (-1) .x (-st)}]
archv
flat (left + (STROKE - fine) * HVCONTRAST) (top - SMALLSMOOTHA) [widths fine 0]
flat (left + (STROKE - fine) * HVCONTRAST) (top - SMALLSMOOTHA - 0.01) [widths fine 0]
curl (left + (STROKE - fine) * HVCONTRAST) (0 + SMALLSMOOTHB) [widths fine 0]
arcvh
g4 (mb) O [widths.heading STROKE 0 {.y (1) .x (-sb)}]
@ -204,7 +201,10 @@ export : define [apply] : begin
[if ((SMALLSMOOTHA + SMALLSMOOTHB) / top > 0.75) flat.ai flat] (RIGHTSB - OX) (0 + SMALLSMOOTHA)
[if ((SMALLSMOOTHA + SMALLSMOOTHB) / top > 0.75) curl.ai curl] (RIGHTSB - OX) (top - SMALLSMOOTHB)
arcvh
close
g4 (mt) (top - O) [widths.heading STROKE 0 {.y (-1) .x (-st)}]
archv
flat (left + (STROKE - fine) * HVCONTRAST) (top - SMALLSMOOTHA) [widths fine 0]
curl (left + (STROKE - fine) * HVCONTRAST) (top - SMALLSMOOTHA - 0.01) [widths fine 0]
define [OBarRightShape top right] : glyph-construction
include : create-glyph [OBarLeftShape top (WIDTH - [fallback right RIGHTSB])]

View File

@ -2564,11 +2564,11 @@ export : define [apply] : begin
save 'cyrtshe' 0x45B
### F
define [FShape top y] : glyph-construction
define [FShape top y noserif] : glyph-construction
include : VBarLeft (SB * 1.5) 0 [fallback top CAP]
include : HBarTop (SB * 1.5 - O) RIGHTSB [fallback top CAP]
include : HBar (SB * 1.5 - O) (RIGHTSB - [Math.max HALFSTROKE ((RIGHTSB - SB) * 0.15)] - [if SLAB (STROKE * 0.25) 0]) ([fallback top CAP] * [fallback y [if SLAB 0.52 0.54]])
if SLAB : begin
if (SLAB && !noserif) : begin
include : LeftwardTopSerif (SB * 1.5) [fallback top CAP] SIDEJUT
include : CenterBottomSerif (SB * 1.5 + HALFSTROKE * HVCONTRAST) 0 JUT
tag-contour 'serifBottom'
@ -2778,9 +2778,13 @@ export : define [apply] : begin
### E
define [EShape top] : glyph-construction
include : FShape top
include : FShape top nothing true
include : HBarBottom (SB * 1.5 - O) RIGHTSB 0
if SLAB : begin
include : LeftwardTopSerif (SB * 1.5) [fallback top CAP] SIDEJUT
include : CenterBottomSerif (SB * 1.5 + HALFSTROKE * HVCONTRAST) 0 JUT
tag-contour 'serifBottom'
include : DownwardRightSerif RIGHTSB [fallback top CAP] VJUT
include : LeftwardBottomSerif (SB * 1.5) 0 SIDEJUT
include : UpwardRightSerif RIGHTSB 0 VJUT

View File

@ -138,12 +138,20 @@ export : define [apply] : begin
sketch # six
include markset.capital
include : OShape (CAP * 0.6) 0 SB RIGHTSB
local ymiddlea : (CAP * 0.6 - SMALLSMOOTHA + SMALLSMOOTHB) / 2
local top (CAP * 0.6)
local ymiddlea : (top - SMALLSMOOTHA + SMALLSMOOTHB) / 2
local ymiddleb : (top - SMALLSMOOTHB + SMALLSMOOTHA) / 2
include : dispiro
widths.rhs
g4.up.start (SB + OX) ymiddlea
g4.up.start (SB + OX + STROKE * 0.5 * HVCONTRAST) ymiddlea [widths.heading 0 (STROKE * 0.5) UPWARD]
arcvh
g4 (MIDDLE - CORRECTION_OMIDS) (top - O) [widths.rhs]
archv
g4.down.mid (RIGHTSB - OX) ymiddleb
arcvh
g4 (MIDDLE + CORRECTION_OMIDS) (O)
archv
g4.up.mid (SB + OX) ymiddlea
quadcontrols 0 0.8
g4 ([mix SB RIGHTSB 0.85] - HALFSTROKE * HVCONTRAST) CAP
save 'six' '6'

View File

@ -11,7 +11,7 @@ PATELC = node ./node_modules/patel/bin/patel-c
GLYPH_SEGMENTS = glyphs/common-shapes.js glyphs/overmarks.js glyphs/letters-unified-basic.js glyphs/letters-unified-extended.js glyphs/numbers.js glyphs/symbol-punctuation.js glyphs/symbol-math.js glyphs/symbol-letter.js glyphs/symbol-geometric.js glyphs/symbol-other.js glyphs/symbol-braille.js glyphs/autobuilds.js buildglyphs.js
SUPPORT_FILES_FROM_PTL = support/glyph.js support/spiroexpand.js support/spirokit.js parameters.js support/anchor.js support/point.js support/transform.js support/utils.js meta/aesthetics.js meta/naming.js meta/features.js
SUPPORT_FILES_JS = generator.js emptyfont.toml parameters.toml support/fairify.js
SUPPORT_FILES_JS = generator.js emptyfont.toml parameters.toml support/fairify.js support/autoref.js
SUPPORT_FILES = $(SUPPORT_FILES_FROM_PTL) $(SUPPORT_FILES_JS)
SCRIPTS = $(SUPPORT_FILES) $(GLYPH_SEGMENTS)
SCRIPTS_FROM_PTL = $(SUPPORT_FILES_FROM_PTL) $(GLYPH_SEGMENTS)

View File

@ -58,7 +58,7 @@ fonts : $(DISTTARGETS)
svgs : $(SVG0)
# Pass 0 : file construction
OUTPUTS = --meta $@ --svg $(subst .fdt,.svg,$@)
OUTPUTS = -o $@
OUTPUT_CM = $(if $(NOCHARMAP),,--charmap $(subst .fdt,.charmap,$(subst $(OBJDIR)/.pass0-,$(OBJDIR)/,$@)))
$(OBJDIR)/.pass0-$(PREFIX)-thin.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-thin s-upright $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS)
@ -111,14 +111,14 @@ $(MAPS) : $(OBJDIR)/%.charmap : $(OBJDIR)/.pass0-%.fdt
$(PASS)
# Pass 1 : Outline cleanup and merge features
$(PASS1) : $(OBJDIR)/.pass1-%.ttf : pass1-cleanup.py $(OBJDIR)/.pass0-%.svg
@echo Fontforge $< --> $@
@fontforge -quiet -script $^ $@.a.ttf $(if $(findstring italic,$@),10,$(if $(findstring oblique,$@),10,0)) $(_DONTREF) $(SUPPRESS_ERRORS)
@$(HINT) $@.a.ttf $@
@-rm $@.a.ttf
$(TARGETS) : $(OBJDIR)/%.ttf : $(OBJDIR)/.pass0-%.fdt
@otfccbuild $< -o $@.a.ttf
@$(HINT) $@.a.ttf $@.b.ttf
@otfccdump $@.b.ttf | otfccbuild -O3 -s -o $@
@-rm $@.a.ttf $@.b.ttf
# Pass 2 : add metadata
$(TARGETS) : $(OBJDIR)/%.ttf : pass2-finalize.js $(OBJDIR)/.pass1-%.ttf $(OBJDIR)/.pass0-%.fdt
@otfccdump $(word 2,$^) | $(NODE) $< $(word 3,$^) | otfccbuild -s -O3 -o $@ --keep-average-char-width $(HINT_SUFFIX)
#$(TARGETS) : $(OBJDIR)/%.ttf : pass2-finalize.js $(OBJDIR)/.pass1-%.ttf $(OBJDIR)/.pass0-%.fdt
# @otfccdump $(word 2,$^) | $(NODE) $< $(word 3,$^) | otfccbuild -s -O3 -o $@ --keep-average-char-width $(HINT_SUFFIX)
$(DISTTARGETS) : $(DISTDIR)/%.ttf : $(OBJDIR)/%.ttf
@cp $< $@

View File

@ -5,6 +5,8 @@
"dependencies": {
"bezier-js": "^2.0.0",
"cubic2quad": "^1.0.0",
"otfcc-c2q": "^0.5.0",
"caryll-shapeops": "^0.2.0",
"libspiro-js": ">=0.3.0",
"patel": ">=0.32.0",
"toml": ">=2.3.0",

99
support/autoref.js Normal file
View File

@ -0,0 +1,99 @@
var Point = require("./point");
function delta(a, b) {
return Math.round((a - b) * 32);
}
function contourHash(c) {
if (!c || c.length < 2) return ".";
var lx = c[0].x, ly = c[0].y;
var buf = "";
for (var j = 1; j < c.length; j++) {
var z = c[j];
buf += `${z.on ? 'o':'f'}${z.cubic?'c':'q'}${delta(z.x, lx)},${delta(z.y, ly)};`;
lx = z.x, ly = z.y;
}
return buf;
}
function match(g1, g2, _n) {
for (let j = 0; j + g1.contours.length <= g2.contours.length; j++) {
var found = true;
for (var k = j; k < g2.contours.length && k - j < g1.contours.length; k++) {
if (g1.contours[k - j].hash !== g2.contours[k].hash
|| !(k <= j || delta(g1.contours[k - j][0].x, g1.contours[k - j - 1][0].x) === delta(g2.contours[k][0].x, g2.contours[k - 1][0].x)
&& delta(g1.contours[k - j][0].y, g1.contours[k - j - 1][0].y) === delta(g2.contours[k][0].y, g2.contours[k - 1][0].y))) {
found = false;
break;
}
}
if (found) {
if (!g2.references) g2.references = [];
g2.references.push({
glyph: g1.name,
_n: _n,
x: g2.contours[j][0].x - g1.contours[0][0].x,
y: g2.contours[j][0].y - g1.contours[0][0].y
});
g2.contours.splice(j, g1.contours.length);
return true;
}
}
return false;
}
function unlinkRef(g, dx, dy, glyf) {
var cntrs = g.contours.map(c => c.map(z => new Point(z.x + dx, z.y + dy, z.on, z.cubic)));
if (g.references)
for (let r of g.references) {
cntrs = cntrs.concat(unlinkRef(glyf[r._n], r.x + dx, r.y + dy, glyf));
}
return cntrs;
}
function autoref(glyf) {
for (var j = 0; j < glyf.length; j++) {
var g = glyf[j];
if (g.contours) {
for (var k = 0; k < g.contours.length; k++) {
var contour = g.contours[k];
contour.hash = contourHash(contour);
}
}
}
// Refl-referencify, forward.
for (var j = 0; j < glyf.length; j++) {
if (!glyf[j].contours.length || glyf[j].references && glyf[j].references.length) continue;
for (var k = j + 1; k < glyf.length; k++) {
if (glyf[j].contours.length === glyf[k].contours.length) {
if (match(glyf[j], glyf[k], j)) {
// console.log("Refl", glyf[j].name, glyf[j].unicode, "->", glyf[k].name, glyf[k].unicode);
}
}
}
}
// referencify, backward
for (var j = 0; j < glyf.length; j++) {
if (glyf[j].cmpPriority < 0 || !glyf[j].contours.length || glyf[j].references && glyf[j].references.length) continue;
for (var k = j - 1; k >= 0; k--) {
if (glyf[j].contours.length > glyf[k].contours.length) continue;
while(match(glyf[j], glyf[k], j)){
// console.log("Part", glyf[j].name, "->", glyf[k].name);
}
}
}
// unlink composite
for (var j = 0; j < glyf.length; j++) {
if (glyf[j].contours.length === 0 || !glyf[j].references || glyf[j].references.length === 0) continue;
// console.log("Unlink", glyf[j].name);
var cs = unlinkRef(glyf[j], 0, 0, glyf);
glyf[j].contours = g.contours.concat(cs);
glyf[j].references = [];
}
}
module.exports = autoref;

View File

@ -122,9 +122,9 @@ function splitAtExtrema(z1, z2, z3, z4, angles, splitpoints) {
var t2 = ts[k];
var bef = splitBefore(z1, z2, z3, z4, t2);
var seg = splitAfter(bef[0], bef[1], bef[2], bef[3], t1 / t2);
seg[1].onCurve = seg[2].onCurve = false;
seg[1].on = seg[2].on = false;
seg[1].cubic = seg[2].cubic = true;
seg[3].onCurve = true;
seg[3].on = true;
splitpoints.push(seg[1], seg[2], seg[3]);
}
}
@ -211,7 +211,7 @@ function fairify(scurve, gizmo, denseQ, cleanMore) {
var splitpoints = [scurve[0]];
var last = scurve[0];
for (var j = 1; j < scurve.length; j++) {
if (scurve[j].onCurve) {
if (scurve[j].on) {
splitpoints.push(last = scurve[j]);
} else if (scurve[j].cubic) {
var z1 = last,
@ -238,13 +238,13 @@ function fairify(scurve, gizmo, denseQ, cleanMore) {
}
// Mark corners and extrema
for (var j = 1; j < splitpoints.length - 1; j++) {
if (splitpoints[j].onCurve && !splitpoints[j - 1].onCurve) {
if (splitpoints[j].on && !splitpoints[j - 1].on) {
splitpoints[j].prev = splitpoints[j - 1];
}
if (splitpoints[j].onCurve && !splitpoints[j + 1].onCurve) {
if (splitpoints[j].on && !splitpoints[j + 1].on) {
splitpoints[j].next = splitpoints[j + 1];
}
if (splitpoints[j].onCurve && !splitpoints[j - 1].onCurve && !splitpoints[j + 1].onCurve) {
if (splitpoints[j].on && !splitpoints[j - 1].on && !splitpoints[j + 1].on) {
var z1 = splitpoints[j],
z0 = splitpoints[j - 1],
z2 = splitpoints[j + 1];
@ -272,7 +272,7 @@ function fairify(scurve, gizmo, denseQ, cleanMore) {
} else {
z1.mark = true; // also corner
}
} else if (splitpoints[j].onCurve) {
} else if (splitpoints[j].on) {
splitpoints[j].mark = true; // corner
}
}
@ -312,7 +312,7 @@ function fairify(scurve, gizmo, denseQ, cleanMore) {
nextmark = splitpoints[k];
segments = estimateSegments(lastmark, nextmark);
}
if (splitpoints[j].onCurve && !splitpoints[j].mark) {
if (splitpoints[j].on && !splitpoints[j].mark) {
var z1 = splitpoints[j],
z0 = splitpoints[j - 1],
z2 = splitpoints[j + 1];
@ -327,12 +327,12 @@ function fairify(scurve, gizmo, denseQ, cleanMore) {
}
}
// Rebuild curve
for (var j = 0; j < splitpoints.length; j++) if (splitpoints[j].onCurve && !splitpoints[j].remove && splitpoints[j + 1] && !splitpoints[j + 1].onCurve) {
for (var j = 0; j < splitpoints.length; j++) if (splitpoints[j].on && !splitpoints[j].remove && splitpoints[j + 1] && !splitpoints[j + 1].on) {
for (var k = j + 2; k < splitpoints.length && splitpoints[k].remove; k++);
if (k - j > 2) {
var zs = fitpts(splitpoints[j], splitpoints[j + 1], splitpoints[k], splitpoints[k + 1]);
if (zs) {
zs[0].onCurve = zs[1].onCurve = false;
zs[0].on = zs[1].on = false;
zs[0].cubic = zs[1].cubic = true;
splitpoints[j + 1] = zs[0];
splitpoints[k] = zs[1];

View File

@ -25,7 +25,7 @@ define [closepoint p q t] : begin
define [oncurveRemovable a b c t] : begin
local xm : (a.x + c.x) / 2
local ym : (a.y + c.y) / 2
return : [not a.onCurve] && b.onCurve && [not c.onCurve] && [not a.cubic] && [not c.cubic] && (a.x <= b.x && b.x <= c.x || a.x >= b.x && b.x >= c.x) && (a.y <= b.y && b.y <= c.y || a.y >= b.y && b.y >= c.y) && [Math.abs (b.x - xm)] <= (t / 2) && [Math.abs (b.y - ym)] <= (t / 2)
return : [not a.on] && b.on && [not c.on] && [not a.cubic] && [not c.cubic] && (a.x <= b.x && b.x <= c.x || a.x >= b.x && b.x >= c.x) && (a.y <= b.y && b.y <= c.y || a.y >= b.y && b.y >= c.y) && [Math.abs (b.x - xm)] <= (t / 2) && [Math.abs (b.y - ym)] <= (t / 2)
define PRECISION 1000
define [cov x] : piecewise
@ -154,7 +154,7 @@ export all : class Glyph
local c {}
set c.tag : contour.tag || component.tag || t.defaultTag
foreach [point : items-of contour] : begin
c.push : new Point (point.x + shiftx) (point.y + shifty) point.onCurve point.cubic point.subdivided
c.push : new Point (point.x + shiftx) (point.y + shifty) point.on point.cubic point.subdivided
newcontours.push c
set this.contours : this.contours.concat newcontours
if (([not contours] || copyAnchors) && glyph.anchors) : begin
@ -187,7 +187,7 @@ export all : class Glyph
for [local j 1] (j < contour.length) [inc j] : begin
local point contour.(j)
piecewise
point.onCurve : begin
point.on : begin
if delta
: then : set buf : buf + "l \[cov : point.x - lx] \[cov : point.y - ly]"
: else : set buf : buf + "L \[cov point.x] \[cov point.y]"
@ -215,16 +215,52 @@ export all : class Glyph
inc j
set buf : buf + " Z\n"
return buf
static [contourToStandardCubic contour] : begin
local c {}
if (!contour || !contour.length) : return c
local lx contour.0.x
local ly contour.0.y
c.push {.x lx .y ly .on true}
for [local j 1] (j < contour.length) [inc j] : begin
local point contour.(j)
piecewise
point.on : begin
c.push {.x point.x .y point.y .on true}
set {.x lx .y ly} point
point.cubic : begin
local z1 point
local z2 contour.(j + 1)
local z3 contour.(j + 2)
c.push {.x z1.x .y z1.y .on false}
c.push {.x z2.x .y z2.y .on false}
c.push {.x z3.x .y z3.y .on true}
set {.x lx .y ly} z3
set j : j + 2
true : begin
local zc point
local zf : if contour.(j + 1) contour.(j + 1) contour.0
local x1 : mix lx zc.x (2 / 3)
local y1 : mix ly zc.y (2 / 3)
local x2 : mix zf.x zc.x (2 / 3)
local y2 : mix zf.y zc.y (2 / 3)
c.push {.x x1 .y y1 .on false}
c.push {.x x2 .y y2 .on false}
c.push {.x zf.x .y zf.y .on true}
set {.x lx .y ly} zf
inc j
return c
public [cleanup t] : begin
foreach c [range 0 this.contours.length] : begin
local ocontour this.contours.(c)
# add infections
local contour {[new Point ocontour.0.x ocontour.0.y ocontour.0.onCurve]}
local contour {[new Point ocontour.0.x ocontour.0.y ocontour.0.on]}
local flag 0
foreach [j : range 1 (ocontour.length - 1)] : piecewise
flag : dec flag
ocontour.(j).onCurve : contour.push ocontour.(j)
ocontour.(j).on : contour.push ocontour.(j)
ocontour.(j).cubic : begin
local p0 contour.(contour.length - 1)
local p1 ocontour.(j)
@ -249,7 +285,7 @@ export all : class Glyph
local p0 contour.(contour.length - 1)
local p1 ocontour.(j)
local p2 ocontour.(j + 1)
if [not p2.onCurve] : set p2 : new Point [mix p1.x p2.x 0.5] [mix p1.y p2.y 0.5] true
if [not p2.on] : set p2 : new Point [mix p1.x p2.x 0.5] [mix p1.y p2.y 0.5] true
local strand : new Bezier p0.x p0.y p1.x p1.y p2.x p2.y
local ts [strand.extrema].y
piecewise
@ -265,7 +301,7 @@ export all : class Glyph
new Point s.points.2.x s.points.2.y true
set flag 1
contour.push [new Point ocontour.(ocontour.length - 1).x ocontour.(ocontour.length - 1).y ocontour.(ocontour.length - 1).onCurve]
contour.push [new Point ocontour.(ocontour.length - 1).x ocontour.(ocontour.length - 1).y ocontour.(ocontour.length - 1).on]
# cleanup
local cleanedContour {}
@ -296,7 +332,7 @@ export all : class Glyph
set contour.(k + 2).unimportant true
set k : k + 2
if found : begin
set contour.(j).onCurve true
set contour.(j).on true
set j (k - 1)
foreach point [items-of contour] : if [not point.unimportant] : cleanedContour.push point
this.contours.(c) = cleanedContour

View File

@ -1,14 +1,14 @@
export all : class Point
public [new x y onCurve cubic subdivided] : begin
public [new x y on cubic subdivided] : begin
this.x = x
this.y = y
this.onCurve = onCurve || false
this.on = on || false
this.subdivided = subdivided || false
this.cubic = cubic || false
static [transformed tfm x y onCurve cubic subdivided] : new Point
static [transformed tfm x y on cubic subdivided] : new Point
* x * tfm.xx + y * tfm.yx + tfm.x
* x * tfm.xy + y * tfm.yy + tfm.y
* onCurve
* on
* cubic
* subdivided

View File

@ -14,7 +14,7 @@ export all : class Transform
static [transformPoint tfm pt] : new Point
* pt.x * tfm.xx + pt.y * tfm.yx + tfm.x
* pt.x * tfm.xy + pt.y * tfm.yy + tfm.y
* pt.onCurve
* pt.on
* pt.cubic
* pt.subdivided
static [inverse tfm] : begin
@ -31,6 +31,6 @@ export all : class Transform
return : new Point
* (xx * tfm.yy - yy * tfm.yx) / denom
* (yy * tfm.xx - xx * tfm.xy) / denom
* pt.onCurve
* pt.on
* pt.cubic
* pt.subdivided