Coverage for /usr/lib/python3/dist-packages/fontTools/ttLib/tables/_s_b_i_x.py: 23%

69 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1from fontTools.misc import sstruct 

2from fontTools.misc.textTools import safeEval, num2binary, binary2num 

3from . import DefaultTable 

4from .sbixStrike import Strike 

5 

6 

7sbixHeaderFormat = """ 

8 > 

9 version: H # Version number (set to 1) 

10 flags: H # The only two bits used in the flags field are bits 0 

11 # and 1. For historical reasons, bit 0 must always be 1. 

12 # Bit 1 is a sbixDrawOutlines flag and is interpreted as 

13 # follows: 

14 # 0: Draw only 'sbix' bitmaps 

15 # 1: Draw both 'sbix' bitmaps and outlines, in that 

16 # order 

17 numStrikes: L # Number of bitmap strikes to follow 

18""" 

19sbixHeaderFormatSize = sstruct.calcsize(sbixHeaderFormat) 

20 

21 

22sbixStrikeOffsetFormat = """ 

23 > 

24 strikeOffset: L # Offset from begining of table to data for the 

25 # individual strike 

26""" 

27sbixStrikeOffsetFormatSize = sstruct.calcsize(sbixStrikeOffsetFormat) 

28 

29 

30class table__s_b_i_x(DefaultTable.DefaultTable): 

31 def __init__(self, tag=None): 

32 DefaultTable.DefaultTable.__init__(self, tag) 

33 self.version = 1 

34 self.flags = 1 

35 self.numStrikes = 0 

36 self.strikes = {} 

37 self.strikeOffsets = [] 

38 

39 def decompile(self, data, ttFont): 

40 # read table header 

41 sstruct.unpack(sbixHeaderFormat, data[:sbixHeaderFormatSize], self) 

42 # collect offsets to individual strikes in self.strikeOffsets 

43 for i in range(self.numStrikes): 

44 current_offset = sbixHeaderFormatSize + i * sbixStrikeOffsetFormatSize 

45 offset_entry = sbixStrikeOffset() 

46 sstruct.unpack( 

47 sbixStrikeOffsetFormat, 

48 data[current_offset : current_offset + sbixStrikeOffsetFormatSize], 

49 offset_entry, 

50 ) 

51 self.strikeOffsets.append(offset_entry.strikeOffset) 

52 

53 # decompile Strikes 

54 for i in range(self.numStrikes - 1, -1, -1): 

55 current_strike = Strike(rawdata=data[self.strikeOffsets[i] :]) 

56 data = data[: self.strikeOffsets[i]] 

57 current_strike.decompile(ttFont) 

58 # print " Strike length: %xh" % len(bitmapSetData) 

59 # print "Number of Glyph entries:", len(current_strike.glyphs) 

60 if current_strike.ppem in self.strikes: 

61 from fontTools import ttLib 

62 

63 raise ttLib.TTLibError("Pixel 'ppem' must be unique for each Strike") 

64 self.strikes[current_strike.ppem] = current_strike 

65 

66 # after the glyph data records have been extracted, we don't need the offsets anymore 

67 del self.strikeOffsets 

68 del self.numStrikes 

69 

70 def compile(self, ttFont): 

71 sbixData = b"" 

72 self.numStrikes = len(self.strikes) 

73 sbixHeader = sstruct.pack(sbixHeaderFormat, self) 

74 

75 # calculate offset to start of first strike 

76 setOffset = sbixHeaderFormatSize + sbixStrikeOffsetFormatSize * self.numStrikes 

77 

78 for si in sorted(self.strikes.keys()): 

79 current_strike = self.strikes[si] 

80 current_strike.compile(ttFont) 

81 # append offset to this strike to table header 

82 current_strike.strikeOffset = setOffset 

83 sbixHeader += sstruct.pack(sbixStrikeOffsetFormat, current_strike) 

84 setOffset += len(current_strike.data) 

85 sbixData += current_strike.data 

86 

87 return sbixHeader + sbixData 

88 

89 def toXML(self, xmlWriter, ttFont): 

90 xmlWriter.simpletag("version", value=self.version) 

91 xmlWriter.newline() 

92 xmlWriter.simpletag("flags", value=num2binary(self.flags, 16)) 

93 xmlWriter.newline() 

94 for i in sorted(self.strikes.keys()): 

95 self.strikes[i].toXML(xmlWriter, ttFont) 

96 

97 def fromXML(self, name, attrs, content, ttFont): 

98 if name == "version": 

99 setattr(self, name, safeEval(attrs["value"])) 

100 elif name == "flags": 

101 setattr(self, name, binary2num(attrs["value"])) 

102 elif name == "strike": 

103 current_strike = Strike() 

104 for element in content: 

105 if isinstance(element, tuple): 

106 name, attrs, content = element 

107 current_strike.fromXML(name, attrs, content, ttFont) 

108 self.strikes[current_strike.ppem] = current_strike 

109 else: 

110 from fontTools import ttLib 

111 

112 raise ttLib.TTLibError("can't handle '%s' element" % name) 

113 

114 

115# Helper classes 

116 

117 

118class sbixStrikeOffset(object): 

119 pass