diff --git a/Lib/ufo2ft/__init__.py b/Lib/ufo2ft/__init__.py index 72102292..5b77dd97 100644 --- a/Lib/ufo2ft/__init__.py +++ b/Lib/ufo2ft/__init__.py @@ -1,5 +1,4 @@ import logging -import os from collections import defaultdict from enum import IntEnum @@ -7,7 +6,7 @@ from fontTools.designspaceLib import DesignSpaceDocument from fontTools.designspaceLib.split import splitInterpolable, splitVariableFonts from fontTools.misc.loggingTools import Timer -from fontTools.otlLib.optimize.gpos import GPOS_COMPACT_MODE_ENV_KEY +from fontTools.otlLib.optimize.gpos import COMPRESSION_LEVEL as GPOS_COMPRESSION_LEVEL from ufo2ft.constants import SPARSE_OTF_MASTER_TABLES, SPARSE_TTF_MASTER_TABLES from ufo2ft.errors import InvalidDesignSpaceData @@ -27,6 +26,7 @@ _notdefGlyphFallback, colrClipBoxQuantization, ensure_all_sources_have_names, + getDefaultMasterFont, init_kwargs, location_to_string, prune_unknown_kwargs, @@ -110,6 +110,7 @@ def call_postprocessor(otf, ufo, glyphSet, *, postProcessorClass, **kwargs): colrAutoClipBoxes=True, colrClipBoxQuantization=colrClipBoxQuantization, # Callable[[Font], int] feaIncludeDir=None, + ftConfig=None, ) compileOTF_args = { @@ -841,6 +842,7 @@ def _compileNeededSources( if source.name in sourcesToCompile: sourcesByName[source.name] = source + ftConfig = kwargs.pop("ftConfig") or {} # Compile all needed sources in each interpolable subspace to make sure # they're all compatible; that also ensures that sub-vfs within the same # interpolable sub-space are compatible too. @@ -850,25 +852,25 @@ def _compileNeededSources( if not subDoc.sources: continue - # FIXME: Hack until we get a fontTools config module. Disable GPOS - # compaction while building masters because the compaction will be undone - # anyway by varLib merge and then done again on the VF - gpos_compact_value = os.environ.pop(GPOS_COMPACT_MODE_ENV_KEY, None) - try: - ttfDesignSpace = compileInterpolatableFunc( - subDoc, - **{ - **kwargs, - **dict( - useProductionNames=False, # will rename glyphs after varfont is built - # No need to post-process intermediate fonts. - postProcessorClass=None, - ), - }, - ) - finally: - if gpos_compact_value is not None: - os.environ[GPOS_COMPACT_MODE_ENV_KEY] = gpos_compact_value + # Disable GPOS compaction while building masters because the compaction + # will be undone anyway by varLib merge and then done again on the VF + gpos_compact_value = ftConfig.pop(GPOS_COMPRESSION_LEVEL, None) + ttfDesignSpace = compileInterpolatableFunc( + subDoc, + ftConfig=ftConfig, + **{ + **kwargs, + **dict( + useProductionNames=False, # will rename glyphs after varfont is built + # No need to post-process intermediate fonts. + postProcessorClass=None, + ), + }, + ) + if gpos_compact_value is not None: + baseTtf = getDefaultMasterFont(ttfDesignSpace) + baseTtf.cfg[GPOS_COMPRESSION_LEVEL] = gpos_compact_value + ftConfig[GPOS_COMPRESSION_LEVEL] = gpos_compact_value # Stick TTFs back into original big DS for ttfSource in ttfDesignSpace.sources: diff --git a/Lib/ufo2ft/outlineCompiler.py b/Lib/ufo2ft/outlineCompiler.py index 5b6d8511..1b7adf5a 100644 --- a/Lib/ufo2ft/outlineCompiler.py +++ b/Lib/ufo2ft/outlineCompiler.py @@ -108,6 +108,7 @@ def __init__( colrLayerReuse=True, colrAutoClipBoxes=True, colrClipBoxQuantization=colrClipBoxQuantization, + ftConfig=None, ): self.ufo = font # use the previously filtered glyphSet, if any @@ -126,6 +127,7 @@ def __init__( self.colrLayerReuse = colrLayerReuse self.colrAutoClipBoxes = colrAutoClipBoxes self.colrClipBoxQuantization = colrClipBoxQuantization + self.ftConfig = ftConfig or {} # cached values defined later on self._glyphBoundingBoxes = None self._fontBoundingBox = None @@ -136,7 +138,7 @@ def compile(self): """ Compile the OpenType binary. """ - self.otf = TTFont(sfntVersion=self.sfntVersion) + self.otf = TTFont(sfntVersion=self.sfntVersion, cfg=self.ftConfig) # only compile vertical metrics tables if vhea metrics are defined vertical_metrics = [ @@ -1104,6 +1106,7 @@ def __init__( colrLayerReuse=True, colrAutoClipBoxes=True, colrClipBoxQuantization=colrClipBoxQuantization, + ftConfig=None, ): if roundTolerance is not None: self.roundTolerance = float(roundTolerance) @@ -1119,6 +1122,7 @@ def __init__( colrLayerReuse=colrLayerReuse, colrAutoClipBoxes=colrAutoClipBoxes, colrClipBoxQuantization=colrClipBoxQuantization, + ftConfig=ftConfig, ) self.optimizeCFF = optimizeCFF self._defaultAndNominalWidths = None diff --git a/Lib/ufo2ft/postProcessor.py b/Lib/ufo2ft/postProcessor.py index 56f2292c..a7c25d18 100644 --- a/Lib/ufo2ft/postProcessor.py +++ b/Lib/ufo2ft/postProcessor.py @@ -404,4 +404,5 @@ def _reloadFont(font: TTFont) -> TTFont: stream = BytesIO() font.save(stream) stream.seek(0) - return TTFont(stream) + # keep the same Config (constructor will make a copy) + return TTFont(stream, cfg=font.cfg)