add variant for 1
This commit is contained in:
parent
bf2aecee9d
commit
6f344b626d
4 changed files with 126 additions and 119 deletions
210
generator.js
210
generator.js
|
@ -1,22 +1,22 @@
|
||||||
var fs = require("fs");
|
let fs = require("fs");
|
||||||
var path = require("path");
|
let path = require("path");
|
||||||
|
|
||||||
// var TTFWriter = require('node-sfnt').TTFWriter;
|
// let TTFWriter = require('node-sfnt').TTFWriter;
|
||||||
var argv = require("yargs").argv;
|
let argv = require("yargs").argv;
|
||||||
var buildGlyphs = require("./buildglyphs.js");
|
let buildGlyphs = require("./buildglyphs.js");
|
||||||
var parameters = require("./support/parameters");
|
let parameters = require("./support/parameters");
|
||||||
var toml = require("toml");
|
let toml = require("toml");
|
||||||
|
|
||||||
var Glyph = require("./support/glyph");
|
let Glyph = require("./support/glyph");
|
||||||
var autoref = require("./support/autoref");
|
let autoref = require("./support/autoref");
|
||||||
const objectAssign = require("object-assign");
|
const objectAssign = require("object-assign");
|
||||||
|
|
||||||
var caryllShapeOps = require("caryll-shapeops");
|
let caryllShapeOps = require("caryll-shapeops");
|
||||||
var c2q = require("megaminx").geometry.c2q;
|
let c2q = require("megaminx").geometry.c2q;
|
||||||
|
|
||||||
function hasv(obj) {
|
function hasv(obj) {
|
||||||
if (!obj) return false;
|
if (!obj) return false;
|
||||||
for (var k in obj) if (obj[k]) return true;
|
for (let k in obj) if (obj[k]) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,8 +70,25 @@ function formVariantData(data, para) {
|
||||||
return vs;
|
return vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Font building
|
function byGlyphPriority(a, b) {
|
||||||
const font = (function() {
|
const pri1 = a.cmpPriority || 0;
|
||||||
|
const pri2 = b.cmpPriority || 0;
|
||||||
|
if (pri1 > pri2) return -1;
|
||||||
|
if (pri1 < pri2) return 1;
|
||||||
|
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.advanceWidth < b.advanceWidth) return -1;
|
||||||
|
if (a.advanceWidth > b.advanceWidth) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParameters(argv) {
|
||||||
const parametersData = Object.assign(
|
const parametersData = Object.assign(
|
||||||
{},
|
{},
|
||||||
toml.parse(fs.readFileSync(path.join(__dirname, "parameters.toml"), "utf-8")),
|
toml.parse(fs.readFileSync(path.join(__dirname, "parameters.toml"), "utf-8")),
|
||||||
|
@ -80,7 +97,6 @@ const font = (function() {
|
||||||
: []
|
: []
|
||||||
);
|
);
|
||||||
const variantData = toml.parse(fs.readFileSync(path.join(__dirname, "variants.toml"), "utf-8"));
|
const variantData = toml.parse(fs.readFileSync(path.join(__dirname, "variants.toml"), "utf-8"));
|
||||||
const emptyFont = toml.parse(fs.readFileSync(path.join(__dirname, "emptyfont.toml"), "utf-8"));
|
|
||||||
|
|
||||||
const para = parameters.build(parametersData, argv._);
|
const para = parameters.build(parametersData, argv._);
|
||||||
const vsdata = formVariantData(variantData, para);
|
const vsdata = formVariantData(variantData, para);
|
||||||
|
@ -88,9 +104,13 @@ const font = (function() {
|
||||||
para.variantSelector = parameters.build(vsdata, argv._);
|
para.variantSelector = parameters.build(vsdata, argv._);
|
||||||
para.defaultVariant = vsdata.default;
|
para.defaultVariant = vsdata.default;
|
||||||
if (argv.family) para.family = argv.family;
|
if (argv.family) para.family = argv.family;
|
||||||
const fontUniqueName =
|
return para;
|
||||||
para.family + " " + para.style + " " + para.version + " (" + para.codename + ")";
|
}
|
||||||
|
|
||||||
|
// Font building
|
||||||
|
const font = (function() {
|
||||||
|
const emptyFont = toml.parse(fs.readFileSync(path.join(__dirname, "emptyfont.toml"), "utf-8"));
|
||||||
|
const para = getParameters(argv);
|
||||||
const font = buildGlyphs.build.call(emptyFont, para);
|
const font = buildGlyphs.build.call(emptyFont, para);
|
||||||
|
|
||||||
font.parameters = para;
|
font.parameters = para;
|
||||||
|
@ -99,83 +119,46 @@ const font = (function() {
|
||||||
g.gord = j;
|
g.gord = j;
|
||||||
return g;
|
return g;
|
||||||
})
|
})
|
||||||
.sort(function(a, b) {
|
.sort(byGlyphPriority);
|
||||||
const pri1 = a.cmpPriority || 0;
|
|
||||||
const pri2 = b.cmpPriority || 0;
|
|
||||||
if (pri1 > pri2) return -1;
|
|
||||||
if (pri1 < pri2) return 1;
|
|
||||||
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.advanceWidth < b.advanceWidth) return -1;
|
|
||||||
if (a.advanceWidth > b.advanceWidth) 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;
|
return font;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
if (argv.charmap) {
|
if (argv.charmap) {
|
||||||
fs.writeFileSync(
|
const charmap = font.glyf.map(function(glyph) {
|
||||||
argv.charmap,
|
return [
|
||||||
JSON.stringify(
|
glyph.name,
|
||||||
font.glyf.map(function(glyph) {
|
glyph.unicode,
|
||||||
return [
|
glyph.advanceWidth === 0
|
||||||
glyph.name,
|
? hasv(glyph.anchors) ? 1 : glyph.contours && glyph.contours.length ? 2 : 0
|
||||||
glyph.unicode,
|
: 0
|
||||||
glyph.advanceWidth === 0
|
];
|
||||||
? hasv(glyph.anchors) ? 1 : glyph.contours && glyph.contours.length ? 2 : 0
|
});
|
||||||
: 0
|
fs.writeFileSync(argv.charmap, JSON.stringify(charmap), "utf8");
|
||||||
];
|
|
||||||
})
|
|
||||||
),
|
|
||||||
"utf8"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv.o) {
|
if (argv.o) {
|
||||||
var o_glyf = {};
|
function regulateGlyph(g, skew) {
|
||||||
var cmap = {};
|
|
||||||
var skew = (argv.uprightify ? 1 : 0) * Math.tan((font.post.italicAngle || 0) / 180 * Math.PI);
|
|
||||||
// autoref
|
|
||||||
autoref(font.glyf);
|
|
||||||
// regulate
|
|
||||||
font.glyf.forEach(g => {
|
|
||||||
if (!g.contours) return;
|
if (!g.contours) return;
|
||||||
for (var k = 0; k < g.contours.length; k++) {
|
|
||||||
var contour = g.contours[k];
|
// Regulate
|
||||||
for (var p = 0; p < contour.length; p++) {
|
for (let k = 0; k < g.contours.length; k++) {
|
||||||
|
const contour = g.contours[k];
|
||||||
|
for (let p = 0; p < contour.length; p++) {
|
||||||
contour[p].x += contour[p].y * skew;
|
contour[p].x += contour[p].y * skew;
|
||||||
if (!contour[p].on) continue;
|
if (!contour[p].on) continue;
|
||||||
contour[p].x = Math.round(contour[p].x);
|
contour[p].x = Math.round(contour[p].x);
|
||||||
}
|
}
|
||||||
var offJ = null,
|
let offJ = null,
|
||||||
mx = null;
|
mx = null;
|
||||||
for (var p = 0; p < contour.length; p++) {
|
for (let p = 0; p < contour.length; p++) {
|
||||||
if (!contour[p].on) continue;
|
if (!contour[p].on) continue;
|
||||||
if (offJ) {
|
if (offJ) {
|
||||||
var origx = contour[p].x;
|
const origx = contour[p].x;
|
||||||
var rx = Math.round(contour[p].x * 4) / 4;
|
const rx = Math.round(contour[p].x * 4) / 4;
|
||||||
var origx0 = mx;
|
const origx0 = mx;
|
||||||
var rx0 = contour[offJ - 1].x;
|
const rx0 = contour[offJ - 1].x;
|
||||||
if (origx === origx0) continue;
|
if (origx === origx0) continue;
|
||||||
for (var poff = offJ; poff < p; poff++) {
|
for (let poff = offJ; poff < p; poff++) {
|
||||||
contour[poff].x =
|
contour[poff].x =
|
||||||
(contour[poff].x - origx0) / (origx - origx0) * (rx - rx0) + rx0;
|
(contour[poff].x - origx0) / (origx - origx0) * (rx - rx0) + rx0;
|
||||||
}
|
}
|
||||||
|
@ -185,44 +168,51 @@ if (argv.o) {
|
||||||
offJ = p + 1;
|
offJ = p + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var c1 = [];
|
const c1 = [];
|
||||||
for (var k = 0; k < g.contours.length; k++) {
|
for (let k = 0; k < g.contours.length; k++) {
|
||||||
c1.push(Glyph.contourToStandardCubic(g.contours[k]));
|
c1.push(Glyph.contourToStandardCubic(g.contours[k]));
|
||||||
}
|
}
|
||||||
g.contours = c1;
|
|
||||||
});
|
// De-overlap
|
||||||
// overlap removal
|
g.contours = caryllShapeOps.removeOverlap(c1, 1, 256, true);
|
||||||
font.glyf.forEach(g => {
|
|
||||||
if (g.contours) {
|
// Finalize
|
||||||
g.contours = caryllShapeOps.removeOverlap(g.contours, 1, 256, true);
|
Glyph.prototype.cleanup.call(g, 0.1);
|
||||||
}
|
g.contours = c2q.contours(g.contours);
|
||||||
});
|
for (let k = 0; k < g.contours.length; k++) {
|
||||||
// reorder
|
const contour = g.contours[k];
|
||||||
font.glyf = font.glyf.sort((a, b) => a.gord - b.gord);
|
for (let p = 0; p < contour.length; p++) {
|
||||||
// finalize
|
contour[p].x -= contour[p].y * skew;
|
||||||
font.glyf.forEach(g => {
|
|
||||||
if (g.contours) {
|
|
||||||
Glyph.prototype.cleanup.call(g, 0.1);
|
|
||||||
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;
|
const skew = (argv.uprightify ? 1 : 0) * Math.tan((font.post.italicAngle || 0) / 180 * Math.PI);
|
||||||
font.cmap = cmap;
|
// autoref
|
||||||
font.glyfMap = null;
|
autoref(font.glyf);
|
||||||
|
// regulate
|
||||||
|
for (let g of font.glyf) regulateGlyph(g, skew);
|
||||||
|
|
||||||
|
// reorder
|
||||||
|
font.glyf = font.glyf.sort((a, b) => a.gord - b.gord);
|
||||||
|
|
||||||
|
// finalize
|
||||||
|
const o_glyf = {};
|
||||||
|
const o_cmap = {};
|
||||||
|
for (let g of font.glyf) {
|
||||||
|
o_glyf[g.name] = g;
|
||||||
|
if (!g.unicode) continue;
|
||||||
|
for (let u of g.unicode) o_cmap[u] = g.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare OTD
|
||||||
|
const otd = Object.assign({}, font);
|
||||||
|
otd.glyf = o_glyf;
|
||||||
|
otd.cmap = o_cmap;
|
||||||
|
otd.glyfMap = null;
|
||||||
if (argv.o === "|") {
|
if (argv.o === "|") {
|
||||||
process.stdout.write(JSON.stringify(font));
|
process.stdout.write(JSON.stringify(otd));
|
||||||
} else {
|
} else {
|
||||||
fs.writeFileSync(argv.o, JSON.stringify(font));
|
fs.writeFileSync(argv.o, JSON.stringify(otd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,16 +30,20 @@ export : define [apply] : begin
|
||||||
|
|
||||||
select-variant 'zero' '0'
|
select-variant 'zero' '0'
|
||||||
|
|
||||||
sketch # one
|
sketch # one.hooky
|
||||||
include markset.capital
|
include markset.capital
|
||||||
include : VBar (MIDDLE + ONEBALANCE) 0 CAP
|
include : VBar (MIDDLE + ONEBALANCE) 0 CAP
|
||||||
include : dispiro
|
include : dispiro
|
||||||
flat (MIDDLE - HALFSTROKE * HVCONTRAST + ONEBALANCE) CAP [widths STROKE 0]
|
flat (MIDDLE - HALFSTROKE * HVCONTRAST + ONEBALANCE) CAP [widths STROKE 0]
|
||||||
curl (MIDDLE - HOOKX * 1.25 + ONEBALANCE) (CAP - HOOK * 0.75)
|
curl (MIDDLE - HOOKX * 1.25 + ONEBALANCE) (CAP - HOOK * 0.75)
|
||||||
|
save 'one.hooky'
|
||||||
|
|
||||||
if SLAB : begin
|
sketch # one.serifed
|
||||||
include : CenterBottomSerif (MIDDLE + ONEBALANCE) 0 LONGJUT
|
include glyphs.'one.hooky' AS_BASE
|
||||||
save 'one' '1'
|
include : CenterBottomSerif (MIDDLE + ONEBALANCE) 0 LONGJUT
|
||||||
|
save 'one.serifed'
|
||||||
|
|
||||||
|
select-variant 'one' '1'
|
||||||
|
|
||||||
sketch # two
|
sketch # two
|
||||||
include markset.capital
|
include markset.capital
|
||||||
|
|
|
@ -118,11 +118,12 @@ define [buildGSUB para glyphList markGlyphs] : begin
|
||||||
commonList.push feature
|
commonList.push feature
|
||||||
set lookups.(feature).subtables.0.(glyph.name) fs.(feature)
|
set lookups.(feature).subtables.0.(glyph.name) fs.(feature)
|
||||||
# ssxx
|
# ssxx
|
||||||
foreach [{name composition} : pairs-of para.variants] : if (name.length === 4 && composition.__isComposite) : begin
|
foreach [{name composition} : pairs-of para.variants] : begin
|
||||||
commonList.push name
|
if (name.length === 4 && composition.__isComposite && [name.slice 0 2] === 'ss') : begin
|
||||||
local tags {.}
|
commonList.push name
|
||||||
foreach [{ch tag} : pairs-of composition.__cvmap] : set tags.(tag) true
|
local tags {.}
|
||||||
set features.(name) : [Object.keys tags].filter (tag => tags.(tag))
|
foreach [{ch tag} : pairs-of composition.__cvmap] : set tags.(tag) true
|
||||||
|
set features.(name) : [Object.keys tags].filter (tag => tags.(tag))
|
||||||
|
|
||||||
set languages.'cyrl_SRB ' {.features [{'locl_srb'}.concat commonList]}
|
set languages.'cyrl_SRB ' {.features [{'locl_srb'}.concat commonList]}
|
||||||
set languages.'cyrl_MKD ' {.features [{'locl_srb'}.concat commonList]}
|
set languages.'cyrl_MKD ' {.features [{'locl_srb'}.concat commonList]}
|
||||||
|
|
|
@ -199,6 +199,14 @@ tag = "cv48"
|
||||||
y = "curly"
|
y = "curly"
|
||||||
tag = "cv49"
|
tag = "cv49"
|
||||||
|
|
||||||
|
[simple.v-one-hooky]
|
||||||
|
one = "hooky"
|
||||||
|
tag = "cv50"
|
||||||
|
|
||||||
|
[simple.v-one-serifed]
|
||||||
|
one = "serifed"
|
||||||
|
tag = "cv51"
|
||||||
|
|
||||||
[simple.others]
|
[simple.others]
|
||||||
I = 'serifed'
|
I = 'serifed'
|
||||||
J = 'serifed'
|
J = 'serifed'
|
||||||
|
@ -221,6 +229,7 @@ design = [
|
||||||
'v-dollar-through',
|
'v-dollar-through',
|
||||||
'v-numbersign-upright',
|
'v-numbersign-upright',
|
||||||
'v-three-twoarcs',
|
'v-three-twoarcs',
|
||||||
|
'v-one-hooky',
|
||||||
'others'
|
'others'
|
||||||
]
|
]
|
||||||
upright = [
|
upright = [
|
||||||
|
@ -238,6 +247,9 @@ italic = [
|
||||||
'v-y-curly'
|
'v-y-curly'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[composite.slab]
|
||||||
|
design = ['v-one-serifed']
|
||||||
|
|
||||||
# Composite character options, overrides default settings above.
|
# Composite character options, overrides default settings above.
|
||||||
# Andale Mono Style
|
# Andale Mono Style
|
||||||
[composite.ss01]
|
[composite.ss01]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue