From e719992f2ca7c4054dab27ddd5532aaae507ffab Mon Sep 17 00:00:00 2001 From: be5invis Date: Tue, 27 Oct 2020 21:16:05 -0700 Subject: [PATCH] Make stylistic sets able to specify variants only enabled under Oblique --- README.md | 183 ++---------------- font-src/support/variant-data.js | 10 +- params/variants.toml | 10 +- .../description-cheery-picking-styles.md | 1 + ...escription-cherry-picking-ligation-sets.md | 1 + .../description-predefined-ligation-sets.md | 1 + .../fragments/description-stylistic-sets.md | 1 + utility/amend-readme/index.js | 37 ++-- utility/export-data/index.js | 2 +- ...arse-variants-data.js => variants-data.js} | 20 +- utility/generate-snapshot-page/index.js | 2 +- 11 files changed, 67 insertions(+), 201 deletions(-) create mode 100644 utility/amend-readme/fragments/description-cheery-picking-styles.md create mode 100644 utility/amend-readme/fragments/description-cherry-picking-ligation-sets.md create mode 100644 utility/amend-readme/fragments/description-predefined-ligation-sets.md create mode 100644 utility/amend-readme/fragments/description-stylistic-sets.md rename utility/export-data/{parse-variants-data.js => variants-data.js} (85%) diff --git a/README.md b/README.md index 87abb710b..ab6db7a20 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Iosevka ![Version](https://img.shields.io/github/release/be5invis/Iosevka.svg) -Coders’ typeface, built from code. +**Iosevka** is an *open-source*, *sans-serif* + *slab-serif*, *monospace* + *quasi‑proportional* typeface family, designed for *writing code*, using in *terminals*, and preparing *technical documents*. ![](images/preview-all.png) @@ -7,10 +7,16 @@ Coders’ typeface, built from code. Quit your editor/program. Unzip and open the folder. -* **Instructions for Windows**: Download the fonts from the [Releases](https://github.com/be5invis/Iosevka/releases), select the font files and right click, then hit "Install". - * On Windows 10 1809 or newer the default font installation is per-user, and it may cause compatibility issues for some applications, mostly written in Java. To cope with this, right click and select "Install for all users" instead. [Ref.](https://youtrack.jetbrains.com/issue/JRE-1166?p=IDEA-200145) -* **[Instructions for macOS](http://support.apple.com/kb/HT2509)** - * Standard distribution in Homebrew: `brew tap homebrew/cask-fonts && brew cask install font-iosevka && brew cask install font-iosevka-slab`. Search for other variants using `brew search font-iosevka` and install what you want. +* **Windows**: Download the fonts from the [Releases](https://github.com/be5invis/Iosevka/releases), select the font files and right click, then hit “Install”. + + * On Windows 10 1809 or newer the default font installation is per-user, and it may cause compatibility issues for some applications, mostly written in Java. To cope with this, right click and select “Install for all users” instead. [Ref.](https://youtrack.jetbrains.com/issue/JRE-1166?p=IDEA-200145) +* **[macOS](http://support.apple.com/kb/HT2509)** + * Standard distribution in Homebrew: + ```bash + brew tap homebrew/cask-fonts + brew cask install font-iosevka + ``` + * Search for other variants using `brew search font-iosevka` and install what you want. * Customizable install using Homebrew: see [robertgzr/homebrew-tap](https://github.com/robertgzr/homebrew-tap). * **Linux** : Copy the TTF files to your fonts directory → Run `sudo fc-cache`. - Arch Linux users can install the font from the AUR [here](https://aur.archlinux.org/packages/ttf-iosevka) using an AUR wrapper or by doing it manually. [All variants](https://aur.archlinux.org/packages/?O=0&SeB=nd&K=ttf-iosevka&SB=n&SO=a&PP=50&do_Search=Go). @@ -18,9 +24,9 @@ Quit your editor/program. Unzip and open the folder. * **FreeBSD**: The font can be installed with `pkg install iosevka`. * **OpenBSD**: Run `pkg_info -Q iosevka` to see which Iosevka packages are available. Use `pkg_add` to install the chosen package(s). -## Weights, Variants and OpenType features +## Features -The typeface contains 9 weights (Thin to Heavy) alongside with both italic and oblique versions, with the same metrics as the regular one. +In the official package, Iosevka provides 6 monospace subfamilies and 3 quasi-proportional subfamilies. In all the monospace subfamilies, 9 weights (Thin to Heavy), 2 widths (Normal and Extended), and 3 slopes (Upright, Italic and Oblique) are included. In the quasi-proportional subfamilies, the quantity of widths is reduced to 1. ![Weights sample](images/weights.png) @@ -67,14 +73,14 @@ You will find TTFs, as well as WOFF(2) web fonts and one Webfont CSS in the `dis Refer to these [instructions.](https://github.com/ejuarezg/containers/tree/master/iosevka_font#container-method) -## Build Your Own Style +## Customized Build To create a custom build, you need: 1. Create `private-build-plans.toml` file if absent. 2. Add a build plan into `private-build-plans.toml`. The configurable properties are described in the following sections. - + 3. Run `npm run build -- contents::` and the built fonts would be available in `dist/`. Aside from `contents::`, other options are: 1. `contents::` : TTF (Hinted and Unhinted), WOFF(2) and Web font CSS; @@ -200,7 +206,7 @@ Subsection `variants` is used to configure character variants in the font. Prope -* `design`, `upright` and `italic`: Optional, Dictionary, defines styles for individual characters. The choices are organized in key-value pairs, assigning a variant to a character group. Alternatively, you could assign numbers to `cv##` tags, like what you did when using OpenType in CSS.The valid combinations include: +* `design`, `upright`, `italic`, and `oblique`: Optional, Dictionary, defines styles for individual characters. The choices are organized in key-value pairs, assigning a variant to a character group. Alternatively, you could assign numbers to `cv##` tags, like what you did when using OpenType in CSS. Assignments under `design` will be applied to all the slopes, and `upright`, `italic`, and `oblique` will apply to corresponded slopes. The valid combinations include: - Styles for `A`, `Λ`, `Δ`: + `turn-v = 'straight'`, `cv01 = 1`: Standard, straight `A`, `Λ`, `Δ` (default). @@ -526,162 +532,7 @@ sequence = '<*>' #### Sample Configuration -A sample configuration could be found at [private-build-plans.sample.toml](private-build-plans.sample.toml): - - - - -```toml -[buildPlans.iosevka-custom] # is your plan name -family = "Iosevka Custom" # Font menu family name -spacing = "normal" # Optional; Values: `normal`, `term`, `fontconfig-mono`, or `fixed` -serifs = "sans" # Optional; Values: `sans` or `slab` -digit-form = "lining" # Optional; Values `lining` or `old-style` - -################################################################################################### -# Configure variants - -# Optional; Whether to inherit a `ss##` variant -[buildPlans.iosevka-custom.variants] -inherits = "ss01" - -# Optional; Configure single character's variant -[buildPlans.iosevka-custom.variants.design] -g = 'singlestorey' - -# Optional; Configure single character's variant for Upright and Oblique; Overrides [design] -[buildPlans.iosevka-custom.variants.upright] -i = 'zshaped' -l = 'zshaped' - -# Optional; Configure single character's variant for Italic only; Overrides [design] -[buildPlans.iosevka-custom.variants.italic] -i = 'italic' -l = 'italic' - -# End variant section -################################################################################################### - -################################################################################################### -# Configure ligations - -[buildPlans.iosevka-custom.ligations] -inherits = "calt" # Optional; inherits an existing ligation set -disables = [] # Optional; disable specific ligation groups, overrides inherited ligation set -enables = [] # Optional; enable specific ligation groups, overrides inherited ligation set - -# End ligation section -################################################################################################### - - -################################################################################################### -# Override default building weights -# When buildPlans..weights is absent, all weights would built and mapped to -# default values. -# IMPORTANT : Currently "menu" and "css" property only support numbers between 0 and 1000. -# and "shape" properly only supports number between 100 and 900 (inclusive). -# If you decide to use custom weights you have to define all the weights you -# plan to use otherwise they will not be built. -[buildPlans.iosevka-custom.weights.regular] -shape = 400 # Weight for glyph shapes. -menu = 400 # Weight for the font's names. -css = 400 # Weight for webfont CSS. - -[buildPlans.iosevka-custom.weights.book] -shape = 450 -menu = 450 # Use 450 here to name the font's weight "Book" -css = 450 - -[buildPlans.iosevka-custom.weights.bold] -shape = 700 -menu = 700 -css = 700 - -# End weight section -################################################################################################### - -################################################################################################### -# Override default building slope sets -# Format: = <"normal"|"italic"|"oblique"> -# When this section is absent, all slopes would be built. - -[buildPlans.iosevka-custom.slopes] -upright = "normal" -italic = "italic" -oblique = "oblique" - -# End slope section -################################################################################################### - -################################################################################################### -# Override default building widths -# When buildPlans..widths is absent, all widths would built and mapped to -# default values. -# IMPORTANT : Currently "shape" property only supports numbers between 434 and 664 (inclusive), -# while "menu" only supports integers between 1 and 9 (inclusive). -# The "shape" parameter specifies the unit width, measured in 1/1000 em. The glyphs' -# width are equal to, or a simple multiple of the unit width. -# If you decide to use custom widths you have to define all the widths you plan to use, -# otherwise they will not be built. - -[buildPlans.iosevka-custom.widths.normal] -shape = 500 # Unit Width, measured in 1/1000 em. -menu = 5 # Width grade for the font's names. -css = "normal" # "font-stretch' property of webfont CSS. - -[buildPlans.iosevka-custom.widths.extended] -shape = 576 -menu = 7 -css = "expanded" - -# 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 -################################################################################################### -``` - - +A sample configuration could be found at [private-build-plans.sample.toml](private-build-plans.sample.toml). ## For Chinese and Japanese users... diff --git a/font-src/support/variant-data.js b/font-src/support/variant-data.js index 3778fe801..76c9d285d 100644 --- a/font-src/support/variant-data.js +++ b/font-src/support/variant-data.js @@ -73,12 +73,18 @@ class Composite { this.description = cfg.description; this.inherits = cfg.inherits; this.design = cfg.design; - this.upright = cfg.upright; + this.upright = cfg.upright || cfg["upright-oblique"]; + this.oblique = cfg.oblique || cfg["upright-oblique"]; this.italic = cfg.italic; } + decompose(para, selTree) { const ans = []; - const cfg = Object.assign({}, this.design, para.isItalic ? this.italic : this.upright); + const cfg = Object.assign( + {}, + this.design, + para.isItalic ? this.italic : para.isOblique ? this.oblique : this.upright + ); for (const [k, v] of Object.entries(cfg)) { const pv = selTree.get(k, v); if (!pv) throw new Error(`Composite ${this.key} cannot be resolved: ${[k, v]}.`); diff --git a/params/variants.toml b/params/variants.toml index 93e7ccc0e..583520e49 100644 --- a/params/variants.toml +++ b/params/variants.toml @@ -1717,7 +1717,7 @@ h = 'straight' m = 'normal' n = 'straight' -[default.upright] +[default.upright-oblique] a = 'doublestorey' d = 'toothed' f = 'straight' @@ -1814,7 +1814,7 @@ one = 'base' six = 'open-contour' nine = 'open-contour' -[composite.ss03.upright] +[composite.ss03.upright-oblique] g = 'doublestorey' y = 'straight-turn' @@ -1940,7 +1940,7 @@ ampersand = 'upper-open' six = 'closed-contour' nine = 'closed-contour' -[composite.ss08.upright] +[composite.ss08.upright-oblique] g = 'doublestorey' [composite.ss08.italic] @@ -1965,7 +1965,7 @@ one = 'base' six = 'closed-contour' nine = 'closed-contour' -[composite.ss09.upright] +[composite.ss09.upright-oblique] i = 'hooky' g = 'doublestorey' @@ -2090,7 +2090,7 @@ lambda = 'curly' six = 'open-contour' nine = 'open-contour' -[composite.ss20.upright] +[composite.ss20.upright-oblique] k = 'curly' y = 'curly' diff --git a/utility/amend-readme/fragments/description-cheery-picking-styles.md b/utility/amend-readme/fragments/description-cheery-picking-styles.md new file mode 100644 index 000000000..5e3ca14a0 --- /dev/null +++ b/utility/amend-readme/fragments/description-cheery-picking-styles.md @@ -0,0 +1 @@ +* `design`, `upright`, `italic`, and `oblique`: Optional, Dictionary, defines styles for individual characters. The choices are organized in key-value pairs, assigning a variant to a character group. Alternatively, you could assign numbers to `cv##` tags, like what you did when using OpenType in CSS. Assignments under `design` will be applied to all the slopes, and `upright`, `italic`, and `oblique` will apply to corresponded slopes. The valid combinations include: diff --git a/utility/amend-readme/fragments/description-cherry-picking-ligation-sets.md b/utility/amend-readme/fragments/description-cherry-picking-ligation-sets.md new file mode 100644 index 000000000..2886a61a9 --- /dev/null +++ b/utility/amend-readme/fragments/description-cherry-picking-ligation-sets.md @@ -0,0 +1 @@ +* `disables` and `enables`: Optional, String Array, Cherry-picking ligation groups to be disabled or enabled. Valid values include: diff --git a/utility/amend-readme/fragments/description-predefined-ligation-sets.md b/utility/amend-readme/fragments/description-predefined-ligation-sets.md new file mode 100644 index 000000000..4e2fc219f --- /dev/null +++ b/utility/amend-readme/fragments/description-predefined-ligation-sets.md @@ -0,0 +1 @@ +* `inherits`: Optional, String, defines the inherited ligation set. When absent, the ligation set will not inherit any other sets. Valid values are: diff --git a/utility/amend-readme/fragments/description-stylistic-sets.md b/utility/amend-readme/fragments/description-stylistic-sets.md new file mode 100644 index 000000000..98d28b791 --- /dev/null +++ b/utility/amend-readme/fragments/description-stylistic-sets.md @@ -0,0 +1 @@ +* `inherits`: Optional, String, defines the inherited stylistic set. Valid options include: diff --git a/utility/amend-readme/index.js b/utility/amend-readme/index.js index e8530c7e0..b5dc6a05d 100644 --- a/utility/amend-readme/index.js +++ b/utility/amend-readme/index.js @@ -2,7 +2,7 @@ const fs = require("fs-extra"); const path = require("path"); -const parseVariantsData = require("../export-data/parse-variants-data"); +const parseVariantsData = require("../export-data/variants-data"); const parseLigationData = require("../export-data/ligation-data"); const getCharMapAndSupportedLanguageList = require("../export-data/supported-languages"); const execMain = require("../shared/execMain"); @@ -29,10 +29,8 @@ async function main() { async function processSs() { const variantsData = await parseVariantsData(); const md = new MdCol("Section-Stylistic-Sets"); - md.log( - `* \`inherits\`: Optional, String, defines the inherited stylistic set. ` + - `Valid options include:\n` - ); + const headerPath = path.resolve(__dirname, "fragments/description-stylistic-sets.md"); + md.log(await fs.readFile(headerPath, "utf-8")); for (const gr of variantsData.ssData) { if (!gr.effective) continue; md.log(` - \`${gr.tag}\`: Set character variant to “${gr.description}”.`); @@ -42,15 +40,10 @@ async function processSs() { async function processCv() { const variantsData = await parseVariantsData(); const md = new MdCol("Section-Cherry-Picking-Styles"); - md.log( - `* \`design\`, \`upright\` and \`italic\`: Optional, Dictionary, ` + - `defines styles for individual characters. ` + - `The choices are organized in key-value pairs, ` + - `assigning a variant to a character group. ` + - `Alternatively, you could assign numbers to \`cv##\` tags, ` + - `like what you did when using OpenType in CSS.` + - `The valid combinations include:\n` - ); + + const headerPath = path.resolve(__dirname, "fragments/description-cheery-picking-styles.md"); + md.log(await fs.readFile(headerPath, "utf-8")); + for (const gr of variantsData.cvData) { const sampleText = gr.descSampleText .map(c => (c === "`" ? "`` ` ``" : `\`${c}\``)) @@ -160,11 +153,12 @@ function figureOutDefaults(variantsData, gr) { async function processLigSetCherryPicking() { const ligData = await parseLigationData(); const md = new MdCol("Section-Cherry-Picking-Ligation-Sets"); - md.log( - `* \`disables\` and \`enables\`: Optional, String Array, ` + - `Cherry-picking ligation groups to be disabled or enabled. ` + - `Valid values include:\n` + const headerPath = path.resolve( + __dirname, + "fragments/description-cherry-picking-ligation-sets.md" ); + md.log(await fs.readFile(headerPath, "utf-8")); + for (const gr in ligData.cherry) { md.log(` - \`${gr}\`: ${ligData.cherry[gr].desc}.`); } @@ -174,11 +168,8 @@ async function processLigSetCherryPicking() { async function processLigSetPreDef() { const ligData = await parseLigationData(); const md = new MdCol("Section-Predefined-Ligation-Sets"); - md.log( - `* \`inherits\`: Optional, String, defines the inherited ligation set. ` + - `When absent, the ligation set will not inherit any other sets. ` + - `Valid values are:\n` - ); + const headerPath = path.resolve(__dirname, "fragments/description-predefined-ligation-sets.md"); + md.log(await fs.readFile(headerPath, "utf-8")); for (const gr in ligData.rawSets) { if (ligData.rawSets[gr].isOptOut) continue; const longDesc = diff --git a/utility/export-data/index.js b/utility/export-data/index.js index 18382dd07..fac24fd12 100644 --- a/utility/export-data/index.js +++ b/utility/export-data/index.js @@ -1,7 +1,7 @@ "use strict"; const fs = require("fs-extra"); -const parseVariantsData = require("./parse-variants-data"); +const parseVariantsData = require("./variants-data"); const parseLigationData = require("./ligation-data"); const getCharMapAndSupportedLanguageList = require("./supported-languages"); const execMain = require("../shared/execMain"); diff --git a/utility/export-data/parse-variants-data.js b/utility/export-data/variants-data.js similarity index 85% rename from utility/export-data/parse-variants-data.js rename to utility/export-data/variants-data.js index 01f978cbd..3e7bf8941 100644 --- a/utility/export-data/parse-variants-data.js +++ b/utility/export-data/variants-data.js @@ -57,7 +57,8 @@ function getCvData(parsed) { return Array.from(samplerGroups.values()); } -const UPRIGHT = { isItalic: false }; +const UPRIGHT = {}; +const OBLIQUE = { isOblique: true }; const ITALIC = { isItalic: true }; function getSsData(variants) { @@ -68,16 +69,20 @@ function getSsData(variants) { description: "Default", uprightComposition: [], italicComposition: [], + obliqueComposition: [], hotCharSetUpright: [], - hotCharSetItalic: [] + hotCharSetItalic: [], + hotCharSetOblique: [] } ]; const defaultUpright = buildupComposite(variants, UPRIGHT, variants.defaultComposite); + const defaultOblique = buildupComposite(variants, OBLIQUE, variants.defaultComposite); const defaultItalic = buildupComposite(variants, ITALIC, variants.defaultComposite); for (const [key, composite] of variants.composites) { if (!composite.tag) continue; const upright = buildupComposite(variants, UPRIGHT, composite); + const oblique = buildupComposite(variants, OBLIQUE, composite); const italic = buildupComposite(variants, ITALIC, composite); result.push({ @@ -86,8 +91,10 @@ function getSsData(variants) { description: composite.description, uprightComposition: upright.composition, italicComposition: italic.composition, + obliqueComposition: oblique.composition, hotCharSetUpright: Array.from(uniqueHotChars(defaultUpright, upright.hotChars)), - hotCharSetItalic: Array.from(uniqueHotChars(defaultItalic, italic.hotChars)) + hotCharSetItalic: Array.from(uniqueHotChars(defaultItalic, italic.hotChars)), + hotCharSetOblique: Array.from(uniqueHotChars(defaultOblique, oblique.hotChars)) }); } return result; @@ -97,6 +104,7 @@ function getDefaultCompData(variants) { return { sansUpright: buildupComposite(variants, UPRIGHT, variants.defaultComposite), sansItalic: buildupComposite(variants, ITALIC, variants.defaultComposite), + sansOblique: buildupComposite(variants, OBLIQUE, variants.defaultComposite), slabUpright: buildupComposite( variants, UPRIGHT, @@ -108,6 +116,12 @@ function getDefaultCompData(variants) { ITALIC, variants.defaultComposite, variants.composites.get("slab") + ), + slabOblique: buildupComposite( + variants, + OBLIQUE, + variants.defaultComposite, + variants.composites.get("slab") ) }; } diff --git a/utility/generate-snapshot-page/index.js b/utility/generate-snapshot-page/index.js index 8f5b3b928..1e6b61034 100644 --- a/utility/generate-snapshot-page/index.js +++ b/utility/generate-snapshot-page/index.js @@ -3,7 +3,7 @@ const ejs = require("ejs"); const fs = require("fs-extra"); const path = require("path"); -const parseVariantsData = require("../export-data/parse-variants-data"); +const parseVariantsData = require("../export-data/variants-data"); const getLigationData = require("../export-data/ligation-data"); const execMain = require("../shared/execMain");