OTL codegen cleanup
This commit is contained in:
parent
d471e9d948
commit
c6dc8c370c
11 changed files with 120 additions and 123 deletions
|
@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {.}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue