Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply DesignSpace variable-font's public.fontInfo lib key to variable fonts #816

Merged
merged 6 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions Lib/ufo2ft/_compilers/baseCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ def compileOutlines(self, ufo, glyphSet):
outlineCompiler = self.outlineCompilerClass(ufo, glyphSet=glyphSet, **kwargs)
return outlineCompiler.compile()

def postprocess(self, ttf, ufo, glyphSet):
def postprocess(self, ttf, ufo, glyphSet, info=None):
if self.postProcessorClass is not None:
postProcessor = self.postProcessorClass(ttf, ufo, glyphSet=glyphSet)
postProcessor = self.postProcessorClass(
ttf, ufo, glyphSet=glyphSet, info=info
)
kwargs = prune_unknown_kwargs(self.__dict__, postProcessor.process)
ttf = postProcessor.process(**kwargs)
return ttf
Expand Down Expand Up @@ -249,7 +251,10 @@ def _compileNeededSources(self, designSpaceDoc):
f"No default source; expected default master at {default_location}."
f" Found master locations:\n{master_location_descriptions}"
)
vfNameToBaseUfo[vfName] = default_source.font
vfNameToBaseUfo[vfName] = (
default_source.font,
vfDoc.lib.get("public.fontInfo"),
)
for source in vfDoc.sources:
sourcesToCompile.add(source.name)

Expand Down Expand Up @@ -359,8 +364,9 @@ def compile_variable(self, designSpaceDoc):
designSpaceDoc, vfNameToTTFont, originalSources, originalGlyphsets
)
for vfName, varfont in list(vfNameToTTFont.items()):
ufo, info = vfNameToBaseUfo[vfName]
vfNameToTTFont[vfName] = self.postprocess(
varfont, vfNameToBaseUfo[vfName], glyphSet=None
varfont, ufo, glyphSet=None, info=info
)

return vfNameToTTFont
Expand Down
6 changes: 4 additions & 2 deletions Lib/ufo2ft/_compilers/otfCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ def compileOutlines(self, ufo, glyphSet):
outlineCompiler = self.outlineCompilerClass(ufo, glyphSet=glyphSet, **kwargs)
return outlineCompiler.compile()

def postprocess(self, font, ufo, glyphSet):
def postprocess(self, font, ufo, glyphSet, info=None):
if self.postProcessorClass is not None:
postProcessor = self.postProcessorClass(font, ufo, glyphSet=glyphSet)
postProcessor = self.postProcessorClass(
font, ufo, glyphSet=glyphSet, info=info
)
kwargs = prune_unknown_kwargs(self.__dict__, postProcessor.process)
kwargs["optimizeCFF"] = self.optimizeCFF >= CFFOptimization.SUBROUTINIZE
font = postProcessor.process(**kwargs)
Expand Down
2 changes: 1 addition & 1 deletion Lib/ufo2ft/outlineCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ def adjustOffset(offset, angle):
os2.ulUnicodeRange2 = intListToNum(uniRanges, 32, 32)
os2.ulUnicodeRange3 = intListToNum(uniRanges, 64, 32)
os2.ulUnicodeRange4 = intListToNum(uniRanges, 96, 32)
else:
elif "cmap" in self.otf:
os2.recalcUnicodeRanges(self.otf)

# codepage ranges
Expand Down
101 changes: 99 additions & 2 deletions Lib/ufo2ft/postProcessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
KEEP_GLYPH_NAMES,
USE_PRODUCTION_NAMES,
)
from ufo2ft.outlineCompiler import BaseOutlineCompiler

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -38,10 +39,10 @@ class SubroutinizerBackend(enum.Enum):
2: SubroutinizerBackend.CFFSUBR,
}

def __init__(self, otf, ufo, glyphSet=None):
def __init__(self, otf, ufo, glyphSet=None, info=None):
self.ufo = ufo
self.glyphSet = glyphSet if glyphSet is not None else ufo

self.info = info
self.otf = otf

self._postscriptNames = ufo.lib.get("public.postscriptNames")
Expand Down Expand Up @@ -103,6 +104,9 @@ def process(

self.process_glyph_names(useProductionNames)

if self.info:
self.apply_fontinfo()
khaledhosny marked this conversation as resolved.
Show resolved Hide resolved

return self.otf

def process_cff(self, *, optimizeCFF=True, cffVersion=None, subroutinizer=None):
Expand Down Expand Up @@ -357,6 +361,99 @@ def _subroutinize_with_cffsubr(cls, otf, cffVersion):

return cffsubr.subroutinize(otf, cff_version=cffVersion, keep_glyph_names=False)

def apply_fontinfo(self):
"""Apply the fontinfo data from the DesignSpace variable-font's lib to
the compiled font."""
import copy

# Create a temporary UFO and sets its fontinfo to the union of the main
# UFO's fontinfo and the DesignSpace variable-font’s info.
temp_ufo = type(self.ufo)()
temp_ufo.info = copy.copy(self.ufo.info)
for k, v in self.info.items():
setattr(temp_ufo.info, k, v)
khaledhosny marked this conversation as resolved.
Show resolved Hide resolved

# Build a temporary font with the only tables that can be modified with
# fontinfo.
tables = {"head", "hhea", "name", "OS/2", "post"} & set(self.otf.keys())
anthrotype marked this conversation as resolved.
Show resolved Hide resolved
compiler = InfoCompiler(
temp_ufo,
glyphSet={},
glyphOrder=[],
tables=tables,
)
temp_otf = compiler.compile()

# Merge the modified data from the temporary font to the main font.
for tag in tables:
temp = temp_otf[tag]
orig = self.otf[tag]
if tag == "name":
temp_names = {
(n.nameID, n.platformID, n.platEncID, n.langID): n
for n in temp.names
}
orig_names = {
(n.nameID, n.platformID, n.platEncID, n.langID): n
for n in orig.names
}
orig_names.update(temp_names)
orig.names = list(orig_names.values())
continue

for attr in temp.__dict__:
khaledhosny marked this conversation as resolved.
Show resolved Hide resolved
if attr.startswith("_"):
continue
if attr.startswith("reserved"):
continue
if attr in ("tableTag", "tableVersion"):
continue
if tag == "head" and attr in {
"created",
"modified",
"xMin",
"yMin",
"xMax",
"yMax",
"fontDirectionHint",
"indexToLocFormat",
"glyphDataFormat",
}:
continue
if tag == "hhea" and attr in {
"checksumAdjustment",
khaledhosny marked this conversation as resolved.
Show resolved Hide resolved
"metricDataFormat",
"numberOfHMetrics",
"advanceWidthMax",
"minLeftSideBearing",
"minRightSideBearing",
"xMaxExtent",
}:
continue
if tag == "OS/2" and attr in {
"xAvgCharWidth",
"usMaxContext",
}:
continue
if tag == "post" and attr in {"formatType"}:
continue

setattr(orig, attr, getattr(temp, attr))


class InfoCompiler(BaseOutlineCompiler):
@staticmethod
def makeMissingRequiredGlyphs(*args, **kwargs):
return

def makeFontBoundingBox(self):
from ufo2ft.outlineCompiler import EMPTY_BOUNDING_BOX

return EMPTY_BOUNDING_BOX

def setupTable_maxp(self):
return


# Adapted from fontTools.cff.specializer.programToCommands
# https://github.com/fonttools/fonttools/blob/babca16
Expand Down
Loading