aboutsummaryrefslogtreecommitdiff
path: root/Lib/fontTools/ttLib/ttCollection.py
blob: 3db4c8cd3c24a1f83cdafdbb5a9324cdb96a3aeb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
from fontTools.ttLib.ttFont import TTFont
from fontTools.ttLib.sfnt import readTTCHeader, writeTTCHeader
from io import BytesIO
import struct
import logging

log = logging.getLogger(__name__)


class TTCollection(object):

	"""Object representing a TrueType Collection / OpenType Collection.
	The main API is self.fonts being a list of TTFont instances.

	If shareTables is True, then different fonts in the collection
	might point to the same table object if the data for the table was
	the same in the font file.  Note, however, that this might result
	in suprises and incorrect behavior if the different fonts involved
	have different GlyphOrder.  Use only if you know what you are doing.
	"""

	def __init__(self, file=None, shareTables=False, **kwargs):
		fonts = self.fonts = []
		if file is None:
			return

		assert 'fontNumber' not in kwargs, kwargs

		if not hasattr(file, "read"):
			file = open(file, "rb")

		tableCache = {} if shareTables else None

		header = readTTCHeader(file)
		for i in range(header.numFonts):
			font = TTFont(file, fontNumber=i, _tableCache=tableCache, **kwargs)
			fonts.append(font)
			
	def __enter__(self):
		return self
	
	def __exit__(self, type, value, traceback):
		self.close()
		
	def close(self):
		for font in self.fonts:
			font.close()

	def save(self, file, shareTables=True):
		"""Save the font to disk. Similarly to the constructor,
		the 'file' argument can be either a pathname or a writable
		file object.
		"""
		if not hasattr(file, "write"):
			final = None
			file = open(file, "wb")
		else:
			# assume "file" is a writable file object
			# write to a temporary stream to allow saving to unseekable streams
			final = file
			file = BytesIO()

		tableCache = {} if shareTables else None

		offsets_offset = writeTTCHeader(file, len(self.fonts))
		offsets = []
		for font in self.fonts:
			offsets.append(file.tell())
			font._save(file, tableCache=tableCache)
			file.seek(0,2)

		file.seek(offsets_offset)
		file.write(struct.pack(">%dL" % len(self.fonts), *offsets))

		if final:
			final.write(file.getvalue())
		file.close()

	def saveXML(self, fileOrPath, newlinestr=None, writeVersion=True, **kwargs):

		from fontTools.misc import xmlWriter
		writer = xmlWriter.XMLWriter(fileOrPath, newlinestr=newlinestr)

		if writeVersion:
			from fontTools import version
			version = ".".join(version.split('.')[:2])
			writer.begintag("ttCollection", ttLibVersion=version)
		else:
			writer.begintag("ttCollection")
		writer.newline()
		writer.newline()

		for font in self.fonts:
			font._saveXML(writer, writeVersion=False, **kwargs)
			writer.newline()

		writer.endtag("ttCollection")
		writer.newline()

		writer.close()


	def __getitem__(self, item):
		return self.fonts[item]

	def __setitem__(self, item, value):
		self.fonts[item] = value

	def __delitem__(self, item):
		return self.fonts[item]

	def __len__(self):
		return len(self.fonts)

	def __iter__(self):
		return iter(self.fonts)