Merge pull request #3430 from fonttools/fealib-aalt-order

This commit is contained in:
Cosimo Lupo 2024-01-25 15:15:08 +00:00 committed by GitHub
commit 3bdcbe9269
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 19 deletions

View File

@ -285,7 +285,11 @@ class Builder(object):
def build_feature_aalt_(self): def build_feature_aalt_(self):
if not self.aalt_features_ and not self.aalt_alternates_: if not self.aalt_features_ and not self.aalt_alternates_:
return return
alternates = {g: set(a) for g, a in self.aalt_alternates_.items()} # > alternate glyphs will be sorted in the order that the source features
# > are named in the aalt definition, not the order of the feature definitions
# > in the file. Alternates defined explicitly ... will precede all others.
# https://github.com/fonttools/fonttools/issues/836
alternates = {g: list(a) for g, a in self.aalt_alternates_.items()}
for location, name in self.aalt_features_ + [(None, "aalt")]: for location, name in self.aalt_features_ + [(None, "aalt")]:
feature = [ feature = [
(script, lang, feature, lookups) (script, lang, feature, lookups)
@ -302,17 +306,14 @@ class Builder(object):
lookuplist = [lookuplist] lookuplist = [lookuplist]
for lookup in lookuplist: for lookup in lookuplist:
for glyph, alts in lookup.getAlternateGlyphs().items(): for glyph, alts in lookup.getAlternateGlyphs().items():
alternates.setdefault(glyph, set()).update(alts) alts_for_glyph = alternates.setdefault(glyph, [])
alts_for_glyph.extend(
g for g in alts if g not in alts_for_glyph
)
single = { single = {
glyph: list(repl)[0] for glyph, repl in alternates.items() if len(repl) == 1 glyph: repl[0] for glyph, repl in alternates.items() if len(repl) == 1
}
# TODO: Figure out the glyph alternate ordering used by makeotf.
# https://github.com/fonttools/fonttools/issues/836
multi = {
glyph: sorted(repl, key=self.font.getGlyphID)
for glyph, repl in alternates.items()
if len(repl) > 1
} }
multi = {glyph: repl for glyph, repl in alternates.items() if len(repl) > 1}
if not single and not multi: if not single and not multi:
return return
self.features_ = { self.features_ = {
@ -1249,8 +1250,9 @@ class Builder(object):
def add_single_subst(self, location, prefix, suffix, mapping, forceChain): def add_single_subst(self, location, prefix, suffix, mapping, forceChain):
if self.cur_feature_name_ == "aalt": if self.cur_feature_name_ == "aalt":
for from_glyph, to_glyph in mapping.items(): for from_glyph, to_glyph in mapping.items():
alts = self.aalt_alternates_.setdefault(from_glyph, set()) alts = self.aalt_alternates_.setdefault(from_glyph, [])
alts.add(to_glyph) if to_glyph not in alts:
alts.append(to_glyph)
return return
if prefix or suffix or forceChain: if prefix or suffix or forceChain:
self.add_single_subst_chained_(location, prefix, suffix, mapping) self.add_single_subst_chained_(location, prefix, suffix, mapping)
@ -1303,8 +1305,8 @@ class Builder(object):
# GSUB 3 # GSUB 3
def add_alternate_subst(self, location, prefix, glyph, suffix, replacement): def add_alternate_subst(self, location, prefix, glyph, suffix, replacement):
if self.cur_feature_name_ == "aalt": if self.cur_feature_name_ == "aalt":
alts = self.aalt_alternates_.setdefault(glyph, set()) alts = self.aalt_alternates_.setdefault(glyph, [])
alts.update(replacement) alts.extend(g for g in replacement if g not in alts)
return return
if prefix or suffix: if prefix or suffix:
chain = self.get_lookup_(location, ChainContextSubstBuilder) chain = self.get_lookup_(location, ChainContextSubstBuilder)

View File

@ -774,7 +774,10 @@ class ChainContextSubstBuilder(ChainContextualBuilder):
if lookup is not None: if lookup is not None:
alts = lookup.getAlternateGlyphs() alts = lookup.getAlternateGlyphs()
for glyph, replacements in alts.items(): for glyph, replacements in alts.items():
result.setdefault(glyph, set()).update(replacements) alts_for_glyph = result.setdefault(glyph, [])
alts_for_glyph.extend(
g for g in replacements if g not in alts_for_glyph
)
return result return result
def find_chainable_single_subst(self, mapping): def find_chainable_single_subst(self, mapping):
@ -1238,7 +1241,7 @@ class SingleSubstBuilder(LookupBuilder):
return self.buildLookup_(subtables) return self.buildLookup_(subtables)
def getAlternateGlyphs(self): def getAlternateGlyphs(self):
return {glyph: set([repl]) for glyph, repl in self.mapping.items()} return {glyph: [repl] for glyph, repl in self.mapping.items()}
def add_subtable_break(self, location): def add_subtable_break(self, location):
self.mapping[(self.SUBTABLE_BREAK_, location)] = self.SUBTABLE_BREAK_ self.mapping[(self.SUBTABLE_BREAK_, location)] = self.SUBTABLE_BREAK_

View File

@ -99,18 +99,18 @@
<!-- SubTableCount=1 --> <!-- SubTableCount=1 -->
<AlternateSubst index="0"> <AlternateSubst index="0">
<AlternateSet glyph="a"> <AlternateSet glyph="a">
<Alternate glyph="A.sc"/>
<Alternate glyph="a.alt1"/> <Alternate glyph="a.alt1"/>
<Alternate glyph="a.alt2"/> <Alternate glyph="a.alt2"/>
<Alternate glyph="a.alt3"/> <Alternate glyph="a.alt3"/>
<Alternate glyph="A.sc"/>
</AlternateSet> </AlternateSet>
<AlternateSet glyph="b"> <AlternateSet glyph="b">
<Alternate glyph="B.sc"/>
<Alternate glyph="b.alt"/> <Alternate glyph="b.alt"/>
<Alternate glyph="B.sc"/>
</AlternateSet> </AlternateSet>
<AlternateSet glyph="c"> <AlternateSet glyph="c">
<Alternate glyph="C.sc"/>
<Alternate glyph="c.mid"/> <Alternate glyph="c.mid"/>
<Alternate glyph="C.sc"/>
</AlternateSet> </AlternateSet>
<AlternateSet glyph="d"> <AlternateSet glyph="d">
<Alternate glyph="d.alt"/> <Alternate glyph="d.alt"/>