def compileOTF(ufo, outlineCompilerClass=OutlineOTFCompiler, featureCompilerClass=FeatureCompiler, mtiFeaFiles=None, kernWriterClass=KernFeatureWriter, markWriterClass=MarkFeatureWriter, glyphOrder=None, useProductionNames=True, optimizeCFF=True, roundTolerance=None): """Create FontTools CFF font from a UFO. *optimizeCFF* sets whether the CFF table should be subroutinized. *roundTolerance* (float) controls the rounding of point coordinates. It is defined as the maximum absolute difference between the original float and the rounded integer value. By default, all floats are rounded to integer (tolerance 0.5); a value of 0 completely disables rounding; values in between only round floats which are close to their integral part within the tolerated range. """ outlineCompiler = outlineCompilerClass( ufo, glyphOrder, roundTolerance=roundTolerance) otf = outlineCompiler.compile() featureCompiler = featureCompilerClass( ufo, otf, kernWriterClass=kernWriterClass, markWriterClass=markWriterClass, mtiFeaFiles=mtiFeaFiles) featureCompiler.compile() postProcessor = PostProcessor(otf, ufo) otf = postProcessor.process(useProductionNames, optimizeCFF) return otf
def compileTTF(ufo, outlineCompilerClass=OutlineTTFCompiler, featureCompilerClass=FeatureCompiler, kernWriterClass=KernFeatureWriter, markWriterClass=MarkFeatureWriter, glyphOrder=None, useProductionNames=True, convertCubics=True, cubicConversionError=None): """Create FontTools TrueType font from a UFO. *convertCubics* and *cubicConversionError* specify how the conversion from cubic to quadratic curves should be handled. """ outlineCompiler = outlineCompilerClass(ufo, glyphOrder, convertCubics, cubicConversionError) otf = outlineCompiler.compile() featureCompiler = featureCompilerClass(ufo, otf, kernWriterClass=kernWriterClass, markWriterClass=markWriterClass, mtiFeatures=_getMtiFeatures(ufo)) featureCompiler.compile() postProcessor = PostProcessor(otf, ufo) otf = postProcessor.process(useProductionNames) return otf
def compileVariableTTF( designSpaceDoc, preProcessorClass=TTFInterpolatablePreProcessor, outlineCompilerClass=OutlineTTFCompiler, featureCompilerClass=None, featureWriters=None, glyphOrder=None, useProductionNames=None, cubicConversionError=None, reverseDirection=True, excludeVariationTables=(), optimizeGvar=True, flattenComponents=False, inplace=False, debugFeatureFile=None, notdefGlyph=None, ): """Create FontTools TrueType variable font from the DesignSpaceDocument UFO sources with interpolatable outlines, using fontTools.varLib.build. *optimizeGvar*, if set to False, will not perform IUP optimization on the generated 'gvar' table. *excludeVariationTables* is a list of sfnt table tags (str) that is passed on to fontTools.varLib.build, to skip building some variation tables. The rest of the arguments works the same as in the other compile functions. Returns a new variable TTFont object. """ baseUfo = getDefaultMasterFont(designSpaceDoc) ttfDesignSpace = compileInterpolatableTTFsFromDS( designSpaceDoc, preProcessorClass=preProcessorClass, outlineCompilerClass=outlineCompilerClass, featureCompilerClass=featureCompilerClass, featureWriters=featureWriters, glyphOrder=glyphOrder, useProductionNames=False, # will rename glyphs after varfont is built cubicConversionError=cubicConversionError, reverseDirection=reverseDirection, flattenComponents=flattenComponents, inplace=inplace, debugFeatureFile=debugFeatureFile, notdefGlyph=notdefGlyph, ) logger.info("Building variable TTF font") varfont = varLib.build(ttfDesignSpace, exclude=excludeVariationTables, optimize=optimizeGvar)[0] postProcessor = PostProcessor(varfont, baseUfo) varfont = postProcessor.process(useProductionNames) return varfont
def compileTTF( ufo, preProcessorClass=TTFPreProcessor, outlineCompilerClass=OutlineTTFCompiler, featureCompilerClass=FeatureCompiler, kernWriterClass=None, # deprecated markWriterClass=None, # deprecated featureWriters=None, glyphOrder=None, useProductionNames=None, convertCubics=True, cubicConversionError=None, reverseDirection=True, removeOverlaps=False, inplace=False): """Create FontTools TrueType font from a UFO. *removeOverlaps* performs a union operation on all the glyphs' contours. *convertCubics* and *cubicConversionError* specify how the conversion from cubic to quadratic curves should be handled. """ preProcessor = preProcessorClass(ufo, inplace=inplace, removeOverlaps=removeOverlaps, convertCubics=convertCubics, conversionError=cubicConversionError, reverseDirection=reverseDirection) glyphSet = preProcessor.process() outlineCompiler = outlineCompilerClass(ufo, glyphSet=glyphSet, glyphOrder=glyphOrder) otf = outlineCompiler.compile() featureWriters = _replaceDeprecatedFeatureWriters(featureWriters, kernWriterClass, markWriterClass) featureCompiler = featureCompilerClass(ufo, otf, featureWriters=featureWriters, mtiFeatures=_getMtiFeatures(ufo)) featureCompiler.compile() postProcessor = PostProcessor(otf, ufo) otf = postProcessor.process(useProductionNames) return otf
def compileVariableCFF2( designSpaceDoc, preProcessorClass=OTFPreProcessor, outlineCompilerClass=OutlineOTFCompiler, featureCompilerClass=None, featureWriters=None, glyphOrder=None, useProductionNames=None, roundTolerance=None, excludeVariationTables=(), inplace=False, debugFeatureFile=None, ): """Create FontTools CFF2 variable font from the DesignSpaceDocument UFO sources with interpolatable outlines, using fontTools.varLib.build. *excludeVariationTables* is a list of sfnt table tags (str) that is passed on to fontTools.varLib.build, to skip building some variation tables. The rest of the arguments works the same as in the other compile functions. Returns a new variable TTFont object. """ baseUfo = getDefaultMasterFont(designSpaceDoc) otfDesignSpace = compileInterpolatableOTFsFromDS( designSpaceDoc, preProcessorClass=preProcessorClass, outlineCompilerClass=outlineCompilerClass, featureCompilerClass=featureCompilerClass, featureWriters=featureWriters, glyphOrder=glyphOrder, useProductionNames=False, # will rename glyphs after varfont is built roundTolerance=roundTolerance, inplace=inplace, debugFeatureFile=debugFeatureFile, ) logger.info("Building variable CFF2 font") varfont = varLib.build(otfDesignSpace, exclude=excludeVariationTables)[0] postProcessor = PostProcessor(varfont, baseUfo) varfont = postProcessor.process(useProductionNames) return varfont
def compileInterpolatableTTFs(ufos, preProcessorClass=TTFInterpolatablePreProcessor, outlineCompilerClass=OutlineTTFCompiler, featureCompilerClass=FeatureCompiler, featureWriters=None, glyphOrder=None, useProductionNames=None, cubicConversionError=None, reverseDirection=True, inplace=False): """Create FontTools TrueType fonts from a list of UFOs with interpolatable outlines. Cubic curves are converted compatibly to quadratic curves using the Cu2Qu conversion algorithm. Return an iterator object that yields a TTFont instance for each UFO. """ preProcessor = preProcessorClass(ufos, inplace=inplace, conversionError=cubicConversionError, reverseDirection=reverseDirection) glyphSets = preProcessor.process() for ufo, glyphSet in zip(ufos, glyphSets): outlineCompiler = outlineCompilerClass(ufo, glyphSet=glyphSet, glyphOrder=glyphOrder) ttf = outlineCompiler.compile() featureCompiler = featureCompilerClass( ufo, ttf, featureWriters=featureWriters, mtiFeatures=_getMtiFeatures(ufo)) featureCompiler.compile() postProcessor = PostProcessor(ttf, ufo) ttf = postProcessor.process(useProductionNames) yield ttf
def compileOTF( ufo, preProcessorClass=OTFPreProcessor, outlineCompilerClass=OutlineOTFCompiler, featureCompilerClass=None, featureWriters=None, glyphOrder=None, useProductionNames=None, optimizeCFF=CFFOptimization.SUBROUTINIZE, roundTolerance=None, removeOverlaps=False, overlapsBackend=None, inplace=False, layerName=None, skipExportGlyphs=None, _tables=None, ): """Create FontTools CFF font from a UFO. *removeOverlaps* performs a union operation on all the glyphs' contours. *optimizeCFF* (int) defines whether the CFF charstrings should be specialized and subroutinized. By default both optimization are enabled. A value of 0 disables both; 1 only enables the specialization; 2 (default) does both specialization and subroutinization. *roundTolerance* (float) controls the rounding of point coordinates. It is defined as the maximum absolute difference between the original float and the rounded integer value. By default, all floats are rounded to integer (tolerance 0.5); a value of 0 completely disables rounding; values in between only round floats which are close to their integral part within the tolerated range. *featureWriters* argument is a list of BaseFeatureWriter subclasses or pre-initialized instances. Features will be written by each feature writer in the given order. If featureWriters is None, the default feature writers [KernFeatureWriter, MarkFeatureWriter] are used. *useProductionNames* renames glyphs in TrueType 'post' or OpenType 'CFF ' tables based on the 'public.postscriptNames' mapping in the UFO lib, if present. Otherwise, uniXXXX names are generated from the glyphs' unicode values. The default value (None) will first check if the UFO lib has the 'com.github.googlei18n.ufo2ft.useProductionNames' key. If this is missing or True (default), the glyphs are renamed. Set to False to keep the original names. **inplace** (bool) specifies whether the filters should modify the input UFO's glyphs, a copy should be made first. *layerName* specifies which layer should be compiled. When compiling something other than the default layer, feature compilation is skipped. *skipExportGlyphs* is a list or set of glyph names to not be exported to the final font. If these glyphs are used as components in any other glyph, those components get decomposed. If the parameter is not passed in, the UFO's "public.skipExportGlyphs" lib key will be consulted. If it doesn't exist, all glyphs are exported. UFO groups and kerning will be pruned of skipped glyphs. """ logger.info("Pre-processing glyphs") if skipExportGlyphs is None: skipExportGlyphs = ufo.lib.get("public.skipExportGlyphs", []) preProcessor = preProcessorClass( ufo, inplace=inplace, removeOverlaps=removeOverlaps, overlapsBackend=overlapsBackend, layerName=layerName, skipExportGlyphs=skipExportGlyphs, ) glyphSet = preProcessor.process() logger.info("Building OpenType tables") optimizeCFF = CFFOptimization(optimizeCFF) outlineCompiler = outlineCompilerClass( ufo, glyphSet=glyphSet, glyphOrder=glyphOrder, roundTolerance=roundTolerance, optimizeCFF=optimizeCFF >= CFFOptimization.SPECIALIZE, tables=_tables, ) otf = outlineCompiler.compile() # Only the default layer is likely to have all glyphs used in feature code. if layerName is None: compileFeatures( ufo, otf, glyphSet=glyphSet, featureWriters=featureWriters, featureCompilerClass=featureCompilerClass, ) postProcessor = PostProcessor(otf, ufo, glyphSet=glyphSet) otf = postProcessor.process( useProductionNames, optimizeCFF=optimizeCFF >= CFFOptimization.SUBROUTINIZE) return otf
def compileInterpolatableTTFs( ufos, preProcessorClass=TTFInterpolatablePreProcessor, outlineCompilerClass=OutlineTTFCompiler, featureCompilerClass=None, featureWriters=None, glyphOrder=None, useProductionNames=None, cubicConversionError=None, reverseDirection=True, inplace=False, layerNames=None, skipExportGlyphs=None, ): """Create FontTools TrueType fonts from a list of UFOs with interpolatable outlines. Cubic curves are converted compatibly to quadratic curves using the Cu2Qu conversion algorithm. Return an iterator object that yields a TTFont instance for each UFO. *layerNames* refers to the layer names to use glyphs from in the order of the UFOs in *ufos*. By default, this is a list of `[None]` times the number of UFOs, i.e. using the default layer from all the UFOs. When the layerName is not None for a given UFO, the corresponding TTFont object will contain only a minimum set of tables ("head", "hmtx", "glyf", "loca", "maxp", "post" and "vmtx"), and no OpenType layout tables. *skipExportGlyphs* is a list or set of glyph names to not be exported to the final font. If these glyphs are used as components in any other glyph, those components get decomposed. If the parameter is not passed in, the union of all UFO's "public.skipExportGlyphs" lib keys will be used. If they don't exist, all glyphs are exported. UFO groups and kerning will be pruned of skipped glyphs. """ from ufo2ft.util import _LazyFontName if layerNames is None: layerNames = [None] * len(ufos) assert len(ufos) == len(layerNames) if skipExportGlyphs is None: skipExportGlyphs = set() for ufo in ufos: skipExportGlyphs.update(ufo.lib.get("public.skipExportGlyphs", [])) logger.info("Pre-processing glyphs") preProcessor = preProcessorClass( ufos, inplace=inplace, conversionError=cubicConversionError, reverseDirection=reverseDirection, layerNames=layerNames, skipExportGlyphs=skipExportGlyphs, ) glyphSets = preProcessor.process() for ufo, glyphSet, layerName in zip(ufos, glyphSets, layerNames): fontName = _LazyFontName(ufo) if layerName is not None: logger.info("Building OpenType tables for %s-%s", fontName, layerName) else: logger.info("Building OpenType tables for %s", fontName) outlineCompiler = outlineCompilerClass( ufo, glyphSet=glyphSet, glyphOrder=glyphOrder, tables=SPARSE_TTF_MASTER_TABLES if layerName else None, ) ttf = outlineCompiler.compile() # Only the default layer is likely to have all glyphs used in feature # code. if layerName is None: compileFeatures( ufo, ttf, glyphSet=glyphSet, featureWriters=featureWriters, featureCompilerClass=featureCompilerClass, ) postProcessor = PostProcessor(ttf, ufo, glyphSet=glyphSet) ttf = postProcessor.process(useProductionNames) if layerName is not None: # for sparse masters (i.e. containing only a subset of the glyphs), we # need to include the post table in order to store glyph names, so that # fontTools.varLib can interpolate glyphs with same name across masters. # However we want to prevent the underlinePosition/underlineThickness # fields in such sparse masters to be included when computing the deltas # for the MVAR table. Thus, we set them to this unlikely, limit value # (-36768) which is a signal varLib should ignore them when building MVAR. ttf["post"].underlinePosition = -0x8000 ttf["post"].underlineThickness = -0x8000 yield ttf
def compileTTF( ufo, preProcessorClass=TTFPreProcessor, outlineCompilerClass=OutlineTTFCompiler, featureCompilerClass=None, featureWriters=None, glyphOrder=None, useProductionNames=None, convertCubics=True, cubicConversionError=None, reverseDirection=True, rememberCurveType=True, removeOverlaps=False, overlapsBackend=None, inplace=False, layerName=None, skipExportGlyphs=None, ): """Create FontTools TrueType font from a UFO. *removeOverlaps* performs a union operation on all the glyphs' contours. *convertCubics* and *cubicConversionError* specify how the conversion from cubic to quadratic curves should be handled. *layerName* specifies which layer should be compiled. When compiling something other than the default layer, feature compilation is skipped. *skipExportGlyphs* is a list or set of glyph names to not be exported to the final font. If these glyphs are used as components in any other glyph, those components get decomposed. If the parameter is not passed in, the UFO's "public.skipExportGlyphs" lib key will be consulted. If it doesn't exist, all glyphs are exported. UFO groups and kerning will be pruned of skipped glyphs. """ logger.info("Pre-processing glyphs") if skipExportGlyphs is None: skipExportGlyphs = ufo.lib.get("public.skipExportGlyphs", []) preProcessor = preProcessorClass( ufo, inplace=inplace, removeOverlaps=removeOverlaps, overlapsBackend=overlapsBackend, convertCubics=convertCubics, conversionError=cubicConversionError, reverseDirection=reverseDirection, rememberCurveType=rememberCurveType, layerName=layerName, skipExportGlyphs=skipExportGlyphs, ) glyphSet = preProcessor.process() logger.info("Building OpenType tables") outlineCompiler = outlineCompilerClass(ufo, glyphSet=glyphSet, glyphOrder=glyphOrder) otf = outlineCompiler.compile() # Only the default layer is likely to have all glyphs used in feature code. if layerName is None: compileFeatures( ufo, otf, glyphSet=glyphSet, featureWriters=featureWriters, featureCompilerClass=featureCompilerClass, ) postProcessor = PostProcessor(otf, ufo, glyphSet=glyphSet) otf = postProcessor.process(useProductionNames) return otf
def compileVariableCFF2( designSpaceDoc, preProcessorClass=OTFPreProcessor, outlineCompilerClass=OutlineOTFCompiler, featureCompilerClass=None, featureWriters=None, glyphOrder=None, useProductionNames=None, roundTolerance=None, excludeVariationTables=(), inplace=False, debugFeatureFile=None, optimizeCFF=CFFOptimization.SPECIALIZE, notdefGlyph=None, ): """Create FontTools CFF2 variable font from the DesignSpaceDocument UFO sources with interpolatable outlines, using fontTools.varLib.build. *excludeVariationTables* is a list of sfnt table tags (str) that is passed on to fontTools.varLib.build, to skip building some variation tables. *optimizeCFF* (int) defines whether the CFF charstrings should be specialized and subroutinized. 1 (default) only enables the specialization; 2 (default) does both specialization and subroutinization. The value 0 is supposed to disable both optimizations, however it's currently unused, because fontTools has some issues generating a VF with non-specialized CFF2 charstrings: fonttools/fonttools#1979. NOTE: Subroutinization of variable CFF2 requires the "cffsubr" extra requirement. The rest of the arguments works the same as in the other compile functions. Returns a new variable TTFont object. """ baseUfo = getDefaultMasterFont(designSpaceDoc) otfDesignSpace = compileInterpolatableOTFsFromDS( designSpaceDoc, preProcessorClass=preProcessorClass, outlineCompilerClass=outlineCompilerClass, featureCompilerClass=featureCompilerClass, featureWriters=featureWriters, glyphOrder=glyphOrder, useProductionNames=False, # will rename glyphs after varfont is built roundTolerance=roundTolerance, inplace=inplace, debugFeatureFile=debugFeatureFile, notdefGlyph=notdefGlyph, ) logger.info("Building variable CFF2 font") optimizeCFF = CFFOptimization(optimizeCFF) varfont = varLib.build( otfDesignSpace, exclude=excludeVariationTables, # NOTE optimize=False won't change anything until this PR is merged # https://github.com/fonttools/fonttools/pull/1979 optimize=optimizeCFF >= CFFOptimization.SPECIALIZE, )[0] postProcessor = PostProcessor(varfont, baseUfo) varfont = postProcessor.process( useProductionNames, optimizeCFF=optimizeCFF >= CFFOptimization.SUBROUTINIZE, ) return varfont
def compileTTF( ufo, preProcessorClass=TTFPreProcessor, outlineCompilerClass=OutlineTTFCompiler, featureCompilerClass=None, featureWriters=None, glyphOrder=None, useProductionNames=None, convertCubics=True, cubicConversionError=None, reverseDirection=True, rememberCurveType=True, removeOverlaps=False, overlapsBackend=None, inplace=False, layerName=None, ): """Create FontTools TrueType font from a UFO. *removeOverlaps* performs a union operation on all the glyphs' contours. *convertCubics* and *cubicConversionError* specify how the conversion from cubic to quadratic curves should be handled. *layerName* specifies which layer should be compiled. When compiling something other than the default layer, feature compilation is skipped. """ logger.info("Pre-processing glyphs") preProcessor = preProcessorClass( ufo, inplace=inplace, removeOverlaps=removeOverlaps, overlapsBackend=overlapsBackend, convertCubics=convertCubics, conversionError=cubicConversionError, reverseDirection=reverseDirection, rememberCurveType=rememberCurveType, layerName=layerName, ) glyphSet = preProcessor.process() logger.info("Building OpenType tables") outlineCompiler = outlineCompilerClass(ufo, glyphSet=glyphSet, glyphOrder=glyphOrder) otf = outlineCompiler.compile() # Only the default layer is likely to have all glyphs used in feature code. if layerName is None: compileFeatures( ufo, otf, glyphSet=glyphSet, featureWriters=featureWriters, featureCompilerClass=featureCompilerClass, ) postProcessor = PostProcessor(otf, ufo, glyphSet=glyphSet) otf = postProcessor.process(useProductionNames) return otf
def compileOTF( ufo, preProcessorClass=OTFPreProcessor, outlineCompilerClass=OutlineOTFCompiler, featureCompilerClass=FeatureCompiler, kernWriterClass=None, # deprecated markWriterClass=None, # deprecated featureWriters=None, glyphOrder=None, useProductionNames=None, optimizeCFF=True, roundTolerance=None, removeOverlaps=False, inplace=False): """Create FontTools CFF font from a UFO. *removeOverlaps* performs a union operation on all the glyphs' contours. *optimizeCFF* sets whether the CFF table should be subroutinized. *roundTolerance* (float) controls the rounding of point coordinates. It is defined as the maximum absolute difference between the original float and the rounded integer value. By default, all floats are rounded to integer (tolerance 0.5); a value of 0 completely disables rounding; values in between only round floats which are close to their integral part within the tolerated range. *featureWriters* argument is a list of BaseFeatureWriter subclasses or pre-initialized instances. Features will be written by each feature writer in the given order. If featureWriters is None, the default feature writers [KernFeatureWriter, MarkFeatureWriter] are used. *useProductionNames* renames glyphs in TrueType 'post' or OpenType 'CFF ' tables based on the 'public.postscriptNames' mapping in the UFO lib, if present. Otherwise, uniXXXX names are generated from the glyphs' unicode values. The default value (None) will first check if the UFO lib has the 'com.github.googlei18n.ufo2ft.useProductionNames' key. If this is missing or True (default), the glyphs are renamed. Set to False to keep the original names. """ preProcessor = preProcessorClass(ufo, inplace=inplace, removeOverlaps=removeOverlaps) glyphSet = preProcessor.process() outlineCompiler = outlineCompilerClass(ufo, glyphSet=glyphSet, glyphOrder=glyphOrder, roundTolerance=roundTolerance) otf = outlineCompiler.compile() featureWriters = _replaceDeprecatedFeatureWriters(featureWriters, kernWriterClass, markWriterClass) featureCompiler = featureCompilerClass(ufo, otf, featureWriters=featureWriters, mtiFeatures=_getMtiFeatures(ufo)) featureCompiler.compile() postProcessor = PostProcessor(otf, ufo) otf = postProcessor.process(useProductionNames, optimizeCFF) return otf