override SFNTReader __deepcopy__ for 'file' isn't copyable; use it in varLib

This commit is contained in:
Cosimo Lupo 2018-12-20 14:18:59 +00:00
parent 9b4509496f
commit 4001ded199
No known key found for this signature in database
GPG Key ID: 59D54DB0C9976482
4 changed files with 29 additions and 15 deletions

View File

@ -123,6 +123,31 @@ class SFNTReader(object):
def close(self): def close(self):
self.file.close() self.file.close()
def __deepcopy__(self, memo):
"""Overrides the default deepcopy of SFNTReader object, to make it work
in the case when TTFont is loaded with lazy=True, and thus reader holds a
reference to a file object which is not pickleable.
We work around it by manually copying the data into a in-memory stream.
"""
from copy import deepcopy
cls = self.__class__
obj = cls.__new__(cls)
for k, v in self.__dict__.items():
if k == "file":
f = self.file
start = f.tell()
f.seek(0)
buf = BytesIO(f.read())
f.seek(start)
buf.seek(start)
if hasattr(f, "name"):
buf.name = f.name
obj.file = buf
else:
obj.__dict__[k] = deepcopy(v, memo)
return obj
# default compression level for WOFF 1.0 tables and metadata # default compression level for WOFF 1.0 tables and metadata
ZLIB_COMPRESSION_LEVEL = 6 ZLIB_COMPRESSION_LEVEL = 6

View File

@ -693,19 +693,6 @@ class TTFont(object):
""" """
return self["cmap"].getBestCmap(cmapPreferences=cmapPreferences) return self["cmap"].getBestCmap(cmapPreferences=cmapPreferences)
def copy(self):
"""Return a new TTFont instance containing the same data.
>>> f1 = TTFont()
>>> f2 = f1.copy()
>>> f2 is not f1
True
"""
buf = BytesIO()
self.save(buf)
buf.seek(0)
return TTFont(buf)
class _TTGlyphSet(object): class _TTGlyphSet(object):

View File

@ -40,6 +40,7 @@ from fontTools.designspaceLib import DesignSpaceDocument, AxisDescriptor
from collections import OrderedDict, namedtuple from collections import OrderedDict, namedtuple
import os.path import os.path
import logging import logging
from copy import deepcopy
from pprint import pformat from pprint import pformat
log = logging.getLogger("fontTools.varLib") log = logging.getLogger("fontTools.varLib")
@ -764,7 +765,7 @@ def build(designspace, master_finder=lambda s:s, exclude=[], optimize=True):
master_ttfs.append(None) # in-memory fonts have no path master_ttfs.append(None) # in-memory fonts have no path
# Copy the base master to work from it # Copy the base master to work from it
vf = master_fonts[ds.base_idx].copy() vf = deepcopy(master_fonts[ds.base_idx])
# TODO append masters as named-instances as well; needs .designspace change. # TODO append masters as named-instances as well; needs .designspace change.
fvar = _add_fvar(vf, ds.axes, ds.instances) fvar = _add_fvar(vf, ds.axes, ds.instances)

View File

@ -8,6 +8,7 @@ from fontTools.varLib import models, VarLibError, load_designspace, load_masters
from fontTools.varLib.merger import InstancerMerger from fontTools.varLib.merger import InstancerMerger
import os.path import os.path
import logging import logging
from copy import deepcopy
from pprint import pformat from pprint import pformat
log = logging.getLogger("fontTools.varLib.interpolate_layout") log = logging.getLogger("fontTools.varLib.interpolate_layout")
@ -37,7 +38,7 @@ def interpolate_layout(designspace, loc, master_finder=lambda s:s, mapped=False)
log.info("Loading master fonts") log.info("Loading master fonts")
master_fonts = load_masters(designspace, master_finder) master_fonts = load_masters(designspace, master_finder)
font = master_fonts[ds.base_idx].copy() font = deepcopy(master_fonts[ds.base_idx])
log.info("Location: %s", pformat(loc)) log.info("Location: %s", pformat(loc))
if not mapped: if not mapped: