Optimize the footprint of TTCs and Super-TTCs by 1/3.

This commit is contained in:
be5invis 2021-06-12 03:13:46 -07:00
parent ededbbc703
commit 6135354a30
28 changed files with 252 additions and 169 deletions

View file

@ -88,6 +88,7 @@ function markGlyphsInitial(glyphStore, excludedChars) {
} }
function markGlyphsStep(glyphStore, sink, otl, cfg) { function markGlyphsStep(glyphStore, sink, otl, cfg) {
const glyphCount = sink.size; const glyphCount = sink.size;
if (otl.GSUB) { if (otl.GSUB) {
for (const l in otl.GSUB.lookups) { for (const l in otl.GSUB.lookups) {
const lookup = otl.GSUB.lookups[l]; const lookup = otl.GSUB.lookups[l];

View file

@ -42,7 +42,7 @@ function regulateCompositeGlyph(glyphStore, memo, g) {
for (const sr of refs) { for (const sr of refs) {
const gn = glyphStore.queryNameOf(sr.glyph); const gn = glyphStore.queryNameOf(sr.glyph);
if (!gn || sr.glyph.autoRefPriority < 0) return memoSet(memo, g, false); if (!gn) return memoSet(memo, g, false);
} }
// De-doppelganger // De-doppelganger

View file

@ -2,21 +2,38 @@
const finalizeGlyphs = require("./glyphs"); const finalizeGlyphs = require("./glyphs");
const gcFont = require("./gc"); const gcFont = require("./gc");
const { Nwid, Wwid } = require("../../support/gr");
module.exports = function finalizeFont(cache, para, glyphStore, excludedCodePoints, restFont) { module.exports = function finalizeFont(cache, para, glyphStore, excludedCodePoints, restFont) {
assignGrAndCodeRank(glyphStore, Nwid, Wwid);
assignSubRank(glyphStore);
glyphStore = gcFont(glyphStore, excludedCodePoints, restFont, {}); glyphStore = gcFont(glyphStore, excludedCodePoints, restFont, {});
glyphStore = finalizeGlyphs(cache, para, glyphStore); glyphStore = finalizeGlyphs(cache, para, glyphStore);
validateMonospace(para, glyphStore); validateMonospace(para, glyphStore);
return glyphStore; return glyphStore;
}; };
function assignGrAndCodeRank(glyphStore, ...flatteners) {
for (const g of glyphStore.glyphs()) {
g.codeRank = 0xffffffff;
for (const c of glyphStore.flattenCodes(g, flatteners)) if (c < g.codeRank) g.codeRank = c;
g.grRank = 0;
for (let i = 0; i < flatteners.length; i++) if (flatteners[i].get(g)) g.grRank |= 1 << i;
}
}
function assignSubRank(glyphStore) {
let sr = 0;
for (const g of glyphStore.glyphs()) g.subRank = sr++;
}
// In FontConfig, a font is considered "monospace" if and only if all non-combining characters // In FontConfig, a font is considered "monospace" if and only if all non-combining characters
// (AW > 0) have the same width. We use this method to validate whether our "Fixed" subfamilies // (AW > 0) have the same width. We use this method to validate whether our "Fixed" subfamilies
// are properly built. // are properly built.
function validateMonospace(para, glyphStore) { function validateMonospace(para, glyphStore) {
if (!para.forceMonospace) return; if (!para.forceMonospace) return;
let awSet = new Set(); let awSet = new Set();
for (const g of glyphStore.glyphs()) { for (const [u, g] of glyphStore.encodedEntries()) {
const aw = Math.round(g.advanceWidth || 0); const aw = Math.round(g.advanceWidth || 0);
if (aw > 0) awSet.add(aw); if (aw > 0) awSet.add(aw);
} }

View file

@ -1,4 +1,4 @@
const { Joining, AnyCv, TieMark } = require("../../support/gr"); const { Joining, AnyCv, TieMark, Nwid, Wwid } = require("../../support/gr");
const ApplePostNames = new Map([ const ApplePostNames = new Map([
/* spell-checker: disable */ /* spell-checker: disable */
@ -261,9 +261,9 @@ const ApplePostNames = new Map([
/* spell-checker: enable */ /* spell-checker: enable */
]); ]);
function nameSingleGlyph1(gid, gSrc, primaryUnicode, conflictSet) { function byCode(gSrc, primaryUnicode, conflictSet) {
if (gid === 0) return ".notdef"; if (gSrc.glyphRank === 9999) return ".notdef";
if (gid === 1) return ".null"; if (gSrc.glyphRank === 9998) return ".null";
let preferredName = null; let preferredName = null;
if (primaryUnicode) { if (primaryUnicode) {
@ -279,32 +279,61 @@ function nameSingleGlyph1(gid, gSrc, primaryUnicode, conflictSet) {
function formatCodePointHex(u) { function formatCodePointHex(u) {
return u.toString(16).padStart(4, "0").toUpperCase(); return u.toString(16).padStart(4, "0").toUpperCase();
} }
function bySpacing(gSrcBase, gOtBase, internalNameMap, conflictSet) {
function nameSingleGlyph2(gSrcBase, baseName, internalNameMap, conflictSet) { if (!gOtBase.name) return 0;
if (!baseName) return; let n = 0;
n += nameByPairGr(Nwid, Wwid, "NWID", "WWID", gSrcBase, gOtBase, internalNameMap, conflictSet);
n += nameByPairGr(Wwid, Nwid, "WWID", "NWID", gSrcBase, gOtBase, internalNameMap, conflictSet);
return n;
}
function byGr(gSrcBase, gOtBase, internalNameMap, conflictSet) {
if (!gOtBase.name) return 0;
let n = 0;
for (const cv of AnyCv.query(gSrcBase)) { for (const cv of AnyCv.query(gSrcBase)) {
nameByGr(cv, gSrcBase, baseName, internalNameMap, conflictSet); n += nameByGr(cv, gSrcBase, gOtBase, internalNameMap, conflictSet);
} }
if (TieMark.get(gSrcBase)) { if (TieMark.get(gSrcBase)) {
nameByGr(TieMark, gSrcBase, baseName, internalNameMap, conflictSet); n += nameByGr(TieMark, gSrcBase, gOtBase, internalNameMap, conflictSet);
} }
return n;
} }
function nameByGr(gr, gSrcBase, baseName, internalNameMap, conflictSet) { function nameByPairGr(grCis, grTrans, tagCis, tagTrans, gSrcBase, gOtBase, nm, conflictSet) {
const gnDst = grCis.get(gSrcBase);
if (!gnDst) return 0;
const gOtDst = nm.get(gnDst);
if (!gOtDst || gOtDst.name) return 0;
const nameS = gOtBase.name + "." + tagTrans;
const nameT = gOtBase.name + "." + tagCis;
if (!conflictSet.has(nameS) && !conflictSet.has(nameT)) {
conflictSet.add(nameS);
conflictSet.add(nameT);
gOtBase.name = nameS;
gOtDst.name = nameT;
return 1;
}
return 0;
}
function nameByGr(gr, gSrcBase, gOtBase, internalNameMap, conflictSet) {
const gnDst = gr.get(gSrcBase); const gnDst = gr.get(gSrcBase);
if (!gnDst) return 0;
const gOtDst = internalNameMap.get(gnDst); const gOtDst = internalNameMap.get(gnDst);
const nameT = gr.amendOtName(baseName); if (!gOtDst || gOtDst.name) return 0;
if (gOtDst && !gOtDst.name && !conflictSet.has(nameT)) { const nameT = gr.amendOtName(gOtBase.name);
if (!conflictSet.has(nameT)) {
conflictSet.add(nameT); conflictSet.add(nameT);
gOtDst.name = nameT; gOtDst.name = nameT;
return 1;
} }
return 0;
} }
function nameSingleGlyph3(gid, gSrc, gnOrig) { function byBuildOrder(rank, gSrc, gnOrig) {
if (!gnOrig) gnOrig = `.gid${gid}`; if (!gnOrig) gnOrig = `.g${rank}`;
gnOrig = Joining.amendOtName(gnOrig, Joining.get(gSrc)); gnOrig = Joining.amendOtName(gnOrig, Joining.get(gSrc));
return gnOrig; return gnOrig;
} }
exports.nameSingleGlyph1 = nameSingleGlyph1; exports.byCode = byCode;
exports.nameSingleGlyph2 = nameSingleGlyph2; exports.bySpacing = bySpacing;
exports.nameSingleGlyph3 = nameSingleGlyph3; exports.byGr = byGr;
exports.byBuildOrder = byBuildOrder;

View file

@ -1,6 +1,7 @@
const { Ot } = require("ot-builder"); const { Ot } = require("ot-builder");
const Point = require("../../support/point"); const Point = require("../../support/point");
const { nameSingleGlyph1, nameSingleGlyph2, nameSingleGlyph3 } = require("./glyph-name"); const Gr = require("../../support/gr");
const { byCode, bySpacing, byGr, byBuildOrder } = require("./glyph-name");
class MappedGlyphStore { class MappedGlyphStore {
constructor() { constructor() {
@ -16,6 +17,7 @@ class MappedGlyphStore {
setPrimaryUnicode(source, u) { setPrimaryUnicode(source, u) {
this.m_primaryUnicodeMapping.set(u, source); this.m_primaryUnicodeMapping.set(u, source);
} }
queryBySourceGlyph(source) { queryBySourceGlyph(source) {
return this.m_mapping.get(source); return this.m_mapping.get(source);
} }
@ -48,23 +50,44 @@ class MappedGlyphStore {
let conflictSet = new Set(); let conflictSet = new Set();
let rev = new Map(); let rev = new Map();
for (const [u, g] of this.m_primaryUnicodeMapping) rev.set(g, u); for (const [u, g] of this.m_primaryUnicodeMapping) rev.set(g, u);
for (const [gSrc, gOt] of this.m_mapping) gOt.name = undefined;
const glyphsInBuildOrder = Array.from(this.m_mapping).sort(
([a], [b]) => a.subRank - b.subRank
);
for (const [gSrc, gOt] of glyphsInBuildOrder) gOt.name = undefined;
// Name by Unicode // Name by Unicode
gid = 0; for (const [gSrc, gOt] of glyphsInBuildOrder) {
for (const [gSrc, gOt] of this.m_mapping) { gOt.name = byCode(gSrc, rev.get(gSrc), conflictSet);
gOt.name = nameSingleGlyph1(gid, gSrc, rev.get(gSrc), conflictSet);
gid++;
}
// Name by CV
for (const [gSrcBase, gOtBase] of this.m_mapping) {
nameSingleGlyph2(gSrcBase, gOtBase.name, this.m_nameMapping, conflictSet);
} }
// Name by NWID/WWID
let nNewNames = 0;
do {
nNewNames = 0;
for (const [gSrcBase, gOtBase] of glyphsInBuildOrder) {
nNewNames += bySpacing(gSrcBase, gOtBase, this.m_nameMapping, conflictSet);
}
} while (nNewNames > 0);
// Name by Gr
do {
nNewNames = 0;
for (const [gSrcBase, gOtBase] of glyphsInBuildOrder) {
nNewNames += byGr(gSrcBase, gOtBase, this.m_nameMapping, conflictSet);
}
} while (nNewNames > 0);
// Name rest // Name rest
gid = 0; for (const [gSrc, gOt] of glyphsInBuildOrder) {
for (const [gSrc, gOt] of this.m_mapping) { gOt.name = byBuildOrder(gSrc.subRank, gSrc, gOt.name);
gOt.name = nameSingleGlyph3(gid, gSrc, gOt.name); }
gid++;
// validate
{
let gnSet = new Set();
for (const [gSrc, gOt] of this.m_mapping) {
if (gnSet.has(gOt.name)) throw new Error("Unreachable! duplicate name " + gOt.name);
gnSet.add(gOt.name);
}
} }
} }
@ -101,14 +124,12 @@ class MappedGlyphStore {
module.exports = convertGlyphs; module.exports = convertGlyphs;
function convertGlyphs(gsOrig) { function convertGlyphs(gsOrig) {
const sortedEntries = Array.from(gsOrig.indexedNamedEntries()) const sortedEntries = Array.from(gsOrig.namedEntries(Gr.Nwid, Gr.Wwid)).sort(byRank);
.map(([j, gn, g]) => [j, gn, queryOrderingUnicode(gsOrig, g), g])
.sort(byRank);
const gs = new MappedGlyphStore(); const gs = new MappedGlyphStore();
const cmap = new Ot.Cmap.Table(); const cmap = new Ot.Cmap.Table();
for (const [origIndex, name, uOrd, gSrc] of sortedEntries) { for (const [name, gSrc] of sortedEntries) {
gs.declare(name, gSrc); gs.declare(name, gSrc);
const us = gsOrig.queryUnicodeOf(gSrc); const us = gsOrig.queryUnicodeOf(gSrc);
if (us) { if (us) {
@ -119,17 +140,16 @@ function convertGlyphs(gsOrig) {
} }
} }
} }
for (const [origIndex, name, uOrd, gSrc] of sortedEntries) gs.fill(name, gSrc); for (const [name, gSrc] of sortedEntries) gs.fill(name, gSrc);
gs.fillOtGlyphNames(); gs.fillOtGlyphNames();
return { glyphs: gs, cmap }; return { glyphs: gs, cmap };
} }
function queryOrderingUnicode(gs, g) {
const us = gs.queryUnicodeOf(g); function byRank([gna, a], [gnb, b]) {
if (us && us.size) return Array.from(us).sort((a, b) => a - b)[0];
else return 0xffffff;
}
function byRank([ja, gna, ua, a], [jb, gnb, ub, b]) {
return ( return (
(b.glyphRank || 0) - (a.glyphRank || 0) || (ua || 0) - (ub || 0) || (ja || 0) - (jb || 0) b.glyphRank - a.glyphRank ||
a.grRank - b.grRank ||
a.codeRank - b.codeRank ||
a.subRank - b.subRank
); );
} }

View file

@ -569,8 +569,6 @@ glyph-block AutoBuild-Enclosure : begin
ps.push p ps.push p
include : Translate width 0 include : Translate width 0
if jobDecomposable : CvDecompose.set currentGlyph ps if jobDecomposable : CvDecompose.set currentGlyph ps
set currentGlyph.autoRefPriority 11
define gnSpace : '.dotted-space.' + [{ digits suffix }.join '/'] define gnSpace : '.dotted-space.' + [{ digits suffix }.join '/']
if [not : query-glyph gnSpace] : create-glyph gnSpace : glyph-proc if [not : query-glyph gnSpace] : create-glyph gnSpace : glyph-proc

View file

@ -80,7 +80,7 @@ glyph-block Autobuild-Transformed : begin
scale -- 0.7 scale -- 0.7
mono -- true mono -- true
sbscale -- 1 sbscale -- 1
foreach {unicode glyphid pri} [items-of records] foreach {unicode glyphid} [items-of records]
if [not : query-glyph targetNameMap.(glyphid)] if [not : query-glyph targetNameMap.(glyphid)]
create-glyph (targetNameMap.(glyphid)) unicode : glyph-proc create-glyph (targetNameMap.(glyphid)) unicode : glyph-proc
if [not : miniatureFont.queryByName glyphid] : begin if [not : miniatureFont.queryByName glyphid] : begin
@ -92,7 +92,6 @@ glyph-block Autobuild-Transformed : begin
include [Scale 0.7] true include [Scale 0.7] true
include [Translate middle (CAP + Accent / 2)] true include [Translate middle (CAP + Accent / 2)] true
include [Italify] true include [Italify] true
if pri : set currentGlyph.autoRefPriority pri
link-relations relSets link-relations relSets
return { targetNameMap records } return { targetNameMap records }
@ -104,7 +103,7 @@ glyph-block Autobuild-Transformed : begin
scale -- 0.7 scale -- 0.7
mono -- true mono -- true
sbscale -- 1 sbscale -- 1
foreach {unicode glyphid pri} [items-of records] foreach {unicode glyphid} [items-of records]
if [not : query-glyph targetNameMap.(glyphid)] if [not : query-glyph targetNameMap.(glyphid)]
create-glyph (targetNameMap.(glyphid)) unicode : glyph-proc create-glyph (targetNameMap.(glyphid)) unicode : glyph-proc
local middle : [miniatureFont.queryByName glyphid].advanceWidth / 2 local middle : [miniatureFont.queryByName glyphid].advanceWidth / 2
@ -114,7 +113,6 @@ glyph-block Autobuild-Transformed : begin
include [Scale 0.7] true include [Scale 0.7] true
include [Translate middle (Descender / 2)] true include [Translate middle (Descender / 2)] true
include [Italify] true include [Italify] true
if pri : set currentGlyph.autoRefPriority pri
link-relations relSets link-relations relSets
# Not used today -- may be used in the future # Not used today -- may be used in the future
@ -314,11 +312,11 @@ glyph-block Autobuild-Transformed : begin
list 0x1D41 'U' list 0x1D41 'U'
list 0x1D42 'W' list 0x1D42 'W'
list 0x2C7D 'V' list 0x2C7D 'V'
list 0x207A 'plus' (-11) list 0x207A 'plus'
list 0x207B 'minus' (-11) list 0x207B 'minus'
list 0x207C 'equal' (-11) list 0x207C 'equal'
list 0x207D 'parenLeft' (-11) list 0x207D 'parenLeft'
list 0x207E 'parenRight' (-11) list 0x207E 'parenRight'
list 0xA7F8 'smcpHbar' list 0xA7F8 'smcpHbar'
list 0xA7F9 'oe' list 0xA7F9 'oe'
@ -364,11 +362,11 @@ glyph-block Autobuild-Transformed : begin
list 0x1D69 'grek/phi' list 0x1D69 'grek/phi'
list 0x1D6A 'grek/chi' list 0x1D6A 'grek/chi'
list 0x2C7C 'j' list 0x2C7C 'j'
list 0x208A 'plus' (-11) list 0x208A 'plus'
list 0x208B 'minus' (-11) list 0x208B 'minus'
list 0x208C 'equal' (-11) list 0x208C 'equal'
list 0x208D 'parenLeft' (-11) list 0x208D 'parenLeft'
list 0x208E 'parenRight' (-11) list 0x208E 'parenRight'
createMedievalCombs 0 XH : list createMedievalCombs 0 XH : list
list 0x363 'a' list 0x363 'a'

View file

@ -102,7 +102,6 @@ glyph-block Common-Derivatives : begin
define x : if (_x <@ Function) [_x.call currentGlyph] _x define x : if (_x <@ Function) [_x.call currentGlyph] _x
define y : if (_y <@ Function) [_y.call currentGlyph] _y define y : if (_y <@ Function) [_y.call currentGlyph] _y
include : FlipAround x y include : FlipAround x y
set currentGlyph.autoRefPriority [query-glyph src].autoRefPriority
define [link-reduced-variant] : params [dstGid srcGid gr follow] : begin define [link-reduced-variant] : params [dstGid srcGid gr follow] : begin
if [not : query-glyph dstGid] : select-variant dstGid (shapeFrom -- srcGid) (follow -- [fallback follow dstGid]) if [not : query-glyph dstGid] : select-variant dstGid (shapeFrom -- srcGid) (follow -- [fallback follow dstGid])

View file

@ -3,6 +3,7 @@ import '../support/glyph-store' as GlyphStore
import '../support/glyph-block' as GlyphBlock import '../support/glyph-block' as GlyphBlock
import '../support/point' as Point import '../support/point' as Point
import '../support/anchor' as Anchor import '../support/anchor' as Anchor
import '../support/gr' as Gr
import '../kits/spiro-kit' as spirokit import '../kits/spiro-kit' as spirokit
import '../kits/boole-kit' as BooleKit import '../kits/boole-kit' as BooleKit
import [ DesignParameters ] from "../meta/aesthetics" import [ DesignParameters ] from "../meta/aesthetics"
@ -155,5 +156,7 @@ export all : define [buildGlyphs para recursive recursiveCodes] : begin
foreach [gb : items-of $$Capture$$.$pendingGlyphBlocks$] : gb.resolve foreach [gb : items-of $$Capture$$.$pendingGlyphBlocks$] : gb.resolve
return : object glyphStore fontMetrics Gr.linkSuffixPairGr glyphStore 'NWID' 'WWID' Gr.Nwid Gr.Wwid
Gr.linkSuffixPairGr glyphStore 'lnum' 'onum' Gr.Lnum Gr.Onum
return : object glyphStore fontMetrics

View file

@ -43,7 +43,6 @@ glyph-block Letter-Latin-Lower-L : begin
define [SeriflessBody df xMiddle] : glyph-proc define [SeriflessBody df xMiddle] : glyph-proc
include : VBar xMiddle 0 CAP include : VBar xMiddle 0 CAP
set currentGlyph.autoRefPriority (-2)
define [SerifedBody df xMiddle] : glyph-proc define [SerifedBody df xMiddle] : glyph-proc
include : VBar xMiddle 0 CAP include : VBar xMiddle 0 CAP

View file

@ -1197,7 +1197,6 @@ glyph-block Marks : begin
flat 0 (-O) [heading Downward] flat 0 (-O) [heading Downward]
curl 0 0 [heading Downward] curl 0 0 [heading Downward]
straight.right.end (HookX - HalfStroke * HVContrast) (-Hook + HalfStroke) straight.right.end (HookX - HalfStroke * HVContrast) (-Hook + HalfStroke)
set currentGlyph.autoRefPriority (-2)
create-glyph 'rRetroflexTailBR' : glyph-proc create-glyph 'rRetroflexTailBR' : glyph-proc
set-width 0 set-width 0
@ -1209,7 +1208,6 @@ glyph-block Marks : begin
flat (SideJut) Stroke [heading Downward] flat (SideJut) Stroke [heading Downward]
curl (SideJut) 0 [heading Downward] curl (SideJut) 0 [heading Downward]
straight.right.end (HookX - HalfStroke * HVContrast) (-Hook + HalfStroke) straight.right.end (HookX - HalfStroke * HVContrast) (-Hook + HalfStroke)
set currentGlyph.autoRefPriority (-2)
create-glyph 'ltailBR' 0x321 : glyph-proc create-glyph 'ltailBR' 0x321 : glyph-proc
set-width 0 set-width 0
@ -1220,7 +1218,6 @@ glyph-block Marks : begin
flat 0 (-O) [heading Downward] flat 0 (-O) [heading Downward]
curl 0 0 [heading Downward] curl 0 0 [heading Downward]
straight.left.end (-HookX - HalfStroke * HVContrast) (-Hook - HalfStroke) straight.left.end (-HookX - HalfStroke * HVContrast) (-Hook - HalfStroke)
set currentGlyph.autoRefPriority (-2)
# Overlay Marks # Overlay Marks
create-glyph 'tildeOver' 0x334 : glyph-proc create-glyph 'tildeOver' 0x334 : glyph-proc
@ -1424,7 +1421,6 @@ glyph-block Marks : begin
include : Translate (0 - k) 0 include : Translate (0 - k) 0
set-mark-anchor 'above' markMiddle XH markMiddle aboveMarkTop set-mark-anchor 'above' markMiddle XH markMiddle aboveMarkTop
set currentGlyph.autoRefPriority 50
create-glyph "\(id)GrekUpperTonos" : glyph-proc create-glyph "\(id)GrekUpperTonos" : glyph-proc
set-width 0 set-width 0
@ -1455,7 +1451,6 @@ glyph-block Marks : begin
archv archv
g4.down.end (markMiddle + radius) yc [heading Downward] g4.down.end (markMiddle + radius) yc [heading Downward]
set-mark-anchor 'above' markMiddle XH markMiddle (aboveMarkTop + markHalfStroke * 2) set-mark-anchor 'above' markMiddle XH markMiddle (aboveMarkTop + markHalfStroke * 2)
set currentGlyph.autoRefPriority 50
create-glyph 'psiliPerispomeniGrekUpperTonos' : glyph-proc create-glyph 'psiliPerispomeniGrekUpperTonos' : glyph-proc
set-width 0 set-width 0
@ -1479,7 +1474,6 @@ glyph-block Marks : begin
archv archv
g4.down.end (markMiddle + radius) yc [heading Downward] g4.down.end (markMiddle + radius) yc [heading Downward]
set-mark-anchor 'above' markMiddle XH markMiddle (aboveMarkTop + markHalfStroke * 2) set-mark-anchor 'above' markMiddle XH markMiddle (aboveMarkTop + markHalfStroke * 2)
set currentGlyph.autoRefPriority 50
create-glyph 'dasiaPerispomeniGrekUpperTonos' : glyph-proc create-glyph 'dasiaPerispomeniGrekUpperTonos' : glyph-proc
set-width 0 set-width 0
@ -1499,7 +1493,6 @@ glyph-block Marks : begin
alsoThru.g2 0.5 0.5 alsoThru.g2 0.5 0.5
g2.right.end (markMiddle + [Math.max radius (markExtend * 2)]) yc [heading Rightward] g2.right.end (markMiddle + [Math.max radius (markExtend * 2)]) yc [heading Rightward]
set-mark-anchor 'above' markMiddle XH markMiddle (aboveMarkTop + markHalfStroke * 2) set-mark-anchor 'above' markMiddle XH markMiddle (aboveMarkTop + markHalfStroke * 2)
set currentGlyph.autoRefPriority 50
create-glyph 'spaced_dasiaPerispomeni' 0x1FDF : glyph-proc create-glyph 'spaced_dasiaPerispomeni' 0x1FDF : glyph-proc
include [refer-glyph 'markBaseSpace'] AS_BASE include [refer-glyph 'markBaseSpace'] AS_BASE

View file

@ -53,7 +53,6 @@ glyph-block Digits-One : begin
create-glyph 'one.lnum.line' : glyph-proc create-glyph 'one.lnum.line' : glyph-proc
include : MarkSet.capital include : MarkSet.capital
include : VBar Middle 0 CAP include : VBar Middle 0 CAP
set currentGlyph.autoRefPriority (-2)
create-glyph 'one.onum.nobase' : glyph-proc create-glyph 'one.onum.nobase' : glyph-proc
include : OnumMarks.e include : OnumMarks.e
@ -85,7 +84,6 @@ glyph-block Digits-One : begin
create-glyph 'one.onum.line' : glyph-proc create-glyph 'one.onum.line' : glyph-proc
include : OnumMarks.e include : OnumMarks.e
include : VBar Middle 0 OnumHeight include : VBar Middle 0 OnumHeight
set currentGlyph.autoRefPriority (-2)
select-variant 'one.lnum' [CodeLnum '1'] (follow -- 'one') select-variant 'one.lnum' [CodeLnum '1'] (follow -- 'one')
select-variant 'one.onum' [CodeOnum '1'] (follow -- 'one') select-variant 'one.onum' [CodeOnum '1'] (follow -- 'one')

View file

@ -10,11 +10,9 @@ glyph-block Symbol-Mosaic-NotDef : begin
create-glyph '.null' : glyph-proc create-glyph '.null' : glyph-proc
set-width 0 set-width 0
set currentGlyph.autoRefPriority (-9998)
set currentGlyph.glyphRank (9998) set currentGlyph.glyphRank (9998)
create-glyph 'space' ' ' : glyph-proc create-glyph 'space' ' ' : glyph-proc
set currentGlyph.autoRefPriority (-100)
local df : DivFrame para.diversityI local df : DivFrame para.diversityI
set-width df.width set-width df.width
@ -38,7 +36,6 @@ glyph-block Symbol-Mosaic-NotDef : begin
create-glyph 'zwsp' 0x200B : glyph-proc create-glyph 'zwsp' 0x200B : glyph-proc
set-width 0 set-width 0
set currentGlyph.autoRefPriority (-9999)
alias 'nonmarkingreturn' 0x000D 'zwsp' alias 'nonmarkingreturn' 0x000D 'zwsp'
alias 'cgj' 0x34F 'zwsp' alias 'cgj' 0x34F 'zwsp'

View file

@ -288,6 +288,10 @@ glyph-block Symbol-Arrow : for-width-kinds WideWidth1
MkArrow ArrowShape [MangleName 'arrowDownRight'] [MangleUnicode 0x2198] arrowDiagSB arrowDiagTop arrowDiagRSB arrowDiagBot MkArrow ArrowShape [MangleName 'arrowDownRight'] [MangleUnicode 0x2198] arrowDiagSB arrowDiagTop arrowDiagRSB arrowDiagBot
MkArrow ArrowShape [MangleName 'arrowDownLeft'] [MangleUnicode 0x2199] arrowDiagRSB arrowDiagTop arrowDiagSB arrowDiagBot MkArrow ArrowShape [MangleName 'arrowDownLeft'] [MangleUnicode 0x2199] arrowDiagRSB arrowDiagTop arrowDiagSB arrowDiagBot
define kLong 0.5
MkArrow ArrowShape [MangleName 'longArrowLeft'] [MangleUnicode 0x27F5] [mix MosaicWidth arrowRSB kLong] SymbolMid [mix 0 arrowSB kLong] SymbolMid
MkArrow ArrowShape [MangleName 'longArrowRight'] [MangleUnicode 0x27F6] [mix 0 arrowSB kLong] SymbolMid [mix MosaicWidth arrowRSB kLong] SymbolMid
do "Dash Straight Arrow" do "Dash Straight Arrow"
MkArrow DashArrowShape [MangleName 'dashArrowLeft'] [MangleUnicode 0x21E0] arrowRSB SymbolMid arrowSB SymbolMid MkArrow DashArrowShape [MangleName 'dashArrowLeft'] [MangleUnicode 0x21E0] arrowRSB SymbolMid arrowSB SymbolMid
MkArrow DashArrowShape [MangleName 'dashArrowUp'] [MangleUnicode 0x21E1] arrowMidX arrowBot arrowMidX arrowTop MkArrow DashArrowShape [MangleName 'dashArrowUp'] [MangleUnicode 0x21E1] arrowMidX arrowBot arrowMidX arrowTop
@ -687,7 +691,3 @@ glyph-block Symbol-Arrow : for-width-kinds WideWidth1
if (MosaicWidthScalar == 1) : begin if (MosaicWidthScalar == 1) : begin
glyph-block-export ArrowShape glyph-block-export ArrowShape
if (!para.forceMonospace && MosaicNameSuffix === '.WWID') : begin
alias 'longArrowLeft' 0x27F5 'arrowLeft.WWID'
alias 'longArrowRight' 0x27F6 'arrowRight.WWID'

View file

@ -68,7 +68,6 @@ glyph-block Symbol-Ligation : begin
create-glyph "hyphen.lig.\(lS)\(rS)" : glyph-proc create-glyph "hyphen.lig.\(lS)\(rS)" : glyph-proc
include : SetJoiningKind lS rS include : SetJoiningKind lS rS
include : HBar left right SymbolMid OperatorStroke include : HBar left right SymbolMid OperatorStroke
set currentGlyph.autoRefPriority (-3)
create-glyph "hyphen.lig.\(lS)\(rS).notched" : glyph-proc create-glyph "hyphen.lig.\(lS)\(rS).notched" : glyph-proc
include : SetJoiningKind lS rS include : SetJoiningKind lS rS
include : difference include : difference
@ -87,7 +86,6 @@ glyph-block Symbol-Ligation : begin
include : SetJoiningKind lS rS include : SetJoiningKind lS rS
include : HBarTop left right (SymbolMid + dblArrowD) dblArrowSw include : HBarTop left right (SymbolMid + dblArrowD) dblArrowSw
include : HBarBottom left right (SymbolMid - dblArrowD) dblArrowSw include : HBarBottom left right (SymbolMid - dblArrowD) dblArrowSw
set currentGlyph.autoRefPriority (-3)
do "Waves" do "Waves"
glyph-block-import Shared-Symbol-Shapes : CreateWaveShape glyph-block-import Shared-Symbol-Shapes : CreateWaveShape

View file

@ -49,7 +49,7 @@ glyph-block Symbol-Math-Integrals : begin
include [shape] include [shape]
include : Translate (Width * 0.275) 0 include : Translate (Width * 0.275) 0
define [IntegrateRingMask kx] : OShapeOutline (SymbolMid + (RightSB - SB) / 2) (SymbolMid - (RightSB - SB) / 2) [mix 0 SB kx] [mix Width RightSB kx] define [IntegrateRingMask kx] : OShapeOutline.NoOvershoot (SymbolMid + (RightSB - SB) / 2) (SymbolMid - (RightSB - SB) / 2) [mix 0 SB kx] [mix Width RightSB kx]
define [IntegrateRing kx sw] : OShape (SymbolMid + (RightSB - SB) / 2) (SymbolMid - (RightSB - SB) / 2) [mix 0 SB kx] [mix Width RightSB kx] sw define [IntegrateRing kx sw] : OShape (SymbolMid + (RightSB - SB) / 2) (SymbolMid - (RightSB - SB) / 2) [mix 0 SB kx] [mix Width RightSB kx] sw
define RingIntFine : AdviceStroke 4 define RingIntFine : AdviceStroke 4

View file

@ -872,5 +872,4 @@ glyph-block Symbol-Mosaic-NotDef : begin
difference difference
Rect CAP 0 SB RightSB Rect CAP 0 SB RightSB
Rect (CAP - sw) (0 + sw) (SB + sw) (RightSB - sw) Rect (CAP - sw) (0 + sw) (SB + sw) (RightSB - sw)
set currentGlyph.autoRefPriority (-9999)
set currentGlyph.glyphRank (9999) set currentGlyph.glyphRank (9999)

View file

@ -105,7 +105,7 @@ glyph-block Symbol-Pictograph-IEC-Power-And-Playback : for-width-kinds WideWidth
corner (df.middle + trigRad / 2) (SymbolMid + trigRad) corner (df.middle + trigRad / 2) (SymbolMid + trigRad)
corner (df.middle - trigRad / 2) (SymbolMid) corner (df.middle - trigRad / 2) (SymbolMid)
create-glyph [MangleUnicode 'playback/eject'] [MangleUnicode 0x23CF] : glyph-proc create-glyph [MangleName 'playback/eject'] [MangleUnicode 0x23CF] : glyph-proc
set-width df.width set-width df.width
include : Rect (SymbolMid - squareRadiusFW / 3) (SymbolMid - squareRadiusFW) (df.middle - squareRadiusFW) (df.middle + squareRadiusFW) include : Rect (SymbolMid - squareRadiusFW / 3) (SymbolMid - squareRadiusFW) (df.middle - squareRadiusFW) (df.middle + squareRadiusFW)
include : spiro-outline include : spiro-outline

View file

@ -66,7 +66,3 @@ glyph-block Symbol-Punctuation-Dashes : begin
include : HBar 0 emDashWidth SymbolMid include : HBar 0 emDashWidth SymbolMid
alias [MangleName 'horizontalBar'] [MangleUnicode 0x2015] [MangleName 'emDash'] alias [MangleName 'horizontalBar'] [MangleUnicode 0x2015] [MangleName 'emDash']
create-glyph [MangleName 'doubleEmDash'] : glyph-proc
set-width (emDashWidth * 2)
include : HBar 0 (emDashWidth * 2) SymbolMid

View file

@ -11,12 +11,12 @@ glyph-block Symbol-Punctuation-Interpuncts : begin
glyph-block-import Common-Derivatives glyph-block-import Common-Derivatives
glyph-block-import Symbol-Punctuation-Small glyph-block-import Symbol-Punctuation-Small
create-glyph 'period.mid' : glyph-proc create-glyph 'interpunct' 0xB7 : glyph-proc
local df : DivFrame para.diversityF local df : DivFrame para.diversityF
set-width df.width set-width df.width
include : DotAt df.middle SymbolMid (PeriodRadius - O) include : DotAt df.middle SymbolMid (PeriodRadius - O)
alias 'interpunct' 0xB7 'period.mid' alias 'period.mid' 0xB7 'interpunct'
alias 'greekbullet' 0x387 'period.mid' alias 'greekbullet' 0x387 'interpunct'
alias 'hyphenpoint' 0x2027 'period.mid' alias 'hyphenpoint' 0x2027 'interpunct'
alias 'mathCDot' 0x22C5 'period.mid' alias 'mathCDot' 0x22C5 'interpunct'

View file

@ -75,7 +75,6 @@ export : define [BuildCompatLigatures para glyphStore GSUB GDEF config] : begin
define g1Name : '$clig.' + cldef.unicode define g1Name : '$clig.' + cldef.unicode
local g1 : new Glyph g1Name local g1 : new Glyph g1Name
set g1.advanceWidth 0 set g1.advanceWidth 0
set g1.autoRefPriority 1
foreach [gn : items-of gnames] : begin foreach [gn : items-of gnames] : begin
local g : glyphStore.queryByName gn local g : glyphStore.queryByName gn
g1.applyTransform : new Transform 1 0 0 1 (-g1.advanceWidth) 0 g1.applyTransform : new Transform 1 0 0 1 (-g1.advanceWidth) 0

22
font-src/otl/gsub-gr.ptl Normal file
View file

@ -0,0 +1,22 @@
import [add-common-feature add-feature add-lookup BeginLookupBlock EndLookupBlock] from "./table-util"
# Name-driven feature pairs
export : define [buildGrFeature sink glyphStore tag gr] : begin
local rec : BeginLookupBlock sink
local mapping {.}
foreach { gnSrc glyph } [glyphStore.namedEntries] : begin
local gnDst : gr.get glyph
local glyphDst : glyphStore.queryByName gnDst
if (glyphDst && ([glyphStore.queryUnicodeOf glyph] || [glyphStore.queryUnicodeOf glyphDst]))
set mapping.(gnSrc) gnDst
if [objectIsNotEmpty mapping] : begin
define lookup1 : add-lookup sink {.type 'gsub_single' .substitutions mapping}
define feature1 : add-feature sink tag
feature1.lookups.push lookup1
add-common-feature sink feature1
EndLookupBlock rec sink
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length

View file

@ -1,35 +0,0 @@
import [add-common-feature add-feature add-lookup BeginLookupBlock EndLookupBlock] from "./table-util"
# Name-driven feature pairs
export : define [buildPairFeature sink tag1 tag2 glyphStore codedOnly] : begin
local rec : BeginLookupBlock sink
local mapTag2 {.}
local mapTag1 {.}
define reHidden : regex "^\\."
define reTag1 : new RegExp ("\\." + tag1 + "$")
foreach { glyphName glyph } [glyphStore.namedEntries] : begin
if ([reTag1.test glyphName] && ![reHidden.test glyphName]) : do
local gnTag2 : glyphName.replace reTag1 ('.' + tag2)
local glyphTag2 : glyphStore.queryByName gnTag2
if (glyphTag2) : begin
if(!codedOnly || [glyphStore.queryUnicodeOf glyph])
set mapTag2.(glyphName) gnTag2
if(!codedOnly || [glyphStore.queryUnicodeOf glyphTag2])
set mapTag1.(gnTag2) glyphName
if [objectIsNotEmpty mapTag1] : begin
define lookup1 : add-lookup sink {.type 'gsub_single' .substitutions mapTag1}
define feature1 : add-feature sink tag1
feature1.lookups.push lookup1
add-common-feature sink feature1
if [objectIsNotEmpty mapTag2] : begin
define lookup2 : add-lookup sink {.type 'gsub_single' .substitutions mapTag2}
define feature2 : add-feature sink tag2
feature2.lookups.push lookup2
add-common-feature sink feature2
EndLookupBlock rec sink
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length

View file

@ -1,12 +1,13 @@
import 'toposort' as toposort import 'toposort' as toposort
import '../support/glyph' as Glyph import '../support/glyph' as Glyph
import '../support/transform' as Transform import '../support/transform' as Transform
import '../support/gr' as Gr
import [CreateEmptyTable finalizeTable MoveBackUtilityLookups] from "./table-util" import [CreateEmptyTable finalizeTable MoveBackUtilityLookups] from "./table-util"
import [buildLigations] from './gsub-ligation' import [buildLigations] from './gsub-ligation'
import [buildCCMP] from './gsub-ccmp' import [buildCCMP] from './gsub-ccmp'
import [buildPairFeature] from './gsub-pairing' import [buildGrFeature] from './gsub-gr'
import [buildCVSS] from './gsub-cv-ss' import [buildCVSS] from './gsub-cv-ss'
import [buildLOCL] from './gsub-locl' import [buildLOCL] from './gsub-locl'
import [buildGsubThousands] from './gsub-thousands' import [buildGsubThousands] from './gsub-thousands'
@ -22,11 +23,13 @@ define [buildGSUB para glyphStore markGlyphs] : begin
define gsub : CreateEmptyTable define gsub : CreateEmptyTable
# lnum / onum # lnum / onum
buildPairFeature gsub 'lnum' 'onum' glyphStore true buildGrFeature gsub glyphStore 'lnum' Gr.Lnum
buildGrFeature gsub glyphStore 'onum' Gr.Onum
# NWID / WWID # NWID / WWID
if (!para.forceMonospace || para.spacing > 0) : begin if (!para.forceMonospace || para.spacing > 0) : begin
buildPairFeature gsub 'NWID' 'WWID' glyphStore true buildGrFeature gsub glyphStore 'NWID' Gr.Nwid
buildGrFeature gsub glyphStore 'WWID' Gr.Wwid
# ccmp # ccmp
buildCCMP gsub glyphStore markGlyphs buildCCMP gsub glyphStore markGlyphs

View file

@ -14,11 +14,23 @@ class GlyphStore {
namedEntries() { namedEntries() {
return this.nameForward.entries(); return this.nameForward.entries();
} }
*indexedNamedEntries() { encodedEntries() {
let i = 0; return this.encodingForward.entries();
for (const [name, g] of this.nameForward.entries()) { }
yield [i, name, g];
i++; *flattenCodes(g, flatteners) {
{
const codes = this.encodingBackward.get(g);
if (codes) for (const c of codes) yield c;
}
for (const gr of flatteners) {
const gn = gr.get(g);
if (!gn) continue;
const g2 = this.nameForward.get(gn);
if (!g2) continue;
const codes2 = this.encodingBackward.get(g2);
if (codes2) for (const c of codes2) yield c;
} }
} }
@ -104,16 +116,6 @@ class GlyphStore {
} }
return gs1; return gs1;
} }
filterByGlyph(glyphSet) {
const gs1 = new GlyphStore();
for (const [name, g] of this.nameForward) {
if (!glyphSet.has(g)) continue;
gs1.addGlyph(name, g);
const us = this.encodingBackward.get(g);
if (us) for (const u of us) gs1.encodeGlyph(u, g);
}
return gs1;
}
} }
module.exports = GlyphStore; module.exports = GlyphStore;

View file

@ -8,12 +8,23 @@ const Geom = require("./geometry");
module.exports = class Glyph { module.exports = class Glyph {
constructor(_identifier) { constructor(_identifier) {
this._m_identifier = _identifier; this._m_identifier = _identifier;
// Ranks
this.glyphRank = 0;
this.grRank = 0;
this.codeRank = 0xffffffff;
this.subRank = 0xffffffff;
// Geometry
this.geometry = new Geom.CombineGeometry(); this.geometry = new Geom.CombineGeometry();
this.gizmo = Transform.Id();
// Metrics
this.advanceWidth = 500; this.advanceWidth = 500;
this.autoRefPriority = 0;
this.markAnchors = {}; this.markAnchors = {};
this.baseAnchors = {}; this.baseAnchors = {};
this.gizmo = Transform.Id();
// Tracking
this.dependencies = []; this.dependencies = [];
this.ctxTag = null; this.ctxTag = null;
} }
@ -69,11 +80,7 @@ module.exports = class Glyph {
// Combine anchors and get offset // Combine anchors and get offset
let shift = { x: 0, y: 0 }; let shift = { x: 0, y: 0 };
if (g.markAnchors) { this.combineMarks(g, shift);
for (const m in this.baseAnchors) {
this.combineAnchor(shift, this.baseAnchors[m], g.markAnchors[m], g.baseAnchors);
}
}
this.includeGlyphImpl(g, shift.x, shift.y); this.includeGlyphImpl(g, shift.x, shift.y);
if (copyAnchors || g.isMarkSet) this.copyAnchors(g); if (copyAnchors || g.isMarkSet) this.copyAnchors(g);
@ -90,7 +97,6 @@ module.exports = class Glyph {
this.related = g.related; this.related = g.related;
} }
cloneRankFromGlyph(g) { cloneRankFromGlyph(g) {
this.autoRefPriority = g.autoRefPriority;
this.glyphRank = g.glyphRank; this.glyphRank = g.glyphRank;
this.avoidBeingComposite = g.avoidBeingComposite; this.avoidBeingComposite = g.avoidBeingComposite;
} }
@ -147,17 +153,26 @@ module.exports = class Glyph {
} }
// Anchors // Anchors
combineAnchor(shift, baseThis, markThat, basesThat) { combineMarks(g, shift) {
if (!baseThis || !markThat) return; if (!g.markAnchors) return;
shift.x = baseThis.x - markThat.x; for (const m in g.markAnchors) {
shift.y = baseThis.y - markThat.y; const markThat = g.markAnchors[m];
if (basesThat) { const baseThis = this.baseAnchors[m];
for (const bk in basesThat) { if (!baseThis) continue;
this.baseAnchors[bk] = new Anchor( shift.x = baseThis.x - markThat.x;
shift.x + basesThat[bk].x, shift.y = baseThis.y - markThat.y;
shift.y + basesThat[bk].y let fSuppress = true;
); if (g.baseAnchors) {
for (const m2 in g.baseAnchors) {
if (m2 === m) fSuppress = false;
const baseDerived = g.baseAnchors[m2];
this.baseAnchors[m2] = new Anchor(
shift.x + baseDerived.x,
shift.y + baseDerived.y
);
}
} }
if (fSuppress) delete this.baseAnchors[m];
} }
} }
copyAnchors(g) { copyAnchors(g) {

View file

@ -35,6 +35,11 @@ const DollarShrinkKernel = SimpleProp("DollarShrinkKernel");
const DollarShorterBar = SimpleProp("DollarShorterBar"); const DollarShorterBar = SimpleProp("DollarShorterBar");
const MathSansSerif = SimpleProp("MathSansSerif"); const MathSansSerif = SimpleProp("MathSansSerif");
const Nwid = SimpleProp("Nwid");
const Wwid = SimpleProp("Wwid");
const Lnum = SimpleProp("Lnum");
const Onum = SimpleProp("Onum");
const CvDecompose = { const CvDecompose = {
get(glyph) { get(glyph) {
if (glyph && glyph.related) return glyph.related.CvDecompose; if (glyph && glyph.related) return glyph.related.CvDecompose;
@ -386,6 +391,19 @@ function queryCvFeatureTagsOf(sink, gid, glyph, variantAssignmentSet) {
for (const g of m.values()) if (g.length) sink.push(g); for (const g of m.values()) if (g.length) sink.push(g);
} }
function linkSuffixPairGr(gs, tagCis, tagTrans, grCis, grTrans) {
const reTagCis = new RegExp("\\." + tagCis + "$");
for (const [gnCis, gCis] of gs.namedEntries()) {
if (reTagCis.test(gnCis) && !/^\./.test(gnCis)) {
const gnTrans = gnCis.replace(reTagCis, "." + tagTrans);
const gTrans = gs.queryByName(gnTrans);
if (!gTrans) continue;
grTrans.set(gCis, gnTrans);
grCis.set(gTrans, gnCis);
}
}
}
exports.Dotless = Dotless; exports.Dotless = Dotless;
exports.LowerYDotAtBelow = LowerYDotAtBelow; exports.LowerYDotAtBelow = LowerYDotAtBelow;
exports.Cv = Cv; exports.Cv = Cv;
@ -401,8 +419,15 @@ exports.Joining = Joining;
exports.AnyDerivingCv = AnyDerivingCv; exports.AnyDerivingCv = AnyDerivingCv;
exports.CcmpDecompose = CcmpDecompose; exports.CcmpDecompose = CcmpDecompose;
exports.CvDecompose = CvDecompose; exports.CvDecompose = CvDecompose;
exports.createGrDisplaySheet = createGrDisplaySheet;
exports.DollarShrinkKernel = DollarShrinkKernel; exports.DollarShrinkKernel = DollarShrinkKernel;
exports.DollarShorterBar = DollarShorterBar; exports.DollarShorterBar = DollarShorterBar;
exports.MathSansSerif = MathSansSerif; exports.MathSansSerif = MathSansSerif;
exports.Nwid = Nwid;
exports.Wwid = Wwid;
exports.Lnum = Lnum;
exports.Onum = Onum;
exports.createGrDisplaySheet = createGrDisplaySheet;
exports.linkSuffixPairGr = linkSuffixPairGr;
exports.SvInheritableRelations = [DollarShrinkKernel, DollarShorterBar, Joining]; exports.SvInheritableRelations = [DollarShrinkKernel, DollarShorterBar, Joining];

View file

@ -36,6 +36,7 @@ const webfontFormatsPages = [["woff2", "woff2"]];
const WIDTH_NORMAL = "normal"; const WIDTH_NORMAL = "normal";
const WEIGHT_NORMAL = "regular"; const WEIGHT_NORMAL = "regular";
const SLOPE_NORMAL = "upright"; const SLOPE_NORMAL = "upright";
const SLOPE_OBLIQUE = "oblique";
const DEFAULT_SUBFAMILY = "regular"; const DEFAULT_SUBFAMILY = "regular";
const BUILD_PLANS = "build-plans.toml"; const BUILD_PLANS = "build-plans.toml";
@ -409,7 +410,7 @@ async function getCollectPlans(target, rawCollectPlans, config, fnFileName) {
sfi.slope sfi.slope
); );
const glyfTtcFileName = fnFileName( const glyfTtcFileName = fnFileName(
{ ...config, distinguishWidths: true }, { ...config, distinguishWidths: true, distinguishWhetherUpright: true },
collectPrefix, collectPrefix,
sfi.weight, sfi.weight,
sfi.width, sfi.width,
@ -440,7 +441,13 @@ function fnStandardTtc(collectConfig, prefix, w, wd, s) {
const ttcSuffix = makeSuffix( const ttcSuffix = makeSuffix(
collectConfig.distinguishWeights ? w : WEIGHT_NORMAL, collectConfig.distinguishWeights ? w : WEIGHT_NORMAL,
collectConfig.distinguishWidths ? wd : WIDTH_NORMAL, collectConfig.distinguishWidths ? wd : WIDTH_NORMAL,
collectConfig.distinguishSlope ? s : SLOPE_NORMAL, collectConfig.distinguishSlope
? s
: collectConfig.distinguishWhetherUpright
? s === SLOPE_NORMAL
? SLOPE_NORMAL
: SLOPE_OBLIQUE
: SLOPE_NORMAL,
DEFAULT_SUBFAMILY DEFAULT_SUBFAMILY
); );
return `${prefix}-${ttcSuffix}`; return `${prefix}-${ttcSuffix}`;