Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/fontTools/ttLib/ttCollection.py: 24%
74 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:33 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:33 +0000
1from fontTools.ttLib.ttFont import TTFont
2from fontTools.ttLib.sfnt import readTTCHeader, writeTTCHeader
3from io import BytesIO
4import struct
5import logging
7log = logging.getLogger(__name__)
10class TTCollection(object):
12 """Object representing a TrueType Collection / OpenType Collection.
13 The main API is self.fonts being a list of TTFont instances.
15 If shareTables is True, then different fonts in the collection
16 might point to the same table object if the data for the table was
17 the same in the font file. Note, however, that this might result
18 in suprises and incorrect behavior if the different fonts involved
19 have different GlyphOrder. Use only if you know what you are doing.
20 """
22 def __init__(self, file=None, shareTables=False, **kwargs):
23 fonts = self.fonts = []
24 if file is None:
25 return
27 assert "fontNumber" not in kwargs, kwargs
29 closeStream = False
30 if not hasattr(file, "read"):
31 file = open(file, "rb")
32 closeStream = True
34 tableCache = {} if shareTables else None
36 header = readTTCHeader(file)
37 for i in range(header.numFonts):
38 font = TTFont(file, fontNumber=i, _tableCache=tableCache, **kwargs)
39 fonts.append(font)
41 # don't close file if lazy=True, as the TTFont hold a reference to the original
42 # file; the file will be closed once the TTFonts are closed in the
43 # TTCollection.close(). We still want to close the file if lazy is None or
44 # False, because in that case the TTFont no longer need the original file
45 # and we want to avoid 'ResourceWarning: unclosed file'.
46 if not kwargs.get("lazy") and closeStream:
47 file.close()
49 def __enter__(self):
50 return self
52 def __exit__(self, type, value, traceback):
53 self.close()
55 def close(self):
56 for font in self.fonts:
57 font.close()
59 def save(self, file, shareTables=True):
60 """Save the font to disk. Similarly to the constructor,
61 the 'file' argument can be either a pathname or a writable
62 file object.
63 """
64 if not hasattr(file, "write"):
65 final = None
66 file = open(file, "wb")
67 else:
68 # assume "file" is a writable file object
69 # write to a temporary stream to allow saving to unseekable streams
70 final = file
71 file = BytesIO()
73 tableCache = {} if shareTables else None
75 offsets_offset = writeTTCHeader(file, len(self.fonts))
76 offsets = []
77 for font in self.fonts:
78 offsets.append(file.tell())
79 font._save(file, tableCache=tableCache)
80 file.seek(0, 2)
82 file.seek(offsets_offset)
83 file.write(struct.pack(">%dL" % len(self.fonts), *offsets))
85 if final:
86 final.write(file.getvalue())
87 file.close()
89 def saveXML(self, fileOrPath, newlinestr="\n", writeVersion=True, **kwargs):
91 from fontTools.misc import xmlWriter
93 writer = xmlWriter.XMLWriter(fileOrPath, newlinestr=newlinestr)
95 if writeVersion:
96 from fontTools import version
98 version = ".".join(version.split(".")[:2])
99 writer.begintag("ttCollection", ttLibVersion=version)
100 else:
101 writer.begintag("ttCollection")
102 writer.newline()
103 writer.newline()
105 for font in self.fonts:
106 font._saveXML(writer, writeVersion=False, **kwargs)
107 writer.newline()
109 writer.endtag("ttCollection")
110 writer.newline()
112 writer.close()
114 def __getitem__(self, item):
115 return self.fonts[item]
117 def __setitem__(self, item, value):
118 self.fonts[item] = value
120 def __delitem__(self, item):
121 return self.fonts[item]
123 def __len__(self):
124 return len(self.fonts)
126 def __iter__(self):
127 return iter(self.fonts)