[cffLib / varLib] Merge two impls of convertCFFToCFF2

Fixes https://github.com/fonttools/fonttools/issues/1835
This commit is contained in:
Behdad Esfahbod 2024-05-16 15:57:31 -07:00
parent 4384eef42e
commit ec36fe74d5
2 changed files with 33 additions and 108 deletions

View File

@ -40,13 +40,6 @@ def convertCFFToCFF2(cff, otFont):
opOrder = buildOrder(topDictOperators2) opOrder = buildOrder(topDictOperators2)
topDict.order = opOrder topDict.order = opOrder
topDict.cff2GetGlyphOrder = cff2GetGlyphOrder topDict.cff2GetGlyphOrder = cff2GetGlyphOrder
for entry in topDictOperators:
key = entry[1]
if key not in opOrder:
if key in topDict.rawDict:
del topDict.rawDict[key]
if hasattr(topDict, key):
delattr(topDict, key)
if not hasattr(topDict, "FDArray"): if not hasattr(topDict, "FDArray"):
fdArray = topDict.FDArray = FDArrayIndex() fdArray = topDict.FDArray = FDArrayIndex()
@ -63,6 +56,7 @@ def convertCFFToCFF2(cff, otFont):
fdArray.append(fontDict) fdArray.append(fontDict)
fontDict.Private = privateDict fontDict.Private = privateDict
privateOpOrder = buildOrder(privateDictOperators2) privateOpOrder = buildOrder(privateDictOperators2)
if privateDict is not None:
for entry in privateDictOperators: for entry in privateDictOperators:
key = entry[1] key = entry[1]
if key not in privateOpOrder: if key not in privateOpOrder:
@ -78,7 +72,7 @@ def convertCFFToCFF2(cff, otFont):
privateOpOrder = buildOrder(privateDictOperators2) privateOpOrder = buildOrder(privateDictOperators2)
for fontDict in fdArray: for fontDict in fdArray:
fontDict.setCFF2(True) fontDict.setCFF2(True)
for key in fontDict.rawDict.keys(): for key in list(fontDict.rawDict.keys()):
if key not in fontDict.order: if key not in fontDict.order:
del fontDict.rawDict[key] del fontDict.rawDict[key]
if hasattr(fontDict, key): if hasattr(fontDict, key):
@ -88,13 +82,22 @@ def convertCFFToCFF2(cff, otFont):
for entry in privateDictOperators: for entry in privateDictOperators:
key = entry[1] key = entry[1]
if key not in privateOpOrder: if key not in privateOpOrder:
if key in privateDict.rawDict: if key in list(privateDict.rawDict.keys()):
# print "Removing private dict", key # print "Removing private dict", key
del privateDict.rawDict[key] del privateDict.rawDict[key]
if hasattr(privateDict, key): if hasattr(privateDict, key):
delattr(privateDict, key) delattr(privateDict, key)
# print "Removing privateDict attr", key # print "Removing privateDict attr", key
# Now delete up the deprecated topDict operators from CFF 1.0
for entry in topDictOperators:
key = entry[1]
if key not in opOrder:
if key in topDict.rawDict:
del topDict.rawDict[key]
if hasattr(topDict, key):
delattr(topDict, key)
# TODO(behdad): What does the following comment even mean? Both CFF and CFF2 # TODO(behdad): What does the following comment even mean? Both CFF and CFF2
# use the same T2Charstring class. # use the same T2Charstring class.
# What I see missing is dropping the endchar and return operators... # What I see missing is dropping the endchar and return operators...

View File

@ -13,6 +13,7 @@ from fontTools.cffLib import (
) )
from io import BytesIO from io import BytesIO
from fontTools.cffLib.specializer import specializeCommands, commandsToProgram from fontTools.cffLib.specializer import specializeCommands, commandsToProgram
from fontTools.cffLib.CFFToCFF2 import convertCFFToCFF2 as lib_convertCFFToCFF2
from fontTools.ttLib import newTable from fontTools.ttLib import newTable
from fontTools import varLib from fontTools import varLib
from fontTools.varLib.models import allEqual from fontTools.varLib.models import allEqual
@ -49,85 +50,6 @@ def addCFFVarStore(varFont, varModel, varDataList, masterSupports):
fontDict.Private.vstore = topDict.VarStore fontDict.Private.vstore = topDict.VarStore
def lib_convertCFFToCFF2(cff, otFont):
# This assumes a decompiled CFF table.
cff2GetGlyphOrder = cff.otFont.getGlyphOrder
topDictData = TopDictIndex(None, cff2GetGlyphOrder, None)
topDictData.items = cff.topDictIndex.items
cff.topDictIndex = topDictData
topDict = topDictData[0]
if hasattr(topDict, "Private"):
privateDict = topDict.Private
else:
privateDict = None
opOrder = buildOrder(topDictOperators2)
topDict.order = opOrder
topDict.cff2GetGlyphOrder = cff2GetGlyphOrder
if not hasattr(topDict, "FDArray"):
fdArray = topDict.FDArray = FDArrayIndex()
fdArray.strings = None
fdArray.GlobalSubrs = topDict.GlobalSubrs
topDict.GlobalSubrs.fdArray = fdArray
charStrings = topDict.CharStrings
if charStrings.charStringsAreIndexed:
charStrings.charStringsIndex.fdArray = fdArray
else:
charStrings.fdArray = fdArray
fontDict = FontDict()
fontDict.setCFF2(True)
fdArray.append(fontDict)
fontDict.Private = privateDict
privateOpOrder = buildOrder(privateDictOperators2)
if privateDict is not None:
for entry in privateDictOperators:
key = entry[1]
if key not in privateOpOrder:
if key in privateDict.rawDict:
# print "Removing private dict", key
del privateDict.rawDict[key]
if hasattr(privateDict, key):
delattr(privateDict, key)
# print "Removing privateDict attr", key
else:
# clean up the PrivateDicts in the fdArray
fdArray = topDict.FDArray
privateOpOrder = buildOrder(privateDictOperators2)
for fontDict in fdArray:
fontDict.setCFF2(True)
for key in list(fontDict.rawDict.keys()):
if key not in fontDict.order:
del fontDict.rawDict[key]
if hasattr(fontDict, key):
delattr(fontDict, key)
privateDict = fontDict.Private
for entry in privateDictOperators:
key = entry[1]
if key not in privateOpOrder:
if key in privateDict.rawDict:
# print "Removing private dict", key
del privateDict.rawDict[key]
if hasattr(privateDict, key):
delattr(privateDict, key)
# print "Removing privateDict attr", key
# Now delete up the deprecated topDict operators from CFF 1.0
for entry in topDictOperators:
key = entry[1]
if key not in opOrder:
if key in topDict.rawDict:
del topDict.rawDict[key]
if hasattr(topDict, key):
delattr(topDict, key)
# At this point, the Subrs and Charstrings are all still T2Charstring class
# easiest to fix this by compiling, then decompiling again
cff.major = 2
file = BytesIO()
cff.compile(file, otFont, isCFF2=True)
file.seek(0)
cff.decompile(file, otFont, isCFF2=True)
def convertCFFtoCFF2(varFont): def convertCFFtoCFF2(varFont):
# Convert base font to a single master CFF2 font. # Convert base font to a single master CFF2 font.
cffTable = varFont["CFF "] cffTable = varFont["CFF "]