Merge pull request #3034 from fonttools/otlib-gpos7
[otlib] Add a config option to write GPOS 7 lookups
This commit is contained in:
commit
444a349ef4
@ -57,3 +57,18 @@ Config.register_option(
|
||||
parse=Option.parse_optional_bool,
|
||||
validate=Option.validate_optional_bool,
|
||||
)
|
||||
|
||||
Config.register_option(
|
||||
name="fontTools.otlLib.builder:WRITE_GPOS7",
|
||||
help=dedent(
|
||||
"""\
|
||||
macOS before 13.2 didn’t support GPOS LookupType 7 (non-chaining
|
||||
ContextPos lookups), so FontTools.otlLib.builder disables a file size
|
||||
optimisation that would use LookupType 7 instead of 8 when there is no
|
||||
chaining (no prefix or suffix). Set to True to enable the optimization.
|
||||
"""
|
||||
),
|
||||
default=False,
|
||||
parse=Option.parse_optional_bool,
|
||||
validate=Option.validate_optional_bool,
|
||||
)
|
||||
|
@ -369,10 +369,19 @@ class ChainContextualBuilder(LookupBuilder):
|
||||
|
||||
rulesets = self.rulesets()
|
||||
chaining = any(ruleset.hasPrefixOrSuffix for ruleset in rulesets)
|
||||
|
||||
# https://github.com/fonttools/fonttools/issues/2539
|
||||
#
|
||||
# Unfortunately, as of 2022-03-07, Apple's CoreText renderer does not
|
||||
# correctly process GPOS7 lookups, so for now we force contextual
|
||||
# positioning lookups to be chaining (GPOS8).
|
||||
if self.subtable_type == "Pos": # horrible separation of concerns breach
|
||||
#
|
||||
# This seems to be fixed as of macOS 13.2, but we keep disabling this
|
||||
# for now until we are no longer concerned about old macOS versions.
|
||||
# But we allow people to opt-out of this with the config key below.
|
||||
write_gpos7 = self.font.cfg.get("fontTools.otlLib.builder:WRITE_GPOS7")
|
||||
# horrible separation of concerns breach
|
||||
if not write_gpos7 and self.subtable_type == "Pos":
|
||||
chaining = True
|
||||
|
||||
for ruleset in rulesets:
|
||||
|
116
Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_diff.ttx
Normal file
116
Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_diff.ttx
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont>
|
||||
|
||||
<GPOS>
|
||||
<Version value="0x00010000"/>
|
||||
<ScriptList>
|
||||
<!-- ScriptCount=1 -->
|
||||
<ScriptRecord index="0">
|
||||
<ScriptTag value="DFLT"/>
|
||||
<Script>
|
||||
<DefaultLangSys>
|
||||
<ReqFeatureIndex value="65535"/>
|
||||
<!-- FeatureCount=1 -->
|
||||
<FeatureIndex index="0" value="0"/>
|
||||
</DefaultLangSys>
|
||||
<!-- LangSysCount=0 -->
|
||||
</Script>
|
||||
</ScriptRecord>
|
||||
</ScriptList>
|
||||
<FeatureList>
|
||||
<!-- FeatureCount=1 -->
|
||||
<FeatureRecord index="0">
|
||||
<FeatureTag value="xxxx"/>
|
||||
<Feature>
|
||||
<!-- LookupCount=1 -->
|
||||
<LookupListIndex index="0" value="2"/>
|
||||
</Feature>
|
||||
</FeatureRecord>
|
||||
</FeatureList>
|
||||
<LookupList>
|
||||
<!-- LookupCount=3 -->
|
||||
<Lookup index="0">
|
||||
<LookupType value="2"/>
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<PairPos index="0" Format="1">
|
||||
<Coverage>
|
||||
<Glyph value="A"/>
|
||||
</Coverage>
|
||||
<ValueFormat1 value="4"/>
|
||||
<ValueFormat2 value="0"/>
|
||||
<!-- PairSetCount=1 -->
|
||||
<PairSet index="0">
|
||||
<!-- PairValueCount=1 -->
|
||||
<PairValueRecord index="0">
|
||||
<SecondGlyph value="a"/>
|
||||
<Value1 XAdvance="17"/>
|
||||
</PairValueRecord>
|
||||
</PairSet>
|
||||
</PairPos>
|
||||
</Lookup>
|
||||
<Lookup index="1">
|
||||
<LookupType value="4"/>
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<MarkBasePos index="0" Format="1">
|
||||
<MarkCoverage>
|
||||
<Glyph value="uni0303"/>
|
||||
</MarkCoverage>
|
||||
<BaseCoverage>
|
||||
<Glyph value="a"/>
|
||||
</BaseCoverage>
|
||||
<!-- ClassCount=1 -->
|
||||
<MarkArray>
|
||||
<!-- MarkCount=1 -->
|
||||
<MarkRecord index="0">
|
||||
<Class value="0"/>
|
||||
<MarkAnchor Format="1">
|
||||
<XCoordinate value="0"/>
|
||||
<YCoordinate value="510"/>
|
||||
</MarkAnchor>
|
||||
</MarkRecord>
|
||||
</MarkArray>
|
||||
<BaseArray>
|
||||
<!-- BaseCount=1 -->
|
||||
<BaseRecord index="0">
|
||||
<BaseAnchor index="0" Format="1">
|
||||
<XCoordinate value="273"/>
|
||||
<YCoordinate value="510"/>
|
||||
</BaseAnchor>
|
||||
</BaseRecord>
|
||||
</BaseArray>
|
||||
</MarkBasePos>
|
||||
</Lookup>
|
||||
<Lookup index="2">
|
||||
<LookupType value="7"/>
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<ContextPos index="0" Format="1">
|
||||
<Coverage>
|
||||
<Glyph value="A"/>
|
||||
</Coverage>
|
||||
<!-- PosRuleSetCount=1 -->
|
||||
<PosRuleSet index="0">
|
||||
<!-- PosRuleCount=1 -->
|
||||
<PosRule index="0">
|
||||
<!-- GlyphCount=3 -->
|
||||
<!-- PosCount=2 -->
|
||||
<Input index="0" value="a"/>
|
||||
<Input index="1" value="uni0303"/>
|
||||
<PosLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="0"/>
|
||||
</PosLookupRecord>
|
||||
<PosLookupRecord index="1">
|
||||
<SequenceIndex value="2"/>
|
||||
<LookupListIndex value="1"/>
|
||||
</PosLookupRecord>
|
||||
</PosRule>
|
||||
</PosRuleSet>
|
||||
</ContextPos>
|
||||
</Lookup>
|
||||
</LookupList>
|
||||
</GPOS>
|
||||
|
||||
</ttFont>
|
116
Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_same.ttx
Normal file
116
Tests/varLib/data/test_results/InterpolateLayoutGPOS_7_same.ttx
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont>
|
||||
|
||||
<GPOS>
|
||||
<Version value="0x00010000"/>
|
||||
<ScriptList>
|
||||
<!-- ScriptCount=1 -->
|
||||
<ScriptRecord index="0">
|
||||
<ScriptTag value="DFLT"/>
|
||||
<Script>
|
||||
<DefaultLangSys>
|
||||
<ReqFeatureIndex value="65535"/>
|
||||
<!-- FeatureCount=1 -->
|
||||
<FeatureIndex index="0" value="0"/>
|
||||
</DefaultLangSys>
|
||||
<!-- LangSysCount=0 -->
|
||||
</Script>
|
||||
</ScriptRecord>
|
||||
</ScriptList>
|
||||
<FeatureList>
|
||||
<!-- FeatureCount=1 -->
|
||||
<FeatureRecord index="0">
|
||||
<FeatureTag value="xxxx"/>
|
||||
<Feature>
|
||||
<!-- LookupCount=1 -->
|
||||
<LookupListIndex index="0" value="2"/>
|
||||
</Feature>
|
||||
</FeatureRecord>
|
||||
</FeatureList>
|
||||
<LookupList>
|
||||
<!-- LookupCount=3 -->
|
||||
<Lookup index="0">
|
||||
<LookupType value="2"/>
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<PairPos index="0" Format="1">
|
||||
<Coverage>
|
||||
<Glyph value="A"/>
|
||||
</Coverage>
|
||||
<ValueFormat1 value="4"/>
|
||||
<ValueFormat2 value="0"/>
|
||||
<!-- PairSetCount=1 -->
|
||||
<PairSet index="0">
|
||||
<!-- PairValueCount=1 -->
|
||||
<PairValueRecord index="0">
|
||||
<SecondGlyph value="a"/>
|
||||
<Value1 XAdvance="-23"/>
|
||||
</PairValueRecord>
|
||||
</PairSet>
|
||||
</PairPos>
|
||||
</Lookup>
|
||||
<Lookup index="1">
|
||||
<LookupType value="4"/>
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<MarkBasePos index="0" Format="1">
|
||||
<MarkCoverage>
|
||||
<Glyph value="uni0303"/>
|
||||
</MarkCoverage>
|
||||
<BaseCoverage>
|
||||
<Glyph value="a"/>
|
||||
</BaseCoverage>
|
||||
<!-- ClassCount=1 -->
|
||||
<MarkArray>
|
||||
<!-- MarkCount=1 -->
|
||||
<MarkRecord index="0">
|
||||
<Class value="0"/>
|
||||
<MarkAnchor Format="1">
|
||||
<XCoordinate value="0"/>
|
||||
<YCoordinate value="500"/>
|
||||
</MarkAnchor>
|
||||
</MarkRecord>
|
||||
</MarkArray>
|
||||
<BaseArray>
|
||||
<!-- BaseCount=1 -->
|
||||
<BaseRecord index="0">
|
||||
<BaseAnchor index="0" Format="1">
|
||||
<XCoordinate value="260"/>
|
||||
<YCoordinate value="500"/>
|
||||
</BaseAnchor>
|
||||
</BaseRecord>
|
||||
</BaseArray>
|
||||
</MarkBasePos>
|
||||
</Lookup>
|
||||
<Lookup index="2">
|
||||
<LookupType value="7"/>
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<ContextPos index="0" Format="1">
|
||||
<Coverage>
|
||||
<Glyph value="A"/>
|
||||
</Coverage>
|
||||
<!-- PosRuleSetCount=1 -->
|
||||
<PosRuleSet index="0">
|
||||
<!-- PosRuleCount=1 -->
|
||||
<PosRule index="0">
|
||||
<!-- GlyphCount=3 -->
|
||||
<!-- PosCount=2 -->
|
||||
<Input index="0" value="a"/>
|
||||
<Input index="1" value="uni0303"/>
|
||||
<PosLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="0"/>
|
||||
</PosLookupRecord>
|
||||
<PosLookupRecord index="1">
|
||||
<SequenceIndex value="2"/>
|
||||
<LookupListIndex value="1"/>
|
||||
</PosLookupRecord>
|
||||
</PosRule>
|
||||
</PosRuleSet>
|
||||
</ContextPos>
|
||||
</Lookup>
|
||||
</LookupList>
|
||||
</GPOS>
|
||||
|
||||
</ttFont>
|
@ -85,10 +85,12 @@ class InterpolateLayoutTest(unittest.TestCase):
|
||||
font.save(path)
|
||||
self.expect_ttx(TTFont(path), expected_ttx, tables)
|
||||
|
||||
def compile_font(self, path, suffix, temp_dir, features=None):
|
||||
def compile_font(self, path, suffix, temp_dir, features=None, cfg=None):
|
||||
ttx_filename = os.path.basename(path)
|
||||
savepath = os.path.join(temp_dir, ttx_filename.replace(".ttx", suffix))
|
||||
font = TTFont(recalcBBoxes=False, recalcTimestamp=False)
|
||||
if cfg:
|
||||
font.cfg.update(cfg)
|
||||
font.importXML(path)
|
||||
if features:
|
||||
addOpenTypeFeaturesFromString(font, features)
|
||||
@ -734,6 +736,94 @@ class InterpolateLayoutTest(unittest.TestCase):
|
||||
self.expect_ttx(instfont, expected_ttx_path, tables)
|
||||
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
|
||||
|
||||
def test_varlib_interpolate_layout_GPOS_only_LookupType_7_same_val_ttf(self):
|
||||
"""Only GPOS; LookupType 7; same values in all masters."""
|
||||
suffix = ".ttf"
|
||||
ds_path = self.get_test_input("InterpolateLayout.designspace")
|
||||
ufo_dir = self.get_test_input("master_ufo")
|
||||
ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
|
||||
|
||||
fea_str = """
|
||||
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
|
||||
lookup CNTXT_PAIR_POS {
|
||||
pos A a -23;
|
||||
} CNTXT_PAIR_POS;
|
||||
|
||||
lookup CNTXT_MARK_TO_BASE {
|
||||
pos base a <anchor 260 500> mark @MARKS_ABOVE;
|
||||
} CNTXT_MARK_TO_BASE;
|
||||
|
||||
feature xxxx {
|
||||
pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
|
||||
} xxxx;
|
||||
"""
|
||||
features = [fea_str] * 2
|
||||
|
||||
self.temp_dir()
|
||||
ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
|
||||
cfg = {"fontTools.otlLib.builder:WRITE_GPOS7": True}
|
||||
for i, path in enumerate(ttx_paths):
|
||||
self.compile_font(path, suffix, self.tempdir, features[i], cfg)
|
||||
|
||||
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
|
||||
instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
|
||||
|
||||
tables = ["GPOS"]
|
||||
expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_7_same.ttx")
|
||||
self.expect_ttx(instfont, expected_ttx_path, tables)
|
||||
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
|
||||
|
||||
def test_varlib_interpolate_layout_GPOS_only_LookupType_7_diff_val_ttf(self):
|
||||
"""Only GPOS; LookupType 7; different values in each master."""
|
||||
suffix = ".ttf"
|
||||
ds_path = self.get_test_input("InterpolateLayout.designspace")
|
||||
ufo_dir = self.get_test_input("master_ufo")
|
||||
ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
|
||||
|
||||
fea_str_0 = """
|
||||
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
|
||||
lookup CNTXT_PAIR_POS {
|
||||
pos A a -23;
|
||||
} CNTXT_PAIR_POS;
|
||||
|
||||
lookup CNTXT_MARK_TO_BASE {
|
||||
pos base a <anchor 260 500> mark @MARKS_ABOVE;
|
||||
} CNTXT_MARK_TO_BASE;
|
||||
|
||||
feature xxxx {
|
||||
pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
|
||||
} xxxx;
|
||||
"""
|
||||
fea_str_1 = """
|
||||
markClass uni0303 <anchor 0 520> @MARKS_ABOVE;
|
||||
lookup CNTXT_PAIR_POS {
|
||||
pos A a 57;
|
||||
} CNTXT_PAIR_POS;
|
||||
|
||||
lookup CNTXT_MARK_TO_BASE {
|
||||
pos base a <anchor 285 520> mark @MARKS_ABOVE;
|
||||
} CNTXT_MARK_TO_BASE;
|
||||
|
||||
feature xxxx {
|
||||
pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
|
||||
} xxxx;
|
||||
"""
|
||||
features = [fea_str_0, fea_str_1]
|
||||
|
||||
self.temp_dir()
|
||||
ttx_paths = self.get_file_list(ttx_dir, ".ttx", "TestFamily2-")
|
||||
cfg = {"fontTools.otlLib.builder:WRITE_GPOS7": True}
|
||||
for i, path in enumerate(ttx_paths):
|
||||
self.compile_font(path, suffix, self.tempdir, features[i], cfg)
|
||||
|
||||
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace(".ufo", suffix)
|
||||
instfont = interpolate_layout(ds_path, {"weight": 500}, finder)
|
||||
|
||||
tables = ["GPOS"]
|
||||
expected_ttx_path = self.get_test_output("InterpolateLayoutGPOS_7_diff.ttx")
|
||||
self.expect_ttx(instfont, expected_ttx_path, tables)
|
||||
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
|
||||
|
||||
def test_varlib_interpolate_layout_GPOS_only_LookupType_8_same_val_ttf(self):
|
||||
"""Only GPOS; LookupType 8; same values in all masters."""
|
||||
suffix = ".ttf"
|
||||
|
Loading…
x
Reference in New Issue
Block a user