OTL codegen cleanup

This commit is contained in:
be5invis 2020-11-19 18:19:30 -08:00
parent d471e9d948
commit c6dc8c370c
11 changed files with 120 additions and 123 deletions

View file

@ -26,9 +26,9 @@ function markLookups(table, sink) {
let sizeBefore = sink.size; let sizeBefore = sink.size;
for (const l of Array.from(sink)) { for (const l of Array.from(sink)) {
const lookup = table.lookups[l]; const lookup = table.lookups[l];
if (!lookup || !lookup.subtables) continue; if (!lookup) continue;
if (lookup.type === "gsub_chaining" || lookup.type === "gpos_chaining") { if (lookup.type === "gsub_chaining" || lookup.type === "gpos_chaining") {
for (let st of lookup.subtables) { for (let st of lookup.rules) {
if (!st || !st.apply) continue; if (!st || !st.apply) continue;
for (const app of st.apply) sink.add(app.lookup); for (const app of st.apply) sink.add(app.lookup);
} }
@ -91,56 +91,60 @@ function markGlyphsStep(glyphStore, sink, restFont, cfg) {
if (restFont.GSUB) { if (restFont.GSUB) {
for (const l in restFont.GSUB.lookups) { for (const l in restFont.GSUB.lookups) {
const lookup = restFont.GSUB.lookups[l]; const lookup = restFont.GSUB.lookups[l];
if (!lookup || !lookup.subtables) continue; if (!lookup) continue;
for (let st of lookup.subtables) { markGlyphsLookupImpl(sink, lookup, cfg);
markGlyphsSubtable(sink, lookup.type, st, cfg);
}
} }
} }
const glyphCount1 = sink.size; const glyphCount1 = sink.size;
return glyphCount1 > glyphCount; return glyphCount1 > glyphCount;
} }
function markGlyphsSubtable(sink, type, st, cfg) { function markGlyphsLookupImpl(sink, lookup, cfg) {
switch (type) { switch (lookup.type) {
case "gsub_single": case "gsub_single":
return markGlyphsGsubSingle(sink, st, cfg); return markGlyphsGsubSingle(sink, lookup, cfg);
case "gsub_multiple": case "gsub_multiple":
return markGlyphsGsubMultiple(sink, st, cfg); return markGlyphsGsubMultiple(sink, lookup, cfg);
case "gsub_alternate": case "gsub_alternate":
return markGlyphsGsubAlternate(sink, st, cfg); return markGlyphsGsubAlternate(sink, lookup, cfg);
case "gsub_ligature": case "gsub_ligature":
return markGlyphsGsubLigature(sink, st, cfg); return markGlyphsGsubLigature(sink, lookup, cfg);
case "gsub_chaining": case "gsub_chaining":
break; break;
case "gsub_reverse": case "gsub_reverse":
return markGlyphsGsubReverse(sink, st, cfg); return markGlyphsGsubReverse(sink, lookup, cfg);
} }
} }
function markGlyphsGsubSingle(sink, st, cfg) { function markGlyphsGsubSingle(sink, lookup, cfg) {
const st = lookup.substitutions;
for (const k in st) if (sink.has(k) && st[k]) sink.add(st[k]); for (const k in st) if (sink.has(k) && st[k]) sink.add(st[k]);
} }
function markGlyphsGsubMultiple(sink, st, cfg) { function markGlyphsGsubMultiple(sink, lookup, cfg) {
const st = lookup.substitutions;
for (const k in st) if (sink.has(k) && st[k]) for (const g of st[k]) sink.add(g); 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) { function markGlyphsGsubAlternate(sink, lookup, cfg) {
const st = lookup.substitutions;
if (!cfg || !cfg.ignoreAltSub) { if (!cfg || !cfg.ignoreAltSub) {
for (const k in st) if (sink.has(k) && st[k]) for (const g of st[k]) sink.add(g); 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) { function markGlyphsGsubLigature(sink, lookup, cfg) {
for (const sub of st.substitutions) { const st = lookup.substitutions;
for (const sub of st) {
let check = true; let check = true;
for (const g of sub.from) if (!sink.has(g)) check = false; for (const g of sub.from) if (!sink.has(g)) check = false;
if (check && sub.to) sink.add(sub.to); if (check && sub.to) sink.add(sub.to);
} }
} }
function markGlyphsGsubReverse(sink, st, cfg) { function markGlyphsGsubReverse(sink, lookup, cfg) {
if (st.match && st.to) { for (const rule of lookup.rules) {
const matchCoverage = st.match[st.inputIndex]; if (rule.match && rule.to) {
for (let j = 0; j < matchCoverage.length; j++) { const matchCoverage = rule.match[rule.inputIndex];
if (sink.has(matchCoverage[j]) && st.to[j]) sink.add(st.to[j]); for (let j = 0; j < matchCoverage.length; j++) {
if (sink.has(matchCoverage[j]) && rule.to[j]) sink.add(rule.to[j]);
}
} }
} }
} }

View file

@ -23,7 +23,7 @@ class LookupStore {
const dst = this.query(id); const dst = this.query(id);
const handler = this.m_handlers[otdLookup.type]; const handler = this.m_handlers[otdLookup.type];
if (!dst || !handler) return; if (!dst || !handler) return;
if (otdLookup.subtables) throw new Error("Unreachable.");
handler.fill(dst, otdLookup, this); handler.fill(dst, otdLookup, this);
} }
} }
@ -33,12 +33,11 @@ const GsubSingleHandler = {
return new Ot.Gsub.Single(); return new Ot.Gsub.Single();
}, },
fill(dst, src, store) { fill(dst, src, store) {
for (const st of src.subtables) { const st = src.substitutions;
for (const k in st) { for (const k in st) {
const from = store.glyphs.query(k); const from = store.glyphs.query(k);
const to = store.glyphs.query(st[k]); const to = store.glyphs.query(st[k]);
if (from && to) dst.mapping.set(from, to); if (from && to) dst.mapping.set(from, to);
}
} }
} }
}; };
@ -47,13 +46,12 @@ const GsubMultipleHandler = {
return new Ot.Gsub.Multiple(); return new Ot.Gsub.Multiple();
}, },
fill(dst, src, store) { fill(dst, src, store) {
for (const st of src.subtables) { const st = src.substitutions;
out: for (const k in st) { for (const k in st) {
const from = store.glyphs.query(k); const from = store.glyphs.query(k);
const to = mapGlyphListAll(st[k], store); const to = mapGlyphListAll(st[k], store);
if (!from || !to) continue out; if (!from || !to) continue;
dst.mapping.set(from, to); dst.mapping.set(from, to);
}
} }
} }
}; };
@ -68,13 +66,12 @@ const GsubLigatureHandler = {
return new Ot.Gsub.Ligature(); return new Ot.Gsub.Ligature();
}, },
fill(dst, src, store) { fill(dst, src, store) {
for (const st of src.subtables) { const st = src.substitutions;
for (const { from: _from, to: _to } of st.substitutions) { for (const { from: _from, to: _to } of st) {
const to = store.glyphs.query(_to); const to = store.glyphs.query(_to);
const from = mapGlyphListAll(_from, store); const from = mapGlyphListAll(_from, store);
if (!from || !to) continue; if (!from || !to) continue;
dst.mapping.push({ from, to }); dst.mapping.push({ from, to });
}
} }
} }
}; };
@ -84,7 +81,7 @@ const GsubChainingHandler = {
return new Ot.Gsub.Chaining(); return new Ot.Gsub.Chaining();
}, },
fill(dst, src, store) { fill(dst, src, store) {
out: for (const st of src.subtables) { out: for (const st of src.rules) {
const match = []; const match = [];
for (const m of st.match) { for (const m of st.match) {
const m1 = mapGlyphListSome(m, store); const m1 = mapGlyphListSome(m, store);
@ -109,7 +106,7 @@ const GsubReverseHandler = {
return new Ot.Gsub.ReverseSub(); return new Ot.Gsub.ReverseSub();
}, },
fill(dst, src, store) { fill(dst, src, store) {
out: for (const st of src.subtables) { out: for (const st of src.rules) {
const match = []; const match = [];
const doSubAt = st.inputIndex; const doSubAt = st.inputIndex;
const replacement = new Map(); const replacement = new Map();
@ -176,10 +173,9 @@ const GposMarkToBaseHandler = {
return new Ot.Gpos.MarkToBase(); return new Ot.Gpos.MarkToBase();
}, },
fill(dst, src, store) { fill(dst, src, store) {
const st = src.subtables[0]; const mm = collectClassMap(src.marks);
const mm = collectClassMap(st.marks); dst.marks = convertMarkRecords(src.marks, mm, store);
dst.marks = convertMarkRecords(st.marks, mm, store); dst.bases = convertBaseRecords(src.bases, mm, store);
dst.bases = convertBaseRecords(st.bases, mm, store);
} }
}; };
const GposMarkToMarkHandler = { const GposMarkToMarkHandler = {
@ -187,10 +183,9 @@ const GposMarkToMarkHandler = {
return new Ot.Gpos.MarkToMark(); return new Ot.Gpos.MarkToMark();
}, },
fill(dst, src, store) { fill(dst, src, store) {
const st = src.subtables[0]; const mm = collectClassMap(src.marks);
const mm = collectClassMap(st.marks); dst.marks = convertMarkRecords(src.marks, mm, store);
dst.marks = convertMarkRecords(st.marks, mm, store); dst.baseMarks = convertBaseRecords(src.bases, mm, store);
dst.baseMarks = convertBaseRecords(st.bases, mm, store);
} }
}; };
function collectClassMap(marks) { function collectClassMap(marks) {

View file

@ -16,44 +16,42 @@ define [interpretLookup gs lut lookups] : match lut.type
local j 0 local j 0
while (j < gs.length) : begin while (j < gs.length) : begin
local incN 1 local incN 1
do : foreach [subtable : items-of lut.subtables] : begin do : foreach [rule : items-of lut.rules] : begin
local matchT subtable.match local matchT rule.match
local ib subtable.inputBegins local ib rule.inputBegins
local foundMatch true local foundMatch true
for [local k 0] (foundMatch && k < matchT.length) [inc k] : begin for [local k 0] (foundMatch && k < matchT.length) [inc k] : begin
if [not gs.(j + k - ib)] if [not gs.(j + k - ib)]
: then : set foundMatch false : then : set foundMatch false
: else : if ([matchT.(k).indexOf gs.(j + k - ib)] < 0) : set foundMatch false : else : if ([matchT.(k).indexOf gs.(j + k - ib)] < 0) : set foundMatch false
if foundMatch : begin if foundMatch : begin
foreach [app : items-of subtable.apply] : do foreach [app : items-of rule.apply] : do
local aj : j - ib + app.at local aj : j - ib + app.at
local alut lookups.(app.lookup) local alut lookups.(app.lookup)
interpretLookupAt gs aj alut interpretLookupAt gs aj alut
set incN : incN + subtable.inputEnds - subtable.inputBegins set incN : incN + rule.inputEnds - rule.inputBegins
break nothing break nothing
set j : j + incN set j : j + incN
"gsub_reverse" : begin "gsub_reverse" : begin
local j (gs.length - 1) local j (gs.length - 1)
while (j >= 0) : begin while (j >= 0) : begin
do : foreach [subtable : items-of lut.subtables] : begin do : foreach [rule : items-of lut.rules] : begin
local matchT subtable.match local matchT rule.match
local ib subtable.inputIndex local ib rule.inputIndex
local foundMatch true local foundMatch true
for [local k 0] (foundMatch && k < matchT.length) [inc k] : begin for [local k 0] (foundMatch && k < matchT.length) [inc k] : begin
if [not gs.(j + k - ib)] if [not gs.(j + k - ib)]
: then : set foundMatch false : then : set foundMatch false
: else : if ([matchT.(k).indexOf gs.(j + k - ib)] < 0) : set foundMatch false : else : if ([matchT.(k).indexOf gs.(j + k - ib)] < 0) : set foundMatch false
if foundMatch : begin if foundMatch : begin
set gs.(j) : subtable.to.[matchT.(ib).indexOf gs.(j)] || gs.(j) set gs.(j) : rule.to.[matchT.(ib).indexOf gs.(j)] || gs.(j)
set j : j - 1 set j : j - 1
"gsub_single" : begin "gsub_single" : begin
for [local j 0] (j < gs.length) [inc j] : begin for [local j 0] (j < gs.length) [inc j] : begin
interpretLookupAt gs j lut interpretLookupAt gs j lut
define [interpretLookupAt gs j lut] : match lut.type define [interpretLookupAt gs j lut] : match lut.type
"gsub_single" : foreach [subtable : items-of lut.subtables] : begin "gsub_single" : if lut.substitutions.(gs.(j)) : set gs.(j) lut.substitutions.(gs.(j))
if subtable.(gs.(j)) : begin
set gs.(j) subtable.(gs.(j))
export : define [BuildCompatLigatures glyphStore GSUB GDEF config] : begin export : define [BuildCompatLigatures glyphStore GSUB GDEF config] : begin
foreach [cldef : items-of config] : do foreach [cldef : items-of config] : do

View file

@ -16,32 +16,32 @@ export : define [buildMarkMkmk sink glyphStore] : begin
local mkmkLookupNames {} local mkmkLookupNames {}
foreach markCls [items-of MarkClasses] : begin foreach markCls [items-of MarkClasses] : begin
local [object markSubtable mkmkSubtable] : createMTSubtables glyphStore { markCls } local [object markLookup mkmkLookup] : createMTLookups glyphStore { markCls }
if ([objectIsNotEmpty markSubtable.marks] && [objectIsNotEmpty markSubtable.bases]) : begin if ([objectIsNotEmpty markLookup.marks] && [objectIsNotEmpty markLookup.bases]) : begin
local lidMark : add-lookup sink {.type 'gpos_mark_to_base' .subtables { markSubtable }} local lidMark : add-lookup sink markLookup
mark.lookups.push lidMark mark.lookups.push lidMark
markLookupNames.push lidMark markLookupNames.push lidMark
if ([objectIsNotEmpty mkmkSubtable.marks] && [objectIsNotEmpty mkmkSubtable.bases]) : begin if ([objectIsNotEmpty mkmkLookup.marks] && [objectIsNotEmpty mkmkLookup.bases]) : begin
local lidMkmk : add-lookup sink {.type 'gpos_mark_to_mark' .subtables { mkmkSubtable }} local lidMkmk : add-lookup sink mkmkLookup
mkmk.lookups.push lidMkmk mkmk.lookups.push lidMkmk
mkmkLookupNames.push lidMkmk mkmkLookupNames.push lidMkmk
foreach lidMark [items-of markLookupNames] : foreach lidMkmk [items-of mkmkLookupNames] foreach lidMark [items-of markLookupNames] : foreach lidMkmk [items-of mkmkLookupNames]
sink.lookupDep.push { lidMark lidMkmk } sink.lookupDep.push { lidMark lidMkmk }
define [createMTSubtables glyphStore markClasses] : begin define [createMTLookups glyphStore markClasses] : begin
local markSubtable {.marks {.} .bases {.}} local markLookup {.type 'gpos_mark_to_base' .marks {.} .bases {.}}
local mkmkSubtable {.marks {.} .bases {.}} local mkmkLookup {.type 'gpos_mark_to_mark' .marks {.} .bases {.}}
local allowMarkClsSet : new Set markClasses local allowMarkClsSet : new Set markClasses
foreach { gn glyph } [glyphStore.namedEntries] : begin foreach { gn glyph } [glyphStore.namedEntries] : begin
createMarkInfo markSubtable.marks gn glyph allowMarkClsSet createMarkInfo markLookup.marks gn glyph allowMarkClsSet
createMarkInfo mkmkSubtable.marks gn glyph allowMarkClsSet createMarkInfo mkmkLookup.marks gn glyph allowMarkClsSet
local isMark : objectIsNotEmpty glyph.markAnchors local isMark : objectIsNotEmpty glyph.markAnchors
if isMark if isMark
createBaseInfo mkmkSubtable.bases gn glyph allowMarkClsSet createBaseInfo mkmkLookup.bases gn glyph allowMarkClsSet
createBaseInfo markSubtable.bases gn glyph allowMarkClsSet createBaseInfo markLookup.bases gn glyph allowMarkClsSet
return : object markSubtable mkmkSubtable return : object markLookup mkmkLookup
define [createBaseInfo sink gn glyph allowMarkClsSet] : begin define [createBaseInfo sink gn glyph allowMarkClsSet] : begin
local res {.} local res {.}

View file

@ -99,7 +99,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp1 : add-lookup sink : object define lookupCcmp1 : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
# Dot removal (max 6 middle marks are supported) # Dot removal (max 6 middle marks are supported)
chain-rule (dotlessFrom ~> dotlessTo) (markGlyphs.above ~> null) chain-rule (dotlessFrom ~> dotlessTo) (markGlyphs.above ~> null)
chain-rule (dotlessFrom ~> dotlessTo) markGlyphs.all (markGlyphs.above ~> null) chain-rule (dotlessFrom ~> dotlessTo) markGlyphs.all (markGlyphs.above ~> null)
@ -128,7 +128,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp2 : add-lookup sink : object define lookupCcmp2 : add-lookup sink : object
.type 'gsub_ligature' .type 'gsub_ligature'
.subtables : list : object : substitutions : list .substitutions : list
object [from {'commaAbove' 'graveAbove'}] [to 'psilivaria'] object [from {'commaAbove' 'graveAbove'}] [to 'psilivaria']
object [from {'commaAbove' 'acuteAbove'}] [to 'psilioxia'] object [from {'commaAbove' 'acuteAbove'}] [to 'psilioxia']
object [from {'commaAbove' 'perispomeniAbove'}] [to 'psiliperispomeni'] object [from {'commaAbove' 'perispomeniAbove'}] [to 'psiliperispomeni']
@ -141,15 +141,15 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp-TieMarkLigature : add-lookup sink : object define lookupCcmp-TieMarkLigature : add-lookup sink : object
.type 'gsub_ligature' .type 'gsub_ligature'
.subtables : list .substitutions : {}.concat
object : substitutions : TieMarkFrom.map : lambda [gnFrom idx] TieMarkFrom.map : lambda [gnFrom idx]
object [from {gnCgjNwid gnFrom}] [to TieMarkTo.(idx)] object [from {gnCgjNwid gnFrom}] [to TieMarkTo.(idx)]
object : substitutions : TieMarkFrom.map : lambda [gnFrom idx] TieMarkFrom.map : lambda [gnFrom idx]
object [from {gnCgjWwid gnFrom}] [to TieMarkTo.(idx)] object [from {gnCgjWwid gnFrom}] [to TieMarkTo.(idx)]
define lookupCcmp-TieMarkContextual : add-lookup sink : object define lookupCcmp-TieMarkContextual : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list : object .rules : list : object
match {[TieGlyphs.concat TieMarkTo] {gnCgjNwid gnCgjWwid} TieMarkFrom} match {[TieGlyphs.concat TieMarkTo] {gnCgjNwid gnCgjWwid} TieMarkFrom}
inputBegins 1 inputBegins 1
inputEnds 3 inputEnds 3
@ -157,7 +157,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp-ToneStart : add-lookup sink : object define lookupCcmp-ToneStart : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
chain-rule [ToneToToneStart 0] {'tone0'} chain-rule [ToneToToneStart 0] {'tone0'}
chain-rule [ToneToToneStart 1] {'tone1'} chain-rule [ToneToToneStart 1] {'tone1'}
chain-rule [ToneToToneStart 2] {'tone2'} chain-rule [ToneToToneStart 2] {'tone2'}
@ -166,7 +166,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp-ToneMid : add-lookup sink : object define lookupCcmp-ToneMid : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
chain-rule [ToneStartOrMidAt 0] [ToneStartToToneMid 0] chain-rule [ToneStartOrMidAt 0] [ToneStartToToneMid 0]
chain-rule [ToneStartOrMidAt 1] [ToneStartToToneMid 1] chain-rule [ToneStartOrMidAt 1] [ToneStartToToneMid 1]
chain-rule [ToneStartOrMidAt 2] [ToneStartToToneMid 2] chain-rule [ToneStartOrMidAt 2] [ToneStartToToneMid 2]
@ -175,7 +175,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp-ToneEnd : add-lookup sink : object define lookupCcmp-ToneEnd : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
chain-rule [ToneStartOrMidAt 0] [ToneToToneEnd 0] chain-rule [ToneStartOrMidAt 0] [ToneToToneEnd 0]
chain-rule [ToneStartOrMidAt 1] [ToneToToneEnd 1] chain-rule [ToneStartOrMidAt 1] [ToneToToneEnd 1]
chain-rule [ToneStartOrMidAt 2] [ToneToToneEnd 2] chain-rule [ToneStartOrMidAt 2] [ToneToToneEnd 2]
@ -184,7 +184,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp-ToneSandhiStart : add-lookup sink : object define lookupCcmp-ToneSandhiStart : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
chain-rule [ToneSandhiToToneStart 0] {'toneSandhi0'} chain-rule [ToneSandhiToToneStart 0] {'toneSandhi0'}
chain-rule [ToneSandhiToToneStart 1] {'toneSandhi1'} chain-rule [ToneSandhiToToneStart 1] {'toneSandhi1'}
chain-rule [ToneSandhiToToneStart 2] {'toneSandhi2'} chain-rule [ToneSandhiToToneStart 2] {'toneSandhi2'}
@ -193,7 +193,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp-ToneSandhiMid : add-lookup sink : object define lookupCcmp-ToneSandhiMid : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
chain-rule [ToneSandhiStartOrMidAt 0] [ToneSandhiStartToToneMid 0] chain-rule [ToneSandhiStartOrMidAt 0] [ToneSandhiStartToToneMid 0]
chain-rule [ToneSandhiStartOrMidAt 1] [ToneSandhiStartToToneMid 1] chain-rule [ToneSandhiStartOrMidAt 1] [ToneSandhiStartToToneMid 1]
chain-rule [ToneSandhiStartOrMidAt 2] [ToneSandhiStartToToneMid 2] chain-rule [ToneSandhiStartOrMidAt 2] [ToneSandhiStartToToneMid 2]
@ -202,7 +202,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
define lookupCcmp-ToneSandhiEnd : add-lookup sink : object define lookupCcmp-ToneSandhiEnd : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
chain-rule [ToneSandhiStartOrMidAt 0] [ToneSandhiToToneEnd 0] chain-rule [ToneSandhiStartOrMidAt 0] [ToneSandhiToToneEnd 0]
chain-rule [ToneSandhiStartOrMidAt 1] [ToneSandhiToToneEnd 1] chain-rule [ToneSandhiStartOrMidAt 1] [ToneSandhiToToneEnd 1]
chain-rule [ToneSandhiStartOrMidAt 2] [ToneSandhiToToneEnd 2] chain-rule [ToneSandhiStartOrMidAt 2] [ToneSandhiToToneEnd 2]
@ -228,7 +228,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
ccmp.lookups.push lookupCcmp-Decompose ccmp.lookups.push lookupCcmp-Decompose
define lookupCcmp-Decompose : add-lookup sink : object define lookupCcmp-Decompose : add-lookup sink : object
.type 'gsub_multiple' .type 'gsub_multiple'
.subtables : list decompositions .substitutions decompositions
add-common-feature sink ccmp add-common-feature sink ccmp
EndLookupBlock rec sink EndLookupBlock rec sink

View file

@ -20,7 +20,7 @@ export : define [buildCVSS sink para glyphStore] : begin
define lookupNameCvDecompose : add-lookup sink : object define lookupNameCvDecompose : add-lookup sink : object
.type 'gsub_multiple' .type 'gsub_multiple'
.subtables : list decompositions .substitutions decompositions
# cvxx # cvxx
foreach {gn glyph} [glyphStore.namedEntries] : if [not : CvDecompose.get glyph] : do foreach {gn glyph} [glyphStore.namedEntries] : if [not : CvDecompose.get glyph] : do
@ -31,13 +31,13 @@ export : define [buildCVSS sink para glyphStore] : begin
add-common-feature sink feature add-common-feature sink feature
local lookup : pick-lookup sink lookupName local lookup : pick-lookup sink lookupName
begin {.type 'gsub_alternate' .subtables {{.}}} begin {.type 'gsub_alternate' .substitutions {.}}
add-feature-lookup feature lookupNameCvDecompose add-feature-lookup feature lookupNameCvDecompose
add-feature-lookup feature lookupName add-feature-lookup feature lookupName
sink.lookupDep.push { lookupNameCvDecompose lookupName } sink.lookupDep.push { lookupNameCvDecompose lookupName }
cvLookupNameSet.add lookupName cvLookupNameSet.add lookupName
local st [pick-lookup sink lookupName].subtables.0 local st [pick-lookup sink lookupName].substitutions
if [not st.(gn)] : set st.(gn) { } if [not st.(gn)] : set st.(gn) { }
set st.(gn).(gr.rank - 1) : glyphStore.ensureExists : gr.get glyph set st.(gn).(gr.rank - 1) : glyphStore.ensureExists : gr.get glyph
@ -46,11 +46,11 @@ export : define [buildCVSS sink para glyphStore] : begin
local feature : pick-feature sink [FeatureName composition.tag] local feature : pick-feature sink [FeatureName composition.tag]
add-common-feature sink feature add-common-feature sink feature
add-feature-lookup feature lookupNameCvDecompose add-feature-lookup feature lookupNameCvDecompose
local lookupNameSub : add-lookup sink {.type 'gsub_single' .subtables {{.}}} local lookupNameSub : add-lookup sink {.type 'gsub_single' .substitutions {.}}
sink.lookupDep.push { lookupNameCvDecompose lookupNameSub } sink.lookupDep.push { lookupNameCvDecompose lookupNameSub }
add-feature-lookup feature lookupNameSub add-feature-lookup feature lookupNameSub
define st [pick-lookup sink lookupNameSub].subtables.0 define st [pick-lookup sink lookupNameSub].substitutions
local decomp : composition.decompose para para.variants.selectorTree local decomp : composition.decompose para para.variants.selectorTree
foreach { prime pv } [items-of decomp] : if (pv.tag && pv.rank) : begin foreach { prime pv } [items-of decomp] : if (pv.tag && pv.rank) : begin
local gr : Cv pv.tag pv.rank local gr : Cv pv.tag pv.rank
@ -60,7 +60,7 @@ export : define [buildCVSS sink para glyphStore] : begin
# If there are holes in the alternates list, fill them # If there are holes in the alternates list, fill them
foreach lutn cvLookupNameSet : begin foreach lutn cvLookupNameSet : begin
local st [pick-lookup sink lutn].subtables.0 local st [pick-lookup sink lutn].substitutions
foreach { k v } [pairs-of st] : foreach idx [range 0 v.length] : if [not v.(idx)] foreach { k v } [pairs-of st] : foreach idx [range 0 v.length] : if [not v.(idx)]
set v.(idx) k set v.(idx) k

View file

@ -139,14 +139,14 @@ define [buildLigationsImpl sink para featureName mappedFeature rankedLookups] :
define rules : filterNulls _rules define rules : filterNulls _rules
if (rules && rules.length) : AddRankedLookup if (rules && rules.length) : AddRankedLookup
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables rules .rules rules
set lookupRank : lookupRank + 1 set lookupRank : lookupRank + 1
define [CreateReverseLigationLookup _rules] : begin define [CreateReverseLigationLookup _rules] : begin
define rules : filterNulls _rules define rules : filterNulls _rules
if (rules && rules.length) : AddRankedLookup if (rules && rules.length) : AddRankedLookup
.type 'gsub_reverse' .type 'gsub_reverse'
.subtables rules .rules rules
set lookupRank : lookupRank + 1 set lookupRank : lookupRank + 1
do "Operator centering" do "Operator centering"

View file

@ -13,7 +13,7 @@ export : define [buildLOCL sink para glyphStore] : begin
cyrlMKD.features.unshift loclSRB.name cyrlMKD.features.unshift loclSRB.name
loclSRB.lookups.push : add-lookup sink : object loclSRB.lookups.push : add-lookup sink : object
type 'gsub_single' type 'gsub_single'
subtables : list : if para.isItalic substitutions : if para.isItalic
object object
'cyrl/be' : glyphStore.ensureExists 'cyrl/be.SRB' 'cyrl/be' : glyphStore.ensureExists 'cyrl/be.SRB'
'cyrl/ghe' : glyphStore.ensureExists 'cyrl/ghe.SRB' 'cyrl/ghe' : glyphStore.ensureExists 'cyrl/ghe.SRB'
@ -28,7 +28,7 @@ export : define [buildLOCL sink para glyphStore] : begin
cyrlBGR.features.unshift loclBGR.name cyrlBGR.features.unshift loclBGR.name
loclBGR.lookups.push : add-lookup sink : object loclBGR.lookups.push : add-lookup sink : object
type 'gsub_single' type 'gsub_single'
subtables : list : object substitutions : object
'cyrl/ve' : glyphStore.ensureExists 'cyrl/ve.BGR' 'cyrl/ve' : glyphStore.ensureExists 'cyrl/ve.BGR'
'cyrl/ghe' : glyphStore.ensureExists 'cyrl/ghe.italic' 'cyrl/ghe' : glyphStore.ensureExists 'cyrl/ghe.italic'
'cyrl/de' : glyphStore.ensureExists 'cyrl/de.BGR' 'cyrl/de' : glyphStore.ensureExists 'cyrl/de.BGR'

View file

@ -19,13 +19,13 @@ export : define [buildPairFeature sink tag1 tag2 glyphStore codedOnly] : begin
set mapTag1.(gnTag2) glyphName set mapTag1.(gnTag2) glyphName
if [objectIsNotEmpty mapTag1] : begin if [objectIsNotEmpty mapTag1] : begin
define lookup1 : add-lookup sink {.type 'gsub_single' .subtables {mapTag1}} define lookup1 : add-lookup sink {.type 'gsub_single' .substitutions mapTag1}
define feature1 : add-feature sink tag1 define feature1 : add-feature sink tag1
feature1.lookups.push lookup1 feature1.lookups.push lookup1
add-common-feature sink feature1 add-common-feature sink feature1
if [objectIsNotEmpty mapTag2] : begin if [objectIsNotEmpty mapTag2] : begin
define lookup2 : add-lookup sink {.type 'gsub_single' .subtables {mapTag2}} define lookup2 : add-lookup sink {.type 'gsub_single' .substitutions mapTag2}
define feature2 : add-feature sink tag2 define feature2 : add-feature sink tag2
feature2.lookups.push lookup2 feature2.lookups.push lookup2
add-common-feature sink feature2 add-common-feature sink feature2

View file

@ -17,7 +17,7 @@ export : define [buildGsubThousands sink para] : begin
define lookupThousand1 : add-lookup sink : object define lookupThousand1 : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
chain-rule ({'period'} ~> null) (numberGlyphIDs ~> [nd 2]) (numberGlyphIDs ~> null) (numberGlyphIDs ~> null) chain-rule ({'period'} ~> null) (numberGlyphIDs ~> [nd 2]) (numberGlyphIDs ~> null) (numberGlyphIDs ~> null)
chain-rule ([nd 2] ~> null) (numberGlyphIDs ~> [nd 1]) chain-rule ([nd 2] ~> null) (numberGlyphIDs ~> [nd 1])
chain-rule ([nd 1] ~> null) (numberGlyphIDs ~> [nd 6]) chain-rule ([nd 1] ~> null) (numberGlyphIDs ~> [nd 6])
@ -28,13 +28,13 @@ export : define [buildGsubThousands sink para] : begin
define lookupThousand2 : add-lookup sink : object define lookupThousand2 : add-lookup sink : object
.type 'gsub_chaining' .type 'gsub_chaining'
.subtables : list .rules : list
chain-rule (numberGlyphIDs ~> [nd 0]) (numberGlyphIDs ~> null) (numberGlyphIDs ~> null) (numberGlyphIDs ~> null) chain-rule (numberGlyphIDs ~> [nd 0]) (numberGlyphIDs ~> null) (numberGlyphIDs ~> null) (numberGlyphIDs ~> null)
chain-rule ([nd 0] ~> null) (numberGlyphIDs ~> [nd 0]) chain-rule ([nd 0] ~> null) (numberGlyphIDs ~> [nd 0])
define lookupThousand3 : add-lookup sink : object define lookupThousand3 : add-lookup sink : object
.type 'gsub_reverse' .type 'gsub_reverse'
.subtables : list .rules : list
reverse-rule ([nd 0] ~> [nd 1]) ([nd 0] ~> null) reverse-rule ([nd 0] ~> [nd 1]) ([nd 0] ~> null)
reverse-rule ([nd 0] ~> [nd 2]) ([nd 1] ~> null) reverse-rule ([nd 0] ~> [nd 2]) ([nd 1] ~> null)
reverse-rule ([nd 0] ~> [nd 3]) ([nd 2] ~> null) reverse-rule ([nd 0] ~> [nd 3]) ([nd 2] ~> null)

View file

@ -95,9 +95,9 @@ export : define [MoveBackUtilityLookups sink] : begin
export : define [ChainRuleBuilder sink] : begin export : define [ChainRuleBuilder sink] : begin
define [createNewLookup f t] : begin define [createNewLookup f t] : begin
local subtable {.} local subst {.}
foreach [j : range 0 f.length] : set subtable.(f.(j)) t.(j) foreach [j : range 0 f.length] : set subst.(f.(j)) t.(j)
return : add-lookup sink {.type 'gsub_single' .subtables {subtable}} UtilityLookupPrefix return : add-lookup sink {.type 'gsub_single' .substitutions subst} UtilityLookupPrefix
define [getSubLookup left right] : piecewise define [getSubLookup left right] : piecewise
[not right] null [not right] null
@ -108,7 +108,7 @@ export : define [ChainRuleBuilder sink] : begin
local maxMatch 0 local maxMatch 0
local lookupKeys : [Object.keys sink.lookups].reverse local lookupKeys : [Object.keys sink.lookups].reverse
foreach [name : items-of lookupKeys] : begin foreach [name : items-of lookupKeys] : begin
local st sink.lookups.(name).subtables.0 local st sink.lookups.(name).substitutions
if [IsUtilityLookupId name] : begin if [IsUtilityLookupId name] : begin
local compatible true local compatible true
local matchCount 0 local matchCount 0
@ -120,7 +120,7 @@ export : define [ChainRuleBuilder sink] : begin
set maxMatch matchCount set maxMatch matchCount
if found : begin if found : begin
local st sink.lookups.(found).subtables.0 local st sink.lookups.(found).substitutions
foreach [j : range 0 left.length] : set st.(left.(j)) right.(j) foreach [j : range 0 left.length] : set st.(left.(j)) right.(j)
return found return found
@ -128,25 +128,25 @@ export : define [ChainRuleBuilder sink] : begin
define [chain-rule] : begin define [chain-rule] : begin
local terms : [{}.slice.call arguments 0].map (x -> [if x.left x {.left x .right null}]) local terms : [{}.slice.call arguments 0].map (x -> [if x.left x {.left x .right null}])
local subtable {.match {} .apply {} .inputBegins 0 .inputEnds 0} local rule {.match {} .apply {} .inputBegins 0 .inputEnds 0}
local foundi false local foundi false
local founde false local founde false
foreach [j : range 0 terms.length] : if (!foundi && terms.(j).right) : begin foreach [j : range 0 terms.length] : if (!foundi && terms.(j).right) : begin
set subtable.inputBegins j set rule.inputBegins j
set foundi true set foundi true
foreach [j : range (terms.length - 1) downtill 0] : if (!founde && terms.(j).right) : begin foreach [j : range (terms.length - 1) downtill 0] : if (!founde && terms.(j).right) : begin
set subtable.inputEnds (j + 1) set rule.inputEnds (j + 1)
set founde true set founde true
foreach [j : range 0 terms.length] : begin foreach [j : range 0 terms.length] : begin
local term terms.(j) local term terms.(j)
subtable.match.push : Array.from : new Set term.left rule.match.push : Array.from : new Set term.left
local lutn : getSubLookup term.left term.right local lutn : getSubLookup term.left term.right
if lutn : subtable.apply.push {.at j .lookup lutn} if lutn : rule.apply.push {.at j .lookup lutn}
return subtable return rule
define [reverse-rule] : begin define [reverse-rule] : begin
local terms : [{}.slice.call arguments 0].map (x -> [if x.left x {.left x .right null}]) local terms : [{}.slice.call arguments 0].map (x -> [if x.left x {.left x .right null}])
local subtable {.match {} .to {} .inputIndex 0} local rule {.match {} .to {} .inputIndex 0}
local foundi false local foundi false
foreach [j : range 0 terms.length] : begin foreach [j : range 0 terms.length] : begin
@ -157,18 +157,18 @@ export : define [ChainRuleBuilder sink] : begin
if term.right : begin if term.right : begin
if foundi : throw : new Error "Duplicate substitutions in one reverse rule" if foundi : throw : new Error "Duplicate substitutions in one reverse rule"
set foundi true set foundi true
set subtable.inputIndex j set rule.inputIndex j
local toGlyphs : piecewise local toGlyphs : piecewise
(term.right <@ Function) [term.right term.left] (term.right <@ Function) [term.right term.left]
true term.right true term.right
foreach [k : range 0 term.left.length] foreach [k : range 0 term.left.length]
subst.set term.left.(k) (toGlyphs.(k) || term.left.(k)) subst.set term.left.(k) (toGlyphs.(k) || term.left.(k))
set subtable.to : Array.from [subst.values] set rule.to : Array.from [subst.values]
set subtable.match.(j) : Array.from [subst.keys] set rule.match.(j) : Array.from [subst.keys]
return subtable return rule
return {chain-rule reverse-rule} return {chain-rule reverse-rule}