def build_fontmake(self, designspace_path, output=['variable'], output_dir=None, remove_overlaps=False, interpolate=False, autohint=None): if not os.path.isdir(output_dir): os.makedirs(output_dir) project = FontProject() fontmake_args = { 'output': output, 'output_path': None, 'output_dir': output_dir, # 'feature_writers': None, 'interpolate': interpolate, 'remove_overlaps': remove_overlaps, 'overlaps_backend': 'booleanOperations', 'autohint': autohint, 'use_production_names': False } if 'variable' in output: fontmake_args['optimize_gvar'] = True if 'otf' in output: fontmake_args['optimize_cff'] = CFFOptimization.SUBROUTINIZE print( project.run_from_designspace(designspace_path=designspace_path, **fontmake_args))
def makeVanillaFamily(family, *output, newName=" "): # if family not in pan_european_fonts: # print("Please note that these fonts may lack") # print("basic figures and punctuation.") path, folder = getFile(".designspace", family) designSpace = openDesignSpace(path) destination = folder + "/" + "Instances" ### test if mti for file in os.listdir(folder): if file.endswith(".plist"): # INJECT COMPILED TABLE IN FONTS ufoWithMTIfeatures2font(family, output) if newName != " ": renameFonts(family, newName) return fp = FontProject() fonts = fp.run_from_designspace(expand_features_to_instances=True, use_mutatormath=False, designspace_path=path, interpolate=True, output=("otf"), output_dir=destination) ufolist = list() for ufo in os.listdir(os.path.join(folder, "instance_ufos")): if ufo[-4:] == ".ufo": ufolist.append(ufo) instancesFolder = family + "/instance_ufos" ufo2font(instancesFolder, ufolist, output, fromInstances=True) if newName != " ": renameFonts(family, newName)
def main(): parser = ArgumentParser() parser.add_argument('-g', '--glyphs-path') parser.add_argument('-u', '--ufo-paths', nargs='+') parser.add_argument('-m', '--mm-designspace') parser.add_argument('-o', '--output', nargs='+', default=('otf', 'ttf'), choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable')) parser.add_argument('-i', '--interpolate', action='store_true', help='interpolate masters (Glyphs source only)') parser.add_argument('--mti-source') parser.add_argument('--use-afdko', action='store_true') parser.add_argument('--timing', action='store_true') args = vars(parser.parse_args()) project = FontProject(timing=args.pop('timing')) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if not sum(1 for p in [glyphs_path, ufo_paths, designspace_path] if p) == 1: raise ValueError('Exactly one source type required (Glyphs or UFO).') if glyphs_path: project.run_from_glyphs(glyphs_path, **args) elif designspace_path: project.run_from_designspace(designspace_path, **args) else: excluded = 'interpolate' if args[excluded]: raise ValueError( '"%s" argument only available for Glyphs or Designspace source' % excluded) del args[excluded] if ufo_paths: project.run_from_ufos(ufo_paths, **args)
def makeOtfFamily(family, newName=" ", onlyOtf=False): if family not in pan_european_fonts: print("Please note that non-latin OTF fonts can't have") print("the figures and punctuation from Latin merged in it") output = "otf" path, folder = getFile(".designspace", family) designSpace = openDesignSpace(path) destination = folder + "/" + "Instances" ### test if mti for file in os.listdir(folder): if file.endswith(".plist"): # INJECT COMPILED TABLE IN FONTS ufoWithMTIfeatures2font(family, output) if newName != " ": renameFonts(family, newName) return if onlyOtf is True: fp = FontProject() fonts = fp.run_from_designspace(expand_features_to_instances=True, use_mutatormath=False, designspace_path=path, interpolate=True, output=("otf"), output_dir=destination) ufolist = list() for ufo in os.listdir(os.path.join(folder, "instance_ufos")): if ufo[-4:] == ".ufo": ufolist.append(ufo) instancesFolder = family + "/instance_ufos" ufo2font(instancesFolder, ufolist, output, fromInstances=True) if newName != " ": renameFonts(family, newName) ### TEST FUNCTIONS ### # mastersUfos2fonts("NotoSansThaana", "otf") # makeTTFInstancesFromVF("NotoSerifSinhala") # makeTTFInstancesFromVF("NotoSansArabic") # subsetFonts("NotoNaskhArabic", "Core_Arabic") # designSpace2Instances("NotoSansVai", "otf", "ttf") # ufoWithMTIfeatures2font("NotoNastaliqUrdu", "ttf") # subsetFonts("NotoSans", "CyrillicPro", familyNewName = "Avocado Sans", flavor=["ttf"]) # subsetFonts("NotoNaskhArabicUI", "Core_Arabic") # subsetFonts("NotoSans", "SecureSet") # mastersUfos2fonts("NotoSansThaana", "woff2") # renameFonts("NotoMusic", "Tomato Soup", 'otf') # mergeFonts("NotoSans","NotoNastaliqUrdu") # designSpace2Var("NotoSerifThai") # makeTTFInstancesFromVF("NotoSerif") # makeOneInstanceFromVF("NotoSansThaana", {'wght': 190.0}) # mastersUfos2fonts("NotoSansThaana", "ttf") # ufosToGlyphs("NotoSansThaana") # ufo2font("NotoSans", ["NotoSans-Bold.ufo"], "ttf") # designSpace2Instances("NotoSansNko", "ttf", secureSet=False) # mergeFonts("NotoSansThaana", "NotoSerifHebrew") # addSecureSet("NotoSansArabic", "ttf")
def build(args): designspace = os.path.join(args.build, args.designspace) os.environ["SOURCE_DATE_EPOCH"] = epoch(args) autohint = None if args.release: autohint = "" project = FontProject(verbose="WARNING") if args.ufo: project.run_from_ufos([args.ufo], output=args.output, remove_overlaps=False, reverse_direction=False, subroutinize=args.release, autohint=autohint) else: project.run_from_designspace(designspace, output=args.output, subroutinize=args.release, autohint=autohint)
def main(): parser = ArgumentParser() parser.add_argument('-g', '--glyphs-path') parser.add_argument('-u', '--ufo-paths', nargs='+') parser.add_argument('-m', '--mm-designspace') parser.add_argument('-o', '--output', nargs='+', default=('otf', 'ttf'), choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable', 'variable')) parser.add_argument('-i', '--interpolate', action='store_true', help='interpolate masters (for Glyphs or MutatorMath ' 'sources only)') parser.add_argument('-M', '--masters-as-instances', action='store_true', help='treat masters as instances') parser.add_argument('-a', '--autohint', nargs='?', const="", help='can provide arguments to ttfautohint, quoted') parser.add_argument('--mti-source') parser.add_argument('--family-name', help='Family name to use for masters,' ' and to filter output instances by') parser.add_argument('--use-afdko', action='store_true') parser.add_argument('--keep-direction', dest="reverse_direction", action='store_false', help='Do not reverse contour ' 'direction when output is ttf or ttf-interpolatable') parser.add_argument('--keep-overlaps', dest="remove_overlaps", action='store_false', help='Do not remove any overlap.') group1 = parser.add_mutually_exclusive_group(required=False) group1.add_argument( '--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with ' 'production names if available otherwise use uninames.') group1.add_argument('--no-production-names', dest='use_production_names', action='store_false') group2 = parser.add_mutually_exclusive_group(required=False) group2.add_argument('--subset', dest='subset', action='store_true', help='Subset font using export ' 'flags set by glyphsLib') group2.add_argument('--no-subset', dest='subset', action='store_false') group3 = parser.add_mutually_exclusive_group(required=False) group3.add_argument('-s', '--subroutinize', action='store_true', help='Optimize CFF table using compreffor (default)') group3.add_argument('-S', '--no-subroutinize', dest='subroutinize', action='store_false') parser.add_argument('-e', '--conversion-error', type=float, default=None, metavar='ERROR', help="Maximum approximation error for" " cubic to quadratic conversion measured in EM") parser.set_defaults(use_production_names=None, subset=None, subroutinize=True) parser.add_argument('--timing', action='store_true') args = vars(parser.parse_args()) project = FontProject(timing=args.pop('timing')) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if not sum(1 for p in [glyphs_path, ufo_paths, designspace_path] if p) == 1: parser.error('Exactly one source type required (Glyphs, UFO, or ' 'MutatorMath).') def exclude_args(parser, args, excluded_args): exclusive_msg = '"{}" argument only available for {} source' exclusive_src = { 'interpolate': 'Glyphs or MutatorMath', 'family_name': 'Glyphs' } for excluded in excluded_args: if args[excluded]: parser.error( exclusive_msg.format(excluded, exclusive_src[excluded])) del args[excluded] if glyphs_path: project.run_from_glyphs(glyphs_path, **args) elif designspace_path: exclude_args(parser, args, ['family_name']) project.run_from_designspace(designspace_path, **args) else: exclude_args(parser, args, ['family_name', 'interpolate']) if ufo_paths: project.run_from_ufos(ufo_paths, is_instance=args.pop('masters_as_instances'), **args)
def main(args=None): parser = ArgumentParser() parser.add_argument("--version", action="version", version=__version__) inputGroup = parser.add_argument_group( title="Input arguments", description="The following arguments are mutually exclusive.", ) xInputGroup = inputGroup.add_mutually_exclusive_group(required=True) xInputGroup.add_argument("-g", "--glyphs-path", metavar="GLYPHS", help="Path to .glyphs source file") xInputGroup.add_argument( "-u", "--ufo-paths", nargs="+", metavar="UFO", help="One or more paths to UFO files", ) xInputGroup.add_argument( "-m", "--mm-designspace", metavar="DESIGNSPACE", help="Path to .designspace file", ) outputGroup = parser.add_argument_group(title="Output arguments") outputGroup.add_argument( "-o", "--output", nargs="+", default=("otf", "ttf"), metavar="FORMAT", help="Output font formats. Choose between: %(choices)s. " "Default: otf, ttf", choices=( "ufo", "otf", "ttf", "ttf-interpolatable", "otf-interpolatable", "variable", "variable-cff2", ), ) outputSubGroup = outputGroup.add_mutually_exclusive_group() outputSubGroup.add_argument( "--output-path", default=None, help="Output font file path. Only valid when the output is a single " "file (e.g. input is a single UFO or output is variable font)", ) outputSubGroup.add_argument( "--output-dir", default=None, help="Output folder. By default, output folders are created in the " "current working directory, grouping output fonts by format.", ) outputGroup.add_argument( "-i", "--interpolate", nargs="?", default=False, const=True, metavar="INSTANCE_NAME", help="Interpolate masters and generate all the instances defined. " "To only interpolate a specific instance (or instances) that " 'match a given "name" attribute, you can pass as argument ' "the full instance name or a regular expression. " 'E.g.: -i "Noto Sans Bold"; or -i ".* UI Condensed". ' "(for Glyphs or MutatorMath sources only). ", ) outputGroup.add_argument( "-M", "--masters-as-instances", action="store_true", help="Output masters as instances", ) outputGroup.add_argument( "--family-name", help="Family name to use for masters, and to filter output instances", ) outputGroup.add_argument( "--round-instances", dest="round_instances", action="store_true", help="Apply integer rounding to all geometry when interpolating", ) outputGroup.add_argument( "--designspace-path", default=None, help="Path to output designspace file (for Glyphs sources only).", ) outputGroup.add_argument( "--master-dir", default=None, help='Directory where to write master UFO. Default: "./master_ufo". ' 'If value is "{tmp}", a temporary directory is created and ' "removed at the end (for Glyphs sources only).", ) outputGroup.add_argument( "--instance-dir", default=None, help="Directory where to write instance UFOs. Default: " '"./instance_ufo". If value is "{tmp}", a temporary directory ' "is created and removed at the end (for Glyphs sources only).", ) outputGroup.add_argument( "--validate-ufo", action="store_true", help="Enable ufoLib validation on reading/writing UFO files. It is " "disabled by default", ) contourGroup = parser.add_argument_group(title="Handling of contours") contourGroup.add_argument( "--keep-overlaps", dest="remove_overlaps", action="store_false", help="Do not remove any overlap.", ) contourGroup.add_argument( "--overlaps-backend", dest="overlaps_backend", metavar="BACKEND", choices=("booleanOperations", "pathops"), default="booleanOperations", help="Select library to remove overlaps. Choose between: %(choices)s " "(default: %(default)s)", ) contourGroup.add_argument( "--keep-direction", dest="reverse_direction", action="store_false", help="Do not reverse contour direction when output is ttf or " "ttf-interpolatable", ) contourGroup.add_argument( "-e", "--conversion-error", type=float, default=None, metavar="ERROR", help="Maximum approximation error for cubic to quadratic conversion " "measured in EM", ) contourGroup.add_argument( "-a", "--autohint", nargs="?", const="", help="Run ttfautohint. Can provide arguments, quoted", ) contourGroup.add_argument( "--cff-round-tolerance", type=float, default=None, metavar="FLOAT", help="Restrict rounding of point coordinates in CFF table to only " "those floats whose absolute difference from their integral part " "is less than or equal to the tolerance. By default, all floats " "are rounded to integer (tolerance 0.5); 0 disables rounding.", ) contourGroup.add_argument( "--optimize-cff", type=lambda s: CFFOptimization(int(s)), default=CFFOptimization.SUBROUTINIZE, help="0 disables all optimizations; 1 specializes the CFF charstring " "operators; 2 (default) also enables subroutinization", ) layoutGroup = parser.add_argument_group( title="Handling of OpenType Layout") layoutGroup.add_argument( "--interpolate-binary-layout", nargs="?", default=False, const=True, metavar="MASTER_DIR", help="Interpolate layout tables from compiled master binaries. " "Requires Glyphs or MutatorMath source.", ) layoutGroup.add_argument( "--feature-writer", metavar="CLASS", action="append", dest="feature_writer_specs", help="string specifying a feature writer class to load, either " "built-in or from an external module, optionally initialized with " "the given keyword arguments. The class and module names are " "separated by '::'. The option can be repeated multiple times " "for each writer class. A special value of 'None' will disable " "all automatic feature generation. The option overrides both the " "default ufo2ft writers and those specified in the UFO lib.", ) feaCompilerGroup = layoutGroup.add_mutually_exclusive_group(required=False) feaCompilerGroup.add_argument( "--use-afdko", action="store_true", help="Use makeOTF instead of feaLib to compile FEA.", ) feaCompilerGroup.add_argument( "--mti-source", help="Path to mtiLib .txt feature definitions (use instead of FEA)", ) glyphnamesGroup = parser.add_mutually_exclusive_group(required=False) glyphnamesGroup.add_argument( "--production-names", dest="use_production_names", action="store_true", help="Rename glyphs with production names if available otherwise use " "uninames.", ) glyphnamesGroup.add_argument("--no-production-names", dest="use_production_names", action="store_false") subsetGroup = parser.add_mutually_exclusive_group(required=False) subsetGroup.add_argument( "--subset", dest="subset", action="store_true", help="Subset font using export flags set by glyphsLib", ) subsetGroup.add_argument("--no-subset", dest="subset", action="store_false") subroutinizeGroup = parser.add_mutually_exclusive_group(required=False) subroutinizeGroup.add_argument( "-s", "--subroutinize", action="store_true", help="Optimize CFF table using compreffor (default) [DEPRECATED: use " "--optimize-cff option instead]", ) subroutinizeGroup.add_argument("-S", "--no-subroutinize", dest="subroutinize", action="store_false") parser.set_defaults(use_production_names=None, subset=None, subroutinize=None) logGroup = parser.add_argument_group(title="Logging arguments") logGroup.add_argument("--timing", action="store_true", help="Print the elapsed time for each steps") logGroup.add_argument( "--verbose", default="INFO", metavar="LEVEL", choices=("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"), help="Configure the logger verbosity level. Choose between: " "%(choices)s. Default: INFO", ) args = vars(parser.parse_args(args)) specs = args.pop("feature_writer_specs") if specs is not None: args["feature_writers"] = _loadFeatureWriters(parser, specs) glyphs_path = args.pop("glyphs_path") ufo_paths = args.pop("ufo_paths") designspace_path = args.pop("mm_designspace") input_format = ("Glyphs" if glyphs_path else "designspace" if designspace_path else "UFO") + " source" if INTERPOLATABLE_OUTPUTS.intersection(args["output"]): if not (glyphs_path or designspace_path): parser.error( "Glyphs or designspace source required for variable font") exclude_args( parser, args, [ "interpolate", "masters_as_instances", "interpolate_binary_layout" ], "variable output", ) try: project = FontProject( timing=args.pop("timing"), verbose=args.pop("verbose"), validate_ufo=args.pop("validate_ufo"), ) if glyphs_path: with _make_tempdirs(parser, args): project.run_from_glyphs(glyphs_path, **args) return exclude_args( parser, args, [ "family_name", "mti_source", "designspace_path", "master_dir", "instance_dir", ], input_format, ) if designspace_path: project.run_from_designspace(designspace_path, **args) return exclude_args( parser, args, ["interpolate", "interpolate_binary_layout", "round_instances"], input_format, ) project.run_from_ufos(ufo_paths, is_instance=args.pop("masters_as_instances"), **args) except FontmakeError as e: import sys sys.exit("fontmake: error: %s" % e)
def main(args=None): parser = ArgumentParser() parser.add_argument("--version", action="version", version=__version__) inputGroup = parser.add_argument_group( title="Input arguments (flags)", description= "The following arguments are mutually exclusive (pick only one):", ) xInputGroup = inputGroup.add_mutually_exclusive_group() xInputGroup.add_argument("-g", "--glyphs-path", metavar="GLYPHS", help="Path to .glyphs source file") xInputGroup.add_argument( "-u", "--ufo-paths", nargs="+", metavar="UFO", help="One or more paths to UFO files", ) xInputGroup.add_argument( "-m", "--mm-designspace", metavar="DESIGNSPACE", help="Path to .designspace file", ) positionalInputs = parser.add_argument_group( title="Input arguments (positonal)", description= "Alternatively, guess source format from filename extension", ) positionalInputs.add_argument( "posargs", nargs="*", metavar="INPUTS", help="Either one *.designspace or *.glyphs file, or one or more *.ufo", ) outputGroup = parser.add_argument_group(title="Output arguments") outputGroup.add_argument( "-o", "--output", nargs="+", default=("otf", "ttf"), metavar="FORMAT", help= "Output font formats. Choose 1 or more from: %(choices)s. Default: otf, ttf. " "(No file paths).", choices=( "ufo", "otf", "otf-cff2", "ttf", "ttf-interpolatable", "otf-interpolatable", "variable", "variable-cff2", ), ) outputSubGroup = outputGroup.add_mutually_exclusive_group() outputSubGroup.add_argument( "--output-path", default=None, help="Output font file path. Only valid when the output is a single " "file (e.g. input is a single UFO or output is variable font)", ) outputSubGroup.add_argument( "--output-dir", default=None, help="Output folder. By default, output folders are created in the " "current working directory, grouping output fonts by format.", ) outputGroup.add_argument( "-i", "--interpolate", nargs="?", default=False, const=True, metavar="INSTANCE_NAME", help="Interpolate masters and generate all the instances defined. " "To only interpolate a specific instance (or instances) that " 'match a given "name" attribute, you can pass as argument ' "the full instance name or a regular expression. " 'E.g.: -i "Noto Sans Bold"; or -i ".* UI Condensed". ' "(for Glyphs or MutatorMath sources only). ", ) outputGroup.add_argument( "--use-mutatormath", action="store_true", help=( "Use MutatorMath to generate instances (supports extrapolation and " "anisotropic locations)."), ) outputGroup.add_argument( "-M", "--masters-as-instances", action="store_true", help="Output masters as instances", ) outputGroup.add_argument( "--family-name", help="Family name to use for masters, and to filter output instances", ) outputGroup.add_argument( "--round-instances", dest="round_instances", action="store_true", help="Apply integer rounding to all geometry when interpolating", ) outputGroup.add_argument( "--designspace-path", default=None, help="Path to output designspace file (for Glyphs sources only).", ) outputGroup.add_argument( "--master-dir", default=None, help='Directory where to write master UFO. Default: "./master_ufo". ' 'If value is "{tmp}", a temporary directory is created and ' "removed at the end (for Glyphs sources only).", ) outputGroup.add_argument( "--instance-dir", default=None, help="Directory where to write instance UFOs. Default: " '"./instance_ufo". If value is "{tmp}", a temporary directory ' "is created and removed at the end (for Glyphs sources only).", ) outputGroup.add_argument( "--no-write-skipexportglyphs", action="store_false", dest="write_skipexportglyphs", help= "Do not store the glyph export flags in the 'public.skipExportGlyphs' " "key of designspace/UFO lib, but use the old private glyph lib key " "'com.schriftgestaltung.Glyphs.Export' (for Glyphs sources only).", ) outputGroup.add_argument( "--validate-ufo", action="store_true", help="Enable ufoLib validation on reading/writing UFO files. It is " "disabled by default", ) outputGroup.add_argument( "--check-compatibility", action="store_true", help="Check if the source files are interpolatable. It is " "disabled by default, but enabled when building variable fonts " "or what the 'Enforce Compatibility Check' custom parameter is " "set on a Glyphs file", ) outputGroup.add_argument( "--expand-features-to-instances", action="store_true", help="Resolves all include()s in the master feature file and writes " "the full feature file to all instance UFOs. Only valid when " "interpolating. Use if you share feature files of masters in " "external files, as instances can end up elsewhere.", ) outputGroup.add_argument( "--no-generate-GDEF", dest="generate_GDEF", action="store_false", help= "Do not auto-generate a GDEF table, but keep an existing one intact.", ) contourGroup = parser.add_argument_group(title="Handling of contours") contourGroup.add_argument( "--keep-overlaps", dest="remove_overlaps", action="store_false", help="Do not remove any overlap.", ) contourGroup.add_argument( "--overlaps-backend", dest="overlaps_backend", metavar="BACKEND", choices=("booleanOperations", "pathops"), default="booleanOperations", help="Select library to remove overlaps. Choose between: %(choices)s " "(default: %(default)s)", ) contourGroup.add_argument( "--keep-direction", dest="reverse_direction", action="store_false", help="Do not reverse contour direction when output is ttf or " "ttf-interpolatable", ) contourGroup.add_argument( "-e", "--conversion-error", type=float, default=None, metavar="ERROR", help="Maximum approximation error for cubic to quadratic conversion " "measured in EM", ) contourGroup.add_argument( "-f", "--flatten-components", dest="flatten_components", action="store_true", help="Flatten nested components to single level.", ) contourGroup.add_argument( "-a", "--autohint", nargs="?", const="", help="Run ttfautohint. Can provide arguments, quoted", ) contourGroup.add_argument( "--cff-round-tolerance", type=float, default=None, metavar="FLOAT", help="Restrict rounding of point coordinates in CFF table to only " "those floats whose absolute difference from their integral part " "is less than or equal to the tolerance. By default, all floats " "are rounded to integer (tolerance 0.5); 0 disables rounding.", ) contourGroup.add_argument( "--optimize-cff", type=lambda s: CFFOptimization(int(s)), default=CFFOptimization.SUBROUTINIZE, help="0 disables all optimizations; 1 specializes the CFF charstring " "operators; 2 (default) also enables subroutinization", ) contourGroup.add_argument( "--subroutinizer", default=None, choices=["compreffor", "cffsubr"], help="name of the library to use for compressing CFF charstrings. " "Choose between: %(choices)s. By default compreffor is used for CFF 1, " "and cffsubr for CFF2. NOTE: compreffor doesn't support CFF2.", ) contourGroup.add_argument( "--no-optimize-gvar", dest="optimize_gvar", action="store_false", help="Do not perform IUP optimization on variable font's 'gvar' table. " "(only works with 'variable' TrueType-flavored output)", ) contourGroup.add_argument( "--filter", metavar="CLASS", action="append", dest="filter_specs", help="string specifying a filter class to load, either " "built-in or from an external module, optionally initialized with " "the given keyword arguments. The class and module names are " "separated by '::'. The option can be repeated multiple times " "for each filter class. The option overrides the filters specified " "in the UFO lib.", ) layoutGroup = parser.add_argument_group( title="Handling of OpenType Layout") layoutGroup.add_argument( "--interpolate-binary-layout", nargs="?", default=False, const=True, metavar="MASTER_DIR", help="Interpolate layout tables from compiled master binaries. " "Requires Glyphs or MutatorMath source.", ) layoutGroup.add_argument( "--feature-writer", metavar="CLASS", action="append", dest="feature_writer_specs", help="string specifying a feature writer class to load, either " "built-in or from an external module, optionally initialized with " "the given keyword arguments. The class and module names are " "separated by '::'. The option can be repeated multiple times " "for each writer class. A special value of 'None' will disable " "all automatic feature generation. The option overrides both the " "default ufo2ft writers and those specified in the UFO lib.", ) layoutGroup.add_argument( "--debug-feature-file", metavar="FILE", type=FileType("w", encoding="utf-8"), default=None, help=( "Path were to dump OpenType features text to debug auto-generated " "features (kern, mark, mkmk, etc.)."), ) feaCompilerGroup = layoutGroup.add_mutually_exclusive_group(required=False) feaCompilerGroup.add_argument( "--mti-source", help="mtiLib feature definition .plist file path (use instead of FEA)", ) glyphnamesGroup = parser.add_mutually_exclusive_group(required=False) glyphnamesGroup.add_argument( "--production-names", dest="use_production_names", action="store_true", help="Rename glyphs with production names if available otherwise use " "uninames.", ) glyphnamesGroup.add_argument("--no-production-names", dest="use_production_names", action="store_false") subsetGroup = parser.add_mutually_exclusive_group(required=False) subsetGroup.add_argument( "--subset", dest="subset", action="store_true", help="Subset font using export flags set by glyphsLib", ) subsetGroup.add_argument("--no-subset", dest="subset", action="store_false") subroutinizeGroup = parser.add_mutually_exclusive_group(required=False) subroutinizeGroup.add_argument( "-s", "--subroutinize", action="store_true", help="Optimize CFF table using compreffor (default) [DEPRECATED: use " "--optimize-cff option instead]", ) subroutinizeGroup.add_argument("-S", "--no-subroutinize", dest="subroutinize", action="store_false") parser.set_defaults(use_production_names=None, subset=None, subroutinize=None) logGroup = parser.add_argument_group(title="Logging arguments") logGroup.add_argument("--timing", action="store_true", help="Print the elapsed time for each steps") logGroup.add_argument( "--verbose", default="INFO", metavar="LEVEL", choices=("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"), help="Configure the logger verbosity level. Choose between: " "%(choices)s. Default: INFO", ) args = vars(parser.parse_args(args)) specs = args.pop("feature_writer_specs") if specs is not None: args["feature_writers"] = _loadFeatureWriters(parser, specs) specs = args.pop("filter_specs") if specs is not None: args["filters"] = _loadFilters(parser, specs) inputs = parse_mutually_exclusive_inputs(parser, args) if INTERPOLATABLE_OUTPUTS.intersection(args["output"]): if not (inputs.glyphs_path or inputs.designspace_path): parser.error( "Glyphs or designspace source required for variable font") exclude_args( parser, args, [ "interpolate", "masters_as_instances", "interpolate_binary_layout", "use_mutatormath", ], "variable output", ) else: exclude_args(parser, args, ["optimize_gvar"], "static output", positive=False) if args.get("use_mutatormath"): for module in ("defcon", "mutatorMath"): try: __import__(module) except ImportError: parser.error( f"{module} module not found; reinstall fontmake with the " "[mutatormath] extra") PRINT_TRACEBACK = args.get("verbose", "INFO") == "DEBUG" try: project = FontProject( timing=args.pop("timing"), verbose=args.pop("verbose"), validate_ufo=args.pop("validate_ufo"), ) if inputs.glyphs_path: with _make_tempdirs(parser, args): project.run_from_glyphs(inputs.glyphs_path, **args) return exclude_args( parser, args, [ "family_name", "mti_source", "designspace_path", "master_dir", "instance_dir", ], inputs.format_name, ) exclude_args(parser, args, ["write_skipexportglyphs"], inputs.format_name, positive=False) if inputs.designspace_path: project.run_from_designspace(inputs.designspace_path, **args) return exclude_args( parser, args, [ "interpolate", "use_mutatormath", "interpolate_binary_layout", "round_instances", "expand_features_to_instances", "check_compatibility", ], inputs.format_name, ) project.run_from_ufos(inputs.ufo_paths, is_instance=args.pop("masters_as_instances"), **args) except FontmakeError as e: if PRINT_TRACEBACK: logging.exception(e) sys.exit(1) sys.exit(f"fontmake: Error: {str(e)}") finally: debug_feature_file = args.get("debug_feature_file") if debug_feature_file is not None: debug_feature_file.close()
def main(args=None): parser = ArgumentParser() parser.add_argument('--version', action='version', version=__version__) inputGroup = parser.add_argument_group( title='Input arguments', description='The following arguments are mutually exclusive.') xInputGroup = inputGroup.add_mutually_exclusive_group(required=True) xInputGroup.add_argument( '-g', '--glyphs-path', metavar='GLYPHS', help='Path to .glyphs source file') xInputGroup.add_argument( '-u', '--ufo-paths', nargs='+', metavar='UFO', help='One or more paths to UFO files') xInputGroup.add_argument( '-m', '--mm-designspace', metavar='DESIGNSPACE', help='Path to .designspace file') outputGroup = parser.add_argument_group(title='Output arguments') outputGroup.add_argument( '-o', '--output', nargs='+', default=('otf', 'ttf'), metavar="FORMAT", help='Output font formats. Choose between: %(choices)s. ' 'Default: otf, ttf', choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable', 'variable')) outputGroup.add_argument( '-i', '--interpolate', action='store_true', help='Interpolate masters (for Glyphs or MutatorMath sources only)') outputGroup.add_argument( '-M', '--masters-as-instances', action='store_true', help='Output masters as instances') outputGroup.add_argument( '--family-name', help='Family name to use for masters, and to filter output instances') contourGroup = parser.add_argument_group(title='Handling of contours') contourGroup.add_argument( '--keep-overlaps', dest='remove_overlaps', action='store_false', help='Do not remove any overlap.') contourGroup.add_argument( '--keep-direction', dest='reverse_direction', action='store_false', help='Do not reverse contour direction when output is ttf or ' 'ttf-interpolatable') contourGroup.add_argument( '-e', '--conversion-error', type=float, default=None, metavar='ERROR', help='Maximum approximation error for cubic to quadratic conversion ' 'measured in EM') contourGroup.add_argument( '-a', '--autohint', nargs='?', const='', help='Run ttfautohint. Can provide arguments, quoted') layoutGroup = parser.add_argument_group(title='Handling of OpenType Layout') layoutGroup.add_argument( '--interpolate-binary-layout', action='store_true', help='Interpolate layout tables from compiled master binaries. ' 'Requires Glyphs or MutatorMath source.') layoutGroup.add_argument( '--use-afdko', action='store_true', help='Use makeOTF instead of feaLib to compile FEA.') layoutGroup.add_argument( '--mti-source', help='Path to mtiLib .txt feature definitions (use instead of FEA)') layoutGroup.add_argument( '--kern-writer-module', metavar="MODULE", dest='kern_writer_class', type=PyClassType('KernFeatureWriter'), help='Module containing a custom `KernFeatureWriter` class.') layoutGroup.add_argument( '--mark-writer-module', metavar="MODULE", dest='mark_writer_class', type=PyClassType('MarkFeatureWriter'), help='Module containing a custom `MarkFeatureWriter` class.') glyphnamesGroup = parser.add_mutually_exclusive_group(required=False) glyphnamesGroup.add_argument( '--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with production names if available otherwise use ' 'uninames.') glyphnamesGroup.add_argument( '--no-production-names', dest='use_production_names', action='store_false') subsetGroup = parser.add_mutually_exclusive_group(required=False) subsetGroup.add_argument( '--subset', dest='subset', action='store_true', help='Subset font using export flags set by glyphsLib') subsetGroup.add_argument( '--no-subset', dest='subset', action='store_false') subroutinizeGroup = parser.add_mutually_exclusive_group(required=False) subroutinizeGroup.add_argument( '-s', '--subroutinize', action='store_true', help='Optimize CFF table using compreffor (default)') subroutinizeGroup.add_argument( '-S', '--no-subroutinize', dest='subroutinize', action='store_false') parser.set_defaults(use_production_names=None, subset=None, subroutinize=True) logGroup = parser.add_argument_group(title='Logging arguments') logGroup.add_argument( '--timing', action='store_true', help="Print the elapsed time for each steps") logGroup.add_argument( '--verbose', default='INFO', metavar='LEVEL', choices=('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'), help='Configure the logger verbosity level. Choose between: ' '%(choices)s. Default: INFO') args = vars(parser.parse_args(args)) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if 'variable' in args['output']: if not (glyphs_path or designspace_path): parser.error( 'Glyphs or designspace source required for variable font') for argname in ('interpolate', 'masters_as_instances', 'interpolate_binary_layout'): if args[argname]: parser.error('--%s option invalid for variable font' % argname.replace("_", "-")) project = FontProject(timing=args.pop('timing'), verbose=args.pop('verbose')) if glyphs_path: project.run_from_glyphs(glyphs_path, **args) return exclude_args(parser, args, ['family_name'], 'Glyphs') if designspace_path: project.run_from_designspace(designspace_path, **args) return exclude_args( parser, args, ['interpolate', 'interpolate_binary_layout'], 'Glyphs or MutatorMath') project.run_from_ufos( ufo_paths, is_instance=args.pop('masters_as_instances'), **args)
def main(): parser = ArgumentParser() parser.add_argument('-g', '--glyphs-path') parser.add_argument('-u', '--ufo-paths', nargs='+') parser.add_argument('-m', '--mm-designspace') parser.add_argument('-o', '--output', nargs='+', default=('otf', 'ttf'), choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable')) parser.add_argument('-i', '--interpolate', action='store_true', help='interpolate masters (for Glyphs or MutatorMath ' 'sources only)') parser.add_argument('-mi', '--masters-as-instances', action='store_true', help='treat masters as instances') parser.add_argument('-a', '--autohint', nargs='?', help='can provide arguments to ttfautohint, quoted') parser.add_argument('--mti-source') parser.add_argument('--family-name', help='Family name to use for masters,' ' and to filter output instances by') parser.add_argument('--use-afdko', action='store_true') parser.add_argument('--keep-direction', dest="reverse_direction", action='store_false', help='Do not reverse contour ' 'direction when output is ttf or ttf-interpolatable') parser.add_argument('--keep-overlaps', dest="remove_overlaps", action='store_false', help='Do not remove any overlap.') group = parser.add_mutually_exclusive_group(required=False) group.add_argument('--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with ' 'production names if available otherwise use uninames.') group.add_argument('--no-production-names', dest='use_production_names', action='store_false', help='Do not rename glyphs with production names. ' 'Keeps original glyph names') parser.set_defaults(use_production_names=None) parser.add_argument('--timing', action='store_true') args = vars(parser.parse_args()) project = FontProject(timing=args.pop('timing')) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if not sum(1 for p in [glyphs_path, ufo_paths, designspace_path] if p) == 1: parser.error('Exactly one source type required (Glyphs, UFO, or ' 'MutatorMath).') def exclude_args(parser, args, excluded_args): exclusive_msg = '"{}" argument only available for {} source' exclusive_src = { 'interpolate': 'Glyphs or MutatorMath', 'family_name': 'Glyphs' } for excluded in excluded_args: if args[excluded]: parser.error( exclusive_msg.format(excluded, exclusive_src[excluded])) del args[excluded] if glyphs_path: project.run_from_glyphs(glyphs_path, **args) elif designspace_path: exclude_args(parser, args, ['family_name']) project.run_from_designspace(designspace_path, **args) else: exclude_args(parser, args, ['family_name', 'interpolate']) if ufo_paths: project.run_from_ufos(ufo_paths, is_instance=args.pop('masters_as_instances'), **args)
def designSpace2Instances(family, *output, newName=" ", secureSet=True): if len(output) == 1 and "otf" in output: makeOtfFamily(family, newName=newName, onlyOtf=True) return securetSetIsIncluded = pan_european_fonts if "otf" in output: makeOtfFamily(family, newName=newName) mergeable = ["ttf", "woff2", "woff"] if family not in securetSetIsIncluded: temp = list(set(mergeable) & set(output)) if len(temp) == 0: output = ["ttf"] else: output = temp if "ttf" not in output: output.append("ttf") path, folder = getFile(".designspace", family) designSpace = openDesignSpace(path) destination = folder + "/" + "Instances" ### ### test if mti for file in os.listdir(folder): if file.endswith(".plist"): print("Make fonts with Mti files") # INJECT COMPILED TABLE IN FONTS ufoWithMTIfeatures2font(family, output) if secureSet is True: for i in output: addSecureSet(family, output) if newName != " ": renameFonts(family, newName) if "woff" in output: destination = os.path.join(folder, "fonts/WOFF") if not os.path.exists(destination): os.makedirs(destination) for ttf in os.listdir(os.path.join(folder, "fonts/TTF")): if ttf.endswith("ttf"): woff = ttLib.TTFont( os.path.join(folder, "fonts/TTF", ttf)) woff.flavor = "woff" woff.save(os.path.join(destination, ttf[:-4] + ".woff")) if "woff2" in output: destination = os.path.join(folder, "fonts/WOFF2") if not os.path.exists(destination): os.makedirs(destination) for ttf in os.listdir(os.path.join(folder, "fonts/TTF")): if ttf.endswith("ttf"): woff = ttLib.TTFont( os.path.join(folder, "fonts/TTF", ttf)) woff.flavor = "woff2" woff.save( os.path.join(destination, ttf[:-4] + ".woff2")) return fp = FontProject() fonts = fp.run_from_designspace(expand_features_to_instances=True, use_mutatormath=False, designspace_path=path, interpolate=True, output=("otf"), output_dir=destination) ufolist = list() for ufo in os.listdir(os.path.join(folder, "instance_ufos")): if ufo[-4:] == ".ufo": ufolist.append(ufo) instancesFolder = family + "/instance_ufos" if "ttf" in output: ufo2font(instancesFolder, ufolist, "ttf", fromInstances=True) if secureSet: addSecureSet(family, output) if "woff" in output: destination = os.path.join(folder, "fonts/WOFF") if not os.path.exists(destination): os.makedirs(destination) for ttf in os.listdir(os.path.join(folder, "fonts/TTF")): if ttf.endswith("ttf"): woff = ttLib.TTFont(os.path.join(folder, "fonts/TTF", ttf)) woff.flavor = "woff" woff.save(os.path.join(destination, ttf[:-4] + ".woff")) if "woff2" in output: destination = os.path.join(folder, "fonts/WOFF2") if not os.path.exists(destination): os.makedirs(destination) for ttf in os.listdir(os.path.join(folder, "fonts/TTF")): if ttf.endswith("ttf"): woff = ttLib.TTFont(os.path.join(folder, "fonts/TTF", ttf)) woff.flavor = "woff2" woff.save(os.path.join(destination, ttf[:-4] + ".woff2")) if newName != " ": renameFonts(family, newName)
def main(): parser = ArgumentParser() parser.add_argument('-g', '--glyphs-path') parser.add_argument('-u', '--ufo-paths', nargs='+') parser.add_argument('-m', '--mm-designspace') parser.add_argument('-o', '--output', nargs='+', default=('otf', 'ttf'), choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable', 'variable')) parser.add_argument( '-i', '--interpolate', action='store_true', help='Interpolate masters (for Glyphs or MutatorMath sources only)') parser.add_argument('-M', '--masters-as-instances', action='store_true', help='Output masters as instances') parser.add_argument( '--family-name', help='Family name to use for masters, and to filter output instances') parser.add_argument('--mti-source') parser.add_argument( '--interpolate-binary-layout', action='store_true', help='Interpolate layout tables from compiled master binaries. ' 'Requires Glyphs or MutatorMath source.') parser.add_argument('--use-afdko', action='store_true') parser.add_argument('-a', '--autohint', nargs='?', const='', help='Run ttfautohint. Can provide arguments, quoted') parser.add_argument( '--keep-direction', dest='reverse_direction', action='store_false', help='Do not reverse contour direction when output is ttf or ' 'ttf-interpolatable') parser.add_argument('--keep-overlaps', dest='remove_overlaps', action='store_false', help='Do not remove any overlap.') group1 = parser.add_mutually_exclusive_group(required=False) group1.add_argument( '--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with production names if available otherwise use ' 'uninames.') group1.add_argument('--no-production-names', dest='use_production_names', action='store_false') group2 = parser.add_mutually_exclusive_group(required=False) group2.add_argument('--subset', dest='subset', action='store_true', help='Subset font using export flags set by glyphsLib') group2.add_argument('--no-subset', dest='subset', action='store_false') group3 = parser.add_mutually_exclusive_group(required=False) group3.add_argument('-s', '--subroutinize', action='store_true', help='Optimize CFF table using compreffor (default)') group3.add_argument('-S', '--no-subroutinize', dest='subroutinize', action='store_false') parser.add_argument( '-e', '--conversion-error', type=float, default=None, metavar='ERROR', help='Maximum approximation error for cubic to quadratic conversion ' 'measured in EM') parser.set_defaults(use_production_names=None, subset=None, subroutinize=True) parser.add_argument('--timing', action='store_true') parser.add_argument('--verbose', default='INFO') args = vars(parser.parse_args()) project = FontProject(timing=args.pop('timing'), verbose=args.pop('verbose')) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if sum(1 for p in [glyphs_path, ufo_paths, designspace_path] if p) != 1: parser.error('Exactly one source type required (Glyphs, UFO, or ' 'MutatorMath).') def exclude_args(parser, args, excluded_args, source_name): msg = '"%s" argument only available for %s source' for excluded in excluded_args: if args[excluded]: parser.error(msg % (excluded, source_name)) del args[excluded] if glyphs_path: project.run_from_glyphs(glyphs_path, **args) return exclude_args(parser, args, ['family_name'], 'Glyphs') if designspace_path: project.run_from_designspace(designspace_path, **args) return exclude_args(parser, args, ['interpolate', 'interpolate_binary_layout'], 'Glyphs or MutatorMath') project.run_from_ufos(ufo_paths, is_instance=args.pop('masters_as_instances'), **args)
def main(): parser = ArgumentParser() parser.add_argument('-g', '--glyphs-path') parser.add_argument('-u', '--ufo-paths', nargs='+') parser.add_argument('-m', '--mm-designspace') parser.add_argument('-o', '--output', nargs='+', default=('otf', 'ttf'), choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable')) parser.add_argument('-i', '--interpolate', action='store_true', help='interpolate masters (for Glyphs or MutatorMath ' 'sources only)') parser.add_argument('-mi', '--masters-as-instances', action='store_true', help='treat masters as instances') parser.add_argument('-a', '--autohint', nargs='?', help='can provide arguments to ttfautohint, quoted') parser.add_argument('--mti-source') parser.add_argument('--family-name', help='Family name to use for masters,' ' and to filter output instances by') parser.add_argument('--use-afdko', action='store_true') parser.add_argument('--keep-direction', dest="reverse_direction", action='store_false', help='Do not reverse contour ' 'direction when output is ttf or ttf-interpolatable') parser.add_argument('--keep-overlaps', dest="remove_overlaps", action='store_false', help='Do not remove any overlap.') group = parser.add_mutually_exclusive_group(required=False) group.add_argument('--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with ' 'production names if available otherwise use uninames.') group.add_argument('--no-production-names', dest='use_production_names', action='store_false', help='Do not rename glyphs with production names. ' 'Keeps original glyph names') parser.set_defaults(use_production_names=None) parser.add_argument('--timing', action='store_true') args = vars(parser.parse_args()) project = FontProject(timing=args.pop('timing')) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if not sum(1 for p in [glyphs_path, ufo_paths, designspace_path] if p) == 1: parser.error('Exactly one source type required (Glyphs, UFO, or ' 'MutatorMath).') def exclude_args(parser, args, excluded_args): exclusive_msg = '"{}" argument only available for {} source' exclusive_src = {'interpolate': 'Glyphs or MutatorMath', 'family_name': 'Glyphs'} for excluded in excluded_args: if args[excluded]: parser.error(exclusive_msg.format( excluded, exclusive_src[excluded])) del args[excluded] if glyphs_path: project.run_from_glyphs(glyphs_path, **args) elif designspace_path: exclude_args(parser, args, ['family_name']) project.run_from_designspace(designspace_path, **args) else: exclude_args(parser, args, ['family_name', 'interpolate']) if ufo_paths: project.run_from_ufos( ufo_paths, is_instance=args.pop('masters_as_instances'), **args)
def main(args=None): parser = ArgumentParser() parser.add_argument('--version', action='version', version=__version__) inputGroup = parser.add_argument_group( title='Input arguments', description='The following arguments are mutually exclusive.') xInputGroup = inputGroup.add_mutually_exclusive_group(required=True) xInputGroup.add_argument('-g', '--glyphs-path', metavar='GLYPHS', help='Path to .glyphs source file') xInputGroup.add_argument('-u', '--ufo-paths', nargs='+', metavar='UFO', help='One or more paths to UFO files') xInputGroup.add_argument('-m', '--mm-designspace', metavar='DESIGNSPACE', help='Path to .designspace file') outputGroup = parser.add_argument_group(title='Output arguments') outputGroup.add_argument( '-o', '--output', nargs='+', default=('otf', 'ttf'), metavar="FORMAT", help='Output font formats. Choose between: %(choices)s. ' 'Default: otf, ttf', choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable', 'variable')) outputSubGroup = outputGroup.add_mutually_exclusive_group() outputSubGroup.add_argument( '--output-path', default=None, help="Output font file path. Only valid when the output is a single " "file (e.g. input is a single UFO or output is variable font)") outputSubGroup.add_argument( '--output-dir', default=None, help="Output folder. By default, output folders are created in the " "current working directory, grouping output fonts by format.") outputGroup.add_argument( '-i', '--interpolate', nargs="?", default=False, const=True, metavar="INSTANCE_NAME", help='Interpolate masters and generate all the instances defined. ' 'To only interpolate a specific instance (or instances) that ' 'match a given "name" attribute, you can pass as argument ' 'the full instance name or a regular expression. ' 'E.g.: -i "Noto Sans Bold"; or -i ".* UI Condensed". ' '(for Glyphs or MutatorMath sources only). ') outputGroup.add_argument('-M', '--masters-as-instances', action='store_true', help='Output masters as instances') outputGroup.add_argument( '--family-name', help='Family name to use for masters, and to filter output instances') outputGroup.add_argument( '--round-instances', dest='round_instances', action='store_true', help='Apply integer rounding to all geometry when interpolating') outputGroup.add_argument( '--designspace-path', default=None, help='Path to output designspace file (for Glyphs sources only).') outputGroup.add_argument( '--master-dir', default=None, help='Directory where to write master UFO. Default: "./master_ufo". ' 'If value is "{tmp}", a temporary directory is created and ' 'removed at the end (for Glyphs sources only).') outputGroup.add_argument( '--instance-dir', default=None, help='Directory where to write instance UFOs. Default: ' '"./instance_ufo". If value is "{tmp}", a temporary directory ' 'is created and removed at the end (for Glyphs sources only).') contourGroup = parser.add_argument_group(title='Handling of contours') contourGroup.add_argument('--keep-overlaps', dest='remove_overlaps', action='store_false', help='Do not remove any overlap.') contourGroup.add_argument( '--keep-direction', dest='reverse_direction', action='store_false', help='Do not reverse contour direction when output is ttf or ' 'ttf-interpolatable') contourGroup.add_argument( '-e', '--conversion-error', type=float, default=None, metavar='ERROR', help='Maximum approximation error for cubic to quadratic conversion ' 'measured in EM') contourGroup.add_argument( '-a', '--autohint', nargs='?', const='', help='Run ttfautohint. Can provide arguments, quoted') contourGroup.add_argument( '--cff-round-tolerance', type=float, default=None, metavar='FLOAT', help='Restrict rounding of point coordinates in CFF table to only ' 'those floats whose absolute difference from their integral part ' 'is less than or equal to the tolerance. By default, all floats ' 'are rounded to integer (tolerance 0.5); 0 disables rounding.') layoutGroup = parser.add_argument_group( title='Handling of OpenType Layout') layoutGroup.add_argument( '--interpolate-binary-layout', nargs="?", default=False, const=True, metavar="MASTER_DIR", help='Interpolate layout tables from compiled master binaries. ' 'Requires Glyphs or MutatorMath source.') layoutGroup.add_argument( "--feature-writer", metavar="CLASS", action="append", dest="feature_writer_specs", help="string specifying a feature writer class to load, either " "built-in or from an external module, optionally initialized with " "the given keyword arguments. The class and module names are " "separated by '::'. The option can be repeated multiple times " "for each writer class. A special value of 'None' will disable " "all automatic feature generation. The option overrides both the " "default ufo2ft writers and those specified in the UFO lib.") feaCompilerGroup = layoutGroup.add_mutually_exclusive_group(required=False) feaCompilerGroup.add_argument( '--use-afdko', action='store_true', help='Use makeOTF instead of feaLib to compile FEA.') feaCompilerGroup.add_argument( '--mti-source', help='Path to mtiLib .txt feature definitions (use instead of FEA)') glyphnamesGroup = parser.add_mutually_exclusive_group(required=False) glyphnamesGroup.add_argument( '--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with production names if available otherwise use ' 'uninames.') glyphnamesGroup.add_argument('--no-production-names', dest='use_production_names', action='store_false') subsetGroup = parser.add_mutually_exclusive_group(required=False) subsetGroup.add_argument( '--subset', dest='subset', action='store_true', help='Subset font using export flags set by glyphsLib') subsetGroup.add_argument('--no-subset', dest='subset', action='store_false') subroutinizeGroup = parser.add_mutually_exclusive_group(required=False) subroutinizeGroup.add_argument( '-s', '--subroutinize', action='store_true', help='Optimize CFF table using compreffor (default)') subroutinizeGroup.add_argument('-S', '--no-subroutinize', dest='subroutinize', action='store_false') parser.set_defaults(use_production_names=None, subset=None, subroutinize=True) logGroup = parser.add_argument_group(title='Logging arguments') logGroup.add_argument('--timing', action='store_true', help="Print the elapsed time for each steps") logGroup.add_argument( '--verbose', default='INFO', metavar='LEVEL', choices=('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'), help='Configure the logger verbosity level. Choose between: ' '%(choices)s. Default: INFO') args = vars(parser.parse_args(args)) specs = args.pop("feature_writer_specs") if specs is not None: args["feature_writers"] = _loadFeatureWriters(parser, specs) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') input_format = ("Glyphs" if glyphs_path else "designspace" if designspace_path else "UFO") + " source" if 'variable' in args['output']: if not (glyphs_path or designspace_path): parser.error( 'Glyphs or designspace source required for variable font') exclude_args(parser, args, [ 'interpolate', 'masters_as_instances', 'interpolate_binary_layout' ], "variable output") try: project = FontProject(timing=args.pop('timing'), verbose=args.pop('verbose')) if glyphs_path: with _make_tempdirs(parser, args): project.run_from_glyphs(glyphs_path, **args) return exclude_args(parser, args, [ 'family_name', 'mti_source', 'designspace_path', 'master_dir', 'instance_dir' ], input_format) if designspace_path: project.run_from_designspace(designspace_path, **args) return exclude_args( parser, args, ['interpolate', 'interpolate_binary_layout', 'round_instances'], input_format) project.run_from_ufos(ufo_paths, is_instance=args.pop('masters_as_instances'), **args) except FontmakeError as e: import sys sys.exit("fontmake: error: %s" % e)
def getRunArguments(): u"""Arguments to be passed to a fontmake project run. The values below make Decovar build without errors. See also fontmake.__main__.py.""" args = { 'subset': None, 'use_production_names': False, #'mark_writer_class': None, 'reverse_direction': False, #'kern_writer_class': None, 'interpolate_binary_layout': False, 'remove_overlaps': True, 'autohint': None, 'conversion_error': None, #'no_round': False, 'masters_as_instances': True, 'interpolate': True, 'use_afdko': False, 'subroutinize': True, 'output':['ttf'], } return args project = FontProject() args = getRunArguments() print(project.run_from_designspace(designspace_path=DS_PATH, **args)) # fontPath = 'otf/' + DS_PATH.replace('.designspace', '.otf') # os.system('open %s' % fontPath)
def main(): parser = ArgumentParser() parser.add_argument('-g', '--glyphs-path') parser.add_argument('-u', '--ufo-paths', nargs='+') parser.add_argument('-m', '--mm-designspace') parser.add_argument( '-o', '--output', nargs='+', default=('otf', 'ttf'), choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable', 'variable')) parser.add_argument('-i', '--interpolate', action='store_true', help='interpolate masters (for Glyphs or MutatorMath ' 'sources only)') parser.add_argument('-M', '--masters-as-instances', action='store_true', help='treat masters as instances') parser.add_argument('-a', '--autohint', nargs='?', const="", help='can provide arguments to ttfautohint, quoted') parser.add_argument('--mti-source') parser.add_argument('--family-name', help='Family name to use for masters,' ' and to filter output instances by') parser.add_argument('--use-afdko', action='store_true') parser.add_argument('--keep-direction', dest="reverse_direction", action='store_false', help='Do not reverse contour ' 'direction when output is ttf or ttf-interpolatable') parser.add_argument('--keep-overlaps', dest="remove_overlaps", action='store_false', help='Do not remove any overlap.') group1 = parser.add_mutually_exclusive_group(required=False) group1.add_argument('--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with ' 'production names if available otherwise use uninames.') group1.add_argument('--no-production-names', dest='use_production_names', action='store_false') group2 = parser.add_mutually_exclusive_group(required=False) group2.add_argument('--subset', dest='subset', action='store_true', help='Subset font using export ' 'flags set by glyphsLib') group2.add_argument('--no-subset', dest='subset', action='store_false') group3 = parser.add_mutually_exclusive_group(required=False) group3.add_argument('-s', '--subroutinize', action='store_true', help='Optimize CFF table using compreffor (default)') group3.add_argument('-S', '--no-subroutinize', dest='subroutinize', action='store_false') parser.add_argument('-e', '--conversion-error', type=float, default=None, metavar='ERROR', help="Maximum approximation error for" " cubic to quadratic conversion measured in EM") parser.set_defaults(use_production_names=None, subset=None, subroutinize=True) parser.add_argument('--timing', action='store_true') args = vars(parser.parse_args()) project = FontProject(timing=args.pop('timing')) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if not sum(1 for p in [glyphs_path, ufo_paths, designspace_path] if p) == 1: parser.error('Exactly one source type required (Glyphs, UFO, or ' 'MutatorMath).') def exclude_args(parser, args, excluded_args): exclusive_msg = '"{}" argument only available for {} source' exclusive_src = {'interpolate': 'Glyphs or MutatorMath', 'family_name': 'Glyphs'} for excluded in excluded_args: if args[excluded]: parser.error(exclusive_msg.format( excluded, exclusive_src[excluded])) del args[excluded] if glyphs_path: project.run_from_glyphs(glyphs_path, **args) elif designspace_path: exclude_args(parser, args, ['family_name']) project.run_from_designspace(designspace_path, **args) else: exclude_args(parser, args, ['family_name', 'interpolate']) if ufo_paths: project.run_from_ufos( ufo_paths, is_instance=args.pop('masters_as_instances'), **args)
def main(args=None): parser = ArgumentParser() parser.add_argument('--version', action='version', version=__version__) inputGroup = parser.add_argument_group( title='Input arguments', description='The following arguments are mutually exclusive.') xInputGroup = inputGroup.add_mutually_exclusive_group(required=True) xInputGroup.add_argument( '-g', '--glyphs-path', metavar='GLYPHS', help='Path to .glyphs source file') xInputGroup.add_argument( '-u', '--ufo-paths', nargs='+', metavar='UFO', help='One or more paths to UFO files') xInputGroup.add_argument( '-m', '--mm-designspace', metavar='DESIGNSPACE', help='Path to .designspace file') outputGroup = parser.add_argument_group(title='Output arguments') outputGroup.add_argument( '-o', '--output', nargs='+', default=('otf', 'ttf'), metavar="FORMAT", help='Output font formats. Choose between: %(choices)s. ' 'Default: otf, ttf', choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable', 'variable')) outputGroup.add_argument( '-i', '--interpolate', action='store_true', help='Interpolate masters (for Glyphs or MutatorMath sources only)') outputGroup.add_argument( '-M', '--masters-as-instances', action='store_true', help='Output masters as instances') outputGroup.add_argument( '--family-name', help='Family name to use for masters, and to filter output instances') contourGroup = parser.add_argument_group(title='Handling of contours') contourGroup.add_argument( '--keep-overlaps', dest='remove_overlaps', action='store_false', help='Do not remove any overlap.') contourGroup.add_argument( '--keep-direction', dest='reverse_direction', action='store_false', help='Do not reverse contour direction when output is ttf or ' 'ttf-interpolatable') contourGroup.add_argument( '-e', '--conversion-error', type=float, default=None, metavar='ERROR', help='Maximum approximation error for cubic to quadratic conversion ' 'measured in EM') contourGroup.add_argument( '-a', '--autohint', nargs='?', const='', help='Run ttfautohint. Can provide arguments, quoted') layoutGroup = parser.add_argument_group(title='Handling of OpenType Layout') layoutGroup.add_argument( '--interpolate-binary-layout', action='store_true', help='Interpolate layout tables from compiled master binaries. ' 'Requires Glyphs or MutatorMath source.') layoutGroup.add_argument( '--kern-writer-module', metavar="MODULE", dest='kern_writer_class', type=PyClassType('KernFeatureWriter'), help='Module containing a custom `KernFeatureWriter` class.') layoutGroup.add_argument( '--mark-writer-module', metavar="MODULE", dest='mark_writer_class', type=PyClassType('MarkFeatureWriter'), help='Module containing a custom `MarkFeatureWriter` class.') feaCompilerGroup = layoutGroup.add_mutually_exclusive_group(required=False) feaCompilerGroup.add_argument( '--use-afdko', action='store_true', help='Use makeOTF instead of feaLib to compile FEA.') feaCompilerGroup.add_argument( '--mti-source', help='Path to mtiLib .txt feature definitions (use instead of FEA)') glyphnamesGroup = parser.add_mutually_exclusive_group(required=False) glyphnamesGroup.add_argument( '--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with production names if available otherwise use ' 'uninames.') glyphnamesGroup.add_argument( '--no-production-names', dest='use_production_names', action='store_false') subsetGroup = parser.add_mutually_exclusive_group(required=False) subsetGroup.add_argument( '--subset', dest='subset', action='store_true', help='Subset font using export flags set by glyphsLib') subsetGroup.add_argument( '--no-subset', dest='subset', action='store_false') subroutinizeGroup = parser.add_mutually_exclusive_group(required=False) subroutinizeGroup.add_argument( '-s', '--subroutinize', action='store_true', help='Optimize CFF table using compreffor (default)') subroutinizeGroup.add_argument( '-S', '--no-subroutinize', dest='subroutinize', action='store_false') parser.set_defaults(use_production_names=None, subset=None, subroutinize=True) logGroup = parser.add_argument_group(title='Logging arguments') logGroup.add_argument( '--timing', action='store_true', help="Print the elapsed time for each steps") logGroup.add_argument( '--verbose', default='INFO', metavar='LEVEL', choices=('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'), help='Configure the logger verbosity level. Choose between: ' '%(choices)s. Default: INFO') args = vars(parser.parse_args(args)) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if 'variable' in args['output']: if not (glyphs_path or designspace_path): parser.error( 'Glyphs or designspace source required for variable font') for argname in ('interpolate', 'masters_as_instances', 'interpolate_binary_layout'): if args[argname]: parser.error('--%s option invalid for variable font' % argname.replace("_", "-")) project = FontProject(timing=args.pop('timing'), verbose=args.pop('verbose')) if glyphs_path: project.run_from_glyphs(glyphs_path, **args) return exclude_args(parser, args, ['family_name', 'mti_source'], 'Glyphs') if designspace_path: project.run_from_designspace(designspace_path, **args) return exclude_args( parser, args, ['interpolate', 'interpolate_binary_layout'], 'Glyphs or MutatorMath') project.run_from_ufos( ufo_paths, is_instance=args.pop('masters_as_instances'), **args)
def main(): parser = ArgumentParser() parser.add_argument('-g', '--glyphs-path') parser.add_argument('-u', '--ufo-paths', nargs='+') parser.add_argument('-m', '--mm-designspace') parser.add_argument( '-o', '--output', nargs='+', default=('otf', 'ttf'), choices=('ufo', 'otf', 'ttf', 'ttf-interpolatable', 'variable')) parser.add_argument( '-i', '--interpolate', action='store_true', help='Interpolate masters (for Glyphs or MutatorMath sources only)') parser.add_argument( '-M', '--masters-as-instances', action='store_true', help='Output masters as instances') parser.add_argument( '--family-name', help='Family name to use for masters, and to filter output instances') parser.add_argument( '--mti-source') parser.add_argument( '--interpolate-binary-layout', action='store_true', help='Interpolate layout tables from compiled master binaries. ' 'Requires Glyphs or MutatorMath source.') parser.add_argument( '--use-afdko', action='store_true') parser.add_argument( '-a', '--autohint', nargs='?', const='', help='Run ttfautohint. Can provide arguments, quoted') parser.add_argument( '--keep-direction', dest='reverse_direction', action='store_false', help='Do not reverse contour direction when output is ttf or ' 'ttf-interpolatable') parser.add_argument( '--keep-overlaps', dest='remove_overlaps', action='store_false', help='Do not remove any overlap.') group1 = parser.add_mutually_exclusive_group(required=False) group1.add_argument( '--production-names', dest='use_production_names', action='store_true', help='Rename glyphs with production names if available otherwise use ' 'uninames.') group1.add_argument( '--no-production-names', dest='use_production_names', action='store_false') group2 = parser.add_mutually_exclusive_group(required=False) group2.add_argument( '--subset', dest='subset', action='store_true', help='Subset font using export flags set by glyphsLib') group2.add_argument( '--no-subset', dest='subset', action='store_false') group3 = parser.add_mutually_exclusive_group(required=False) group3.add_argument( '-s', '--subroutinize', action='store_true', help='Optimize CFF table using compreffor (default)') group3.add_argument( '-S', '--no-subroutinize', dest='subroutinize', action='store_false') parser.add_argument( '-e', '--conversion-error', type=float, default=None, metavar='ERROR', help='Maximum approximation error for cubic to quadratic conversion ' 'measured in EM') parser.set_defaults(use_production_names=None, subset=None, subroutinize=True) parser.add_argument('--timing', action='store_true') parser.add_argument('--verbose', default='INFO') args = vars(parser.parse_args()) project = FontProject(timing=args.pop('timing'), verbose=args.pop('verbose')) glyphs_path = args.pop('glyphs_path') ufo_paths = args.pop('ufo_paths') designspace_path = args.pop('mm_designspace') if sum(1 for p in [glyphs_path, ufo_paths, designspace_path] if p) != 1: parser.error('Exactly one source type required (Glyphs, UFO, or ' 'MutatorMath).') def exclude_args(parser, args, excluded_args, source_name): msg = '"%s" argument only available for %s source' for excluded in excluded_args: if args[excluded]: parser.error(msg % (excluded, source_name)) del args[excluded] if glyphs_path: project.run_from_glyphs(glyphs_path, **args) return exclude_args(parser, args, ['family_name'], 'Glyphs') if designspace_path: project.run_from_designspace(designspace_path, **args) return exclude_args( parser, args, ['interpolate', 'interpolate_binary_layout'], 'Glyphs or MutatorMath') project.run_from_ufos( ufo_paths, is_instance=args.pop('masters_as_instances'), **args)