diff --git a/Lib/fontTools/ttLib/tables/ttProgram.py b/Lib/fontTools/ttLib/tables/ttProgram.py index 182982f21..62e0e1a74 100644 --- a/Lib/fontTools/ttLib/tables/ttProgram.py +++ b/Lib/fontTools/ttLib/tables/ttProgram.py @@ -63,6 +63,7 @@ instructions = [ (0x66, 'FLOOR', 0, 'Floor', 1, 1), # n floor(n) (0x46, 'GC', 1, 'GetCoordOnPVector', 1, 1), # p c (0x88, 'GETINFO', 0, 'GetInfo', 1, 1), # selector result + (0x91, 'GETVARIATION', 0, 'GetVariation', 0, -1), # - a1,..,an (0x0d, 'GFV', 0, 'GetFVector', 0, 2), # - px, py (0x0c, 'GPV', 0, 'GetPVector', 0, 2), # - px, py (0x52, 'GT', 0, 'GreaterThan', 2, 1), # e2, e1 b diff --git a/Lib/fontTools/varLib/mutator.py b/Lib/fontTools/varLib/mutator.py index 7a03e4548..3e9fb168d 100644 --- a/Lib/fontTools/varLib/mutator.py +++ b/Lib/fontTools/varLib/mutator.py @@ -5,8 +5,9 @@ $ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85 """ from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * -from fontTools.misc.fixedTools import floatToFixedToFloat, otRound -from fontTools.ttLib import TTFont +from fontTools.misc.fixedTools import floatToFixedToFloat, otRound, floatToFixed +from fontTools.ttLib import TTFont, newTable +from fontTools.ttLib.tables import ttProgram from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates from fontTools.varLib import _GetCoordinates, _SetCoordinates from fontTools.varLib.models import ( @@ -63,11 +64,11 @@ def instantiateVariableFont(varfont, location, inplace=False): glyf = varfont['glyf'] # get list of glyph names in gvar sorted by component depth glyphnames = sorted( - gvar.variations.keys(), - key=lambda name: ( - glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth - if glyf[name].isComposite() else 0, - name)) + gvar.variations.keys(), + key=lambda name: ( + glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth + if glyf[name].isComposite() else 0, + name)) for glyphname in glyphnames: variations = gvar.variations[glyphname] coordinates,_ = _GetCoordinates(varfont, glyphname) @@ -112,7 +113,7 @@ def instantiateVariableFont(varfont, location, inplace=False): if not delta: continue setattr(varfont[tableTag], itemName, - getattr(varfont[tableTag], itemName) + delta) + getattr(varfont[tableTag], itemName) + delta) if 'GDEF' in varfont: log.info("Mutating GDEF/GPOS/GSUB tables") @@ -121,6 +122,35 @@ def instantiateVariableFont(varfont, location, inplace=False): log.info("Building interpolated tables") merger.instantiate() + for glyph in glyf.glyphs.values(): + if hasattr(glyph, "program"): + instructions = glyph.program.getAssembly() + # If GETVARIATION opcode is used in bytecode of any glyph add IDEF + addidef = False + for instruction in instructions: + if instruction.startswith("GETVARIATION"): + addidef = True + break + if addidef: + asm = [] + if varfont.has_key('fpgm'): + fpgm = varfont['fpgm'] + asm = fpgm.program.getAssembly() + else: + fpgm = newTable('fpgm') + fpgm.program = ttProgram.Program() + varfont['fpgm'] = fpgm + log.info("Adding IDEF to fpgm table for GETVARIATION opcode") + asm.append("PUSHB[000] 145") + asm.append("IDEF[ ]") + args = [str(len(loc))] + for val in loc.values(): + args.append(str(floatToFixed(val, 14))) + asm.append("NPUSHW[ ] " + ' '.join(args)) + asm.append("ENDF[ ]") + fpgm.program.fromAssembly(asm) + break + if 'name' in varfont: log.info("Pruning name table") exclude = {a.axisNameID for a in fvar.axes} @@ -134,7 +164,7 @@ def instantiateVariableFont(varfont, location, inplace=False): if "wght" in location and "OS/2" in varfont: varfont["OS/2"].usWeightClass = otRound( - max(1, min(location["wght"], 1000)) + max(1, min(location["wght"], 1000)) ) if "wdth" in location: wdth = location["wdth"] @@ -160,22 +190,22 @@ def main(args=None): import argparse parser = argparse.ArgumentParser( - "fonttools varLib.mutator", description="Instantiate a variable font") + "fonttools varLib.mutator", description="Instantiate a variable font") parser.add_argument( - "input", metavar="INPUT.ttf", help="Input variable TTF file.") + "input", metavar="INPUT.ttf", help="Input variable TTF file.") parser.add_argument( - "locargs", metavar="AXIS=LOC", nargs="*", - help="List of space separated locations. A location consist in " - "the name of a variation axis, followed by '=' and a number. E.g.: " - " wght=700 wdth=80. The default is the location of the base master.") + "locargs", metavar="AXIS=LOC", nargs="*", + help="List of space separated locations. A location consist in " + "the name of a variation axis, followed by '=' and a number. E.g.: " + " wght=700 wdth=80. The default is the location of the base master.") parser.add_argument( - "-o", "--output", metavar="OUTPUT.ttf", default=None, - help="Output instance TTF file (default: INPUT-instance.ttf).") + "-o", "--output", metavar="OUTPUT.ttf", default=None, + help="Output instance TTF file (default: INPUT-instance.ttf).") logging_group = parser.add_mutually_exclusive_group(required=False) logging_group.add_argument( - "-v", "--verbose", action="store_true", help="Run more verbosely.") + "-v", "--verbose", action="store_true", help="Run more verbosely.") logging_group.add_argument( - "-q", "--quiet", action="store_true", help="Turn verbosity off.") + "-q", "--quiet", action="store_true", help="Turn verbosity off.") options = parser.parse_args(args) varfilename = options.input diff --git a/Tests/varLib/data/master_ttx_getvar_ttf/Mutator_Getvar.ttx b/Tests/varLib/data/master_ttx_getvar_ttf/Mutator_Getvar.ttx new file mode 100755 index 000000000..5360fe40b --- /dev/null +++ b/Tests/varLib/data/master_ttx_getvar_ttf/Mutator_Getvar.ttx @@ -0,0 +1,555 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GETVARIATION[] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + VarFont + + + Regular + + + VarFont Regular: 2017 + + + VarFont Regular + + + VarFont-Regular + + + Width + + + Ascender + + + Regular + + + VarFont + + + Regular + + + VarFont Regular: 2017 + + + VarFont Regular + + + VarFont-Regular + + + Width + + + Ascender + + + Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wdth + 60.0 + 100.0 + 100.0 + 256 + + + + + ASCN + 608.0 + 608.0 + 648.0 + 257 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/varLib/data/test_results/Mutator_Getvar-instance.ttx b/Tests/varLib/data/test_results/Mutator_Getvar-instance.ttx new file mode 100755 index 000000000..651a35faa --- /dev/null +++ b/Tests/varLib/data/test_results/Mutator_Getvar-instance.ttx @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PUSHB[ ] /* 1 value pushed */ + 145 + IDEF[ ] /* InstructionDefinition */ + NPUSHW[ ] /* 3 values pushed */ + 2 -8192 8192 + ENDF[ ] /* EndFunctionDefinition */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GETVARIATION[ ] /* GetVariation */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + VarFont + + + Regular + + + VarFont Regular: 2017 + + + VarFont Regular + + + VarFont-Regular + + + VarFont + + + Regular + + + VarFont Regular: 2017 + + + VarFont Regular + + + VarFont-Regular + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/varLib/mutator_test.py b/Tests/varLib/mutator_test.py index de794f0f7..23e14ca83 100644 --- a/Tests/varLib/mutator_test.py +++ b/Tests/varLib/mutator_test.py @@ -117,6 +117,27 @@ class MutatorTest(unittest.TestCase): expected_ttx_path = self.get_test_output(varfont_name + '.ttx') self.expect_ttx(instfont, expected_ttx_path, tables) + def test_varlib_mutator_getvar_ttf(self): + suffix = '.ttf' + ttx_dir = self.get_test_input('master_ttx_getvar_ttf') + + self.temp_dir() + ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'Mutator_Getvar') + for path in ttx_paths: + self.compile_font(path, suffix, self.tempdir) + + varfont_name = 'Mutator_Getvar' + varfont_path = os.path.join(self.tempdir, varfont_name + suffix) + + args = [varfont_path, 'wdth=80', 'ASCN=628'] + mutator(args) + + instfont_path = os.path.splitext(varfont_path)[0] + '-instance' + suffix + instfont = TTFont(instfont_path) + tables = [table_tag for table_tag in instfont.keys() if table_tag != 'head'] + expected_ttx_path = self.get_test_output(varfont_name + '-instance.ttx') + self.expect_ttx(instfont, expected_ttx_path, tables) + def test_varlib_mutator_iup_ttf(self): suffix = '.ttf' ufo_dir = self.get_test_input('master_ufo')