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

1from fontTools.ttLib.ttFont import TTFont 

2from fontTools.ttLib.sfnt import readTTCHeader, writeTTCHeader 

3from io import BytesIO 

4import struct 

5import logging 

6 

7log = logging.getLogger(__name__) 

8 

9 

10class TTCollection(object): 

11 

12 """Object representing a TrueType Collection / OpenType Collection. 

13 The main API is self.fonts being a list of TTFont instances. 

14 

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 """ 

21 

22 def __init__(self, file=None, shareTables=False, **kwargs): 

23 fonts = self.fonts = [] 

24 if file is None: 

25 return 

26 

27 assert "fontNumber" not in kwargs, kwargs 

28 

29 closeStream = False 

30 if not hasattr(file, "read"): 

31 file = open(file, "rb") 

32 closeStream = True 

33 

34 tableCache = {} if shareTables else None 

35 

36 header = readTTCHeader(file) 

37 for i in range(header.numFonts): 

38 font = TTFont(file, fontNumber=i, _tableCache=tableCache, **kwargs) 

39 fonts.append(font) 

40 

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() 

48 

49 def __enter__(self): 

50 return self 

51 

52 def __exit__(self, type, value, traceback): 

53 self.close() 

54 

55 def close(self): 

56 for font in self.fonts: 

57 font.close() 

58 

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() 

72 

73 tableCache = {} if shareTables else None 

74 

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) 

81 

82 file.seek(offsets_offset) 

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

84 

85 if final: 

86 final.write(file.getvalue()) 

87 file.close() 

88 

89 def saveXML(self, fileOrPath, newlinestr="\n", writeVersion=True, **kwargs): 

90 

91 from fontTools.misc import xmlWriter 

92 

93 writer = xmlWriter.XMLWriter(fileOrPath, newlinestr=newlinestr) 

94 

95 if writeVersion: 

96 from fontTools import version 

97 

98 version = ".".join(version.split(".")[:2]) 

99 writer.begintag("ttCollection", ttLibVersion=version) 

100 else: 

101 writer.begintag("ttCollection") 

102 writer.newline() 

103 writer.newline() 

104 

105 for font in self.fonts: 

106 font._saveXML(writer, writeVersion=False, **kwargs) 

107 writer.newline() 

108 

109 writer.endtag("ttCollection") 

110 writer.newline() 

111 

112 writer.close() 

113 

114 def __getitem__(self, item): 

115 return self.fonts[item] 

116 

117 def __setitem__(self, item, value): 

118 self.fonts[item] = value 

119 

120 def __delitem__(self, item): 

121 return self.fonts[item] 

122 

123 def __len__(self): 

124 return len(self.fonts) 

125 

126 def __iter__(self): 

127 return iter(self.fonts)