Fix compatibility ligature building (#524).
This commit is contained in:
parent
8d7a304b96
commit
6b319855e4
9 changed files with 354 additions and 251 deletions
89
README.md
89
README.md
|
@ -72,12 +72,15 @@ Since version 2.0, Iosevka would no longer support building via `makefile`. To i
|
||||||
2. Add a build plan into `private-build-plans.toml`, following this format:
|
2. Add a build plan into `private-build-plans.toml`, following this format:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[buildPlans.iosevka-custom] # <iosevka-custom> is your plan name
|
[buildPlans.iosevka-custom] # <iosevka-custom> is your plan name
|
||||||
family = "Iosevka Custom" # Font menu family name
|
family = "Iosevka Custom" # Font menu family name
|
||||||
design = ["leading-1500", "v-i-hooky", "v-l-hooky"] # Customize styles
|
design = ["v-i-hooky", "v-l-hooky"] # Customize styles
|
||||||
hintParams = ["-a", "sss"] # Optional custom parameters for ttfautohint
|
# upright = ["upright-styles"] # Uncomment this line to set styles for upright only
|
||||||
|
# italic = ["italic-styles"] # Uncomment this line to set styles for italic only
|
||||||
|
# oblique = ["oblique-styles"] # Uncomment this line to set styles for oblique only
|
||||||
|
hintParams = ["-a", "sss"] # Optional custom parameters for ttfautohint
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
# Override default building weights
|
# Override default building weights
|
||||||
# When buildPlans.<plan name>.weights is absent, all weights would built and mapped to
|
# When buildPlans.<plan name>.weights is absent, all weights would built and mapped to
|
||||||
# default values.
|
# default values.
|
||||||
|
@ -99,19 +102,24 @@ Since version 2.0, Iosevka would no longer support building via `makefile`. To i
|
||||||
shape = 700
|
shape = 700
|
||||||
menu = 700
|
menu = 700
|
||||||
css = 700
|
css = 700
|
||||||
|
|
||||||
# End weight section
|
# End weight section
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
# Override default building slant sets
|
# Override default building slant sets
|
||||||
# Format: <upright|italic|oblique> = <"normal"|"italic"|"oblique">
|
# Format: <upright|italic|oblique> = <"normal"|"italic"|"oblique">
|
||||||
# When this section is absent, all slants would be built.
|
# When this section is absent, all slants would be built.
|
||||||
|
|
||||||
[buildPlans.iosevka-custom.slants]
|
[buildPlans.iosevka-custom.slants]
|
||||||
upright = "normal"
|
upright = "normal"
|
||||||
italic = "italic"
|
italic = "italic"
|
||||||
oblique = "oblique"
|
oblique = "oblique"
|
||||||
# End slant section
|
|
||||||
|
|
||||||
|
|
||||||
|
# End slant section
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
# Override default building widths
|
# Override default building widths
|
||||||
# When buildPlans.<plan name>.widths is absent, all widths would built and mapped to
|
# When buildPlans.<plan name>.widths is absent, all widths would built and mapped to
|
||||||
# default values.
|
# default values.
|
||||||
|
@ -119,17 +127,62 @@ Since version 2.0, Iosevka would no longer support building via `makefile`. To i
|
||||||
# support 1, 2, 3, 4, 5, 6, 7, 8, 9.
|
# support 1, 2, 3, 4, 5, 6, 7, 8, 9.
|
||||||
# If you decide to use custom weights you have to define all the weights you
|
# If you decide to use custom weights you have to define all the weights you
|
||||||
# plan to use otherwise they will not be built.
|
# plan to use otherwise they will not be built.
|
||||||
|
|
||||||
[buildPlans.iosevka-custom.widths.normal]
|
[buildPlans.iosevka-custom.widths.normal]
|
||||||
shape = 5 # Width of glyph shapes.
|
shape = 5 # Width of glyph shapes.
|
||||||
menu = 5 # Width for the font's names.
|
menu = 5 # Width for the font's names.
|
||||||
css = "normal" # "font-stretch' property of webfont CSS.
|
css = "normal" # "font-stretch' property of webfont CSS.
|
||||||
|
|
||||||
|
|
||||||
[buildPlans.iosevka-custom.widths.extended]
|
[buildPlans.iosevka-custom.widths.extended]
|
||||||
shape = 7
|
shape = 7
|
||||||
menu = 7
|
menu = 7
|
||||||
css = "expanded"
|
css = "expanded"
|
||||||
|
|
||||||
# End width section
|
# End width section
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
# Character Exclusion
|
||||||
|
# Specify character ranges in the section below to exclude certain characters from the font being
|
||||||
|
# built. Remove this section when this feature is not needed.
|
||||||
|
|
||||||
|
[buildPlans.iosevka-custom.exclude-chars]
|
||||||
|
ranges = [[10003, 10008]]
|
||||||
|
|
||||||
|
# End character exclusion
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
# Compatibility Ligatures
|
||||||
|
# Certain applications like Emacs does not support proper programming liagtures provided by
|
||||||
|
# OpenType, but can support ligatures provided by PUA codepoints. Therefore you can edit the
|
||||||
|
# following section to build PUA characters that are generated from the OpenType ligatures.
|
||||||
|
# Remove this section when compatibility ligatures are not needed.
|
||||||
|
|
||||||
|
[[buildPlans.iosevka-custom.compatibility-ligatures]]
|
||||||
|
unicode = 57600 # 0xE100
|
||||||
|
featureTag = 'calt'
|
||||||
|
sequence = '<*>'
|
||||||
|
|
||||||
|
# End compatibility ligatures section
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
# Metric overrides
|
||||||
|
# Certain metrics like line height (leading) could be overridden in your build plan file.
|
||||||
|
# Edit the values to change the metrics. Remove this section when overriding is not needed.
|
||||||
|
|
||||||
|
[buildPlans.iosevka-custom.metric-override]
|
||||||
|
leading = 1250
|
||||||
|
winMetricAscenderPad = 0
|
||||||
|
winMetricDescenderPad = 0
|
||||||
|
powerlineScaleY = 1
|
||||||
|
powerlineScaleX = 1
|
||||||
|
powerlineShiftY = 0
|
||||||
|
powerlineShiftX = 0
|
||||||
|
|
||||||
|
# End metric override section
|
||||||
|
###################################################################################################
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Run `npm run build -- contents::<your plan name>` and the built fonts would be avaliable in `dist/`. Aside from `contents::<plan>`, other options are:
|
3. Run `npm run build -- contents::<your plan name>` and the built fonts would be avaliable in `dist/`. Aside from `contents::<plan>`, other options are:
|
||||||
|
@ -212,22 +265,6 @@ The current available styles for `design`/`upright`/`italic`/`oblique` options a
|
||||||
|
|
||||||
<!-- END Section-Cherry-Picking-Ligation-Sets -->
|
<!-- END Section-Cherry-Picking-Ligation-Sets -->
|
||||||
|
|
||||||
* Styles for changing the line space (leading):
|
|
||||||
|
|
||||||
* `leading-750`, `leading-1000`, `leading-1250`, `leading-1500`, `leading-1750`, `leading-2000`: Change the line space. Default is `leading-1250`.
|
|
||||||
* `win-metric-pad-0`, `win-metric-pad-50`, `win-metric-pad-100`, `win-metric-pad-150`, `win-metric-pad-200`, `win-metric-pad-250`, `win-metric-pad-300`: Add extra space to [OS/2 table’s Win metrics](https://docs.microsoft.com/en-us/typography/opentype/spec/os2#uswinascent) to avoid clipping in certain legacy software.
|
|
||||||
|
|
||||||
* Styles for changing Powerline symbols' position:
|
|
||||||
|
|
||||||
* `powerline-scale-y-750`, `powerline-scale-y-875`, `powerline-scale-y-1000`, `powerline-scale-y-1125`, `powerline-scale-y-1250`, `powerline-scale-y-1375`, `powerline-scale-y-1500`: Resize the Powerline symbols vertically, from 75% to 150%.
|
|
||||||
* `powerline-scale-x-750`, `powerline-scale-x-875`, `powerline-scale-x-1000`, `powerline-scale-x-1125`, `powerline-scale-x-1250`, `powerline-scale-x-1375`, `powerline-scale-x-1500`: Resize the Powerline symbols horizontally, from 75% to 150%.
|
|
||||||
* `powerline-shift-y-n500`, `powerline-shift-y-n450`, `powerline-shift-y-n400`, `powerline-shift-y-n350`, `powerline-shift-y-n300`, `powerline-shift-y-n250`, `powerline-shift-y-n200`, `powerline-shift-y-n150`, `powerline-shift-y-n100`, `powerline-shift-y-n50`, `powerline-shift-y-0`, `powerline-shift-y-p50`, `powerline-shift-y-p100`, `powerline-shift-y-p150`, `powerline-shift-y-p200`, `powerline-shift-y-p250`, `powerline-shift-y-p300`, `powerline-shift-y-p350`, `powerline-shift-y-p400`, `powerline-shift-y-p450`, `powerline-shift-y-p500`: Shift the Powerline symbols vertically, from -0.5em to +0.5em.
|
|
||||||
* `powerline-shift-x-n500`, `powerline-shift-x-n450`, `powerline-shift-x-n400`, `powerline-shift-x-n350`, `powerline-shift-x-n300`, `powerline-shift-x-n250`, `powerline-shift-x-n200`, `powerline-shift-x-n150`, `powerline-shift-x-n100`, `powerline-shift-x-n50`, `powerline-shift-x-0`, `powerline-shift-x-p50`, `powerline-shift-x-p100`, `powerline-shift-x-p150`, `powerline-shift-x-p200`, `powerline-shift-x-p250`, `powerline-shift-x-p300`, `powerline-shift-x-p350`, `powerline-shift-x-p400`, `powerline-shift-x-p450`, `powerline-shift-x-p500`: Shift the Powerline symbols horizontally, from -0.5em to +0.5em.
|
|
||||||
|
|
||||||
* Symbol exclusion:
|
|
||||||
|
|
||||||
* `exclude-check-and-cross-symbol`: Exclude `✓✔✕✖✗✘` (U+2713 – U+2718) from the font.
|
|
||||||
|
|
||||||
<!-- BEGIN Section-Stylistic-Sets -->
|
<!-- BEGIN Section-Stylistic-Sets -->
|
||||||
<!-- THIS SECTION IS AUTOMATICALLY GENERATED. DO NOT EDIT. -->
|
<!-- THIS SECTION IS AUTOMATICALLY GENERATED. DO NOT EDIT. -->
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
* Fix missing mapping regression of U+1D0D (#510).
|
* Fix missing mapping regression of U+1D0D (#510).
|
||||||
* Fix dot removal on various derived glyphs (#513).
|
* Fix dot removal on various derived glyphs (#513).
|
||||||
* Fix styling features for Bulgarian, Macedonian, or Serbian (#514).
|
* Fix styling features for Bulgarian, Macedonian, or Serbian (#514).
|
||||||
* Fix seam on certain Cyrillic letters with descender shape (#517).
|
* Fix seam on certain Cyrillic letters with descender shape (#517).
|
||||||
|
* Fix compatibility ligature building (#524). Also moved metric override configuration, compatibility ligature configuration and character removal configuration into build plans.
|
42
gen/index.js
42
gen/index.js
|
@ -3,16 +3,16 @@
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
const buildFont = require("./build-font.js");
|
const BuildFont = require("./build-font.js");
|
||||||
const parameters = require("../support/parameters");
|
const Parameters = require("../support/parameters");
|
||||||
const formVariantData = require("../support/variant-data");
|
const FormVariantData = require("../support/variant-data");
|
||||||
const formLigationData = require("../support/ligation-data");
|
const FormLigationData = require("../support/ligation-data");
|
||||||
const toml = require("toml");
|
const Toml = require("toml");
|
||||||
|
|
||||||
module.exports = async function main(argv) {
|
module.exports = async function main(argv) {
|
||||||
const para = await getParameters(argv);
|
const para = await getParameters(argv);
|
||||||
const font = buildFont(para);
|
const font = BuildFont(para);
|
||||||
if (argv.charmap) await saveCharMap(argv, font);
|
if (argv.oCharMap) await saveCharMap(argv, font);
|
||||||
if (argv.o) await saveOtd(argv, font);
|
if (argv.o) await saveOtd(argv, font);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,23 +31,27 @@ async function getParameters(argv) {
|
||||||
const rawVariantsData = await tryParseToml(VARIANTS_TOML);
|
const rawVariantsData = await tryParseToml(VARIANTS_TOML);
|
||||||
const rawLigationData = await tryParseToml(LIGATIONS_TOML);
|
const rawLigationData = await tryParseToml(LIGATIONS_TOML);
|
||||||
|
|
||||||
const para = parameters.build(parametersData, argv.hives, { shapeWeight: argv.shapeWeight });
|
const para = Parameters.build(parametersData, argv.hives, { shapeWeight: argv.shape.weight });
|
||||||
|
|
||||||
const variantsData = formVariantData(rawVariantsData, para);
|
const variantsData = FormVariantData(rawVariantsData, para);
|
||||||
para.variants = variantsData;
|
para.variants = variantsData;
|
||||||
para.variantSelector = parameters.build(variantsData, ["default", ...argv.hives]);
|
para.variantSelector = Parameters.build(variantsData, ["default", ...argv.hives]);
|
||||||
para.defaultVariant = variantsData.default;
|
para.defaultVariant = variantsData.default;
|
||||||
|
|
||||||
const ligationData = formLigationData(rawLigationData, para);
|
const ligationData = FormLigationData(rawLigationData, para);
|
||||||
para.defaultBuildup = ligationData.defaultBuildup;
|
para.defaultBuildup = ligationData.defaultBuildup;
|
||||||
para.ligation = parameters.build(ligationData.hives, ["default", ...argv.hives]);
|
para.ligation = Parameters.build(ligationData.hives, ["default", ...argv.hives]);
|
||||||
|
|
||||||
|
if (argv.excludedCharRanges) para.excludedCodePointRanges = argv.excludedCharRanges;
|
||||||
|
if (argv.compatibilityLigatures) para.compLig = argv.compatibilityLigatures;
|
||||||
|
if (argv.metricOverride) Parameters.applymetricOverride(para, argv.metricOverride);
|
||||||
|
|
||||||
para.naming = {
|
para.naming = {
|
||||||
family: argv.family,
|
family: argv.menu.family,
|
||||||
version: argv.version,
|
version: argv.menu.version,
|
||||||
weight: argv.menuWeight - 0,
|
weight: argv.menu.weight - 0,
|
||||||
width: argv.menuWidth - 0,
|
width: argv.menu.width - 0,
|
||||||
slant: argv.menuSlant
|
slant: argv.menu.slant
|
||||||
};
|
};
|
||||||
|
|
||||||
return para;
|
return para;
|
||||||
|
@ -55,7 +59,7 @@ async function getParameters(argv) {
|
||||||
|
|
||||||
async function tryParseToml(str) {
|
async function tryParseToml(str) {
|
||||||
try {
|
try {
|
||||||
return toml.parse(await fs.readFile(str, "utf-8"));
|
return Toml.parse(await fs.readFile(str, "utf-8"));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to parse configuration file ${str}.\nPlease validate whether there's syntax error.\n${e}`
|
`Failed to parse configuration file ${str}.\nPlease validate whether there's syntax error.\n${e}`
|
||||||
|
@ -101,5 +105,5 @@ async function saveCharMap(argv, font) {
|
||||||
glyph.featureSelector ? Object.keys(glyph.featureSelector) : []
|
glyph.featureSelector ? Object.keys(glyph.featureSelector) : []
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
await fs.writeFile(argv.charmap, JSON.stringify(charMap), "utf8");
|
await fs.writeFile(argv.oCharMap, JSON.stringify(charMap), "utf8");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ define GDEF_MARK 3
|
||||||
define [interpretLookups gs lutns lookups] : begin
|
define [interpretLookups gs lutns lookups] : begin
|
||||||
foreach [lutn : items-of lutns] : begin
|
foreach [lutn : items-of lutns] : begin
|
||||||
local lut lookups.(lutn)
|
local lut lookups.(lutn)
|
||||||
interpretLookup gs lut lookups
|
if lut : interpretLookup gs lut lookups
|
||||||
|
|
||||||
define [interpretLookup gs lut lookups] : match lut.type
|
define [interpretLookup gs lut lookups] : match lut.type
|
||||||
"gsub_chaining" : begin
|
"gsub_chaining" : begin
|
||||||
|
@ -59,15 +59,20 @@ export : define [BuildCompatLigatures glyphs glyphList unicodeGlyphs GSUB GDEF c
|
||||||
foreach [cldef : items-of config] : do
|
foreach [cldef : items-of config] : do
|
||||||
if [not cldef.unicode] : break nothing
|
if [not cldef.unicode] : break nothing
|
||||||
if [not cldef.featureTag] : break nothing
|
if [not cldef.featureTag] : break nothing
|
||||||
if [not GSUB.features.(cldef.featureTag)] : break nothing
|
|
||||||
if [not cldef.sequence] : break nothing
|
if [not cldef.sequence] : break nothing
|
||||||
|
|
||||||
|
local feature null
|
||||||
|
foreach [fn : items-of GSUB.languages.'DFLT_DFLT'.features]
|
||||||
|
if (cldef.featureTag === [fn.slice 0 4]) : set feature GSUB.features.(fn)
|
||||||
|
|
||||||
|
if [not feature] : break nothing
|
||||||
|
|
||||||
local gnames {}
|
local gnames {}
|
||||||
for [local j 0] [j < cldef.sequence.length] [inc j] : begin
|
for [local j 0] [j < cldef.sequence.length] [inc j] : begin
|
||||||
if [not unicodeGlyphs.[cldef.sequence.charCodeAt j]] : break nothing
|
if [not unicodeGlyphs.[cldef.sequence.charCodeAt j]] : break nothing
|
||||||
gnames.push unicodeGlyphs.[cldef.sequence.charCodeAt j].name
|
gnames.push unicodeGlyphs.[cldef.sequence.charCodeAt j].name
|
||||||
|
|
||||||
interpretLookups gnames GSUB.features.(cldef.featureTag) GSUB.lookups
|
interpretLookups gnames feature GSUB.lookups
|
||||||
|
|
||||||
local g1 : new Glyph ('$clig.' + cldef.unicode)
|
local g1 : new Glyph ('$clig.' + cldef.unicode)
|
||||||
set g1.advanceWidth 0
|
set g1.advanceWidth 0
|
||||||
|
@ -84,4 +89,3 @@ export : define [BuildCompatLigatures glyphs glyphList unicodeGlyphs GSUB GDEF c
|
||||||
set unicodeGlyphs.(cldef.unicode) g1
|
set unicodeGlyphs.(cldef.unicode) g1
|
||||||
glyphList.push g1
|
glyphList.push g1
|
||||||
set GDEF.glyphClassDef.(g1.name) GDEF_LIGATURE
|
set GDEF.glyphClassDef.(g1.name) GDEF_LIGATURE
|
||||||
|
|
||||||
|
|
|
@ -307,6 +307,11 @@ enableLigation = false
|
||||||
[no-cv-ss]
|
[no-cv-ss]
|
||||||
enableCvSs = false
|
enableCvSs = false
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
### Metric-override hives
|
||||||
|
### These hives are now discouraged in favor of 'metric-override' in build plans but they are
|
||||||
|
### still supported in version 3.x.
|
||||||
|
|
||||||
###### Leading
|
###### Leading
|
||||||
[leading-750]
|
[leading-750]
|
||||||
leading = 750
|
leading = 750
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
[buildPlans.iosevka-custom] # <iosevka-custom> is your plan name
|
[buildPlans.iosevka-custom] # <iosevka-custom> is your plan name
|
||||||
family = "Iosevka Custom" # Font menu family name
|
family = "Iosevka Custom" # Font menu family name
|
||||||
design = ["leading-1500", "v-i-hooky", "v-l-hooky"] # Customize styles
|
design = ["v-i-hooky", "v-l-hooky"] # Customize styles
|
||||||
hintParams = ["-a", "sss"] # Optional custom parameters for ttfautohint
|
# upright = ["upright-styles"] # Uncomment this line to set styles for upright only
|
||||||
|
# italic = ["italic-styles"] # Uncomment this line to set styles for italic only
|
||||||
|
# oblique = ["oblique-styles"] # Uncomment this line to set styles for oblique only
|
||||||
|
hintParams = ["-a", "sss"] # Optional custom parameters for ttfautohint
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
# Override default building weights
|
# Override default building weights
|
||||||
# When buildPlans.<plan name>.weights is absent, all weights would built and mapped to
|
# When buildPlans.<plan name>.weights is absent, all weights would built and mapped to
|
||||||
# default values.
|
# default values.
|
||||||
|
@ -25,19 +28,24 @@ css = 450
|
||||||
shape = 700
|
shape = 700
|
||||||
menu = 700
|
menu = 700
|
||||||
css = 700
|
css = 700
|
||||||
|
|
||||||
# End weight section
|
# End weight section
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
# Override default building slant sets
|
# Override default building slant sets
|
||||||
# Format: <upright|italic|oblique> = <"normal"|"italic"|"oblique">
|
# Format: <upright|italic|oblique> = <"normal"|"italic"|"oblique">
|
||||||
# When this section is absent, all slants would be built.
|
# When this section is absent, all slants would be built.
|
||||||
|
|
||||||
[buildPlans.iosevka-custom.slants]
|
[buildPlans.iosevka-custom.slants]
|
||||||
upright = "normal"
|
upright = "normal"
|
||||||
italic = "italic"
|
italic = "italic"
|
||||||
oblique = "oblique"
|
oblique = "oblique"
|
||||||
|
|
||||||
# End slant section
|
# End slant section
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
# Override default building widths
|
# Override default building widths
|
||||||
# When buildPlans.<plan name>.widths is absent, all widths would built and mapped to
|
# When buildPlans.<plan name>.widths is absent, all widths would built and mapped to
|
||||||
# default values.
|
# default values.
|
||||||
|
@ -45,6 +53,7 @@ oblique = "oblique"
|
||||||
# support 1, 2, 3, 4, 5, 6, 7, 8, 9.
|
# support 1, 2, 3, 4, 5, 6, 7, 8, 9.
|
||||||
# If you decide to use custom weights you have to define all the weights you
|
# If you decide to use custom weights you have to define all the weights you
|
||||||
# plan to use otherwise they will not be built.
|
# plan to use otherwise they will not be built.
|
||||||
|
|
||||||
[buildPlans.iosevka-custom.widths.normal]
|
[buildPlans.iosevka-custom.widths.normal]
|
||||||
shape = 5 # Width of glyph shapes.
|
shape = 5 # Width of glyph shapes.
|
||||||
menu = 5 # Width for the font's names.
|
menu = 5 # Width for the font's names.
|
||||||
|
@ -54,4 +63,49 @@ css = "normal" # "font-stretch' property of webfont CSS.
|
||||||
shape = 7
|
shape = 7
|
||||||
menu = 7
|
menu = 7
|
||||||
css = "expanded"
|
css = "expanded"
|
||||||
|
|
||||||
# End width section
|
# End width section
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
# Character Exclusion
|
||||||
|
# Specify character ranges in the section below to exclude certain characters from the font being
|
||||||
|
# built. Remove this section when this feature is not needed.
|
||||||
|
|
||||||
|
[buildPlans.iosevka-custom.exclude-chars]
|
||||||
|
ranges = [[10003, 10008]]
|
||||||
|
|
||||||
|
# End character exclusion
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
# Compatibility Ligatures
|
||||||
|
# Certain applications like Emacs does not support proper programming liagtures provided by
|
||||||
|
# OpenType, but can support ligatures provided by PUA codepoints. Therefore you can edit the
|
||||||
|
# following section to build PUA characters that are generated from the OpenType ligatures.
|
||||||
|
# Remove this section when compatibility ligatures are not needed.
|
||||||
|
|
||||||
|
[[buildPlans.iosevka-custom.compatibility-ligatures]]
|
||||||
|
unicode = 57600 # 0xE100
|
||||||
|
featureTag = 'calt'
|
||||||
|
sequence = '<*>'
|
||||||
|
|
||||||
|
# End compatibility ligatures section
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
# Metric overrides
|
||||||
|
# Certain metrics like line height (leading) could be overridden in your build plan file.
|
||||||
|
# Edit the values to change the metrics. Remove this section when overriding is not needed.
|
||||||
|
|
||||||
|
[buildPlans.iosevka-custom.metric-override]
|
||||||
|
leading = 1250
|
||||||
|
winMetricAscenderPad = 0
|
||||||
|
winMetricDescenderPad = 0
|
||||||
|
powerlineScaleY = 1
|
||||||
|
powerlineScaleX = 1
|
||||||
|
powerlineShiftY = 0
|
||||||
|
powerlineShiftX = 0
|
||||||
|
|
||||||
|
# End metric override section
|
||||||
|
###################################################################################################
|
||||||
|
|
|
@ -22,3 +22,22 @@ export : define [build parametersData styles blendParams] : begin
|
||||||
|
|
||||||
foreach [style : items-of styles] : introStyle style
|
foreach [style : items-of styles] : introStyle style
|
||||||
return param
|
return param
|
||||||
|
|
||||||
|
extern isFinite
|
||||||
|
define [numericConfigExists x] : [isFinite x] && (x != null)
|
||||||
|
|
||||||
|
export : define [applymetricOverride para mo] : begin
|
||||||
|
if [numericConfigExists mo.leading]
|
||||||
|
set para.leading mo.leading
|
||||||
|
if [numericConfigExists mo.winMetricAscenderPad]
|
||||||
|
set para.winMetricAscenderPad mo.winMetricAscenderPad
|
||||||
|
if [numericConfigExists mo.winMetricDescenderPad]
|
||||||
|
set para.winMetricDescenderPad mo.winMetricDescenderPad
|
||||||
|
if [numericConfigExists mo.powerlineScaleY]
|
||||||
|
set para.powerlineScaleY mo.powerlineScaleY
|
||||||
|
if [numericConfigExists mo.powerlineScaleX]
|
||||||
|
set para.powerlineScaleX mo.powerlineScaleX
|
||||||
|
if [numericConfigExists mo.powerlineShiftY]
|
||||||
|
set para.powerlineShiftY mo.powerlineShiftY
|
||||||
|
if [numericConfigExists mo.powerlineShiftX]
|
||||||
|
set para.powerlineShiftX mo.powerlineShiftX
|
||||||
|
|
|
@ -10,20 +10,20 @@ module.exports = function (output, family, hs, formats) {
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: '${family + " Web"}';
|
font-family: '${family + " Web"}';
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-weight: ${term.cssWeight};
|
font-weight: ${term.css.weight};
|
||||||
font-stretch: ${term.cssStretch};
|
font-stretch: ${term.css.stretch};
|
||||||
font-style: ${term.cssStyle};
|
font-style: ${term.css.style};
|
||||||
src: ${src};
|
src: ${src};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
if (term.cssStyle === "oblique") {
|
if (term.css.style === "oblique") {
|
||||||
// CHROME hates a family with both Italic and Oblique
|
// CHROME hates a family with both Italic and Oblique
|
||||||
ans += `
|
ans += `
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: '${family + " Web Oblique"}';
|
font-family: '${family + " Web Oblique"}';
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-weight: ${term.cssWeight};
|
font-weight: ${term.css.weight};
|
||||||
font-stretch: ${term.cssStretch};
|
font-stretch: ${term.css.stretch};
|
||||||
src: ${src};
|
src: ${src};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
355
verdafile.js
355
verdafile.js
|
@ -51,7 +51,7 @@ const Version = oracle(`metadata:version`, async () => {
|
||||||
|
|
||||||
async function tryParseToml(str) {
|
async function tryParseToml(str) {
|
||||||
try {
|
try {
|
||||||
return toml.parse(fs.readFileSync(str, "utf-8"));
|
return JSON.parse(JSON.stringify(toml.parse(fs.readFileSync(str, "utf-8"))));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to parse configuration file ${str}.\n` +
|
`Failed to parse configuration file ${str}.\n` +
|
||||||
|
@ -69,33 +69,16 @@ const RawPlans = oracle(`metadata:raw-plans`, async target => {
|
||||||
const privateBP = await tryParseToml(PRIVATE_BUILD_PLANS);
|
const privateBP = await tryParseToml(PRIVATE_BUILD_PLANS);
|
||||||
Object.assign(bp.buildPlans, privateBP.buildPlans);
|
Object.assign(bp.buildPlans, privateBP.buildPlans);
|
||||||
}
|
}
|
||||||
for (const prefix in bp.buildPlans) {
|
|
||||||
const plan = bp.buildPlans[prefix];
|
|
||||||
plan.prefix = prefix;
|
|
||||||
|
|
||||||
// Style groups
|
|
||||||
if (!plan.pre) plan.pre = {};
|
|
||||||
if (!plan.post) plan.post = {};
|
|
||||||
|
|
||||||
if (!plan.pre.design) plan.pre.design = plan.design || [];
|
|
||||||
if (!plan.pre.upright) plan.pre.upright = plan.upright || [];
|
|
||||||
if (!plan.pre.oblique) plan.pre.oblique = plan.oblique || [];
|
|
||||||
if (!plan.pre.italic) plan.pre.italic = plan.italic || [];
|
|
||||||
|
|
||||||
if (!plan.post.design) plan.post.design = [];
|
|
||||||
if (!plan.post.upright) plan.post.upright = [];
|
|
||||||
if (!plan.post.oblique) plan.post.oblique = [];
|
|
||||||
if (!plan.post.italic) plan.post.italic = [];
|
|
||||||
}
|
|
||||||
for (const prefix in bp.collectPlans) {
|
|
||||||
bp.collectPlans[prefix].prefix = prefix;
|
|
||||||
}
|
|
||||||
return bp;
|
return bp;
|
||||||
});
|
});
|
||||||
|
|
||||||
const BuildPlans = computed("metadata:build-plans", async target => {
|
const RawCollectPlans = computed("metadata:raw-collect-plans", async target => {
|
||||||
const [rp] = await target.need(RawPlans);
|
const [rp] = await target.need(RawPlans);
|
||||||
return rp.buildPlans;
|
return rp.collectPlans;
|
||||||
|
});
|
||||||
|
const CollectConfig = computed("metadata:collect-config", async target => {
|
||||||
|
const [rp] = await target.need(RawPlans);
|
||||||
|
return rp.collectConfig;
|
||||||
});
|
});
|
||||||
const ExportPlans = computed("metadata:export-plans", async target => {
|
const ExportPlans = computed("metadata:export-plans", async target => {
|
||||||
const [rp] = await target.need(RawCollectPlans);
|
const [rp] = await target.need(RawCollectPlans);
|
||||||
|
@ -105,27 +88,130 @@ const ExportPlans = computed("metadata:export-plans", async target => {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
const RawCollectPlans = computed("metadata:raw-collect-plans", async target => {
|
|
||||||
|
const BuildPlans = computed("metadata:build-plans", async target => {
|
||||||
const [rp] = await target.need(RawPlans);
|
const [rp] = await target.need(RawPlans);
|
||||||
return rp.collectPlans;
|
const rawBuildPlans = rp.buildPlans;
|
||||||
|
|
||||||
|
const returnBuildPlans = {};
|
||||||
|
const fileNameToBpMap = {};
|
||||||
|
for (const prefix in rawBuildPlans) {
|
||||||
|
const bp = { ...rawBuildPlans[prefix] };
|
||||||
|
shimBuildPlans(bp, rp.weights, rp.slants, rp.widths);
|
||||||
|
|
||||||
|
bp.targets = [];
|
||||||
|
const suffixMapping = getSuffixMapping(bp.weights, bp.slants, bp.widths);
|
||||||
|
for (const suffix in suffixMapping) {
|
||||||
|
const sfi = suffixMapping[suffix];
|
||||||
|
if (bp.weights && !bp.weights[sfi.weight]) continue;
|
||||||
|
if (bp.slants && !bp.slants[sfi.slant]) continue;
|
||||||
|
const fileName = [prefix, suffix].join("-");
|
||||||
|
bp.targets.push(fileName);
|
||||||
|
fileNameToBpMap[fileName] = { prefix, suffix };
|
||||||
|
}
|
||||||
|
returnBuildPlans[prefix] = bp;
|
||||||
|
}
|
||||||
|
return { fileNameToBpMap, buildPlans: returnBuildPlans };
|
||||||
});
|
});
|
||||||
const Weights = computed("metadata:global-weights", async target => {
|
|
||||||
const [rp] = await target.need(RawPlans);
|
function shimBuildPlans(bp, dWeights, dSlants, dWidths) {
|
||||||
return rp.weights;
|
if (!bp.pre) bp.pre = {};
|
||||||
|
if (!bp.post) bp.post = {};
|
||||||
|
|
||||||
|
if (!bp.pre.design) bp.pre.design = bp.design || [];
|
||||||
|
if (!bp.pre.upright) bp.pre.upright = bp.upright || [];
|
||||||
|
if (!bp.pre.oblique) bp.pre.oblique = bp.oblique || [];
|
||||||
|
if (!bp.pre.italic) bp.pre.italic = bp.italic || [];
|
||||||
|
|
||||||
|
if (!bp.post.design) bp.post.design = [];
|
||||||
|
if (!bp.post.upright) bp.post.upright = [];
|
||||||
|
if (!bp.post.oblique) bp.post.oblique = [];
|
||||||
|
if (!bp.post.italic) bp.post.italic = [];
|
||||||
|
|
||||||
|
bp.weights = bp.weights || dWeights;
|
||||||
|
bp.slants = bp.slants || dSlants;
|
||||||
|
bp.widths = bp.widths || dWidths;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BuildPlanOf = computed.group("metadata:build-plan-of", async (target, gid) => {
|
||||||
|
const [{ buildPlans }] = await target.need(BuildPlans);
|
||||||
|
const plan = buildPlans[gid];
|
||||||
|
if (!plan) fail(`Build plan for '${gid}' not found.` + whyBuildPlanIsnNotThere(gid));
|
||||||
|
return plan;
|
||||||
});
|
});
|
||||||
const Slants = computed("metadata:global-slants", async target => {
|
|
||||||
const [rp] = await target.need(RawPlans);
|
const GroupFontsOf = computed.group("metadata:group-fonts-of", async (target, gid) => {
|
||||||
return rp.slants;
|
const [plan] = await target.need(BuildPlanOf(gid));
|
||||||
|
return plan.targets;
|
||||||
});
|
});
|
||||||
const Widths = computed("metadata:global-widths", async target => {
|
|
||||||
const [rp] = await target.need(RawPlans);
|
const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileName) => {
|
||||||
return rp.widths;
|
const [{ fileNameToBpMap, buildPlans }] = await target.need(BuildPlans);
|
||||||
});
|
const [version] = await target.need(Version);
|
||||||
const CollectConfig = computed("metadata:collect-config", async target => {
|
|
||||||
const [rp] = await target.need(RawPlans);
|
const fi0 = fileNameToBpMap[fileName];
|
||||||
return rp.collectConfig;
|
if (!fi0) fail(`Build plan for '${fileName}' not found.` + whyBuildPlanIsnNotThere(fileName));
|
||||||
|
|
||||||
|
const bp = buildPlans[fi0.prefix];
|
||||||
|
if (!bp) fail(`Build plan for '${fileName}' not found.` + whyBuildPlanIsnNotThere(fileName));
|
||||||
|
|
||||||
|
const sfi = getSuffixMapping(bp.weights, bp.slants, bp.widths)[fi0.suffix];
|
||||||
|
const preHives = [...bp.pre.design, ...bp.pre[sfi.slant]];
|
||||||
|
const postHives = [...bp.post.design, ...bp.post[sfi.slant]];
|
||||||
|
return {
|
||||||
|
name: fileName,
|
||||||
|
hives: ["iosevka", ...preHives, ...sfi.hives, ...postHives],
|
||||||
|
shape: {
|
||||||
|
weight: sfi.shapeWeight,
|
||||||
|
width: sfi.shapeWidth
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
family: bp.family,
|
||||||
|
version: version,
|
||||||
|
width: sfi.menuWidth,
|
||||||
|
slant: sfi.menuSlant,
|
||||||
|
weight: sfi.menuWeight
|
||||||
|
},
|
||||||
|
css: {
|
||||||
|
weight: sfi.cssWeight,
|
||||||
|
stretch: sfi.cssStretch,
|
||||||
|
style: sfi.cssStyle
|
||||||
|
},
|
||||||
|
hintParams: bp.hintParams || [],
|
||||||
|
compatibilityLigatures: bp["compatibility-ligatures"] || null,
|
||||||
|
metricOverride: bp["metric-override"] || null,
|
||||||
|
excludedCharRanges: bp["exclude-chars"] ? bp["exclude-chars"].ranges || null : null
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getSuffixMapping(weights, slants, widths) {
|
||||||
|
const mapping = {};
|
||||||
|
for (const w in weights) {
|
||||||
|
validateRecommendedWeight(w, weights[w].menu, "Menu");
|
||||||
|
validateRecommendedWeight(w, weights[w].css, "CSS");
|
||||||
|
for (const s in slants) {
|
||||||
|
for (const wd in widths) {
|
||||||
|
const suffix = makeSuffix(w, wd, s, "regular");
|
||||||
|
mapping[suffix] = {
|
||||||
|
hives: [`shapeWeight`, `s-${s}`, `wd-${widths[wd].shape}`],
|
||||||
|
weight: w,
|
||||||
|
shapeWeight: nValidate("Shape weight of " + w, weights[w].shape, vlShapeWeight),
|
||||||
|
cssWeight: nValidate("CSS weight of " + w, weights[w].css, vlCssWeight),
|
||||||
|
menuWeight: nValidate("Menu weight of " + w, weights[w].menu, vlMenuWeight),
|
||||||
|
width: wd,
|
||||||
|
shapeWidth: nValidate("Shape width of " + wd, widths[wd].shape, vlShapeWidth),
|
||||||
|
cssStretch: widths[wd].css || wd,
|
||||||
|
menuWidth: nValidate("Menu width of " + wd, widths[wd].menu, vlMenuWidth),
|
||||||
|
slant: s,
|
||||||
|
cssStyle: slants[s] || s,
|
||||||
|
menuSlant: slants[s] || s
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
function makeSuffix(w, wd, s, fallback) {
|
function makeSuffix(w, wd, s, fallback) {
|
||||||
return (
|
return (
|
||||||
(wd === "normal" ? "" : wd) + (w === "regular" ? "" : w) + (s === "upright" ? "" : s) ||
|
(wd === "normal" ? "" : wd) + (w === "regular" ? "" : w) + (s === "upright" ? "" : s) ||
|
||||||
|
@ -133,6 +219,15 @@ function makeSuffix(w, wd, s, fallback) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateRecommendedWeight(w, value, label) {
|
||||||
|
if (recommendedMenuWeights[w] && recommendedMenuWeights[w] !== value) {
|
||||||
|
echo.warn(
|
||||||
|
`${label} weight settings of ${w} ( = ${value}) doesn't match ` +
|
||||||
|
`the recommended value ( = ${recommendedMenuWeights[w]}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function nValidate(key, v, f) {
|
function nValidate(key, v, f) {
|
||||||
if (typeof v !== "number" || !isFinite(v) || (f && !f(v))) {
|
if (typeof v !== "number" || !isFinite(v) || (f && !f(v))) {
|
||||||
throw new TypeError(`${key} = "${v}" is not a valid number.`);
|
throw new TypeError(`${key} = "${v}" is not a valid number.`);
|
||||||
|
@ -166,113 +261,50 @@ const recommendedMenuWeights = {
|
||||||
extrabold: 800,
|
extrabold: 800,
|
||||||
heavy: 900
|
heavy: 900
|
||||||
};
|
};
|
||||||
function validateRecommendedWeight(w, value, label) {
|
|
||||||
if (recommendedMenuWeights[w] && recommendedMenuWeights[w] !== value) {
|
function whyBuildPlanIsnNotThere(gid) {
|
||||||
echo.warn(
|
if (!fs.existsSync(PRIVATE_BUILD_PLANS))
|
||||||
`${label} weight settings of ${w} ( = ${value}) doesn't match ` +
|
return "\n -- Possible reason: Config file 'private-build-plans.toml' does not exist.";
|
||||||
`the recommended value ( = ${recommendedMenuWeights[w]}).`
|
return "";
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSuffixSet(weights, slants, widths) {
|
const CollectPlans = computed(`metadata:collect-plans`, async target => {
|
||||||
const mapping = {};
|
const [rawCollectPlans, suffixMapping, collectConfig] = await target.need(
|
||||||
for (const w in weights) {
|
RawCollectPlans,
|
||||||
validateRecommendedWeight(w, weights[w].menu, "Menu");
|
StandardSuffixes,
|
||||||
validateRecommendedWeight(w, weights[w].css, "CSS");
|
CollectConfig
|
||||||
for (const s in slants) {
|
);
|
||||||
for (const wd in widths) {
|
return await getCollectPlans(
|
||||||
const suffix = makeSuffix(w, wd, s, "regular");
|
target,
|
||||||
mapping[suffix] = {
|
rawCollectPlans,
|
||||||
hives: [`shapeWeight`, `s-${s}`, `wd-${widths[wd].shape}`],
|
suffixMapping,
|
||||||
weight: w,
|
collectConfig,
|
||||||
shapeWeight: nValidate("Shape weight of " + w, weights[w].shape, vlShapeWeight),
|
fnStandardTtc
|
||||||
cssWeight: nValidate("CSS weight of " + w, weights[w].css, vlCssWeight),
|
);
|
||||||
menuWeight: nValidate("Menu weight of " + w, weights[w].menu, vlMenuWeight),
|
|
||||||
width: wd,
|
|
||||||
shapeWidth: nValidate("Shape width of " + wd, widths[wd].shape, vlShapeWidth),
|
|
||||||
cssStretch: widths[wd].css || wd,
|
|
||||||
menuWidth: nValidate("Menu width of " + wd, widths[wd].menu, vlMenuWidth),
|
|
||||||
slant: s,
|
|
||||||
cssStyle: slants[s] || s,
|
|
||||||
menuSlant: slants[s] || s
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Suffixes = computed(`metadata:suffixes`, async target => {
|
|
||||||
const [weights, slants, widths] = await target.need(Weights, Slants, Widths);
|
|
||||||
return getSuffixSet(weights, slants, widths);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const FontBuildingParameters = computed(`metadata:font-building-parameters`, async target => {
|
const StandardSuffixes = computed(`metadata:standard-suffixes`, async target => {
|
||||||
const [buildPlans, defaultWeights, defaultSlants, defaultWidths] = await target.need(
|
const [rp] = await target.need(RawPlans);
|
||||||
BuildPlans,
|
return getSuffixMapping(rp.weights, rp.slants, rp.widths);
|
||||||
Weights,
|
|
||||||
Slants,
|
|
||||||
Widths
|
|
||||||
);
|
|
||||||
const fontInfos = {};
|
|
||||||
const bp = {};
|
|
||||||
for (const p in buildPlans) {
|
|
||||||
const { pre, post, prefix, family, weights, slants, widths, hintParams } = buildPlans[p];
|
|
||||||
const targets = [];
|
|
||||||
const suffixMapping = getSuffixSet(
|
|
||||||
weights || defaultWeights,
|
|
||||||
slants || defaultSlants,
|
|
||||||
widths || defaultWidths
|
|
||||||
);
|
|
||||||
for (const suffix in suffixMapping) {
|
|
||||||
if (weights && !weights[suffixMapping[suffix].weight]) continue;
|
|
||||||
if (slants && !slants[suffixMapping[suffix].slant]) continue;
|
|
||||||
const fileName = [prefix, suffix].join("-");
|
|
||||||
const preHives = [...pre.design, ...pre[suffixMapping[suffix].slant]];
|
|
||||||
const postHives = [...post.design, ...post[suffixMapping[suffix].slant]];
|
|
||||||
fontInfos[fileName] = {
|
|
||||||
name: fileName,
|
|
||||||
family,
|
|
||||||
hives: ["iosevka", ...preHives, ...suffixMapping[suffix].hives, ...postHives],
|
|
||||||
shapeWeight: suffixMapping[suffix].shapeWeight,
|
|
||||||
shapeWidth: suffixMapping[suffix].shapeWidth,
|
|
||||||
menuWeight: suffixMapping[suffix].menuWeight,
|
|
||||||
menuWidth: suffixMapping[suffix].menuWidth,
|
|
||||||
menuSlant: suffixMapping[suffix].menuSlant,
|
|
||||||
cssWeight: suffixMapping[suffix].cssWeight,
|
|
||||||
cssStretch: suffixMapping[suffix].cssStretch,
|
|
||||||
cssStyle: suffixMapping[suffix].cssStyle,
|
|
||||||
hintParams: hintParams || []
|
|
||||||
};
|
|
||||||
targets.push(fileName);
|
|
||||||
}
|
|
||||||
bp[prefix] = {
|
|
||||||
family,
|
|
||||||
prefix,
|
|
||||||
targets
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return { fontInfos, buildPlans: bp };
|
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getCollectPlans(target, rawCollectPlans, suffixMapping, config, fnFileName) {
|
async function getCollectPlans(target, rawCollectPlans, suffixMapping, config, fnFileName) {
|
||||||
const ttcComposition = {},
|
const ttcComposition = {},
|
||||||
ttcContents = {},
|
ttcContents = {},
|
||||||
groupDecomposition = {};
|
groupDecomposition = {};
|
||||||
for (const gid in rawCollectPlans) {
|
for (const collectPrefix in rawCollectPlans) {
|
||||||
const groupFileList = new Set();
|
const groupFileList = new Set();
|
||||||
const collect = rawCollectPlans[gid];
|
const collect = rawCollectPlans[collectPrefix];
|
||||||
if (!collect || !collect.from || !collect.from.length) continue;
|
if (!collect || !collect.from || !collect.from.length) continue;
|
||||||
|
|
||||||
for (const prefix of collect.from) {
|
for (const prefix of collect.from) {
|
||||||
const [gri] = await target.need(GroupInfo(prefix));
|
const [gri] = await target.need(BuildPlanOf(prefix));
|
||||||
const ttfFileNameSet = new Set(gri.targets);
|
const ttfFileNameSet = new Set(gri.targets);
|
||||||
for (const suffix in suffixMapping) {
|
for (const suffix in suffixMapping) {
|
||||||
const gr = suffixMapping[suffix];
|
const gr = suffixMapping[suffix];
|
||||||
const ttcFileName = fnFileName(
|
const ttcFileName = fnFileName(
|
||||||
config,
|
config,
|
||||||
collect.prefix,
|
collectPrefix,
|
||||||
gr.weight,
|
gr.weight,
|
||||||
gr.width,
|
gr.width,
|
||||||
gr.slant
|
gr.slant
|
||||||
|
@ -285,8 +317,8 @@ async function getCollectPlans(target, rawCollectPlans, suffixMapping, config, f
|
||||||
groupFileList.add(ttcFileName);
|
groupFileList.add(ttcFileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ttcContents[gid] = [...groupFileList];
|
ttcContents[collectPrefix] = [...groupFileList];
|
||||||
groupDecomposition[gid] = [...collect.from];
|
groupDecomposition[collectPrefix] = [...collect.from];
|
||||||
}
|
}
|
||||||
return { ttcComposition, ttcContents, groupDecomposition };
|
return { ttcComposition, ttcContents, groupDecomposition };
|
||||||
}
|
}
|
||||||
|
@ -300,46 +332,6 @@ function fnStandardTtc(collectConfig, prefix, w, wd, s) {
|
||||||
return `${prefix}-${ttcSuffix}`;
|
return `${prefix}-${ttcSuffix}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CollectPlans = computed(`metadata:collect-plans`, async target => {
|
|
||||||
const [rawCollectPlans, suffixMapping, collectConfig] = await target.need(
|
|
||||||
RawCollectPlans,
|
|
||||||
Suffixes,
|
|
||||||
CollectConfig
|
|
||||||
);
|
|
||||||
return await getCollectPlans(
|
|
||||||
target,
|
|
||||||
rawCollectPlans,
|
|
||||||
suffixMapping,
|
|
||||||
collectConfig,
|
|
||||||
fnStandardTtc
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const HivesOf = computed.group("metadata:hives-of", async (target, gid) => {
|
|
||||||
const [{ fontInfos }] = await target.need(FontBuildingParameters);
|
|
||||||
const hvs = fontInfos[gid];
|
|
||||||
if (!hvs) fail(`Build plan for '${gid}' not found.` + whyBuildPlanIsnNotThere(gid));
|
|
||||||
return hvs;
|
|
||||||
});
|
|
||||||
|
|
||||||
const GroupInfo = computed.group("metadata:group-info", async (target, gid) => {
|
|
||||||
const [{ buildPlans }] = await target.need(FontBuildingParameters);
|
|
||||||
const plan = buildPlans[gid];
|
|
||||||
if (!plan) fail(`Build plan for '${gid}' not found.` + whyBuildPlanIsnNotThere(gid));
|
|
||||||
return plan;
|
|
||||||
});
|
|
||||||
|
|
||||||
function whyBuildPlanIsnNotThere(gid) {
|
|
||||||
if (!fs.existsSync(PRIVATE_BUILD_PLANS))
|
|
||||||
return "\n -- Possible reason: Config file 'private-build-plans.toml' does not exist.";
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const GroupFontsOf = computed.group("metadata:group-fonts-of", async (target, gid) => {
|
|
||||||
const [plan] = await target.need(GroupInfo(gid));
|
|
||||||
return plan.targets;
|
|
||||||
});
|
|
||||||
|
|
||||||
const CollectionPartsOf = computed.group("metadata:collection-parts-of", async (target, id) => {
|
const CollectionPartsOf = computed.group("metadata:collection-parts-of", async (target, id) => {
|
||||||
const [{ ttcComposition }] = await target.need(CollectPlans);
|
const [{ ttcComposition }] = await target.need(CollectPlans);
|
||||||
return ttcComposition[id];
|
return ttcComposition[id];
|
||||||
|
@ -351,24 +343,11 @@ const CollectionPartsOf = computed.group("metadata:collection-parts-of", async (
|
||||||
|
|
||||||
const BuildOTD = file.make(
|
const BuildOTD = file.make(
|
||||||
(gr, fn) => `${BUILD}/${gr}/${fn}.otd`,
|
(gr, fn) => `${BUILD}/${gr}/${fn}.otd`,
|
||||||
async (target, output, _gr, fn) => {
|
async (target, output, gr, fn) => {
|
||||||
const [
|
const [fi] = await target.need(FontInfoOf(fn), Version);
|
||||||
{ hives, family, shapeWeight, menuWeight, menuSlant, menuWidth },
|
|
||||||
version
|
|
||||||
] = await target.need(HivesOf(fn), Version);
|
|
||||||
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}`);
|
||||||
await node("gen/index", {
|
await node("gen/index", { o: output.full, oCharMap: charmap, ...fi });
|
||||||
o: output.full,
|
|
||||||
charmap,
|
|
||||||
family,
|
|
||||||
version,
|
|
||||||
shapeWeight,
|
|
||||||
menuWeight,
|
|
||||||
menuSlant,
|
|
||||||
menuWidth,
|
|
||||||
hives
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -407,7 +386,7 @@ const DistUnhintedTTF = file.make(
|
||||||
const DistHintedTTF = file.make(
|
const DistHintedTTF = file.make(
|
||||||
(gr, fn) => `${DIST}/${gr}/ttf/${fn}.ttf`,
|
(gr, fn) => `${DIST}/${gr}/ttf/${fn}.ttf`,
|
||||||
async (target, path, gr, f) => {
|
async (target, path, gr, f) => {
|
||||||
const [{ hintParams }] = await target.need(HivesOf(f));
|
const [{ hintParams }] = await target.need(FontInfoOf(f));
|
||||||
const [from] = await target.need(BuildTTF(gr, f), de`${path.dir}`);
|
const [from] = await target.need(BuildTTF(gr, f), de`${path.dir}`);
|
||||||
await run("ttfautohint", hintParams, from.full, path.full);
|
await run("ttfautohint", hintParams, from.full, path.full);
|
||||||
}
|
}
|
||||||
|
@ -453,8 +432,8 @@ const DistWebFontCSS = file.make(
|
||||||
gid => `${DIST}/${gid}/${gid}.css`,
|
gid => `${DIST}/${gid}/${gid}.css`,
|
||||||
async (target, out, gid) => {
|
async (target, out, gid) => {
|
||||||
// Note: this target does NOT depend on the font files.
|
// Note: this target does NOT depend on the font files.
|
||||||
const [gr, ts] = await target.need(GroupInfo(gid), GroupFontsOf(gid), de(out.dir));
|
const [gr, ts] = await target.need(BuildPlanOf(gid), GroupFontsOf(gid), de(out.dir));
|
||||||
const hs = await target.need(...ts.map(HivesOf));
|
const hs = await target.need(...ts.map(FontInfoOf));
|
||||||
await node("utility/make-webfont-css.js", out.full, gr.family, hs, webfontFormats);
|
await node("utility/make-webfont-css.js", out.full, gr.family, hs, webfontFormats);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue