mirror of
https://github.com/be5invis/Iosevka.git
synced 2026-10-28 16:38:35 +00:00
245 lines
8.6 KiB
Plaintext
245 lines
8.6 KiB
Plaintext
import 'topsort' as topsort
|
|
import '../support/glyph' as Glyph
|
|
import '../support/transform' as Transform
|
|
import [progLigNameMap buildLigations] from './feature/ligation'
|
|
import './feature/opbd' as buildOPBD
|
|
import './feature/ccmp' as buildCCMP
|
|
import [BuildCompatLigatures] from './feature/compat-ligature'
|
|
|
|
define GDEF_SIMPLE 1
|
|
define GDEF_LIGATURE 2
|
|
define GDEF_MARK 3
|
|
|
|
define-operator "~>" 880 'right' : syntax-rules
|
|
`(@l ~> @r) `{.left @l .right @r}
|
|
|
|
# GSUB
|
|
define [buildGSUB para glyphs glyphList markGlyphs] : begin
|
|
local commonList {}
|
|
local languages
|
|
.DFLT_DFLT {.features commonList}
|
|
.latn_DFLT {.features commonList}
|
|
.grek_DFLT {.features commonList}
|
|
.cyrl_DFLT {.features commonList}
|
|
.kana_DFLT {.features commonList}
|
|
.hani_DFLT {.features commonList}
|
|
local features {.}
|
|
local lookups {.}
|
|
local lookupOrder {}
|
|
|
|
# Chaining lookup builder
|
|
define [lookup-single name f t] : begin
|
|
local subtable {.}
|
|
foreach [j : range 0 f.length] : set subtable.(f.(j)) t.(j)
|
|
set lookups.(name) {.type 'gsub_single' .subtables {subtable}}
|
|
define [getsublookup left right] : piecewise
|
|
[not right] null
|
|
([typeof right] === "string") right
|
|
(right <@ Function) : getsublookup left [right left]
|
|
true : begin
|
|
local found null
|
|
foreach [{name lookup} : pairs-of lookups] : match lookup
|
|
{.type "gsub_single" .subtables {st}} : begin
|
|
local check true
|
|
foreach [j : range 0 left.length] : if (st.(left.(j)) !== right.(j)) : set check false
|
|
if check : set found name
|
|
if found : return found
|
|
|
|
local name "_lookup_\([Object.keys lookups].length)"
|
|
lookup-single name left right
|
|
return name
|
|
define [chain-rule] : begin
|
|
local terms : [{}.slice.call arguments 0].map (x -> [if x.left x (x ~> null)])
|
|
local subtable {.match {} .apply {} .inputBegins 0 .inputEnds 0}
|
|
local foundi false
|
|
local founde false
|
|
foreach [j : range 0 terms.length] : if (!foundi && terms.(j).right) : begin
|
|
set subtable.inputBegins j
|
|
set foundi true
|
|
foreach [j : range (terms.length - 1) downtill 0] : if (!founde && terms.(j).right) : begin
|
|
set subtable.inputEnds (j + 1)
|
|
set founde true
|
|
foreach [j : range 0 terms.length] : begin
|
|
local term terms.(j)
|
|
subtable.match.push term.left
|
|
local lutn : getsublookup term.left term.right
|
|
if lutn : subtable.apply.push {.at j .lookup lutn}
|
|
return subtable
|
|
|
|
# hwid-fwid, lnum-onum
|
|
define [MakePairFrature tag1 tag2] : begin
|
|
local mapTag2 {.}
|
|
local mapTag1 {.}
|
|
define reHidden : regex "^\\."
|
|
define reTag1 : new RegExp ("\\." + tag1 + "$")
|
|
foreach [glyph : items-of glyphList] : begin
|
|
if ([reTag1.test glyph.name] && ![reHidden.test glyph.name]) : do
|
|
local gnTag2 : glyph.name.replace reTag1 ('.' + tag2)
|
|
if (glyphs.(gnTag2)) : begin
|
|
set mapTag2.(glyph.name) gnTag2
|
|
set mapTag1.(gnTag2) glyph.name
|
|
set lookups.(tag2) {.type 'gsub_single' .subtables {mapTag2}}
|
|
set lookups.(tag1) {.type 'gsub_single' .subtables {mapTag1}}
|
|
set features.(tag2) {tag2}
|
|
set features.(tag1) {tag1}
|
|
commonList.push tag2 tag1
|
|
|
|
MakePairFrature 'hwid' 'fwid'
|
|
MakePairFrature 'lnum' 'onum'
|
|
|
|
# CCMP
|
|
buildCCMP chain-rule markGlyphs commonList features lookups
|
|
|
|
# Ligation
|
|
if para.enableLigation : do
|
|
define plm : progLigNameMap
|
|
set plm.calt : para.customLigSet || plm.(para.defLigSet) || plm.calt
|
|
buildLigations chain-rule lookupOrder commonList features lookups plm glyphs
|
|
|
|
# CVxx/SSxx
|
|
if para.enableCvSs : begin
|
|
# cvxx
|
|
foreach [glyph : items-of glyphList] : if glyph.featureSelector : begin
|
|
local fs glyph.featureSelector
|
|
foreach [feature : items-of : Object.keys fs] : begin
|
|
if [not lookups.(feature)] : begin
|
|
set features.(feature) {feature}
|
|
set lookups.(feature) {.type 'gsub_single' .subtables{{.}}}
|
|
commonList.push feature
|
|
set lookups.(feature).subtables.0.(glyph.name) fs.(feature)
|
|
# ssxx
|
|
foreach [{name composition} : pairs-of para.variants] : begin
|
|
if (name.length === 4 && composition.__isComposite && [name.slice 0 2] === 'ss') : begin
|
|
commonList.push name
|
|
local tags {.}
|
|
foreach [{ch tag} : pairs-of composition.__cvmap] : set tags.(tag) true
|
|
set features.(name) : [Object.keys tags].filter (tag => tags.(tag))
|
|
|
|
# locl, SRB
|
|
local srbSubtable null
|
|
if para.isItalic
|
|
: then : set srbSubtable : object
|
|
cyrbe 'cyrbe.SRB'
|
|
cyrghe 'cyrghe.SRB'
|
|
cyrde 'cyrde.SRB'
|
|
cyrpe 'cyrpe.SRB'
|
|
cyrte 'cyrte.SRB'
|
|
: else : set srbSubtable : object
|
|
cyrbe 'cyrbe.SRB'
|
|
set lookups.locl_srb {.type 'gsub_single' .subtables {srbSubtable}}
|
|
set features.locl_srb {'locl_srb'}
|
|
|
|
# locl, BGR
|
|
local bgrSubtable : object
|
|
cyrve 'cyrve.BGR'
|
|
cyrghe 'cyrghe.italic'
|
|
cyrde 'g'
|
|
cyrzhe 'cyrzhe.BGR'
|
|
cyrze 'cyrze.BGR'
|
|
cyri 'u'
|
|
cyribreve 'ubreve'
|
|
cyrka 'k'
|
|
cyrEl 'Lambda'
|
|
cyrel 'turnv'
|
|
cyrpe 'n'
|
|
cyrte 'm'
|
|
cyrsha 'cyrsha.italic'
|
|
cyrshcha 'cyrshcha.italic'
|
|
cyryu 'cyryu.BGR'
|
|
cyrtse 'cyrtse.italic'
|
|
set lookups.locl_bgr {.type 'gsub_single' .subtables {bgrSubtable}}
|
|
set features.locl_bgr {'locl_bgr'}
|
|
|
|
set languages.'cyrl_SRB ' {.features [{'locl_srb'}.concat commonList]}
|
|
set languages.'cyrl_MKD ' {.features [{'locl_srb'}.concat commonList]}
|
|
set languages.'cyrl_BGR ' {.features [{'locl_bgr'}.concat commonList]}
|
|
|
|
return {.languages languages .features features .lookups lookups .lookupOrder [topsort lookupOrder]}
|
|
|
|
# GPOS
|
|
define [buildGPOS para glyphs glyphList markGlyphs] : begin
|
|
# mark and mkmk
|
|
define [createBaseInfo g th px py] : begin
|
|
local res {.}
|
|
local pushed false
|
|
foreach key [items-of : Object.keys g.anchors] : if (!th || th.(key)) : begin
|
|
set res.(key) : object
|
|
.x g.anchors.(key).(px || 'x')
|
|
.y g.anchors.(key).(py || 'y')
|
|
set pushed true
|
|
return : if pushed res nothing
|
|
|
|
define [createMTLookup lookupType anchorClasses] : begin
|
|
local subtable {.marks {.} .bases {.}}
|
|
local th {.}
|
|
foreach [ac : items-of anchorClasses] : set th.(ac) true
|
|
foreach glyph [items-of glyphList] : if glyph.anchors : begin
|
|
local anchorKeys : Object.keys glyph.anchors
|
|
local hasAnchor false
|
|
foreach [key : items-of anchorKeys] : if th.(key) : set hasAnchor true
|
|
if hasAnchor : begin
|
|
local isMarkGlyph false
|
|
local markKey nothing
|
|
foreach key [items-of anchorKeys] : if (glyph.anchors.(key).type == 'mark') : begin
|
|
set isMarkGlyph true
|
|
set markKey key
|
|
if isMarkGlyph
|
|
: then : begin
|
|
set subtable.marks.(glyph.name) : object
|
|
class markKey
|
|
x glyph.anchors.(markKey).x
|
|
y glyph.anchors.(markKey).y
|
|
if (lookupType == 'gpos_mark_to_mark'): begin
|
|
local r : createBaseInfo glyph th 'mbx' 'mby'
|
|
if r : set subtable.bases.(glyph.name) r
|
|
: else : if (lookupType == 'gpos_mark_to_base') : begin
|
|
local r : createBaseInfo glyph th 'x' 'y'
|
|
if r : set subtable.bases.(glyph.name) r
|
|
return {.type lookupType .subtables {subtable}}
|
|
|
|
local lookupSet {.}
|
|
local markLookupNames {}
|
|
local mkmkLookupNames {}
|
|
|
|
foreach [marktag : items-of {'above' 'below' 'overlay' 'slash' 'topright' 'bottomright' 'trailing' 'lf'}] : begin
|
|
set lookupSet.('lookup_mark_' + marktag) : createMTLookup 'gpos_mark_to_base' {marktag}
|
|
set lookupSet.('lookup_mkmk_' + marktag) : createMTLookup 'gpos_mark_to_mark' {marktag}
|
|
markLookupNames.push ('lookup_mark_' + marktag)
|
|
mkmkLookupNames.push ('lookup_mkmk_' + marktag)
|
|
|
|
return : object
|
|
languages
|
|
.DFLT_DFLT {.features {'mark0', 'mkmk0'}}
|
|
.latn_DFLT {.features {'mark0', 'mkmk0'}}
|
|
.grek_DFLT {.features {'mark0', 'mkmk0'}}
|
|
.cyrl_DFLT {.features {'mark0', 'mkmk0'}}
|
|
features
|
|
.mark0 markLookupNames
|
|
.mkmk0 mkmkLookupNames
|
|
lookups lookupSet
|
|
|
|
# GDEF
|
|
define [buildGDEF para glyphs glyphList markGlyphs] : begin
|
|
local GDEF {.glyphClassDef {.}}
|
|
foreach glyph [items-of glyphList] : begin
|
|
set GDEF.glyphClassDef.(glyph.name) : if [[regex '_'].test glyph.name] GDEF_LIGATURE GDEF_SIMPLE
|
|
if (glyph.anchors && [begin [local anchorKeys : Object.keys glyph.anchors] anchorKeys.length]) : begin
|
|
foreach key [items-of anchorKeys] : if (glyph.anchors.(key).type == 'mark') : begin
|
|
if [not markGlyphs.(key)] : set markGlyphs.(key) {}
|
|
markGlyphs.(key).push glyph.name
|
|
markGlyphs.all.push glyph.name
|
|
set GDEF.glyphClassDef.(glyph.name) GDEF_MARK
|
|
return GDEF
|
|
|
|
export : define [apply para glyphs glyphList unicodeGlyphs] : begin
|
|
local markGlyphs {.all {} }
|
|
local GPOS : buildGPOS para glyphs glyphList markGlyphs
|
|
local GDEF : buildGDEF para glyphs glyphList markGlyphs
|
|
local GSUB : buildGSUB para glyphs glyphList markGlyphs
|
|
|
|
# Build compatibility ligatures
|
|
if (para.spacing > 0 && para.compLig) : begin
|
|
BuildCompatLigatures glyphs glyphList unicodeGlyphs GSUB GDEF para.compLig
|
|
|
|
return [object GSUB GPOS GDEF]
|