[cffLib] Question on moving Private from topDict to FontDict #2720
Replies: 5 comments 19 replies
-
I have read the source files here: fonttools/Lib/fontTools/varLib/cff.py Line 64 in 21d22ae fdSelectIndex="0" for CID-keyed fonts):
import copy
from fontTools import ttLib
from fontTools.cffLib import (
FDArrayIndex,
FontDict,
FDSelect,
)
font = ttLib.TTFont("fonts/in.otf")
cff = font['CFF '].cff.values()[0]
fontName = font["CFF "].cff.keys()[0]
cff.ROS = ('Adobe','Identity',0)
mapping = {name:("cid"+str(n) if n else ".notdef") for n,name in enumerate(cff.charset)}
charstrings = cff.CharStrings
charstrings.charStrings = {mapping[name]:v for name,v in charstrings.charStrings.items()}
cff.charset = ["cid"+str(n) if n else ".notdef" for n in range(len(cff.charset))]
#sample from https://github.com/fonttools/fonttools/blob/21d22ae30f88b76fab5575f5f2e882b142ee1c08/Lib/fontTools/varLib/cff.py#L64
if not hasattr(cff, "FDArray"):
#format 3 FDSelect
cff.FDSelect = FDSelect(None, None, 3)
#create FDArray
fdArray = cff.FDArray = FDArrayIndex()
fdArray.strings = None
fdArray.GlobalSubrs = cff.GlobalSubrs
cff.GlobalSubrs.fdArray = fdArray
if charstrings.charStringsAreIndexed:
charstrings.charStringsIndex.fdArray = fdArray
else:
charstrings.fdArray = fdArray
#set FDSelectIndex = 0 for every T2CharString in GlobalSubrs
for item in charstrings.keys():
charstrings[item].fdSelectIndex = 0
#create FontDict in FDArray
fontDict = FontDict() #default index 0
fdArray.append(fontDict)
#generate fontdict name
fontDict.FontName = fontName +"-All"
fontDict.FontMatrix = cff.FontMatrix
#add Private from CFF topDict into FontDict
fontDict.Private = copy.deepcopy(cff.Private)
#remove Private from CFF topDict
#cff.Private = None
del cff.Private
font.save("fonts/test.otf", reorderTables=False) The last remaining question is, how do I delete |
Beta Was this translation helpful? Give feedback.
-
I've used something like this in the past (adapted from some internal code, untested): from fontTools.ttLib import TTFont
from fontTools import cffLib
def convertCFFToCIDKeyed(inPath, outPath):
ttFont = TTFont(inPath)
glyphOrder = ttFont.glyphOrder
fontName = ttFont["CFF "].cff.keys()[0]
topDict = ttFont["CFF "].cff.values()[0]
assert topDict.Encoding == "StandardEncoding"
assert topDict.charset == glyphOrder
topDict.ROS = ("Adobe", "Identity", 0) # ???
fontMatrix = topDict.FontMatrix
fontDict = cffLib.FontDict()
fontDict.FontName = fontName
fontDict.FontMatrix = fontMatrix
fontDict.Private = topDict.Private
del topDict.Private
topDict.FDArray = cffLib.FDArrayIndex()
topDict.FDArray.append(fontDict)
topDict.FDSelect = cffLib.FDSelect()
topDict.FDSelect.format = None
topDict.FDSelect.gidArray = [0] * len(glyphOrder)
topDict.CIDCount = len(glyphOrder)
# We'll temporarily monkeypatch cffLib's getCIDfromName() so we can
# provide our own glyph name -> CID mapping. (For now: GID == CID.)
revGlyphOrder = {gn: gid for gid, gn in enumerate(glyphOrder)}
def getCIDfromName(name, strings):
return revGlyphOrder[name]
original_getCIDfromName = cffLib.getCIDfromName
try:
cffLib.getCIDfromName = getCIDfromName
ttFont.save(outPath)
finally:
cffLib.getCIDfromName = original_getCIDfromName |
Beta Was this translation helpful? Give feedback.
-
My final code: import copy
from fontTools import ttLib
from fontTools.cffLib import (
FDArrayIndex,
FontDict,
FDSelect,
)
font = ttLib.TTFont("fonts/in.otf")
glyphOrder = font.getGlyphOrder()
cff = font['CFF '].cff.values()[0]
fontName = font["CFF "].cff.keys()[0]
cff.ROS = ('Adobe','Identity',0)
cff.Copyright = cff.Copyright.replace("\n", " ")
mapping = {name:("cid"+str(n) if n else ".notdef") for n,name in enumerate(cff.charset)}
charstrings = cff.CharStrings
charstrings.charStrings = {mapping[name]:v for name,v in charstrings.charStrings.items()}
cff.charset = ["cid"+str(n) if n else ".notdef" for n in range(len(cff.charset))]
#sample from https://github.com/fonttools/fonttools/blob/21d22ae30f88b76fab5575f5f2e882b142ee1c08/Lib/fontTools/varLib/cff.py#L64
if not hasattr(cff, "FDArray"):
#format 3 FDSelect
cff.FDSelect = FDSelect(None, None, 3)
#create FDArray
fdArray = cff.FDArray = FDArrayIndex()
fdArray.strings = None
fdArray.GlobalSubrs = cff.GlobalSubrs
cff.GlobalSubrs.fdArray = fdArray
if charstrings.charStringsAreIndexed:
charstrings.charStringsIndex.fdArray = fdArray
else:
charstrings.fdArray = fdArray
#set FDSelectIndex = 0 for every T2CharString in GlobalSubrs
for item in charstrings.keys():
charstrings[item].fdSelectIndex = 0
#create FontDict in FDArray
fontDict = FontDict() #default index 0
fdArray.append(fontDict)
#generate fontdict name
fontDict.FontName = fontName +"-All"
#add Private from CFF topDict into FontDict
fontDict.Private = copy.deepcopy(cff.Private)
#remove Private from CFF topDict
#cff.Private = None
del cff.Private
del cff.rawDict["Private"]
font.save("fonts/test.otf", reorderTables=False) The only problem left is that the font saved shows up as "not a valid font" on Windows, but using |
Beta Was this translation helpful? Give feedback.
-
Btw. I have opened #2725 based on this discussion. |
Beta Was this translation helpful? Give feedback.
-
import copy
from fontTools import ttLib
from fontTools.cffLib import (
FDArrayIndex,
FontDict,
FDSelect,
)
font = ttLib.TTFont("fonts/in.otf")
glyphOrder = font.getGlyphOrder()
cff = font["CFF "].cff.values()[0]
fontName = font["CFF "].cff.keys()[0]
cff.ROS = ("Adobe", "Identity", 0)
# delete encoding when converting to CID-keyed
del cff.rawDict["Encoding"]
mapping = {
name: ("cid" + str(n) if n else ".notdef") for n, name in enumerate(cff.charset)
}
charstrings = cff.CharStrings
charstrings.charStrings = {
mapping[name]: v for name, v in charstrings.charStrings.items()
}
cff.charset = ["cid" + str(n) if n else ".notdef" for n in range(len(cff.charset))]
# sample from https://github.com/fonttools/fonttools/blob/21d22ae30f88b76fab5575f5f2e882b142ee1c08/Lib/fontTools/varLib/cff.py#L64
if not hasattr(cff, "FDArray"):
# format 3 FDSelect
cff.FDSelect = FDSelect(None, None, 3)
# create FDArray
fdArray = cff.FDArray = FDArrayIndex()
fdArray.strings = None
fdArray.GlobalSubrs = cff.GlobalSubrs
cff.GlobalSubrs.fdArray = fdArray
if charstrings.charStringsAreIndexed:
charstrings.charStringsIndex.fdArray = fdArray
else:
charstrings.fdArray = fdArray
# set FDSelectIndex = 0 for every T2CharString in GlobalSubrs
for item in charstrings.keys():
charstrings[item].fdSelectIndex = 0
# create FontDict in FDArray
fontDict = FontDict() # default index 0
fdArray.append(fontDict)
# generate fontdict name
fontDict.FontName = fontName + "-All"
# add Private from CFF topDict into FontDict
fontDict.Private = copy.deepcopy(cff.Private)
# remove Private from CFF topDict
# cff.Private = None
del cff.Private
del cff.rawDict["Private"] #remove raw data to prevent rebuilding, see https://github.com/fonttools/fonttools/issues/2725
font.save("fonts/out.otf", reorderTables=False) |
Beta Was this translation helpful? Give feedback.
-
I have copied this code: #147, and now I want to move Private from topDict into a FDArray/FontDict as directly converting it to CID-key makes the font invalid. Example: before
after:
How can I achieve this in Python?
Beta Was this translation helpful? Give feedback.
All reactions