diff --git a/changes/31.8.1.md b/changes/31.8.1.md index ffc6eb113..09d46eede 100644 --- a/changes/31.8.1.md +++ b/changes/31.8.1.md @@ -3,3 +3,4 @@ * Optimize glyphs for cursive variants for Greek Lower Beta (`β`) and Cyrillic Lower Ve (`в`). * Optimize glyphs for Volapük Ae/Oe/Ue (`U+A79A`..`U+A79F`). * Optimize glyph for Cyrillic Lower Dzze (`U+A689`) under italics. +* Allowed customizing menu WWS value to name map (#2488). diff --git a/doc/custom-build.md b/doc/custom-build.md index b2afab437..68e026476 100644 --- a/doc/custom-build.md +++ b/doc/custom-build.md @@ -3634,8 +3634,29 @@ The properties in the `namingOverride` section could be uase to override menu na - `urlDesigner`: Name ID 12, URL of typeface designer. - `license` (or alternatively `licence`): Name ID 13, license description. - `licenseURL` (or alternatively `licenceURL`): Name ID 14, license Info URL. + - `version`: Override font version. The version number should follow [SemVer](https://semver.org/), like being `1.0.0`. -In addition, you can also use the `version` property to override font version. The version number should follow [SemVer](https://semver.org/), like being `1.0.0`. +Additionally, the `namingOverride` section now supports a `menuNameMap` configuration property. This property allows for the customization of menu names based on specific attributes related to the font's style and characteristics. The `menuNameMap` configuration is structured as follows: + +- `weight`: A mapping of menu weight numbers to their corresponding names. +- `width`: A mapping of menu width numbers to their corresponding names. +- `slope`: A mapping of menu slope values (`"normal"`/`"italic"`/`"oblique"`) to their corresponding names. +- `weightShort`: A mapping of menu weight numbers to short names. +- `widthShort`: A mapping of menu width numbers to short names. +- `slopeShort`: A mapping of menu slope values (`"normal"`/`"italic"`/`"oblique"`) to short names. + +You are allowed to provide override names only for the values that you want to have custom names. Any values not specified in these mappings will use the default names. + +For example, the following configuration: + +```toml +[buildPlans.IosevkaCustom.namingOverride.menuNameMap.width] +7 = "Expanded" +[buildPlans.IosevkaCustom.namingOverride.menuNameMap.widthShort] +7 = "Exp" +``` + +... will name width 7 to "Expanded" in full, and "Exp" in short. #### Sample Configuration diff --git a/packages/font/src/naming/index.mjs b/packages/font/src/naming/index.mjs index 161809f32..278ba1296 100644 --- a/packages/font/src/naming/index.mjs +++ b/packages/font/src/naming/index.mjs @@ -12,6 +12,19 @@ export function createNamingDictFromArgv(argv) { weight: argv.menu.weight - 0, width: argv.menu.width - 0, slope: argv.menu.slope, + + menuNameMap: { + weight: { ...WeightToMenuMap, ...argv.namingOverride?.menuNameMap?.weight }, + width: { ...WidthToMenuMap, ...argv.namingOverride?.menuNameMap?.width }, + slope: { ...SlopeToMenuMap, ...argv.namingOverride?.menuNameMap?.slope }, + + weightShort: { + ...WeightToMenuShortMap, + ...argv.namingOverride?.menuNameMap?.weightShort, + }, + widthShort: { ...WidthToMenuShortMap, ...argv.namingOverride?.menuNameMap?.widthShort }, + slopeShort: { ...SlopeToMenuShortMap, ...argv.namingOverride?.menuNameMap?.slopeShort }, + }, }; } @@ -26,7 +39,7 @@ export function assignFontNames(font, naming, isQuasiProportional) { function setMainNames(font, naming) { // Preferred names const family = naming.family.trim(); - const style = getStyle(naming.weight, naming.width, naming.slope); + const style = getStyle(naming.menuNameMap, naming.weight, naming.width, naming.slope); nameFont(font, Ot.Name.NameID.PreferredFamily, family); nameFont(font, Ot.Name.NameID.PreferredSubfamily, style); @@ -34,7 +47,12 @@ function setMainNames(font, naming) { nameFont(font, Ot.Name.NameID.WwsSubfamily, style); // Compat names - const compat = getStyleLinkedStyles(naming.weight, naming.width, naming.slope); + const compat = getStyleLinkedStyles( + naming.menuNameMap, + naming.weight, + naming.width, + naming.slope, + ); let compatFamily = family; if (compat.familySuffix !== "Regular") compatFamily = family + " " + compat.familySuffix; if (compatFamily.length >= 31) compatFamily = family + " " + compat.familySuffixShort; @@ -155,7 +173,7 @@ function applyMiscProps(font) { ); } -///////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// function accumulateFlags(...entries) { let s = 0; @@ -165,7 +183,7 @@ function accumulateFlags(...entries) { return s; } -function getStyleLinkedStyles(weight, width, slope) { +function getStyleLinkedStyles(menuNameMap, weight, width, slope) { let linkWeight = weight; let linkSlope = slope; let nameSuffixWeight = 400; @@ -183,9 +201,14 @@ function getStyleLinkedStyles(weight, width, slope) { } return { - style: getStyle(linkWeight, 5, linkSlope), - familySuffix: getStyle(nameSuffixWeight, nameSuffixWidth, nameSuffixSlope), - familySuffixShort: getShortStyle(nameSuffixWeight, nameSuffixWidth, nameSuffixSlope), + style: getStyle(menuNameMap, linkWeight, 5, linkSlope), + familySuffix: getStyle(menuNameMap, nameSuffixWeight, nameSuffixWidth, nameSuffixSlope), + familySuffixShort: getShortStyle( + menuNameMap, + nameSuffixWeight, + nameSuffixWidth, + nameSuffixSlope, + ), }; } @@ -205,22 +228,24 @@ function nameFontImpl(records, platformID, encodingID, languageID, nameID, value records.push({ platformID, encodingID, languageID, nameID, value }); } -function getStyle(weight, width, slope) { - const weightPart = weightToMenuStyleMap[weight] ?? "W" + weight; - const widthPart = widthToMenuStyleMap[width] ?? "Wd" + width; - const slopePart = slopeToMenuStyleMap[slope] ?? ""; +function getStyle(menuNameMap, weight, width, slope) { + const weightPart = menuNameMap.weight[weight] ?? "W" + weight; + const widthPart = menuNameMap.width[width] ?? "Wd" + width; + const slopePart = menuNameMap.slope[slope] ?? ""; const rawName = weightPart + " " + widthPart + " " + slopePart; return rawName.replace(/ +/g, " ").trim() || "Regular"; } -function getShortStyle(weight, width, slope) { - const weightPart = weightToMenuStyleMapShort[weight] ?? "W" + weight; - const widthPart = widthToMenuStyleMapShort[width] ?? "Wd" + width; - const slopePart = slopeToMenuStyleMapShort[slope] ?? ""; +function getShortStyle(menuNameMap, weight, width, slope) { + const weightPart = menuNameMap.weightShort[weight] ?? "W" + weight; + const widthPart = menuNameMap.widthShort[width] ?? "Wd" + width; + const slopePart = menuNameMap.slopeShort[slope] ?? ""; const rawName = weightPart + " " + widthPart + " " + slopePart; return rawName.replace(/ +/g, " ").trim() || "Regular"; } -const weightToMenuStyleMap = { +/////////////////////////////////////////////////////////////////////////////////////////////////// + +const WeightToMenuMap = { 100: "Thin", 200: "Extralight", 300: "Light", @@ -233,7 +258,7 @@ const weightToMenuStyleMap = { 800: "Extrabold", 900: "Heavy", }; -const widthToMenuStyleMap = { +const WidthToMenuMap = { 1: "Ultra-Condensed", 2: "Extra-Condensed", 3: "Condensed", @@ -244,12 +269,12 @@ const widthToMenuStyleMap = { 8: "Extra-Extended", 9: "Ultra-Extended", }; -const slopeToMenuStyleMap = { +const SlopeToMenuMap = { normal: "", italic: "Italic", oblique: "Oblique", }; -const weightToMenuStyleMapShort = { +const WeightToMenuShortMap = { 100: "Th", 200: "XLt", 300: "Lt", @@ -262,7 +287,7 @@ const weightToMenuStyleMapShort = { 800: "XBd", 900: "Hv", }; -const widthToMenuStyleMapShort = { +const WidthToMenuShortMap = { 1: "UltCn", 2: "XCn", 3: "Cn", @@ -273,13 +298,13 @@ const widthToMenuStyleMapShort = { 8: "XEx", 9: "UltEx", }; -const slopeToMenuStyleMapShort = { +const SlopeToMenuShortMap = { normal: "", italic: "It", oblique: "Obl", }; -///////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// function ancNameEntry(input) { return input.replace(/\{\{currentYear\}\}/g, () => String(new Date().getFullYear()));