1 from __future__ import print_function, division, absolute_import 2 from fontTools.misc.py23 import * 3 from fontTools.ttLib.ttFont import TTFont 4 from fontTools.ttLib.sfnt import readTTCHeader, writeTTCHeader 5 import struct 6 import logging 7 8 log = logging.getLogger(__name__) 9 10 11 class TTCollection(object): 12 13 """Object representing a TrueType Collection / OpenType Collection. 14 The main API is self.fonts being a list of TTFont instances. 15 16 If shareTables is True, then different fonts in the collection 17 might point to the same table object if the data for the table was 18 the same in the font file. Note, however, that this might result 19 in suprises and incorrect behavior if the different fonts involved 20 have different GlyphOrder. Use only if you know what you are doing. 21 """ 22 23 def __init__(self, file=None, shareTables=False, **kwargs): 24 fonts = self.fonts = [] 25 if file is None: 26 return 27 28 assert 'fontNumber' not in kwargs, kwargs 29 30 if not hasattr(file, "read"): 31 file = open(file, "rb") 32 33 tableCache = {} if shareTables else None 34 35 header = readTTCHeader(file) 36 for i in range(header.numFonts): 37 font = TTFont(file, fontNumber=i, _tableCache=tableCache, **kwargs) 38 fonts.append(font) 39 40 def save(self, file, shareTables=True): 41 """Save the font to disk. Similarly to the constructor, 42 the 'file' argument can be either a pathname or a writable 43 file object. 44 """ 45 if not hasattr(file, "write"): 46 final = None 47 file = open(file, "wb") 48 else: 49 # assume "file" is a writable file object 50 # write to a temporary stream to allow saving to unseekable streams 51 final = file 52 file = BytesIO() 53 54 tableCache = {} if shareTables else None 55 56 offsets_offset = writeTTCHeader(file, len(self.fonts)) 57 offsets = [] 58 for font in self.fonts: 59 offsets.append(file.tell()) 60 font._save(file, tableCache=tableCache) 61 file.seek(0,2) 62 63 file.seek(offsets_offset) 64 file.write(struct.pack(">%dL" % len(self.fonts), *offsets)) 65 66 if final: 67 final.write(file.getvalue()) 68 file.close() 69 70 def saveXML(self, fileOrPath, newlinestr=None, writeVersion=True, **kwargs): 71 72 from fontTools.misc import xmlWriter 73 writer = xmlWriter.XMLWriter(fileOrPath, newlinestr=newlinestr) 74 75 if writeVersion: 76 from fontTools import version 77 version = ".".join(version.split('.')[:2]) 78 writer.begintag("ttCollection", ttLibVersion=version) 79 else: 80 writer.begintag("ttCollection") 81 writer.newline() 82 writer.newline() 83 84 for font in self.fonts: 85 font._saveXML(writer, writeVersion=False, **kwargs) 86 writer.newline() 87 88 writer.endtag("ttCollection") 89 writer.newline() 90 91 writer.close() 92 93 94 def __getitem__(self, item): 95 return self.fonts[item] 96 97 def __setitem__(self, item, value): 98 self.fonts[item] = values 99 100 def __delitem__(self, item): 101 return self.fonts[item] 102 103 def __len__(self): 104 return len(self.fonts) 105 106 def __iter__(self): 107 return iter(self.fonts) 108