diff --git a/font-src/glyphs/common/derivatives.ptl b/font-src/glyphs/common/derivatives.ptl index 436f0a4c7..cfee911a7 100644 --- a/font-src/glyphs/common/derivatives.ptl +++ b/font-src/glyphs/common/derivatives.ptl @@ -17,7 +17,7 @@ glyph-block Common-Derivatives : begin local dst : glyphStore.queryByName dstName if dst : g.dependsOn dst if (para.enableCvSs && h.tag && h.rank) : begin - [Cv h.tag h.rank].set g dstName + [Cv h.tag h.rank h.rankGroup h.description].set g dstName if h.nonDeriving : [Cv h.tag h.rank].setPreventDeriving g glyph-block-export select-variant diff --git a/font-src/glyphs/letter/latin/upper-a.ptl b/font-src/glyphs/letter/latin/upper-a.ptl index 132b566fa..5be2ec6d6 100644 --- a/font-src/glyphs/letter/latin/upper-a.ptl +++ b/font-src/glyphs/letter/latin/upper-a.ptl @@ -1,6 +1,6 @@ $$include '../../../meta/macros.ptl' -import [mix linreg clamp fallback] from"../../../support/utils.mjs" +import [mix fallback SuffixCfg] from"../../../support/utils.mjs" import [Dotless CvDecompose MathSansSerif] from"../../../support/gr.mjs" import [maskBits bitOr] from"../../../support/util/mask-bit.mjs" @@ -27,15 +27,16 @@ glyph-block Letter-Latin-Upper-A : begin define [ABarPosition fBaseSlabs top] : mix [if fBaseSlabs Stroke 0] top (XH / 2 / CAP) glyph-block-export AConfig - define AConfig : object - straightSerifless { true SLAB-NONE } - curlySerifless { false SLAB-NONE } - straightTopSerifed { true SLAB-TOP } - curlyTopSerifed { false SLAB-TOP } - straightBaseSerifed { true [bitOr SLAB-LEFT SLAB-RIGHT] } - curlyBaseSerifed { false [bitOr SLAB-LEFT SLAB-RIGHT] } - straightTriSerifed { true [bitOr SLAB-TOP SLAB-LEFT SLAB-RIGHT] } - curlyTriSerifed { false [bitOr SLAB-TOP SLAB-LEFT SLAB-RIGHT] } + define AConfig : SuffixCfg.weave + object + straight true + curly false + + object + serifless SLAB-NONE + topSerifed SLAB-TOP + baseSerifed [bitOr SLAB-LEFT SLAB-RIGHT] + triSerifed [bitOr SLAB-TOP SLAB-LEFT SLAB-RIGHT] define [ASerifs df top sw slabKind] : glyph-proc : begin local sf : SerifFrame.fromDf df top 0 diff --git a/font-src/support/gr.mjs b/font-src/support/gr.mjs index 84f9f9835..65c5004c2 100644 --- a/font-src/support/gr.mjs +++ b/font-src/support/gr.mjs @@ -34,15 +34,15 @@ function LinkedGlyphProp(key) { }; } -export const Nwid = OtlTaggedProp("Nwid", "NWID"); -export const Wwid = OtlTaggedProp("Wwid", "WWID"); -export const Lnum = OtlTaggedProp("Lnum", "lnum"); -export const Onum = OtlTaggedProp("Onum", "onum"); -export const AplForm = OtlTaggedProp("AplForm", "APLF"); +export const Nwid = OtlTaggedProp("Nwid", "NWID", "Wide cell"); +export const Wwid = OtlTaggedProp("Wwid", "WWID", "Narrow cell"); +export const Lnum = OtlTaggedProp("Lnum", "lnum", "Lining number"); +export const Onum = OtlTaggedProp("Onum", "onum", "Old-style number"); +export const AplForm = OtlTaggedProp("AplForm", "APLF", "APL form"); export const NumeratorForm = OtlTaggedProp("Numerator", "numr"); export const DenominatorForm = OtlTaggedProp("Denominator", "dnom"); -function OtlTaggedProp(key, otlTag) { - return { ...LinkedGlyphProp(key), otlTag }; +function OtlTaggedProp(key, otlTag, description) { + return { ...LinkedGlyphProp(key), otlTag, description }; } export const CvDecompose = DecompositionProp("CvDecompose"); @@ -145,12 +145,14 @@ export const Joining = { const CvTagCache = new Map(); -export function Cv(tag, rank) { +export function Cv(tag, rank, rankGroup, description) { const key = tag + "#" + rank; if (CvTagCache.has(key)) return CvTagCache.get(key); const rel = { tag, rank, + rankGroup, + description, get(glyph) { if (glyph && glyph.related && glyph.related.cv) return glyph.related.cv[key]; else return null; @@ -320,39 +322,63 @@ export function createGrDisplaySheet(glyphStore, gid) { if (!glyph) return []; // Query selected typographic features -- mostly NWID and WWID let typographicFeatures = []; - displayQueryPairFeatures(glyphStore, gid, Nwid, Wwid, typographicFeatures); - displayQueryPairFeatures(glyphStore, gid, Lnum, Onum, typographicFeatures); - displayQuerySingleFeature(glyphStore, gid, AplForm, typographicFeatures); + displayQueryPairFeatures(glyphStore, gid, "Width", Nwid, Wwid, typographicFeatures); + displayQueryPairFeatures(glyphStore, gid, "Number Form", Lnum, Onum, typographicFeatures); + displayQuerySingleFeature(glyphStore, gid, "APL Form", AplForm, typographicFeatures); + + // Query selected character variants let charVariantFeatures = []; const decomposition = CvDecompose.get(glyph) || PseudoCvDecompose.get(glyph); if (decomposition) { - const variantAssignmentSet = new Set(); + const tagSet = new Set(); for (const componentGn of decomposition) { const component = glyphStore.queryByName(componentGn); if (!component) continue; - queryCvFeatureTagsOf(charVariantFeatures, componentGn, component, variantAssignmentSet); + queryCvFeatureTagsOf(charVariantFeatures, componentGn, component, tagSet); } } else { queryCvFeatureTagsOf(charVariantFeatures, gid, glyph, null); } return [typographicFeatures, charVariantFeatures]; } -function displayQueryPairFeatures(gs, gid, grCis, grTrans, sink) { + +function FeatureSeries(name, groups) { + return { + name, + groups + }; +} + +function displayQueryPairFeatures(gs, gid, name, grCis, grTrans, sink) { const g = gs.queryByName(gid); if (!g) return; const glyphIsHidden = /^\./.test(gid); if (glyphIsHidden) return; if (grCis.get(g) || grTrans.get(g)) { - sink.push(`'${grCis.otlTag}' 1`, `'${grTrans.otlTag}' 1`); + sink.push( + FeatureSeries(name, [ + [ + { css: `'${grCis.otlTag}' 1`, description: grCis.description }, + { css: `'${grTrans.otlTag}' 1`, description: grTrans.description } + ] + ]) + ); } } -function displayQuerySingleFeature(gs, gid, grCis, sink) { +function displayQuerySingleFeature(gs, gid, name, grCis, sink) { const g = gs.queryByName(gid); if (!g) return; const glyphIsHidden = /^\./.test(gid); if (glyphIsHidden) return; if (grCis.get(g)) { - sink.push(`'${grCis.otlTag}' 0`, `'${grCis.otlTag}' 1`); + sink.push( + FeatureSeries(name, [ + [ + { css: `'${grCis.otlTag}' 0`, description: grCis.description + " disabled" }, + { css: `'${grCis.otlTag}' 1`, description: grCis.description + " enabled" } + ] + ]) + ); } } function byTagPreference(a, b) { @@ -362,30 +388,29 @@ function byTagPreference(a, b) { if (ua > ub) return 1; return 0; } -function queryCvFeatureTagsOf(sink, gid, glyph, variantAssignmentSet) { +function queryCvFeatureTagsOf(sink, gid, glyph, tagSet) { const cvs = AnyCv.query(glyph).sort(byTagPreference); - let existingGlyphs = new Set(); - let m = new Map(); + let existingFeatures = new Map(); + for (const gr of cvs) { - const tag = gr.tag; const target = gr.get(glyph); if (target === gid) continue; - if (existingGlyphs.has(target)) continue; - existingGlyphs.add(target); - let g = m.get(tag); - if (!g) { - g = []; - m.set(tag, g); - } - const assignCss = `'${tag}' ${gr.rank}`; - if (!variantAssignmentSet) { - g.push(assignCss); - } else if (!variantAssignmentSet.has(assignCss)) { - g.push(assignCss); - variantAssignmentSet.add(assignCss); + + let series = existingFeatures.get(gr.tag); + if (!series) { + if (tagSet) { + if (tagSet.has(gr.tag)) continue; + tagSet.add(gr.tag); + } + series = FeatureSeries(gr.tag, [[]]); + existingFeatures.set(gr.tag, series); } + + const featureApp = { css: `'${gr.tag}' ${gr.rank}`, description: gr.description }; + if (!series.groups[gr.rankGroup]) series.groups[gr.rankGroup] = []; + series.groups[gr.rankGroup].push(featureApp); } - for (const g of m.values()) if (g.length) sink.push(g); + for (const g of existingFeatures.values()) sink.push(g); } export function linkSuffixGr(gs, suffix, gr) { diff --git a/font-src/support/variant-data.mjs b/font-src/support/variant-data.mjs index fa0a31abb..1770617eb 100644 --- a/font-src/support/variant-data.mjs +++ b/font-src/support/variant-data.mjs @@ -215,10 +215,12 @@ class VariantBuilder { } } process() { - const globalState = new VbGlobalState(this.stages); + const globalState = new VbGlobalState(this.entry, this.stages); const localState = new VbLocalState(); localState.descriptionLeader = this.descriptionLeader; + globalState.stages.get(this.entry).accept(globalState, localState); + let ans = {}; for (const item of globalState.sink) { let cfg = item.createPrimeVariant(); @@ -285,6 +287,7 @@ class VbStageAlternative { const ans = localState.clone(); ans.stage = this.next; ans.assignments.set(this.stage, this.key); + if (this.stage === globalState.entry) ans.rankGroup = this.rank; if (this.keyAffix) ans.addKeyAffix(this.mode, this.keyAffix); if (this.descriptionJoiner && this.descriptionAffix) ans.addDescription(this.mode, this.descriptionJoiner, this.descriptionAffix); @@ -328,7 +331,8 @@ class VbStageAlternative { } class VbGlobalState { - constructor(stages) { + constructor(entry, stages) { + this.entry = entry; this.stages = stages; this.rank = 0; this.sink = []; @@ -339,6 +343,7 @@ class VbLocalState { constructor() { this.stage = ".start"; this.rank = 0; + this.rankGroup = 0; this.descriptionLeader = ""; this.assignments = new Map(); @@ -351,6 +356,7 @@ class VbLocalState { const ans = new VbLocalState(); ans.stage = this.stage; ans.rank = this.rank; + ans.rankGroup = this.rankGroup; ans.descriptionLeader = this.descriptionLeader; ans.assignments = new Map(this.assignments); ans.key = [...this.key]; @@ -428,6 +434,7 @@ class VbLocalState { return { key: this.produceKey(), rank: this.rank, + rankGroup: this.rankGroup, description: this.produceDescription(), selector: Object.fromEntries(this.selector) }; diff --git a/params/variants.toml b/params/variants.toml index caf3da868..9a91a1ab2 100644 --- a/params/variants.toml +++ b/params/variants.toml @@ -3,61 +3,55 @@ sampler = "A" tag = "cv01" -[prime.capital-a.variants.straight-serifless] +[prime.capital-a.variants-buildup] +entry = "body" +descriptionLeader = "`A`" + +[prime.capital-a.variants-buildup.stages.body."*"] +next = "serifs" + +[prime.capital-a.variants-buildup.stages.body.straight] rank = 1 -description = "Standard, straight `A`, without serifs" -selector.A = "straightSerifless" -selector."A/sansSerif" = "straightSerifless" -selector.AE = "straight" +descriptionAffix = "straight shape" +selectorAffix.A = "straight" +selectorAffix."A/sansSerif" = "straight" +selectorAffix.AE = "straight" -[prime.capital-a.variants.straight-top-serifed] +[prime.capital-a.variants-buildup.stages.body.curly] rank = 2 -description = "Straight `A` with serif at top" -selector.A = "straightTopSerifed" -selector."A/sansSerif" = "straightSerifless" -selector.AE = "straight" +descriptionAffix = "curly shape" +selectorAffix.A = "curly" +selectorAffix."A/sansSerif" = "curly" +selectorAffix.AE = "curly" -[prime.capital-a.variants.straight-base-serifed] +[prime.capital-a.variants-buildup.stages.serifs.serifless] +rank = 1 +descriptionAffix = "serifs" +descriptionJoiner = "without" +selectorAffix.A = "serifless" +selectorAffix."A/sansSerif" = "serifless" +selectorAffix.AE = "" + +[prime.capital-a.variants-buildup.stages.serifs.top-serifed] +rank = 2 +descriptionAffix = "serifs at top" +selectorAffix.A = "topSerifed" +selectorAffix."A/sansSerif" = "serifless" +selectorAffix.AE = "" + +[prime.capital-a.variants-buildup.stages.serifs.base-serifed] rank = 3 -description = "Straight `A` with serif at both top and bottom" -selector.A = "straightBaseSerifed" -selector."A/sansSerif" = "straightSerifless" -selector.AE = "straight" +descriptionAffix = "serifs at base" +selectorAffix.A = "baseSerifed" +selectorAffix."A/sansSerif" = "serifless" +selectorAffix.AE = "" -[prime.capital-a.variants.straight-tri-serifed] +[prime.capital-a.variants-buildup.stages.serifs.tri-serifed] rank = 4 -description = "Straight `A` with serif at both top and bottom" -selector.A = "straightTriSerifed" -selector."A/sansSerif" = "straightSerifless" -selector.AE = "straight" - -[prime.capital-a.variants.curly-serifless] -rank = 5 -description = "Slightly curly `A`, like Iosevka 2.x, without serifs" -selector.A = "curlySerifless" -selector."A/sansSerif" = "curlySerifless" -selector.AE = "curly" - -[prime.capital-a.variants.curly-top-serifed] -rank = 6 -description = "Slightly curly `A`, like Iosevka 2.x, with serif at top" -selector.A = "curlyTopSerifed" -selector."A/sansSerif" = "curlySerifless" -selector.AE = "curly" - -[prime.capital-a.variants.curly-base-serifed] -rank = 7 -description = "Slightly curly `A`, like Iosevka 2.x, with serif at both top and bottom" -selector.A = "curlyBaseSerifed" -selector."A/sansSerif" = "curlySerifless" -selector.AE = "curly" - -[prime.capital-a.variants.curly-tri-serifed] -rank = 8 -description = "Slightly curly `A`, like Iosevka 2.x, with serif at both top and bottom" -selector.A = "curlyTriSerifed" -selector."A/sansSerif" = "curlySerifless" -selector.AE = "curly" +descriptionAffix = "serifs at both top and base" +selectorAffix.A = "triSerifed" +selectorAffix."A/sansSerif" = "serifless" +selectorAffix.AE = "" @@ -65,89 +59,65 @@ selector.AE = "curly" sampler = "B" tag = "cv02" -[prime.capital-b.variants.standard-serifless] +[prime.capital-b.variants-buildup] +entry = "symmetry" +descriptionLeader = "`B`" + +[prime.capital-b.variants-buildup.stages.symmetry."*"] +next = "openness" + +[prime.capital-b.variants-buildup.stages.symmetry.standard] rank = 1 -description = "`B` in near-symmetric proportion, without serifs" -selector.B = "standardSerifless" -selector."B/sansSerif" = "standardSerifless" -selector.smcpB = "standardSerifless" +descriptionAffix = "mostly symmetric shape" +selectorAffix.B = "standard" +selectorAffix."B/sansSerif" = "standard" +selectorAffix.smcpB = "standard" -[prime.capital-b.variants.standard-unilateral-serifed] +[prime.capital-b.variants-buildup.stages.symmetry.more-asymmetric] rank = 2 -description = "`B` in near-symmetric proportion with motion serifs at top" -selector.B = "standardUnilateralSerifed" -selector."B/sansSerif" = "standardSerifless" -selector.smcpB = "standardUnilateralSerifed" +descriptionAffix = "more asymmetric shape" +selectorAffix.B = "moreAsymmetric" +selectorAffix."B/sansSerif" = "moreAsymmetric" +selectorAffix.smcpB = "moreAsymmetric" -[prime.capital-b.variants.standard-bilateral-serifed] +[prime.capital-b.variants-buildup.stages.openness."*"] +next = "serifs" + +[prime.capital-b.variants-buildup.stages.openness.closed] +rank = 1 +keyAffix = "" +selectorAffix.B = "" +selectorAffix."B/sansSerif" = "" +selectorAffix.smcpB = "" + +[prime.capital-b.variants-buildup.stages.openness.interrupted] +rank = 2 +descriptionAffix = "interrupted middle bar" +selectorAffix.B = "interrupted" +selectorAffix."B/sansSerif" = "interrupted" +selectorAffix.smcpB = "interrupted" + +[prime.capital-b.variants-buildup.stages.serifs.serifless] +rank = 1 +descriptionAffix = "serifs" +descriptionJoiner = "without" +selectorAffix.B = "serifless" +selectorAffix."B/sansSerif" = "serifless" +selectorAffix.smcpB = "serifless" + +[prime.capital-b.variants-buildup.stages.serifs.unilateral-serifed] +rank = 2 +descriptionAffix = "serifs at top" +selectorAffix.B = "unilateralSerifed" +selectorAffix."B/sansSerif" = "serifless" +selectorAffix.smcpB = "unilateralSerifed" + +[prime.capital-b.variants-buildup.stages.serifs.bilateral-serifed] rank = 3 -description = "`B` in near-symmetric proportion with motion serifs at both top and bottom" -selector.B = "standardBilateralSerifed" -selector."B/sansSerif" = "standardSerifless" -selector.smcpB = "standardBilateralSerifed" - -[prime.capital-b.variants.more-asymmetric-serifless] -rank = 4 -description = "`B` in more asymmetric proportion to differentiate with `8`, without serifs" -selector.B = "moreAsymmetricSerifless" -selector."B/sansSerif" = "moreAsymmetricSerifless" -selector.smcpB = "standardSerifless" - -[prime.capital-b.variants.more-asymmetric-unilateral-serifed] -rank = 5 -description = "`B` in more asymmetric proportion with motion serifs at top" -selector.B = "moreAsymmetricUnilateralSerifed" -selector."B/sansSerif" = "moreAsymmetricSerifless" -selector.smcpB = "standardUnilateralSerifed" - -[prime.capital-b.variants.more-asymmetric-bilateral-serifed] -rank = 6 -description = "`B` in more asymmetric proportion with motion serifs at both top and bottom" -selector.B = "moreAsymmetricBilateralSerifed" -selector."B/sansSerif" = "moreAsymmetricSerifless" -selector.smcpB = "standardBilateralSerifed" - -[prime.capital-b.variants.standard-interrupted-serifless] -rank = 7 -description = "`B` in near-symmetric proportion with interrupted middle bar, without serifs" -selector.B = "standardInterruptedSerifless" -selector."B/sansSerif" = "standardInterruptedSerifless" -selector.smcpB = "standardInterruptedSerifless" - -[prime.capital-b.variants.standard-interrupted-unilateral-serifed] -rank = 8 -description = "`B` in near-symmetric proportion with interrupted middle bar and motion serifs at top" -selector.B = "standardInterruptedUnilateralSerifed" -selector."B/sansSerif" = "standardInterruptedSerifless" -selector.smcpB = "standardInterruptedUnilateralSerifed" - -[prime.capital-b.variants.standard-interrupted-bilateral-serifed] -rank = 9 -description = "`B` in near-symmetric proportion with interrupted middle bar and motion serifs at both top and bottom" -selector.B = "standardInterruptedBilateralSerifed" -selector."B/sansSerif" = "standardInterruptedSerifless" -selector.smcpB = "standardInterruptedBilateralSerifed" - -[prime.capital-b.variants.more-asymmetric-interrupted-serifless] -rank = 10 -description = "`B` in more asymmetric proportion to differentiate with `8`, with interrupted middle bar, without serifs" -selector.B = "moreAsymmetricInterruptedSerifless" -selector."B/sansSerif" = "moreAsymmetricInterruptedSerifless" -selector.smcpB = "standardInterruptedSerifless" - -[prime.capital-b.variants.more-asymmetric-interrupted-unilateral-serifed] -rank = 11 -description = "`B` in more asymmetric proportion with interrupted middle bar and `8` with motion serifs at top" -selector.B = "moreAsymmetricInterruptedUnilateralSerifed" -selector."B/sansSerif" = "moreAsymmetricInterruptedSerifless" -selector.smcpB = "standardInterruptedUnilateralSerifed" - -[prime.capital-b.variants.more-asymmetric-interrupted-bilateral-serifed] -rank = 12 -description = "`B` in more asymmetric proportion with interrupted middle bar and `8` with motion serifs at both top and bottom" -selector.B = "moreAsymmetricInterruptedBilateralSerifed" -selector."B/sansSerif" = "moreAsymmetricInterruptedSerifless" -selector.smcpB = "standardInterruptedBilateralSerifed" +descriptionAffix = "serifs at both top and bottom" +selectorAffix.B = "bilateralSerifed" +selectorAffix."B/sansSerif" = "serifless" +selectorAffix.smcpB = "bilateralSerifed" diff --git a/utility/export-data/coverage-export/gather-coverage-data.mjs b/utility/export-data/coverage-export/gather-coverage-data.mjs index 9524796c6..b3436a929 100644 --- a/utility/export-data/coverage-export/gather-coverage-data.mjs +++ b/utility/export-data/coverage-export/gather-coverage-data.mjs @@ -20,8 +20,11 @@ function findFirstLastChar(lchBlockStart, lchBlockEnd, cov) { const lchEnd = ((lchLast >>> 4) << 4) + 0x10; return [lchStart, lchEnd]; } + export async function gatherCoverageData(covUpright, covItalic, covOblique) { - const result = []; + const featureSeriesStore = new Map(); + const unicodeCoverage = []; + for (const [[lchBlockStart, lchBlockEnd], block] of await collectBlockData()) { let blockResults = []; const [lchStart, lchEnd] = findFirstLastChar(lchBlockStart, lchBlockEnd, covUpright); @@ -33,19 +36,19 @@ export async function gatherCoverageData(covUpright, covItalic, covOblique) { const cdItalic = covItalic.get(lch); const cdOblique = covOblique.get(lch); if (cdUpright && cdItalic && cdOblique) { - const [glyphName, typographicVariants, charVariantsUpright] = cdUpright; - const [, , charVariantsItalic] = cdItalic; - const [, , charVariantsOblique] = cdOblique; + const [glyphName, typoFs, uprightFs] = cdUpright; + const [, , italicFs] = cdItalic; + const [, , obliqueFs] = cdOblique; blockResults.push({ lch, gc, charName: chName, inFont: true, glyphName: glyphName, - typographicVariants: typographicVariants, - charVariantsUpright, - charVariantsItalic, - charVariantsOblique + ...putFeatSeries(featureSeriesStore, "typographicFeatureSets", typoFs), + ...putFeatSeries(featureSeriesStore, "cvFeatureSetsUpright", uprightFs), + ...putFeatSeries(featureSeriesStore, "cvFeatureSetsItalic", italicFs), + ...putFeatSeries(featureSeriesStore, "cvFeatureSetsOblique", obliqueFs) }); } else { blockResults.push({ @@ -58,11 +61,53 @@ export async function gatherCoverageData(covUpright, covItalic, covOblique) { } } if (blockResults.length) { - result.push({ + unicodeCoverage.push({ name: block, characters: blockResults.sort((a, b) => a.lch - b.lch) }); } } - return result; + + let featureSeries = []; + for (const [id, x] of featureSeriesStore.values()) featureSeries[id] = x; + + return { unicodeCoverage, featureSeries }; +} + +function putFeatSeries(store, k, featSeriesList) { + if (!featSeriesList) return null; + + let reduced = []; + for (const featSeries of featSeriesList) { + const key = + featSeries.name + + ";;" + + featSeries.groups.map(g => g.map(a => a.css).join(";;")).join(";;"); + + let vs = store.get(key); + if (vs) { + reduced.push(vs[0]); + } else { + const idNeo = store.size; + const validated = ValidateFeatureSeries(featSeries); + if (!validated) continue; + store.set(key, [idNeo, validated]); + reduced.push(idNeo); + } + } + + if (!reduced || !reduced.length) return null; + return { [k]: reduced }; +} + +function ValidateFeatureSeries(s) { + let size = 0; + let reducedGroups = []; + for (const g of s.groups) { + if (!g || !g.length) continue; + reducedGroups.push(g); + size += g.length; + } + if (!size) return null; + return { name: s.name, size, groups: reducedGroups }; } diff --git a/utility/export-data/supported-languages.mjs b/utility/export-data/supported-languages.mjs index 96449d153..9d434edd4 100644 --- a/utility/export-data/supported-languages.mjs +++ b/utility/export-data/supported-languages.mjs @@ -93,16 +93,16 @@ export async function getCharMapAndSupportedLanguageList(cmpUpright, cmpItalic, const rawCoverage = getRawCoverage(charMap); const rawCoverageItalic = getRawCoverage(charMapItalic); const rawCoverageOblique = getRawCoverage(charMapOblique); + + const covData = await gatherCoverageData(rawCoverage, rawCoverageItalic, rawCoverageOblique); + return { stats: { glyphCount: charMap.length, codePointCount: rawCoverage.size }, - unicodeCoverage: await gatherCoverageData( - rawCoverage, - rawCoverageItalic, - rawCoverageOblique - ), + featureSeries: covData.featureSeries, + unicodeCoverage: covData.unicodeCoverage, languages: Array.from(getSupportedLanguageSet(rawCoverage)).sort() }; }