* Fix ss02
, ss04
, ss06
, ss13
, ss17
's application on i
and j
(#2033).
This commit is contained in:
parent
1f80407eed
commit
344d8e95d8
24 changed files with 441 additions and 402 deletions
1
changes/27.2.1.md
Normal file
1
changes/27.2.1.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
* Fix `ss02`, `ss04`, `ss06`, `ss13`, `ss17`'s application on `i` and `j` (#2033).
|
|
@ -34,7 +34,11 @@ function markLookups(table, sink, sinkDirect) {
|
||||||
if (lookup.type === "gsub_chaining" || lookup.type === "gpos_chaining") {
|
if (lookup.type === "gsub_chaining" || lookup.type === "gpos_chaining") {
|
||||||
for (let st of lookup.rules) {
|
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) {
|
||||||
|
if (!app.lookup.name)
|
||||||
|
throw new Error("Unreachable: lookup name should be present");
|
||||||
|
sink.add(app.lookup.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +50,7 @@ function markLookupsStart(table, sink, sinkDirect) {
|
||||||
for (let f in table.features) {
|
for (let f in table.features) {
|
||||||
const feature = table.features[f];
|
const feature = table.features[f];
|
||||||
if (!feature) continue;
|
if (!feature) continue;
|
||||||
for (const l of feature) {
|
for (const l of feature.lookups) {
|
||||||
sink.add(l);
|
sink.add(l);
|
||||||
sinkDirect.add(l);
|
sinkDirect.add(l);
|
||||||
}
|
}
|
||||||
|
@ -65,9 +69,15 @@ function sweepFeatures(table, accessibleLookupsIds) {
|
||||||
for (let f in table.features) {
|
for (let f in table.features) {
|
||||||
const feature = table.features[f];
|
const feature = table.features[f];
|
||||||
if (!feature) continue;
|
if (!feature) continue;
|
||||||
const featureFiltered = [];
|
const featureFiltered = {
|
||||||
for (const l of feature) if (accessibleLookupsIds.has(l)) featureFiltered.push(l);
|
name: feature.name,
|
||||||
if (!featureFiltered.length) continue;
|
tag: feature.tag,
|
||||||
|
lookups: []
|
||||||
|
};
|
||||||
|
for (const l of feature.lookups) {
|
||||||
|
if (accessibleLookupsIds.has(l)) featureFiltered.lookups.push(l);
|
||||||
|
}
|
||||||
|
if (!featureFiltered.lookups.length) continue;
|
||||||
features1[f] = featureFiltered;
|
features1[f] = featureFiltered;
|
||||||
}
|
}
|
||||||
table.features = features1;
|
table.features = features1;
|
||||||
|
@ -151,7 +161,11 @@ function markGlyphsByLookup(gsub, lid, markedGlyphs) {
|
||||||
if (!atLeastOneMatch) continue rules;
|
if (!atLeastOneMatch) continue rules;
|
||||||
}
|
}
|
||||||
// If so traverse through the lookup applications
|
// If so traverse through the lookup applications
|
||||||
for (const app of rule.apply) markGlyphsByLookup(gsub, app.lookup, markedGlyphs);
|
for (const app of rule.apply) {
|
||||||
|
if (!app.lookup.name)
|
||||||
|
throw new Error("Unreachable: lookup name should be present");
|
||||||
|
markGlyphsByLookup(gsub, app.lookup.name, markedGlyphs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,9 +106,9 @@ class FeatureStore {
|
||||||
return this.m_mapping.get(id);
|
return this.m_mapping.get(id);
|
||||||
}
|
}
|
||||||
fill(id, data) {
|
fill(id, data) {
|
||||||
const tag = id.slice(0, 4);
|
const tag = data.tag;
|
||||||
const lookups = [];
|
const lookups = [];
|
||||||
for (const lid of data) {
|
for (const lid of data.lookups) {
|
||||||
const lookup = this.lookupStore.query(lid);
|
const lookup = this.lookupStore.query(lid);
|
||||||
if (lookup) lookups.push(lookup);
|
if (lookup) lookups.push(lookup);
|
||||||
}
|
}
|
||||||
|
@ -215,8 +215,9 @@ const GsubChainingHandler = {
|
||||||
const inputEnds = st.inputEnds;
|
const inputEnds = st.inputEnds;
|
||||||
const applications = [];
|
const applications = [];
|
||||||
for (const ap of st.apply) {
|
for (const ap of st.apply) {
|
||||||
const lookup = store.query(ap.lookup);
|
if (!ap.lookup.name) throw new Error("Unreachable: lookup name must not be null");
|
||||||
if (!lookup) continue out;
|
const lookup = store.query(ap.lookup.name);
|
||||||
|
if (!lookup) throw new Error(`Cannot find lookup '${ap.lookup.name}'`);
|
||||||
applications.push({ at: ap.at - inputBegins, apply: lookup });
|
applications.push({ at: ap.at - inputBegins, apply: lookup });
|
||||||
}
|
}
|
||||||
dst.rules.push({ match, inputBegins, inputEnds, applications });
|
dst.rules.push({ match, inputBegins, inputEnds, applications });
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [linreg clamp mix fallback] from"../../support/utils.mjs"
|
import [linreg clamp mix fallback] from"../../support/utils.mjs"
|
||||||
import [getGrTree getGrMesh IsSuperscript IsSubscript] from"../../support/gr.mjs"
|
import [getGrTree IsSuperscript IsSubscript] from"../../support/gr.mjs"
|
||||||
import [AnyCv DotlessOrNot CvDecompose MathSansSerif] from"../../support/gr.mjs"
|
import [AnyCv DotlessOrNot CvDecompose MathSansSerif] from"../../support/gr.mjs"
|
||||||
import [NumeratorForm DenominatorForm] from"../../support/gr.mjs"
|
import [NumeratorForm DenominatorForm] from"../../support/gr.mjs"
|
||||||
import [Transform] from"../../support/geometry/transform.mjs"
|
import [Transform] from"../../support/geometry/transform.mjs"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix clamp fallback SuffixCfg] from"../../support/utils.mjs"
|
import [mix clamp fallback SuffixCfg] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh VS01 Zero] from"../../support/gr.mjs"
|
import [VS01 Zero] from"../../support/gr.mjs"
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh] from"../../support/gr.mjs"
|
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh] from"../../support/gr.mjs"
|
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh] from"../../support/gr.mjs"
|
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix linreg clamp fallback SuffixCfg] from"../../support/utils.mjs"
|
import [mix linreg clamp fallback SuffixCfg] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh] from"../../support/gr.mjs"
|
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh] from"../../support/gr.mjs"
|
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh] from"../../support/gr.mjs"
|
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh] from"../../support/gr.mjs"
|
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$$include '../../meta/macros.ptl'
|
$$include '../../meta/macros.ptl'
|
||||||
|
|
||||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||||
import [AnyCv getGrMesh] from"../../support/gr.mjs"
|
|
||||||
|
|
||||||
glyph-module
|
glyph-module
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import [AddCommonFeature AddFeature AddLookup] from"./table-util.mjs"
|
|
||||||
|
|
||||||
extern Map
|
extern Map
|
||||||
extern Set
|
extern Set
|
||||||
|
|
||||||
|
@ -21,27 +19,22 @@ define MarkInteractions : new Map : list
|
||||||
|
|
||||||
define MkmkStackingLimit : new Set { 'above' 'below' }
|
define MkmkStackingLimit : new Set { 'above' 'below' }
|
||||||
|
|
||||||
export : define [buildMarkMkmk sink glyphStore markGlyphs] : begin
|
export : define [buildMarkMkmk gpos glyphStore markGlyphs] : begin
|
||||||
define validMarkClasses : new Set MarkClasses
|
define validMarkClasses : new Set MarkClasses
|
||||||
|
|
||||||
define mark : object
|
define mark : object
|
||||||
feature : AddFeature sink 'mark'
|
feature : gpos.addCommonFeature : gpos.createFeature 'mark'
|
||||||
lookupMap : new Map
|
lookupMap : new Map
|
||||||
lookupNames : new Set
|
|
||||||
createLookup : function [] {.type 'gpos_mark_to_base' .marks {.} .bases {.}}
|
createLookup : function [] {.type 'gpos_mark_to_base' .marks {.} .bases {.}}
|
||||||
define mkmk : object
|
define mkmk : object
|
||||||
feature : AddFeature sink 'mkmk'
|
feature : gpos.addCommonFeature : gpos.createFeature 'mkmk'
|
||||||
lookupMap : new Map
|
lookupMap : new Map
|
||||||
lookupNames : new Set
|
|
||||||
createLookup : function [] {.type 'gpos_mark_to_mark' .marks {.} .bases {.}}
|
createLookup : function [] {.type 'gpos_mark_to_mark' .marks {.} .bases {.}}
|
||||||
|
|
||||||
AddCommonFeature sink mark.feature
|
|
||||||
AddCommonFeature sink mkmk.feature
|
|
||||||
|
|
||||||
# Populate the marks
|
# Populate the marks
|
||||||
foreach cls [items-of MarkClasses] : begin
|
foreach cls [items-of MarkClasses] : begin
|
||||||
local markLookup : ensureLookup sink mark cls
|
local markLookup : ensureLookup gpos mark cls
|
||||||
local mkmkLookup : ensureLookup sink mkmk cls
|
local mkmkLookup : ensureLookup gpos mkmk cls
|
||||||
|
|
||||||
foreach { gn glyph } [glyphStore.namedEntries] : begin
|
foreach { gn glyph } [glyphStore.namedEntries] : begin
|
||||||
if glyph.markAnchors.(cls) : begin
|
if glyph.markAnchors.(cls) : begin
|
||||||
|
@ -52,8 +45,8 @@ export : define [buildMarkMkmk sink glyphStore markGlyphs] : begin
|
||||||
|
|
||||||
# Populate the bases
|
# Populate the bases
|
||||||
foreach cls [items-of MarkClasses] : begin
|
foreach cls [items-of MarkClasses] : begin
|
||||||
local markLookup : ensureLookup sink mark cls
|
local markLookup : ensureLookup gpos mark cls
|
||||||
local mkmkLookup : ensureLookup sink mkmk cls
|
local mkmkLookup : ensureLookup gpos mkmk cls
|
||||||
|
|
||||||
foreach { gn glyph } [glyphStore.namedEntries] : begin
|
foreach { gn glyph } [glyphStore.namedEntries] : begin
|
||||||
if glyph.baseAnchors.(cls) : begin
|
if glyph.baseAnchors.(cls) : begin
|
||||||
|
@ -61,8 +54,8 @@ export : define [buildMarkMkmk sink glyphStore markGlyphs] : begin
|
||||||
: then : addBaseAnchor mkmkLookup gn cls glyph.baseAnchors.(cls)
|
: then : addBaseAnchor mkmkLookup gn cls glyph.baseAnchors.(cls)
|
||||||
: else : addBaseAnchor markLookup gn cls glyph.baseAnchors.(cls)
|
: else : addBaseAnchor markLookup gn cls glyph.baseAnchors.(cls)
|
||||||
|
|
||||||
foreach lidMark mark.lookupNames : foreach lidMkmk mkmk.lookupNames
|
foreach markLookup [mark.lookupMap.values] : foreach mkmkLookup [mkmk.lookupMap.values]
|
||||||
sink.lookupDep.push { lidMark lidMkmk }
|
gpos.setDependency markLookup mkmkLookup
|
||||||
|
|
||||||
foreach { cls lookup } mkmk.lookupMap : begin
|
foreach { cls lookup } mkmk.lookupMap : begin
|
||||||
local interactionMarkSet : new Set ([MarkInteractions.get cls] || { cls })
|
local interactionMarkSet : new Set ([MarkInteractions.get cls] || { cls })
|
||||||
|
@ -77,17 +70,14 @@ export : define [buildMarkMkmk sink glyphStore markGlyphs] : begin
|
||||||
if (interactionMarkSet.size > 1) : begin
|
if (interactionMarkSet.size > 1) : begin
|
||||||
markGlyphs.markGlyphSets.push : Array.from includeSet
|
markGlyphs.markGlyphSets.push : Array.from includeSet
|
||||||
|
|
||||||
define [ensureLookup sink feat cls] : begin
|
define [ensureLookup gpos feat cls] : begin
|
||||||
local existing : feat.lookupMap.get cls
|
local existing : feat.lookupMap.get cls
|
||||||
if existing : return existing
|
if existing : return existing
|
||||||
|
|
||||||
local novel : feat.createLookup
|
local lookup : gpos.createLookup : feat.createLookup
|
||||||
local lid : AddLookup sink novel
|
feat.feature.addLookup lookup
|
||||||
feat.feature.lookups.push lid
|
feat.lookupMap.set cls lookup
|
||||||
feat.lookupNames.add lid
|
return lookup
|
||||||
feat.lookupMap.set cls novel
|
|
||||||
|
|
||||||
return novel
|
|
||||||
|
|
||||||
define [addMarkAnchor lookup gn cls anchor] : begin
|
define [addMarkAnchor lookup gn cls anchor] : begin
|
||||||
local a : object
|
local a : object
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
$$include '../meta/macros.ptl'
|
$$include '../meta/macros.ptl'
|
||||||
|
|
||||||
import [AddCommonFeature AddFeature AddLookup AddFeatureLookup ChainRuleBuilder BeginLookupBlock EndLookupBlock UkMapToLookup UkMap2ToLookup] from"./table-util.mjs"
|
import [UkMapToLookup UkMap2ToLookup] from"./table-util.mjs"
|
||||||
import [Dotless TieMark TieGlyph OgonekTrY IsSuperscript IsSubscript LeaningMark LeaningMarkSpacer] from"../support/gr.mjs"
|
import [Dotless TieMark TieGlyph OgonekTrY IsSuperscript IsSubscript LeaningMark LeaningMarkSpacer] from"../support/gr.mjs"
|
||||||
import as UnicodeKnowledge from"../meta/unicode-knowledge.mjs"
|
import as UnicodeKnowledge from"../meta/unicode-knowledge.mjs"
|
||||||
|
|
||||||
|
@ -10,29 +10,28 @@ define-macro Ccmp-Group : syntax-rules
|
||||||
`[Ccmp-Group @description @body]
|
`[Ccmp-Group @description @body]
|
||||||
dirty `[$ExecCcmpGroup$ [function [export-lookup chain-rule] @[formOf body]]]
|
dirty `[$ExecCcmpGroup$ [function [export-lookup chain-rule] @[formOf body]]]
|
||||||
|
|
||||||
export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
export : define [buildCCMP gsub glyphStore markGlyphs] : begin
|
||||||
local anyMark : Array.from markGlyphs.all
|
local anyMark : Array.from markGlyphs.all
|
||||||
local aboveMark : filterMarkByClass markGlyphs 'above'
|
local aboveMark : filterMarkByClass markGlyphs 'above'
|
||||||
|
|
||||||
define ccmp : AddFeature sink 'ccmp'
|
define ccmp : gsub.addCommonFeature : gsub.createFeature 'ccmp'
|
||||||
AddCommonFeature sink ccmp
|
|
||||||
|
|
||||||
define [$ExecCcmpGroup$ fn] : begin
|
define [$ExecCcmpGroup$ fn] : begin
|
||||||
local addedLookups {}
|
local addedLookups {}
|
||||||
define [export-lookup lookupName] : begin
|
define [export-lookup lookup] : begin
|
||||||
ccmp.lookups.push lookupName
|
ccmp.addLookup lookup
|
||||||
addedLookups.push lookupName
|
addedLookups.push lookup
|
||||||
|
|
||||||
|
|
||||||
local rec : BeginLookupBlock sink
|
local rec : gsub.beginBlock
|
||||||
define {chain-rule} : ChainRuleBuilder sink
|
define {chain-rule} : gsub.ChainRuleBuilder
|
||||||
|
|
||||||
fn export-lookup chain-rule
|
fn export-lookup chain-rule
|
||||||
|
|
||||||
for [local j 1] (j < addedLookups.length) [inc j] : begin
|
for [local j 1] (j < addedLookups.length) [inc j] : begin
|
||||||
sink.lookupDep.push {addedLookups.(j - 1) addedLookups.(j)}
|
gsub.setDependency addedLookups.(j - 1) addedLookups.(j)
|
||||||
|
|
||||||
EndLookupBlock rec sink
|
gsub.endBlock rec
|
||||||
|
|
||||||
Ccmp-Group "Mark transforms" : begin
|
Ccmp-Group "Mark transforms" : begin
|
||||||
|
|
||||||
|
@ -52,7 +51,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
define [GrekUpperTonosTf] : UkMapToLookup UnicodeKnowledge.upperGrekMarkToTonosTf
|
define [GrekUpperTonosTf] : UkMapToLookup UnicodeKnowledge.upperGrekMarkToTonosTf
|
||||||
|
|
||||||
# Dotless transform
|
# Dotless transform
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'above']
|
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'above']
|
||||||
.rules : list
|
.rules : list
|
||||||
|
@ -60,17 +59,17 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
chain-rule groupGrekUpperTonos [GrekUpperTonosTf]
|
chain-rule groupGrekUpperTonos [GrekUpperTonosTf]
|
||||||
|
|
||||||
# Iota transform
|
# Iota transform
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'below']
|
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'below']
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule groupLF [IotaLF]
|
chain-rule groupLF [IotaLF]
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_ligature'
|
.type 'gsub_ligature'
|
||||||
.substitutions : UkMap2ToLookup UnicodeKnowledge.markCompositionTf
|
.substitutions : UkMap2ToLookup UnicodeKnowledge.markCompositionTf
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_multiple'
|
.type 'gsub_multiple'
|
||||||
.substitutions : object
|
.substitutions : object
|
||||||
'parenAbove' { 'leftParenAbove' 'rightParenAbove' }
|
'parenAbove' { 'leftParenAbove' 'rightParenAbove' }
|
||||||
|
@ -89,13 +88,13 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
TieMarkFrom.push gid
|
TieMarkFrom.push gid
|
||||||
TieMarkTo.push [TieMark.get g]
|
TieMarkTo.push [TieMark.get g]
|
||||||
|
|
||||||
define lookupTieMarkLigature : AddLookup sink : object
|
define lookupTieMarkLigature : gsub.createLookup : object
|
||||||
.type 'gsub_ligature'
|
.type 'gsub_ligature'
|
||||||
.substitutions : {}.concat
|
.substitutions : {}.concat
|
||||||
TieMarkFrom.map : lambda [gnFrom idx]
|
TieMarkFrom.map : lambda [gnFrom idx]
|
||||||
object [from {'cgj' gnFrom}] [to TieMarkTo.(idx)]
|
object [from {'cgj' gnFrom}] [to TieMarkTo.(idx)]
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list : object
|
.rules : list : object
|
||||||
match {[TieGlyphs.concat TieMarkTo] {'cgj'} TieMarkFrom}
|
match {[TieGlyphs.concat TieMarkTo] {'cgj'} TieMarkFrom}
|
||||||
|
@ -105,7 +104,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
|
|
||||||
Ccmp-Group "Special dot-above transformation" : begin
|
Ccmp-Group "Special dot-above transformation" : begin
|
||||||
# b-dot, d-dot, h-dot, k-dot
|
# b-dot, d-dot, h-dot, k-dot
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_ligature'
|
.type 'gsub_ligature'
|
||||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'above']
|
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'above']
|
||||||
.substitutions : list
|
.substitutions : list
|
||||||
|
@ -134,11 +133,11 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
markSpacer.push [LeaningMarkSpacer.get g]
|
markSpacer.push [LeaningMarkSpacer.get g]
|
||||||
splitMapping.push { gn {[LeaningMarkSpacer.get g] [LeaningMark.get g]} }
|
splitMapping.push { gn {[LeaningMarkSpacer.get g] [LeaningMark.get g]} }
|
||||||
|
|
||||||
define lookupTurnMarkIntoLeaningAndSpacer : AddLookup sink : object
|
define lookupTurnMarkIntoLeaningAndSpacer : gsub.createLookup : object
|
||||||
.type 'gsub_multiple'
|
.type 'gsub_multiple'
|
||||||
.substitutions : Object.fromEntries splitMapping
|
.substitutions : Object.fromEntries splitMapping
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs mkCenter]
|
.ignoreGlyphs [filterMarkByClassNegated markGlyphs mkCenter]
|
||||||
.rules : list
|
.rules : list
|
||||||
|
@ -158,7 +157,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
if [IsSuperscript.get g] : superscripts.push gn
|
if [IsSuperscript.get g] : superscripts.push gn
|
||||||
if [IsSubscript.get g] : subscripts.push gn
|
if [IsSubscript.get g] : subscripts.push gn
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.ignoreGlyphs anyMark
|
.ignoreGlyphs anyMark
|
||||||
.rules : list
|
.rules : list
|
||||||
|
@ -230,7 +229,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
e.push ('toneSandhiMid' + toneStart + toneMid + toneEnd)
|
e.push ('toneSandhiMid' + toneStart + toneMid + toneEnd)
|
||||||
return (f ~> e)
|
return (f ~> e)
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule [ToneToToneStart 0] {'tone0'}
|
chain-rule [ToneToToneStart 0] {'tone0'}
|
||||||
|
@ -239,7 +238,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
chain-rule [ToneToToneStart 3] {'tone3'}
|
chain-rule [ToneToToneStart 3] {'tone3'}
|
||||||
chain-rule [ToneToToneStart 4] {'tone4'}
|
chain-rule [ToneToToneStart 4] {'tone4'}
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule [ToneStartOrMidAt 0] [ToneStartToToneMid 0]
|
chain-rule [ToneStartOrMidAt 0] [ToneStartToToneMid 0]
|
||||||
|
@ -248,7 +247,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
chain-rule [ToneStartOrMidAt 3] [ToneStartToToneMid 3]
|
chain-rule [ToneStartOrMidAt 3] [ToneStartToToneMid 3]
|
||||||
chain-rule [ToneStartOrMidAt 4] [ToneStartToToneMid 4]
|
chain-rule [ToneStartOrMidAt 4] [ToneStartToToneMid 4]
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule [ToneStartOrMidAt 0] [ToneToToneEnd 0]
|
chain-rule [ToneStartOrMidAt 0] [ToneToToneEnd 0]
|
||||||
|
@ -257,7 +256,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
chain-rule [ToneStartOrMidAt 3] [ToneToToneEnd 3]
|
chain-rule [ToneStartOrMidAt 3] [ToneToToneEnd 3]
|
||||||
chain-rule [ToneStartOrMidAt 4] [ToneToToneEnd 4]
|
chain-rule [ToneStartOrMidAt 4] [ToneToToneEnd 4]
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule [ToneSandhiToToneStart 0] {'toneSandhi0'}
|
chain-rule [ToneSandhiToToneStart 0] {'toneSandhi0'}
|
||||||
|
@ -266,7 +265,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
chain-rule [ToneSandhiToToneStart 3] {'toneSandhi3'}
|
chain-rule [ToneSandhiToToneStart 3] {'toneSandhi3'}
|
||||||
chain-rule [ToneSandhiToToneStart 4] {'toneSandhi4'}
|
chain-rule [ToneSandhiToToneStart 4] {'toneSandhi4'}
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule [ToneSandhiStartOrMidAt 0] [ToneSandhiStartToToneMid 0]
|
chain-rule [ToneSandhiStartOrMidAt 0] [ToneSandhiStartToToneMid 0]
|
||||||
|
@ -275,7 +274,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
chain-rule [ToneSandhiStartOrMidAt 3] [ToneSandhiStartToToneMid 3]
|
chain-rule [ToneSandhiStartOrMidAt 3] [ToneSandhiStartToToneMid 3]
|
||||||
chain-rule [ToneSandhiStartOrMidAt 4] [ToneSandhiStartToToneMid 4]
|
chain-rule [ToneSandhiStartOrMidAt 4] [ToneSandhiStartToToneMid 4]
|
||||||
|
|
||||||
export-lookup : AddLookup sink : object
|
export-lookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule [ToneSandhiStartOrMidAt 0] [ToneSandhiToToneEnd 0]
|
chain-rule [ToneSandhiStartOrMidAt 0] [ToneSandhiToToneEnd 0]
|
||||||
|
@ -286,11 +285,9 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
||||||
|
|
||||||
return ccmp
|
return ccmp
|
||||||
|
|
||||||
export : define [buildCCMPPostCvSs sink ccmpFeature glyphStore markGlyphs] : begin
|
export : define [buildCCMPPostCvSs gsub ccmp glyphStore markGlyphs] : begin
|
||||||
local anyMark : Array.from markGlyphs.all
|
local anyMark : Array.from markGlyphs.all
|
||||||
local rec : BeginLookupBlock sink
|
local rec : gsub.beginBlock
|
||||||
|
|
||||||
define ccmp : AddFeature sink 'ccmp'
|
|
||||||
|
|
||||||
define triggerGlyphs_Normal { }
|
define triggerGlyphs_Normal { }
|
||||||
define triggerGlyphs_Y { }
|
define triggerGlyphs_Y { }
|
||||||
|
@ -299,14 +296,14 @@ export : define [buildCCMPPostCvSs sink ccmpFeature glyphStore markGlyphs] : beg
|
||||||
[OgonekTrY.get g] : triggerGlyphs_Y.push gid
|
[OgonekTrY.get g] : triggerGlyphs_Y.push gid
|
||||||
true : triggerGlyphs_Normal.push gid
|
true : triggerGlyphs_Normal.push gid
|
||||||
|
|
||||||
define ogonekSpacerNormal : AddLookup sink : object
|
define ogonekSpacerNormal : gsub.createLookup : object
|
||||||
.type 'gsub_multiple'
|
.type 'gsub_multiple'
|
||||||
.substitutions UnicodeKnowledge.ogonekBelowToTRTf
|
.substitutions UnicodeKnowledge.ogonekBelowToTRTf
|
||||||
define ogonekSpacerY : AddLookup sink : object
|
define ogonekSpacerY : gsub.createLookup : object
|
||||||
.type 'gsub_single'
|
.type 'gsub_single'
|
||||||
.substitutions UnicodeKnowledge.ogonekBelowToTRTf_Y
|
.substitutions UnicodeKnowledge.ogonekBelowToTRTf_Y
|
||||||
|
|
||||||
define lookupMarks1 : AddLookup sink : object
|
ccmp.addLookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'below']
|
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'below']
|
||||||
.rules : list
|
.rules : list
|
||||||
|
@ -321,8 +318,7 @@ export : define [buildCCMPPostCvSs sink ccmpFeature glyphStore markGlyphs] : beg
|
||||||
.inputEnds 2
|
.inputEnds 2
|
||||||
.apply {{.at 1 .lookup ogonekSpacerNormal}}
|
.apply {{.at 1 .lookup ogonekSpacerNormal}}
|
||||||
|
|
||||||
ccmpFeature.lookups.push lookupMarks1
|
gsub.endBlock rec
|
||||||
EndLookupBlock rec sink
|
|
||||||
|
|
||||||
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
$$include '../meta/macros.ptl'
|
$$include '../meta/macros.ptl'
|
||||||
|
|
||||||
import [AddLookup AddCommonFeature PickCommonFeature AddFeatureLookup PickLookup BeginLookupBlock EndLookupBlock ChainRuleBuilder] from"./table-util.mjs"
|
|
||||||
import [Cv AnyCv CvDecompose RightDependentLink RightDependentTrigger] from"../support/gr.mjs"
|
import [Cv AnyCv CvDecompose RightDependentLink RightDependentTrigger] from"../support/gr.mjs"
|
||||||
|
|
||||||
extern Map
|
extern Map
|
||||||
|
@ -11,20 +10,68 @@ define look-around null
|
||||||
define [FeatureName tag] : tag + '_cvss'
|
define [FeatureName tag] : tag + '_cvss'
|
||||||
define [SsLookupName tag] : 'lookup_ss_' + tag
|
define [SsLookupName tag] : 'lookup_ss_' + tag
|
||||||
define [CvLookupName tag] : 'lookup_cv_' + tag
|
define [CvLookupName tag] : 'lookup_cv_' + tag
|
||||||
|
define [CvSpecificLookupName tag rank] : 'lookup_cv_' + tag + '_' + rank
|
||||||
define [CvDecomposeLookupName tag] : 'lookup_cv_decompose_' + tag
|
define [CvDecomposeLookupName tag] : 'lookup_cv_decompose_' + tag
|
||||||
|
|
||||||
export : define [buildCVSS sink para glyphStore] : begin
|
class CvLookupManager
|
||||||
define {chain-rule} : ChainRuleBuilder sink
|
public [new table tag feature] : begin
|
||||||
|
set this.table table
|
||||||
|
set this.tag tag
|
||||||
|
set this.feature feature
|
||||||
|
|
||||||
local rec : BeginLookupBlock sink
|
set this.decompositionLookups {}
|
||||||
local cvLookupNameSet : new Set
|
|
||||||
local ssLookupNameSet : new Set
|
|
||||||
|
|
||||||
# Build decomposition lookups
|
set this.substitutionLookups {}
|
||||||
|
set this.altrenatesLookup null
|
||||||
|
set this.singleSubstLookups {}
|
||||||
|
|
||||||
|
public [addDecompositionLookup lookup] : begin
|
||||||
|
this.decompositionLookups.push lookup
|
||||||
|
this.feature.addLookup lookup
|
||||||
|
|
||||||
|
public [alternateSubst] : begin
|
||||||
|
if this.altrenatesLookup : return this.altrenatesLookup
|
||||||
|
|
||||||
|
define lookupName : 'lookup_cv_2_alternates_' + this.tag
|
||||||
|
define lookup : this.table.pickLookup lookupName {.type 'gsub_alternate' .substitutions {.}}
|
||||||
|
|
||||||
|
this.feature.addLookup lookup
|
||||||
|
this.substitutionLookups.push lookup
|
||||||
|
set this.altrenatesLookup lookup
|
||||||
|
return lookup
|
||||||
|
|
||||||
|
public [singleSubst rank] : begin
|
||||||
|
if this.singleSubstLookups.(rank) : return this.singleSubstLookups.(rank)
|
||||||
|
|
||||||
|
define lookupName : 'lookup_cv_1_single_' + this.tag + '_' + rank
|
||||||
|
define lookup : this.table.pickLookup lookupName {.type 'gsub_single' .substitutions {.}}
|
||||||
|
|
||||||
|
this.feature.addLookup lookup
|
||||||
|
this.substitutionLookups.push lookup
|
||||||
|
set this.singleSubstLookups.(rank) lookup
|
||||||
|
return lookup
|
||||||
|
|
||||||
|
public [linkDeps] : begin
|
||||||
|
foreach a [items-of this.decompositionLookups] : begin
|
||||||
|
foreach b [items-of this.substitutionLookups] : begin
|
||||||
|
this.table.setDependency a b
|
||||||
|
|
||||||
|
for [local i 1] (i < this.substitutionLookups.length) [inc i]
|
||||||
|
this.table.setDependency this.substitutionLookups.(i - 1) this.substitutionLookups.(i)
|
||||||
|
|
||||||
|
export : define [buildCVSS gsub para glyphStore] : begin
|
||||||
|
local rec : gsub.beginBlock
|
||||||
|
|
||||||
|
local cvs : new Map
|
||||||
|
|
||||||
|
do "Initialize CV feature atlas"
|
||||||
|
foreach {name prime} para.variants.primes : if prime.tag : begin
|
||||||
|
define feature : gsub.addCommonFeature : gsub.createFeature prime.tag
|
||||||
|
local cvLookupManager : new CvLookupManager gsub prime.tag feature
|
||||||
|
cvs.set prime.tag cvLookupManager
|
||||||
|
|
||||||
|
do "Build decomposition lookups"
|
||||||
local decompositions : new Map
|
local decompositions : new Map
|
||||||
local cvDecompositionLookupNameSet : new Set
|
|
||||||
local cvTagToDecompositionLookups : new Map
|
|
||||||
|
|
||||||
foreach { gn glyph } [glyphStore.namedEntries] : if [CvDecompose.get glyph] : do
|
foreach { gn glyph } [glyphStore.namedEntries] : if [CvDecompose.get glyph] : do
|
||||||
local decomp : object
|
local decomp : object
|
||||||
parts : CvDecompose.get glyph
|
parts : CvDecompose.get glyph
|
||||||
|
@ -38,73 +85,52 @@ export : define [buildCVSS sink para glyphStore] : begin
|
||||||
|
|
||||||
foreach { gn decomp } decompositions : if decomp.influences.size : do
|
foreach { gn decomp } decompositions : if decomp.influences.size : do
|
||||||
define lookupName : CvDecomposeLookupName : [[Array.from decomp.influences].sort].join '/'
|
define lookupName : CvDecomposeLookupName : [[Array.from decomp.influences].sort].join '/'
|
||||||
define lookup : PickLookup sink lookupName {.type 'gsub_multiple' .substitutions {.}}
|
define lookup : gsub.pickLookup lookupName {.type 'gsub_multiple' .substitutions {.}}
|
||||||
cvDecompositionLookupNameSet.add lookupName
|
|
||||||
set lookup.substitutions.(gn) decomp.parts
|
set lookup.substitutions.(gn) decomp.parts
|
||||||
|
|
||||||
foreach cvTag decomp.influences : begin
|
foreach cvTag decomp.influences : [cvs.get cvTag].addDecompositionLookup lookup
|
||||||
local s : cvTagToDecompositionLookups.get cvTag
|
|
||||||
if [not s] : begin
|
|
||||||
set s : new Set
|
|
||||||
cvTagToDecompositionLookups.set cvTag s
|
|
||||||
s.add lookupName
|
|
||||||
|
|
||||||
define [addCvMapping tag src dst rank] : begin
|
do "cvxx"
|
||||||
define feature : PickCommonFeature sink [FeatureName tag]
|
local cvGrs {}
|
||||||
define lookupName : CvLookupName tag
|
foreach {name prime} para.variants.primes : foreach {vn variant} prime.variants : begin
|
||||||
define lookup : PickLookup sink lookupName {.type 'gsub_alternate' .substitutions {.}}
|
if (prime.tag && variant.rank) : cvGrs.push : Cv prime.tag variant.rank
|
||||||
|
cvGrs.sort Cv.compare
|
||||||
|
|
||||||
if [not : cvLookupNameSet.has lookupName] : begin
|
foreach gr [items-of cvGrs] : begin
|
||||||
AddFeatureLookup feature lookupName
|
local cvAlt : [cvs.get gr.tag].alternateSubst
|
||||||
cvLookupNameSet.add lookupName
|
|
||||||
local decompLookups : cvTagToDecompositionLookups.get tag
|
|
||||||
if decompLookups : foreach d decompLookups : AddFeatureLookup feature d
|
|
||||||
|
|
||||||
if [not lookup.substitutions.(src)] : set lookup.substitutions.(src) { }
|
|
||||||
set lookup.substitutions.(src).(rank - 1) dst
|
|
||||||
|
|
||||||
define [addSsSubstitution tag decomp src dst] : begin
|
|
||||||
define feature : PickCommonFeature sink [FeatureName tag]
|
|
||||||
define lookupName : SsLookupName composition.tag
|
|
||||||
define lookup : PickLookup sink lookupName {.type 'gsub_single' .substitutions {.}}
|
|
||||||
|
|
||||||
if [not : ssLookupNameSet.has lookupName] : begin
|
|
||||||
AddFeatureLookup feature lookupName
|
|
||||||
ssLookupNameSet.add lookupName
|
|
||||||
foreach { prime pv } [items-of decomp] : if (pv.tag && pv.rank) : begin
|
|
||||||
local decompLookups : cvTagToDecompositionLookups.get pv.tag
|
|
||||||
if decompLookups : foreach d decompLookups : AddFeatureLookup feature d
|
|
||||||
|
|
||||||
set lookup.substitutions.(src) dst
|
|
||||||
|
|
||||||
# cvxx
|
|
||||||
foreach {gn glyph} [glyphStore.namedEntries] : if [not : CvDecompose.get glyph] : do
|
|
||||||
foreach [gr : items-of : AnyCv.query glyph] : if gr.tag : begin
|
|
||||||
addCvMapping gr.tag gn [glyphStore.ensureExists : gr.get glyph] gr.rank
|
|
||||||
|
|
||||||
# ssxx
|
|
||||||
foreach {name composition} para.variants.composites : if composition.tag : do
|
|
||||||
define decomp : composition.decompose para para.variants.selectorTree
|
|
||||||
foreach { prime pv } [items-of decomp] : if (pv.tag && pv.rank) : begin
|
|
||||||
local gr : Cv pv.tag pv.rank
|
|
||||||
foreach {gn glyph} [glyphStore.namedEntries] : if [not : CvDecompose.get glyph] : begin
|
foreach {gn glyph} [glyphStore.namedEntries] : if [not : CvDecompose.get glyph] : begin
|
||||||
local substituted : gr.get glyph
|
local subst : gr.get glyph
|
||||||
if substituted : addSsSubstitution composition.tag decomp gn substituted
|
if (subst && subst != gn) : begin
|
||||||
|
if [not cvAlt.substitutions.(gn)] : set cvAlt.substitutions.(gn) { }
|
||||||
|
set cvAlt.substitutions.(gn).(gr.rank - 1) : glyphStore.ensureExists subst
|
||||||
|
|
||||||
# If there are holes in the alternates list, fill them
|
do "ssxx" : foreach {name composition} para.variants.composites : if composition.tag : begin
|
||||||
foreach lutn cvLookupNameSet : begin
|
define feature : gsub.addCommonFeature : gsub.createFeature composition.tag
|
||||||
local st [PickLookup sink lutn].substitutions
|
|
||||||
|
define decomp : composition.decompose para para.variants.selectorTree
|
||||||
|
local ssGrs {}
|
||||||
|
foreach { prime pv } [items-of decomp] : if (pv.tag && pv.rank) : begin
|
||||||
|
ssGrs.push : Cv pv.tag pv.rank
|
||||||
|
foreach lookup [items-of [cvs.get pv.tag].decompositionLookups] : begin
|
||||||
|
feature.addLookup lookup
|
||||||
|
ssGrs.sort Cv.compare
|
||||||
|
|
||||||
|
foreach gr [items-of ssGrs] : begin
|
||||||
|
local cvSingle : [cvs.get gr.tag].singleSubst gr.rank
|
||||||
|
feature.addLookup cvSingle
|
||||||
|
foreach {gn glyph} [glyphStore.namedEntries] : if [not : CvDecompose.get glyph] : begin
|
||||||
|
local subst : gr.get glyph
|
||||||
|
if (subst && subst != gn) : begin
|
||||||
|
set cvSingle.substitutions.(gn) : glyphStore.ensureExists subst
|
||||||
|
|
||||||
|
do "Cleanup and link dependency"
|
||||||
|
foreach cv [cvs.values] : begin
|
||||||
|
local st cv.altrenatesLookup.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
|
||||||
|
|
||||||
# Lookup dependency
|
cv.linkDeps
|
||||||
foreach lutnDe cvDecompositionLookupNameSet : foreach lutnCv cvLookupNameSet : begin
|
|
||||||
sink.lookupDep.push { lutnDe lutnCv }
|
|
||||||
foreach lutnDe cvDecompositionLookupNameSet : foreach lutnSs ssLookupNameSet : begin
|
|
||||||
sink.lookupDep.push { lutnDe lutnSs }
|
|
||||||
foreach lutnCv cvLookupNameSet : foreach lutnSs ssLookupNameSet : begin
|
|
||||||
sink.lookupDep.push { lutnCv lutnSs }
|
|
||||||
|
|
||||||
EndLookupBlock rec sink
|
gsub.endBlock rec
|
||||||
|
|
||||||
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
$$include '../meta/macros.ptl'
|
$$include '../meta/macros.ptl'
|
||||||
|
|
||||||
import [AddCommonFeature AddFeature AddLookup BeginLookupBlock EndLookupBlock ChainRuleBuilder] from"./table-util.mjs"
|
|
||||||
import [NumeratorForm DenominatorForm] from"../support/gr.mjs"
|
import [NumeratorForm DenominatorForm] from"../support/gr.mjs"
|
||||||
|
|
||||||
# Name-driven feature pairs
|
# Name-driven feature pairs
|
||||||
export : define [buildFrac sink glyphStore] : begin
|
export : define [buildFrac gsub glyphStore] : begin
|
||||||
local rec : BeginLookupBlock sink
|
local rec : gsub.beginBlock
|
||||||
|
|
||||||
define frac : AddFeature sink 'frac'
|
define frac : gsub.addCommonFeature : gsub.createFeature 'frac'
|
||||||
define { chain-rule reverse-rule } : ChainRuleBuilder sink
|
define { chain-rule reverse-rule } : gsub.ChainRuleBuilder
|
||||||
|
|
||||||
define subSolidus : AddLookup sink : object
|
define subSolidus : gsub.createLookup : object
|
||||||
.type 'gsub_single'
|
.type 'gsub_single'
|
||||||
.substitutions : object ['solidus' 'fractionBar'] ['slash' 'fractionBar']
|
.substitutions : object ['solidus' 'fractionBar'] ['slash' 'fractionBar']
|
||||||
|
|
||||||
|
@ -26,24 +25,22 @@ export : define [buildFrac sink glyphStore] : begin
|
||||||
numSet.push numForm
|
numSet.push numForm
|
||||||
denSet.push denForm
|
denSet.push denForm
|
||||||
|
|
||||||
define subDen : AddLookup sink : object
|
define subDen : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule [{'fractionBar'}.concat denSet] [digitSet ~> denSet]
|
chain-rule [{'fractionBar'}.concat denSet] [digitSet ~> denSet]
|
||||||
|
|
||||||
define subNum : AddLookup sink : object
|
define subNum : gsub.createLookup : object
|
||||||
.type 'gsub_reverse'
|
.type 'gsub_reverse'
|
||||||
.rules : list
|
.rules : list
|
||||||
reverse-rule [digitSet ~> numSet] [{'fractionBar'}.concat numSet]
|
reverse-rule [digitSet ~> numSet] [{'fractionBar'}.concat numSet]
|
||||||
|
|
||||||
frac.lookups.push subSolidus
|
frac.addLookup subSolidus
|
||||||
frac.lookups.push subDen
|
frac.addLookup subDen
|
||||||
frac.lookups.push subNum
|
frac.addLookup subNum
|
||||||
sink.lookupDep.push {subSolidus subDen}
|
gsub.setDependency subSolidus subDen
|
||||||
sink.lookupDep.push {subSolidus subNum}
|
gsub.setDependency subSolidus subNum
|
||||||
|
|
||||||
AddCommonFeature sink frac
|
gsub.endBlock rec
|
||||||
|
|
||||||
EndLookupBlock rec sink
|
|
||||||
|
|
||||||
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import [AddCommonFeature AddFeature AddLookup BeginLookupBlock EndLookupBlock] from"./table-util.mjs"
|
|
||||||
|
|
||||||
# Name-driven feature pairs
|
# Name-driven feature pairs
|
||||||
export : define [buildGrFeature sink glyphStore gr] : begin
|
export : define [buildGrFeature gsub glyphStore gr] : begin
|
||||||
local rec : BeginLookupBlock sink
|
local rec : gsub.beginBlock
|
||||||
|
|
||||||
local mapping {.}
|
local mapping {.}
|
||||||
foreach { gnSrc glyph } [glyphStore.namedEntries] : begin
|
foreach { gnSrc glyph } [glyphStore.namedEntries] : begin
|
||||||
|
@ -12,11 +10,10 @@ export : define [buildGrFeature sink glyphStore gr] : begin
|
||||||
set mapping.(gnSrc) gnDst
|
set mapping.(gnSrc) gnDst
|
||||||
|
|
||||||
if [objectIsNotEmpty mapping] : begin
|
if [objectIsNotEmpty mapping] : begin
|
||||||
define lookup1 : AddLookup sink {.type 'gsub_single' .substitutions mapping}
|
define lookup1 : gsub.createLookup {.type 'gsub_single' .substitutions mapping}
|
||||||
define feature1 : AddFeature sink gr.otlTag
|
define feature1 : gsub.addCommonFeature : gsub.createFeature gr.otlTag
|
||||||
feature1.lookups.push lookup1
|
feature1.addLookup lookup1
|
||||||
AddCommonFeature sink feature1
|
|
||||||
|
|
||||||
EndLookupBlock rec sink
|
gsub.endBlock rec
|
||||||
|
|
||||||
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
define [objectIsNotEmpty obj] : obj && [Object.keys obj].length
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
$$include '../meta/macros.ptl'
|
$$include '../meta/macros.ptl'
|
||||||
|
|
||||||
import [AddCommonFeature AddFeature ChainRuleBuilder BeginLookupBlock EndLookupBlock] from"./table-util.mjs"
|
|
||||||
extern Map
|
extern Map
|
||||||
extern Set
|
extern Set
|
||||||
|
|
||||||
|
@ -12,62 +11,52 @@ define look-around null
|
||||||
define advance : lambda [t] null
|
define advance : lambda [t] null
|
||||||
define ident : lambda [t] : t.map : lambda [x] x
|
define ident : lambda [t] : t.map : lambda [x] x
|
||||||
|
|
||||||
export : define [buildLigations sink para plm] : begin
|
export : define [buildLigations gsub para plm] : begin
|
||||||
# Initialize features
|
# Initialize features
|
||||||
define features : new Map
|
define features : new Map
|
||||||
foreach [ { featureTag } : pairs-of plm] : begin
|
foreach [ { featureTag } : pairs-of plm] : begin
|
||||||
local feature : AddCommonFeature sink : AddFeature sink featureTag
|
local feature : gsub.addCommonFeature : gsub.createFeature featureTag
|
||||||
features.set featureTag feature
|
features.set featureTag feature
|
||||||
|
|
||||||
buildLigationsImpl sink para [DoLigGroupT sink plm features]
|
buildLigationsImpl gsub para [DoLigGroupT gsub plm features]
|
||||||
|
|
||||||
define [DoLigGroupT sink plm features] : function [F] : begin
|
define [DoLigGroupT gsub plm features] : function [F] : begin
|
||||||
define deDupeGroups : new Map
|
define deDupeGroups : new Map
|
||||||
|
|
||||||
# Groupwise deduplicate of the lookups we just added
|
# Groupwise deduplicate of the lookups we just added
|
||||||
|
# Push the lookups if they are indeed new
|
||||||
define [deDupe lookupsToPush] : begin
|
define [deDupe lookupsToPush] : begin
|
||||||
local h ''
|
local h : JSON.stringify lookupsToPush
|
||||||
foreach obj [lookupsToPush.values] : begin
|
|
||||||
set h : h + [JSON.stringify obj] + '\n'
|
|
||||||
|
|
||||||
local g : deDupeGroups.get h
|
local g : deDupeGroups.get h
|
||||||
if g : return { false g }
|
if g : return { false g }
|
||||||
|
|
||||||
deDupeGroups.set h lookupsToPush
|
# We now actually push the lookups
|
||||||
return { true lookupsToPush }
|
|
||||||
|
local results {}
|
||||||
|
local rec : gsub.beginBlock
|
||||||
|
|
||||||
|
local lastLookupInGroup null
|
||||||
|
foreach raw [items-of lookupsToPush] : begin
|
||||||
|
local lookup : gsub.createLookup raw
|
||||||
|
if lastLookupInGroup : gsub.setDependency lastLookupInGroup lookup
|
||||||
|
set lastLookupInGroup lookup
|
||||||
|
results.push lookup
|
||||||
|
|
||||||
|
gsub.endBlock rec
|
||||||
|
|
||||||
|
deDupeGroups.set h results
|
||||||
|
return { true results }
|
||||||
|
|
||||||
# Execute body function F, collect lookups and add them into the GSUB
|
# Execute body function F, collect lookups and add them into the GSUB
|
||||||
foreach [ { featureTag groups } : pairs-of plm] : begin
|
foreach [ { featureTag groups } : pairs-of plm] : begin
|
||||||
define feature : features.get featureTag
|
define feature : features.get featureTag
|
||||||
define { fUnique lookupsToPush } : deDupe
|
define { fUnique lookups } : deDupe : DoFeatureLigGroup gsub feature groups F
|
||||||
DoFeatureLigGroup sink feature groups F
|
foreach lookup [items-of lookups] : feature.addLookup lookup
|
||||||
|
|
||||||
# Set feature lookups
|
define [DoFeatureLigGroup gsub feature groups F] : begin
|
||||||
foreach ln [lookupsToPush.keys] : feature.lookups.push ln
|
|
||||||
|
|
||||||
if fUnique : begin
|
|
||||||
define rec : BeginLookupBlock sink
|
|
||||||
|
|
||||||
# Add lookups into the sink
|
|
||||||
foreach { ln obj } lookupsToPush : begin
|
|
||||||
if sink.lookups.(ln) : throw : new Error "Lookup name conflict \(ln)"
|
|
||||||
set sink.lookups.(ln) obj
|
|
||||||
|
|
||||||
# Set in-group priority
|
|
||||||
local lastLookupInGroup null
|
|
||||||
foreach ln [lookupsToPush.keys] : begin
|
|
||||||
if lastLookupInGroup : sink.lookupDep.push { lastLookupInGroup ln }
|
|
||||||
set lastLookupInGroup ln
|
|
||||||
|
|
||||||
EndLookupBlock rec sink
|
|
||||||
|
|
||||||
define [DoFeatureLigGroup sink feature groups F] : begin
|
|
||||||
define [hasLG ln] : [groups.indexOf ln] >= 0
|
define [hasLG ln] : [groups.indexOf ln] >= 0
|
||||||
define lookupNamePrefix : 'lig_' + feature.tag + '_'
|
define lookupNamePrefix : 'lig_' + feature.tag + '_'
|
||||||
define lookupsToPush : new Map
|
define lookupsToPush {}
|
||||||
|
|
||||||
define [AddLookup obj] : begin
|
|
||||||
lookupsToPush.set (lookupNamePrefix + (feature.lookups.length + lookupsToPush.size)) obj
|
|
||||||
|
|
||||||
define [filterNulls _rules] : begin
|
define [filterNulls _rules] : begin
|
||||||
if [not _rules] : return _rules
|
if [not _rules] : return _rules
|
||||||
|
@ -77,13 +66,13 @@ define [DoFeatureLigGroup sink feature groups F] : begin
|
||||||
|
|
||||||
define [CreateLigationLookup _rules] : begin
|
define [CreateLigationLookup _rules] : begin
|
||||||
define rules : filterNulls _rules
|
define rules : filterNulls _rules
|
||||||
if (rules && rules.length) : AddLookup
|
if (rules && rules.length) : lookupsToPush.push
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules rules
|
.rules rules
|
||||||
|
|
||||||
define [CreateReverseLigationLookup _rules] : begin
|
define [CreateReverseLigationLookup _rules] : begin
|
||||||
define rules : filterNulls _rules
|
define rules : filterNulls _rules
|
||||||
if (rules && rules.length) : AddLookup
|
if (rules && rules.length) : lookupsToPush.push
|
||||||
.type 'gsub_reverse'
|
.type 'gsub_reverse'
|
||||||
.rules rules
|
.rules rules
|
||||||
|
|
||||||
|
@ -99,8 +88,8 @@ define-macro LigGroup : syntax-rules
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
|
||||||
define [buildLigationsImpl sink para $LigGroup$] : begin
|
define [buildLigationsImpl gsub para $LigGroup$] : begin
|
||||||
define { chain-rule reverse-rule } : ChainRuleBuilder sink
|
define { chain-rule reverse-rule } : gsub.ChainRuleBuilder
|
||||||
|
|
||||||
define less {'less'}
|
define less {'less'}
|
||||||
define lessAndEquiv {'less' 'less.lig.shift0' 'less.lig.shift0.anti'}
|
define lessAndEquiv {'less' 'less.lig.shift0' 'less.lig.shift0.anti'}
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
$$include '../meta/macros.ptl'
|
$$include '../meta/macros.ptl'
|
||||||
|
|
||||||
import [CopyLanguage AddFeature AddLookup BeginLookupBlock EndLookupBlock ChainRuleBuilder] from"./table-util.mjs"
|
|
||||||
import [CvDecompose] from"../support/gr.mjs"
|
import [CvDecompose] from"../support/gr.mjs"
|
||||||
|
|
||||||
extern Set
|
extern Set
|
||||||
|
|
||||||
export : define [buildLOCL sink para glyphStore] : begin
|
export : define [buildLOCL gsub para glyphStore] : begin
|
||||||
local rec : BeginLookupBlock sink
|
local rec : gsub.beginBlock
|
||||||
|
|
||||||
define { chain-rule } : ChainRuleBuilder sink
|
define { chain-rule } : gsub.ChainRuleBuilder
|
||||||
|
|
||||||
define cyrlSRB : CopyLanguage sink 'cyrl_SRB ' 'cyrl_DFLT'
|
define cyrlSRB : gsub.copyLanguage 'cyrl_SRB ' 'cyrl_DFLT'
|
||||||
define cyrlMKD : CopyLanguage sink 'cyrl_MKD ' 'cyrl_DFLT'
|
define cyrlMKD : gsub.copyLanguage 'cyrl_MKD ' 'cyrl_DFLT'
|
||||||
define cyrlBGR : CopyLanguage sink 'cyrl_BGR ' 'cyrl_DFLT'
|
define cyrlBGR : gsub.copyLanguage 'cyrl_BGR ' 'cyrl_DFLT'
|
||||||
define latnVIT : CopyLanguage sink 'latn_VIT ' 'latn_DFLT'
|
define latnVIT : gsub.copyLanguage 'latn_VIT ' 'latn_DFLT'
|
||||||
|
|
||||||
# SRB
|
# SRB
|
||||||
define loclSRB : AddFeature sink 'locl'
|
define loclSRB : gsub.createFeature 'locl'
|
||||||
cyrlSRB.features.unshift loclSRB.name
|
cyrlSRB.addFeature loclSRB
|
||||||
cyrlMKD.features.unshift loclSRB.name
|
cyrlMKD.addFeature loclSRB
|
||||||
loclSRB.lookups.push : AddLookup sink : object
|
loclSRB.addLookup : gsub.createLookup
|
||||||
type 'gsub_single'
|
.type 'gsub_single'
|
||||||
substitutions : 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'
|
||||||
|
@ -33,11 +32,10 @@ export : define [buildLOCL sink para glyphStore] : begin
|
||||||
'cyrl/be' : glyphStore.ensureExists 'cyrl/be.SRB'
|
'cyrl/be' : glyphStore.ensureExists 'cyrl/be.SRB'
|
||||||
|
|
||||||
# BGR
|
# BGR
|
||||||
define loclBGR : AddFeature sink 'locl'
|
define loclBGR : cyrlBGR.addFeature : gsub.createFeature 'locl'
|
||||||
cyrlBGR.features.unshift loclBGR.name
|
loclBGR.addLookup : gsub.createLookup
|
||||||
loclBGR.lookups.push : AddLookup sink : object
|
.type 'gsub_single'
|
||||||
type 'gsub_single'
|
.substitutions : 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'
|
||||||
|
@ -64,15 +62,14 @@ export : define [buildLOCL sink para glyphStore] : begin
|
||||||
'cyrl/yeri' : glyphStore.ensureExists 'cyrl/yeri.BGR'
|
'cyrl/yeri' : glyphStore.ensureExists 'cyrl/yeri.BGR'
|
||||||
|
|
||||||
# VIT
|
# VIT
|
||||||
define loclVIT : AddFeature sink 'locl'
|
define loclVIT : latnVIT.addFeature : gsub.createFeature 'locl'
|
||||||
latnVIT.features.unshift loclVIT.name
|
|
||||||
|
|
||||||
define [sx s] : lambda [t] : t.map : lambda [x] "\(x)/\(s)"
|
define [sx s] : lambda [t] : t.map : lambda [x] "\(x)/\(s)"
|
||||||
|
|
||||||
do "Decompose Vietnamese glyphs"
|
do "Decompose Vietnamese glyphs"
|
||||||
|
|
||||||
local decompositionSubstitutions {.}
|
local decompositionSubstitutions {.}
|
||||||
loclVIT.lookups.push : AddLookup sink
|
loclVIT.addLookup : gsub.createLookup
|
||||||
.type 'gsub_multiple'
|
.type 'gsub_multiple'
|
||||||
.substitutions decompositionSubstitutions
|
.substitutions decompositionSubstitutions
|
||||||
|
|
||||||
|
@ -87,7 +84,7 @@ export : define [buildLOCL sink para glyphStore] : begin
|
||||||
local decomp : CvDecompose.get g
|
local decomp : CvDecompose.get g
|
||||||
set decompositionSubstitutions.(gn) decomp
|
set decompositionSubstitutions.(gn) decomp
|
||||||
|
|
||||||
loclVIT.lookups.push : AddLookup sink
|
loclVIT.addLookup : gsub.createLookup
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : list
|
.rules : list
|
||||||
chain-rule
|
chain-rule
|
||||||
|
@ -99,4 +96,4 @@ export : define [buildLOCL sink para glyphStore] : begin
|
||||||
{'breveAbove'} ~> nothing
|
{'breveAbove'} ~> nothing
|
||||||
viShiftableMarks ~> [sx 'viCenter']
|
viShiftableMarks ~> [sx 'viCenter']
|
||||||
|
|
||||||
EndLookupBlock.Front rec sink
|
gsub.endBlockAtFront rec
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
$$include '../meta/macros.ptl'
|
$$include '../meta/macros.ptl'
|
||||||
|
|
||||||
import [AddCommonFeature AddFeature AddLookup ChainRuleBuilder QueryRelatedGlyphs BeginLookupBlock EndLookupBlock] from"./table-util.mjs"
|
import [QueryRelatedGlyphs] from"./table-util.mjs"
|
||||||
|
|
||||||
export : define [buildGsubThousands sink para] : begin
|
export : define [buildGsubThousands gsub para] : begin
|
||||||
local rec : BeginLookupBlock sink
|
local rec : gsub.beginBlock
|
||||||
|
|
||||||
define Thousand : AddFeature sink 'THND'
|
define Thousand : gsub.addCommonFeature : gsub.createFeature 'THND'
|
||||||
define {chain-rule reverse-rule} : ChainRuleBuilder sink
|
define {chain-rule reverse-rule} : gsub.ChainRuleBuilder
|
||||||
define numberGlyphIDs {
|
define numberGlyphIDs {
|
||||||
'zero.lnum' 'one.lnum' 'two.lnum' 'three.lnum' 'four.lnum'
|
'zero.lnum' 'one.lnum' 'two.lnum' 'three.lnum' 'four.lnum'
|
||||||
'five.lnum' 'six.lnum' 'seven.lnum' 'eight.lnum' 'nine.lnum'
|
'five.lnum' 'six.lnum' 'seven.lnum' 'eight.lnum' 'nine.lnum'
|
||||||
|
@ -14,7 +14,7 @@ export : define [buildGsubThousands sink para] : begin
|
||||||
|
|
||||||
define [nd s] : numberGlyphIDs.map : lambda [x] "\(x).nd\(s)"
|
define [nd s] : numberGlyphIDs.map : lambda [x] "\(x).nd\(s)"
|
||||||
|
|
||||||
define lookupThousand1 : AddLookup sink : object
|
define a : Thousand.addLookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : 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)
|
||||||
|
@ -25,13 +25,13 @@ export : define [buildGsubThousands sink para] : begin
|
||||||
chain-rule ([nd 4] ~> null) (numberGlyphIDs ~> [nd 3])
|
chain-rule ([nd 4] ~> null) (numberGlyphIDs ~> [nd 3])
|
||||||
chain-rule ([nd 3] ~> null) (numberGlyphIDs ~> [nd 2])
|
chain-rule ([nd 3] ~> null) (numberGlyphIDs ~> [nd 2])
|
||||||
|
|
||||||
define lookupThousand2 : AddLookup sink : object
|
define b : Thousand.addLookup : gsub.createLookup : object
|
||||||
.type 'gsub_chaining'
|
.type 'gsub_chaining'
|
||||||
.rules : 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 : AddLookup sink : object
|
define c : Thousand.addLookup : gsub.createLookup : object
|
||||||
.type 'gsub_reverse'
|
.type 'gsub_reverse'
|
||||||
.rules : list
|
.rules : list
|
||||||
reverse-rule ([nd 0] ~> [nd 1]) ([nd 0] ~> null)
|
reverse-rule ([nd 0] ~> [nd 1]) ([nd 0] ~> null)
|
||||||
|
@ -42,7 +42,7 @@ export : define [buildGsubThousands sink para] : begin
|
||||||
reverse-rule ([nd 0] ~> [nd 6]) ([nd 5] ~> null)
|
reverse-rule ([nd 0] ~> [nd 6]) ([nd 5] ~> null)
|
||||||
reverse-rule ([nd 0] ~> [nd 1]) ([nd 6] ~> null)
|
reverse-rule ([nd 0] ~> [nd 1]) ([nd 6] ~> null)
|
||||||
|
|
||||||
|
gsub.setDependency a b
|
||||||
|
gsub.setDependency b c
|
||||||
|
|
||||||
Thousand.lookups.push lookupThousand1 lookupThousand2 lookupThousand3
|
gsub.endBlock rec
|
||||||
AddCommonFeature sink Thousand
|
|
||||||
EndLookupBlock rec sink
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import as toposort from 'toposort'
|
import as toposort from 'toposort'
|
||||||
import as Gr from"../support/gr.mjs"
|
import as Gr from"../support/gr.mjs"
|
||||||
|
|
||||||
import [CreateEmptyTable FinalizeTable MoveBackUtilityLookups] from"./table-util.mjs"
|
import [CreateEmptyTable] from"./table-util.mjs"
|
||||||
|
|
||||||
import [buildLigations] from"./gsub-ligation.mjs"
|
import [buildLigations] from"./gsub-ligation.mjs"
|
||||||
import [buildCCMP buildCCMPPostCvSs] from"./gsub-ccmp.mjs"
|
import [buildCCMP buildCCMPPostCvSs] from"./gsub-ccmp.mjs"
|
||||||
|
@ -70,15 +70,14 @@ define [buildGSUB para glyphStore markGlyphs] : begin
|
||||||
# Builds last, but the lookups are added into the beginning of the lookup list
|
# Builds last, but the lookups are added into the beginning of the lookup list
|
||||||
buildLOCL gsub para glyphStore
|
buildLOCL gsub para glyphStore
|
||||||
|
|
||||||
MoveBackUtilityLookups gsub
|
gsub.finalize
|
||||||
FinalizeTable gsub
|
|
||||||
return gsub
|
return gsub
|
||||||
|
|
||||||
# GPOS
|
# GPOS
|
||||||
define [buildGPOS para glyphStore markGlyphs] : begin
|
define [buildGPOS para glyphStore markGlyphs] : begin
|
||||||
define gpos : CreateEmptyTable
|
define gpos : CreateEmptyTable
|
||||||
buildMarkMkmk gpos glyphStore markGlyphs
|
buildMarkMkmk gpos glyphStore markGlyphs
|
||||||
FinalizeTable gpos
|
gpos.finalize
|
||||||
return gpos
|
return gpos
|
||||||
|
|
||||||
# GDEF
|
# GDEF
|
||||||
|
|
|
@ -1,133 +1,137 @@
|
||||||
import toposort from 'toposort'
|
import toposort from 'toposort'
|
||||||
import [AnyCv] from"../support/gr.mjs"
|
import [AnyCv] from"../support/gr.mjs"
|
||||||
|
|
||||||
export : define [CreateEmptyTable] {.languages {.} .features {.} .lookups {.} .lookupDep {}}
|
|
||||||
extern Map
|
extern Map
|
||||||
extern Set
|
extern Set
|
||||||
|
|
||||||
export : define [PickLanguage sink tag] : begin
|
export : define [CreateEmptyTable] : new LayoutTable
|
||||||
if sink.languages.(tag) : return sink.languages.(tag)
|
|
||||||
define lang {.features {}}
|
class LayoutTable
|
||||||
set sink.languages.(tag) lang
|
public [new] : begin
|
||||||
|
set this.languages {.}
|
||||||
|
set this.features {.}
|
||||||
|
set this.lookups {.}
|
||||||
|
set this.lookupDep {}
|
||||||
|
set this.lookupOrder {}
|
||||||
|
|
||||||
|
public [pickLanguage tag] : begin
|
||||||
|
if this.languages.(tag) : return this.languages.(tag)
|
||||||
|
define lang : new LayoutLanguage tag
|
||||||
|
set this.languages.(tag) lang
|
||||||
return lang
|
return lang
|
||||||
|
|
||||||
export : define [CopyLanguage sink tag tagFrom] : begin
|
public [copyLanguage tag tagFrom] : begin
|
||||||
define langFrom : PickLanguage sink tagFrom
|
define langFrom : this.pickLanguage tagFrom
|
||||||
define langTo : PickLanguage sink tag
|
define langTo : this.pickLanguage tag
|
||||||
foreach [feat : items-of langFrom.features] : langTo.features.push feat
|
foreach [feat : items-of langFrom.features] : langTo.features.push feat
|
||||||
return langTo
|
return langTo
|
||||||
|
|
||||||
export : define [AddLangFeature lang fea] : begin
|
public [createFeature tag] : begin
|
||||||
define index : lang.features.indexOf fea.name
|
local feature : new LayoutFeature tag
|
||||||
if (index < 0) : lang.features.push fea.name
|
|
||||||
|
|
||||||
export : define [AddFeature sink tag] : begin
|
|
||||||
define lookupArray {}
|
|
||||||
local n 0
|
local n 0
|
||||||
while true : begin
|
while true : begin
|
||||||
if [not sink.features.(tag + '_' + n)] : begin
|
if [not this.features.(tag + '_' + n)] : begin
|
||||||
set sink.features.(tag + '_' + n) lookupArray
|
set feature.name : tag + '_' + n
|
||||||
return {.tag tag .name (tag + '_' + n) .lookups lookupArray}
|
set this.features.(tag + '_' + n) feature
|
||||||
|
return feature
|
||||||
set n : n + 1
|
set n : n + 1
|
||||||
|
|
||||||
export : define [PickFeature sink name] : begin
|
public [addCommonFeature fea] : begin
|
||||||
if sink.features.(name) : return { .name name .lookups sink.features.(name) }
|
define dfltDflt : this.pickLanguage 'DFLT_DFLT'
|
||||||
define featObj { .name name .lookups {} }
|
define latnDflt : this.pickLanguage 'latn_DFLT'
|
||||||
set sink.features.(name) featObj.lookups
|
define grekDflt : this.pickLanguage 'grek_DFLT'
|
||||||
return featObj
|
define cyrlDflt : this.pickLanguage 'cyrl_DFLT'
|
||||||
|
|
||||||
export : define [PickCommonFeature sink name] : begin
|
dfltDflt.addFeature fea
|
||||||
if sink.features.(name) : return { .name name .lookups sink.features.(name) }
|
latnDflt.addFeature fea
|
||||||
define featObj { .name name .lookups {} }
|
grekDflt.addFeature fea
|
||||||
set sink.features.(name) featObj.lookups
|
cyrlDflt.addFeature fea
|
||||||
AddCommonFeature sink featObj
|
|
||||||
return featObj
|
|
||||||
|
|
||||||
export : define [AddFeatureLookup fea lookupName] : begin
|
|
||||||
define index : fea.lookups.indexOf lookupName
|
|
||||||
if (index < 0) : fea.lookups.push lookupName
|
|
||||||
|
|
||||||
export : define [AddLookup sink data _prefix] : begin
|
|
||||||
local prefix : _prefix || '_lut_'
|
|
||||||
local n 0
|
|
||||||
while true : begin
|
|
||||||
if [not sink.lookups.(prefix + n)] : begin
|
|
||||||
set sink.lookups.(prefix + n) data
|
|
||||||
return (prefix + n)
|
|
||||||
set n : n + 1
|
|
||||||
|
|
||||||
export : define [PickLookup sink name fallback] : begin
|
|
||||||
if sink.lookups.(name) : return sink.lookups.(name)
|
|
||||||
set sink.lookups.(name) fallback
|
|
||||||
return sink.lookups.(name)
|
|
||||||
|
|
||||||
export : define [AddCommonFeature sink fea] : begin
|
|
||||||
define dfltDflt : PickLanguage sink 'DFLT_DFLT'
|
|
||||||
define latnDflt : PickLanguage sink 'latn_DFLT'
|
|
||||||
define grekDflt : PickLanguage sink 'grek_DFLT'
|
|
||||||
define cyrlDflt : PickLanguage sink 'cyrl_DFLT'
|
|
||||||
|
|
||||||
AddLangFeature dfltDflt fea
|
|
||||||
AddLangFeature latnDflt fea
|
|
||||||
AddLangFeature grekDflt fea
|
|
||||||
AddLangFeature cyrlDflt fea
|
|
||||||
|
|
||||||
return fea
|
return fea
|
||||||
|
|
||||||
define UtilityLookupPrefix '.utility-single.'
|
public [createLookup data _prefix] : begin
|
||||||
|
local prefix : _prefix || 'lookup/'
|
||||||
|
local n 0
|
||||||
|
while true : begin
|
||||||
|
if [not this.lookups.(prefix + n)] : begin
|
||||||
|
return : this.addLookupNoCheck (prefix + n) data
|
||||||
|
set n : n + 1
|
||||||
|
|
||||||
export : define [BeginLookupBlock sink] : begin
|
public [pickLookup name fallback] : begin
|
||||||
|
if this.lookups.(name) : return this.lookups.(name)
|
||||||
|
return : this.addLookupNoCheck name fallback
|
||||||
|
|
||||||
|
public [addLookupNoCheck name data] : begin
|
||||||
|
local lookup : Object.fromEntries : Object.entries data
|
||||||
|
set lookup.name name
|
||||||
|
set this.lookups.(name) lookup
|
||||||
|
return lookup
|
||||||
|
|
||||||
|
public [setDependency a b] : begin
|
||||||
|
if [not a.name] : throw : new Error "Invalid lookup"
|
||||||
|
if [not b.name] : throw : new Error "Invalid lookup"
|
||||||
|
|
||||||
|
this.lookupDep.push { a.name b.name }
|
||||||
|
|
||||||
|
public [beginBlock] : begin
|
||||||
return : object
|
return : object
|
||||||
existingLookupNames : new Set : Object.keys sink.lookups
|
existingLookupNames : new Set : Object.keys this.lookups
|
||||||
|
|
||||||
define [IsUtilityLookupId name] : [name.slice 0 UtilityLookupPrefix.length] === UtilityLookupPrefix
|
public [endBlock rec] : begin
|
||||||
|
local currentLookupNames : new Set : Object.keys this.lookups
|
||||||
export : define [EndLookupBlock rec sink] : begin
|
|
||||||
local currentLookupNames : new Set : Object.keys sink.lookups
|
|
||||||
foreach existing rec.existingLookupNames : foreach current currentLookupNames
|
foreach existing rec.existingLookupNames : foreach current currentLookupNames
|
||||||
if (![IsUtilityLookupId existing] && ![IsUtilityLookupId current] && ![rec.existingLookupNames.has current])
|
if (![IsUtilityLookupId existing] && ![IsUtilityLookupId current] && ![rec.existingLookupNames.has current])
|
||||||
sink.lookupDep.push { existing current }
|
this.lookupDep.push { existing current }
|
||||||
|
|
||||||
set EndLookupBlock.Front : lambda [rec sink] : begin
|
public [endBlockAtFront rec] : begin
|
||||||
local currentLookupNames : new Set : Object.keys sink.lookups
|
local currentLookupNames : new Set : Object.keys this.lookups
|
||||||
foreach existing rec.existingLookupNames : foreach current currentLookupNames
|
foreach existing rec.existingLookupNames : foreach current currentLookupNames
|
||||||
if (![IsUtilityLookupId existing] && ![IsUtilityLookupId current] && ![rec.existingLookupNames.has current])
|
if (![IsUtilityLookupId existing] && ![IsUtilityLookupId current] && ![rec.existingLookupNames.has current])
|
||||||
sink.lookupDep.push { current existing }
|
this.lookupDep.push { current existing }
|
||||||
|
|
||||||
export : define [MoveBackUtilityLookups sink] : begin
|
public [finalize] : begin
|
||||||
local lns : new Set : Object.keys sink.lookups
|
local lns : new Set : Object.keys this.lookups
|
||||||
foreach [front lns] : foreach [rear lns]
|
foreach [front lns] : foreach [rear lns]
|
||||||
if (![IsUtilityLookupId front] && [IsUtilityLookupId rear])
|
if (![IsUtilityLookupId front] && [IsUtilityLookupId rear])
|
||||||
sink.lookupDep.push { front rear }
|
this.lookupDep.push { front rear }
|
||||||
|
|
||||||
|
set this.lookupOrder : toposort this.lookupDep
|
||||||
|
foreach [{key lang} : pairs-of this.languages] : begin
|
||||||
|
if lang.features : lang.features.sort
|
||||||
|
|
||||||
|
public [ChainRuleBuilder] : begin
|
||||||
|
local table this
|
||||||
|
|
||||||
export : define [ChainRuleBuilder sink] : begin
|
|
||||||
define [createNewLookup f t] : begin
|
define [createNewLookup f t] : begin
|
||||||
local subst {.}
|
local subst {.}
|
||||||
foreach [j : range 0 f.length] : set subst.(f.(j)) t.(j)
|
foreach [j : range 0 f.length] : set subst.(f.(j)) t.(j)
|
||||||
return : AddLookup sink {.type 'gsub_single' .substitutions subst} UtilityLookupPrefix
|
return : table.createLookup {.type 'gsub_single' .substitutions subst} UtilityLookupPrefix
|
||||||
|
|
||||||
define [getSubLookup left right] : piecewise
|
define [getSubLookup left right] : piecewise
|
||||||
[not right] null
|
[not right] null
|
||||||
([typeof right] === "string") right
|
([typeof right] === "string") : throw : new Error "Invalid substitution"
|
||||||
(right <@ Function) : getSubLookup left [right left]
|
(right <@ Function) : getSubLookup left [right left]
|
||||||
true : begin
|
true : begin
|
||||||
local found null
|
local found null
|
||||||
local maxMatch 0
|
local maxMatch 0
|
||||||
local lookupKeys : [Object.keys sink.lookups].reverse
|
|
||||||
foreach [name : items-of lookupKeys] : begin
|
local lookupKeys : [Object.keys table.lookups].reverse
|
||||||
local st sink.lookups.(name).substitutions
|
foreach [name : items-of lookupKeys] : if [IsUtilityLookupId name] : begin
|
||||||
if [IsUtilityLookupId name] : begin
|
local lookup table.lookups.(name)
|
||||||
|
local st lookup.substitutions
|
||||||
|
|
||||||
local compatible true
|
local compatible true
|
||||||
local matchCount 0
|
local matchCount 0
|
||||||
foreach [j : range 0 left.length] : begin
|
foreach [j : range 0 left.length] : begin
|
||||||
if (st.(left.(j)) && st.(left.(j)) !== right.(j)) : set compatible false
|
if (st.(left.(j)) && st.(left.(j)) !== right.(j)) : set compatible false
|
||||||
if (st.(left.(j)) === right.(j)) : inc matchCount
|
if (st.(left.(j)) === right.(j)) : inc matchCount
|
||||||
|
|
||||||
if (compatible && (!found || matchCount > maxMatch)) : begin
|
if (compatible && (!found || matchCount > maxMatch)) : begin
|
||||||
set found name
|
set found lookup
|
||||||
set maxMatch matchCount
|
set maxMatch matchCount
|
||||||
|
|
||||||
if found : begin
|
if found : begin
|
||||||
local st sink.lookups.(found).substitutions
|
local st 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
|
||||||
|
|
||||||
|
@ -147,8 +151,8 @@ export : define [ChainRuleBuilder sink] : begin
|
||||||
foreach [j : range 0 terms.length] : begin
|
foreach [j : range 0 terms.length] : begin
|
||||||
local term terms.(j)
|
local term terms.(j)
|
||||||
rule.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 lookup : getSubLookup term.left term.right
|
||||||
if lutn : rule.apply.push {.at j .lookup lutn}
|
if lookup : rule.apply.push {.at j .lookup {.name lookup.name}}
|
||||||
return rule
|
return rule
|
||||||
|
|
||||||
define [reverse-rule] : begin
|
define [reverse-rule] : begin
|
||||||
|
@ -179,6 +183,32 @@ export : define [ChainRuleBuilder sink] : begin
|
||||||
|
|
||||||
return {chain-rule reverse-rule}
|
return {chain-rule reverse-rule}
|
||||||
|
|
||||||
|
class LayoutFeature
|
||||||
|
public [new tag] : begin
|
||||||
|
set this.tag tag
|
||||||
|
set this.name tag
|
||||||
|
set this.lookups {}
|
||||||
|
|
||||||
|
public [addLookup lookup] : begin
|
||||||
|
if [not lookup.name] : throw : new Error "Invalid lookup"
|
||||||
|
define index : this.lookups.indexOf lookup.name
|
||||||
|
if (index < 0) : this.lookups.push lookup.name
|
||||||
|
return lookup
|
||||||
|
|
||||||
|
class LayoutLanguage
|
||||||
|
public [new tag] : begin
|
||||||
|
set this.tag tag
|
||||||
|
set this.features {}
|
||||||
|
|
||||||
|
public [addFeature feature] : begin
|
||||||
|
if [not feature.name] : throw : new Error "Invalid feature"
|
||||||
|
define index : this.features.indexOf feature.name
|
||||||
|
if (index < 0) : this.features.push feature.name
|
||||||
|
return feature
|
||||||
|
|
||||||
|
define UtilityLookupPrefix '.utility-single/'
|
||||||
|
define [IsUtilityLookupId name] : [name.slice 0 UtilityLookupPrefix.length] === UtilityLookupPrefix
|
||||||
|
|
||||||
export : define [QueryRelatedGlyphs glyphs para entries] : begin
|
export : define [QueryRelatedGlyphs glyphs para entries] : begin
|
||||||
define sink {}
|
define sink {}
|
||||||
foreach [gid : items-of entries] : if glyphs.(gid) : begin
|
foreach [gid : items-of entries] : if glyphs.(gid) : begin
|
||||||
|
|
|
@ -189,6 +189,14 @@ export function Cv(tag, rank, groupRank, description) {
|
||||||
return rel;
|
return rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cv.compare = function (a, b) {
|
||||||
|
if (a.tag < b.tag) return -1;
|
||||||
|
if (a.tag > b.tag) return 1;
|
||||||
|
if (a.rank < b.rank) return -1;
|
||||||
|
if (a.rank > b.rank) return 1;
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
export const DotlessOrNot = {
|
export const DotlessOrNot = {
|
||||||
query(glyph) {
|
query(glyph) {
|
||||||
if (Dotless.get(glyph)) return [Dotless];
|
if (Dotless.get(glyph)) return [Dotless];
|
||||||
|
@ -265,11 +273,13 @@ function getGrTreeImpl(gid, grSetList, fnGidToGlyph, sink) {
|
||||||
export function getGrMesh(gidList, grq, fnGidToGlyph) {
|
export function getGrMesh(gidList, grq, fnGidToGlyph) {
|
||||||
if (typeof gidList === "string" || !Array.isArray(gidList))
|
if (typeof gidList === "string" || !Array.isArray(gidList))
|
||||||
throw new TypeError(`glyphs must be a glyph array!`);
|
throw new TypeError(`glyphs must be a glyph array!`);
|
||||||
|
|
||||||
const allGrSet = new Set();
|
const allGrSet = new Set();
|
||||||
for (const g of gidList) {
|
for (const g of gidList) {
|
||||||
for (const gr of grq.query(fnGidToGlyph(g))) allGrSet.add(gr);
|
for (const gr of grq.query(fnGidToGlyph(g))) allGrSet.add(gr);
|
||||||
}
|
}
|
||||||
const allGrList = Array.from(allGrSet);
|
const allGrList = Array.from(allGrSet).sort(Cv.compare).reverse();
|
||||||
|
|
||||||
let ret = [];
|
let ret = [];
|
||||||
for (const gr of allGrList) {
|
for (const gr of allGrList) {
|
||||||
const col = [];
|
const col = [];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue