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