Complexity cleanup
This commit is contained in:
parent
f38901ba7a
commit
97920d0f4d
4 changed files with 212 additions and 192 deletions
|
@ -3,78 +3,22 @@
|
|||
const { Radical } = require("../../support/gr");
|
||||
|
||||
module.exports = function gcFont(glyphStore, excludedChars, restFont, cfg) {
|
||||
markSweepOtl(restFont.GSUB);
|
||||
markSweepOtl(restFont.GPOS);
|
||||
const sink = mark(glyphStore, excludedChars, restFont, cfg);
|
||||
markSweepOtlLookups(restFont.GSUB);
|
||||
markSweepOtlLookups(restFont.GPOS);
|
||||
const sink = markGlyphs(glyphStore, excludedChars, restFont, cfg);
|
||||
return sweep(glyphStore, sink);
|
||||
};
|
||||
|
||||
function markSweepOtl(table) {
|
||||
function markSweepOtlLookups(table) {
|
||||
if (!table || !table.features || !table.lookups) return;
|
||||
const accessibleLookupsIds = new Set();
|
||||
markLookups(table, accessibleLookupsIds);
|
||||
let lookups1 = {};
|
||||
for (const l in table.lookups) {
|
||||
if (accessibleLookupsIds.has(l)) lookups1[l] = table.lookups[l];
|
||||
}
|
||||
table.lookups = lookups1;
|
||||
|
||||
let features1 = {};
|
||||
for (let f in table.features) {
|
||||
const feature = table.features[f];
|
||||
if (!feature) continue;
|
||||
const featureFiltered = [];
|
||||
for (const l of feature) if (accessibleLookupsIds.has(l)) featureFiltered.push(l);
|
||||
if (!featureFiltered.length) continue;
|
||||
features1[f] = featureFiltered;
|
||||
}
|
||||
table.features = features1;
|
||||
sweepLookups(table, accessibleLookupsIds);
|
||||
sweepFeatures(table, accessibleLookupsIds);
|
||||
}
|
||||
|
||||
function mark(glyphStore, excludedChars, restFont, cfg) {
|
||||
const sink = markInitial(glyphStore, excludedChars);
|
||||
while (markStep(glyphStore, sink, restFont, cfg));
|
||||
return sink;
|
||||
}
|
||||
|
||||
function markInitial(glyphStore, excludedChars) {
|
||||
let sink = new Set();
|
||||
for (const [gName, g] of glyphStore.namedEntries()) {
|
||||
if (!g) continue;
|
||||
if (g.glyphRank > 0) sink.add(gName);
|
||||
if (Radical.get(g)) sink.add(gName);
|
||||
const unicodeSet = glyphStore.queryUnicodeOf(g);
|
||||
if (unicodeSet) {
|
||||
for (const u of unicodeSet) {
|
||||
if (!excludedChars.has(u)) sink.add(gName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sink;
|
||||
}
|
||||
|
||||
function markStep(glyphStore, sink, restFont, cfg) {
|
||||
const glyphCount = sink.size;
|
||||
if (restFont.GSUB) {
|
||||
for (const l in restFont.GSUB.lookups) {
|
||||
const lookup = restFont.GSUB.lookups[l];
|
||||
if (!lookup || !lookup.subtables) continue;
|
||||
for (let st of lookup.subtables) {
|
||||
markSubtable(sink, lookup.type, st, cfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
const glyphCount1 = sink.size;
|
||||
return glyphCount1 > glyphCount;
|
||||
}
|
||||
|
||||
function markLookups(table, sink) {
|
||||
if (!table || !table.features) return;
|
||||
for (let f in table.features) {
|
||||
const feature = table.features[f];
|
||||
if (!feature) continue;
|
||||
for (const l of feature) sink.add(l);
|
||||
}
|
||||
markLookupsStart(table, sink);
|
||||
let loop = 0,
|
||||
lookupSetChanged = false;
|
||||
do {
|
||||
|
@ -94,37 +38,110 @@ function markLookups(table, sink) {
|
|||
lookupSetChanged = sizeBefore !== sink.size;
|
||||
} while (loop < 0xff && lookupSetChanged);
|
||||
}
|
||||
function markLookupsStart(table, sink) {
|
||||
for (let f in table.features) {
|
||||
const feature = table.features[f];
|
||||
if (!feature) continue;
|
||||
for (const l of feature) sink.add(l);
|
||||
}
|
||||
}
|
||||
function sweepLookups(table, accessibleLookupsIds) {
|
||||
let lookups1 = {};
|
||||
for (const l in table.lookups) {
|
||||
if (accessibleLookupsIds.has(l)) lookups1[l] = table.lookups[l];
|
||||
}
|
||||
table.lookups = lookups1;
|
||||
return accessibleLookupsIds;
|
||||
}
|
||||
function sweepFeatures(table, accessibleLookupsIds) {
|
||||
let features1 = {};
|
||||
for (let f in table.features) {
|
||||
const feature = table.features[f];
|
||||
if (!feature) continue;
|
||||
const featureFiltered = [];
|
||||
for (const l of feature) if (accessibleLookupsIds.has(l)) featureFiltered.push(l);
|
||||
if (!featureFiltered.length) continue;
|
||||
features1[f] = featureFiltered;
|
||||
}
|
||||
table.features = features1;
|
||||
}
|
||||
|
||||
function markSubtable(sink, type, st, cfg) {
|
||||
function markGlyphs(glyphStore, excludedChars, restFont, cfg) {
|
||||
const sink = markGlyphsInitial(glyphStore, excludedChars);
|
||||
while (markGlyphsStep(glyphStore, sink, restFont, cfg));
|
||||
return sink;
|
||||
}
|
||||
function markGlyphsInitial(glyphStore, excludedChars) {
|
||||
let sink = new Set();
|
||||
for (const [gName, g] of glyphStore.namedEntries()) {
|
||||
if (!g) continue;
|
||||
if (g.glyphRank > 0) sink.add(gName);
|
||||
if (Radical.get(g)) sink.add(gName);
|
||||
const unicodeSet = glyphStore.queryUnicodeOf(g);
|
||||
if (unicodeSet) {
|
||||
for (const u of unicodeSet) {
|
||||
if (!excludedChars.has(u)) sink.add(gName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sink;
|
||||
}
|
||||
function markGlyphsStep(glyphStore, sink, restFont, cfg) {
|
||||
const glyphCount = sink.size;
|
||||
if (restFont.GSUB) {
|
||||
for (const l in restFont.GSUB.lookups) {
|
||||
const lookup = restFont.GSUB.lookups[l];
|
||||
if (!lookup || !lookup.subtables) continue;
|
||||
for (let st of lookup.subtables) {
|
||||
markGlyphsSubtable(sink, lookup.type, st, cfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
const glyphCount1 = sink.size;
|
||||
return glyphCount1 > glyphCount;
|
||||
}
|
||||
|
||||
function markGlyphsSubtable(sink, type, st, cfg) {
|
||||
switch (type) {
|
||||
case "gsub_single":
|
||||
for (const k in st) if (sink.has(k) && st[k]) sink.add(st[k]);
|
||||
break;
|
||||
return markGlyphsGsubSingle(sink, st, cfg);
|
||||
case "gsub_multiple":
|
||||
for (const k in st) if (sink.has(k) && st[k]) for (const g of st[k]) sink.add(g);
|
||||
break;
|
||||
return markGlyphsGsubMultiple(sink, st, cfg);
|
||||
case "gsub_alternate":
|
||||
if (!cfg || !cfg.ignoreAltSub) {
|
||||
for (const k in st) if (sink.has(k) && st[k]) for (const g of st[k]) sink.add(g);
|
||||
}
|
||||
break;
|
||||
return markGlyphsGsubAlternate(sink, st, cfg);
|
||||
case "gsub_ligature":
|
||||
for (const sub of st.substitutions) {
|
||||
let check = true;
|
||||
for (const g of sub.from) if (!sink.has(g)) check = false;
|
||||
if (check && sub.to) sink.add(sub.to);
|
||||
}
|
||||
break;
|
||||
return markGlyphsGsubLigature(sink, st, cfg);
|
||||
case "gsub_chaining":
|
||||
break;
|
||||
case "gsub_reverse":
|
||||
if (st.match && st.to) {
|
||||
const matchCoverage = st.match[st.inputIndex];
|
||||
for (let j = 0; j < matchCoverage.length; j++) {
|
||||
if (sink.has(matchCoverage[j]) && st.to[j]) sink.add(st.to[j]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
return markGlyphsGsubReverse(sink, st, cfg);
|
||||
}
|
||||
}
|
||||
|
||||
function markGlyphsGsubSingle(sink, st, cfg) {
|
||||
for (const k in st) if (sink.has(k) && st[k]) sink.add(st[k]);
|
||||
}
|
||||
function markGlyphsGsubMultiple(sink, st, cfg) {
|
||||
for (const k in st) if (sink.has(k) && st[k]) for (const g of st[k]) sink.add(g);
|
||||
}
|
||||
function markGlyphsGsubAlternate(sink, st, cfg) {
|
||||
if (!cfg || !cfg.ignoreAltSub) {
|
||||
for (const k in st) if (sink.has(k) && st[k]) for (const g of st[k]) sink.add(g);
|
||||
}
|
||||
}
|
||||
function markGlyphsGsubLigature(sink, st, cfg) {
|
||||
for (const sub of st.substitutions) {
|
||||
let check = true;
|
||||
for (const g of sub.from) if (!sink.has(g)) check = false;
|
||||
if (check && sub.to) sink.add(sub.to);
|
||||
}
|
||||
}
|
||||
function markGlyphsGsubReverse(sink, st, cfg) {
|
||||
if (st.match && st.to) {
|
||||
const matchCoverage = st.match[st.inputIndex];
|
||||
for (let j = 0; j < matchCoverage.length; j++) {
|
||||
if (sink.has(matchCoverage[j]) && st.to[j]) sink.add(st.to[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue