Ejemplo n.º 1
0
 def compile(self, ttFont):
     keys = sorted(self.data.keys())
     headerSize = sstruct.calcsize(META_HEADER_FORMAT)
     dataOffset = headerSize + len(keys) * sstruct.calcsize(DATA_MAP_FORMAT)
     header = sstruct.pack(
         META_HEADER_FORMAT, {
             "version": 1,
             "flags": 0,
             "dataOffset": dataOffset,
             "numDataMaps": len(keys)
         })
     dataMaps = []
     dataBlocks = []
     for tag in keys:
         if tag in ["dlng", "slng"]:
             data = self.data[tag].encode("utf-8")
         else:
             data = self.data[tag]
         dataMaps.append(
             sstruct.pack(DATA_MAP_FORMAT, {
                 "tag": tag,
                 "dataOffset": dataOffset,
                 "dataLength": len(data)
             }))
         dataBlocks.append(data)
         dataOffset += len(data)
     return bytesjoin([header] + dataMaps + dataBlocks)
Ejemplo n.º 2
0
 def compile(self, ttFont):
     keys = sorted(self.data.keys())
     headerSize = sstruct.calcsize(META_HEADER_FORMAT)
     dataOffset = headerSize + len(keys) * sstruct.calcsize(DATA_MAP_FORMAT)
     header = sstruct.pack(META_HEADER_FORMAT, {
             "version": 1,
             "flags": 0,
             "dataOffset": dataOffset,
             "numDataMaps": len(keys)
     })
     dataMaps = []
     dataBlocks = []
     for tag in keys:
         if tag in ["dlng", "slng"]:
             data = self.data[tag].encode("utf-8")
         else:
             data = self.data[tag]
         dataMaps.append(sstruct.pack(DATA_MAP_FORMAT, {
             "tag": tag,
             "dataOffset": dataOffset,
             "dataLength": len(data)
         }))
         dataBlocks.append(data)
         dataOffset += len(data)
     return bytesjoin([header] + dataMaps + dataBlocks)
Ejemplo n.º 3
0
    def decompile(self, data, ttFont):
        pos = 0  # track current position from to start of VDMX table
        dummy, data = sstruct.unpack2(VDMX_HeaderFmt, data, self)
        pos += sstruct.calcsize(VDMX_HeaderFmt)
        self.ratRanges = []
        for i in range(self.numRatios):
            ratio, data = sstruct.unpack2(VDMX_RatRangeFmt, data)
            pos += sstruct.calcsize(VDMX_RatRangeFmt)
            # the mapping between a ratio and a group is defined further below
            ratio['groupIndex'] = None
            self.ratRanges.append(ratio)
        lenOffset = struct.calcsize('>H')
        _offsets = []  # temporarily store offsets to groups
        for i in range(self.numRatios):
            offset = struct.unpack('>H', data[0:lenOffset])[0]
            data = data[lenOffset:]
            pos += lenOffset
            _offsets.append(offset)
        self.groups = []
        for groupIndex in range(self.numRecs):
            # the offset to this group from beginning of the VDMX table
            currOffset = pos
            group, data = sstruct.unpack2(VDMX_GroupFmt, data)
            # the group lenght and bounding sizes are re-calculated on compile
            recs = group.pop('recs')
            startsz = group.pop('startsz')
            endsz = group.pop('endsz')
            pos += sstruct.calcsize(VDMX_GroupFmt)
            for j in range(recs):
                vTable, data = sstruct.unpack2(VDMX_vTableFmt, data)
                vTableLength = sstruct.calcsize(VDMX_vTableFmt)
                pos += vTableLength
                # group is a dict of (yMax, yMin) tuples keyed by yPelHeight
                group[vTable['yPelHeight']] = (vTable['yMax'], vTable['yMin'])
            # make sure startsz and endsz match the calculated values
            minSize = min(group.keys())
            maxSize = max(group.keys())
            assert startsz == minSize, \
                "startsz (%s) must equal min yPelHeight (%s): group %d" % \
                (group.startsz, minSize, groupIndex)
            assert endsz == maxSize, \
                "endsz (%s) must equal max yPelHeight (%s): group %d" % \
                (group.endsz, maxSize, groupIndex)
            self.groups.append(group)
            # match the defined offsets with the current group's offset
            for offsetIndex, offsetValue in enumerate(_offsets):
                # when numRecs < numRatios there can more than one ratio range
                # sharing the same VDMX group
                if currOffset == offsetValue:
                    # map the group with the ratio range thas has the same
                    # index as the offset to that group (it took me a while..)
                    self.ratRanges[offsetIndex]['groupIndex'] = groupIndex
        # check that all ratio ranges have a group
        for i in range(self.numRatios):
            ratio = self.ratRanges[i]
            if ratio['groupIndex'] is None:
                from fontTools import ttLib

                raise ttLib.TTLibError(
                    "no group defined for ratRange %d" % i)
Ejemplo n.º 4
0
	def decompile(self, data, ttFont):
		pos = 0  # track current position from to start of VDMX table
		dummy, data = sstruct.unpack2(VDMX_HeaderFmt, data, self)
		pos += sstruct.calcsize(VDMX_HeaderFmt)
		self.ratRanges = []
		for i in range(self.numRatios):
			ratio, data = sstruct.unpack2(VDMX_RatRangeFmt, data)
			pos += sstruct.calcsize(VDMX_RatRangeFmt)
			# the mapping between a ratio and a group is defined further below
			ratio['groupIndex'] = None
			self.ratRanges.append(ratio)
		lenOffset = struct.calcsize('>H')
		_offsets = []  # temporarily store offsets to groups
		for i in range(self.numRatios):
			offset = struct.unpack('>H', data[0:lenOffset])[0]
			data = data[lenOffset:]
			pos += lenOffset
			_offsets.append(offset)
		self.groups = []
		for groupIndex in range(self.numRecs):
			# the offset to this group from beginning of the VDMX table
			currOffset = pos
			group, data = sstruct.unpack2(VDMX_GroupFmt, data)
			# the group lenght and bounding sizes are re-calculated on compile
			recs = group.pop('recs')
			startsz = group.pop('startsz')
			endsz = group.pop('endsz')
			pos += sstruct.calcsize(VDMX_GroupFmt)
			for j in range(recs):
				vTable, data = sstruct.unpack2(VDMX_vTableFmt, data)
				vTableLength = sstruct.calcsize(VDMX_vTableFmt)
				pos += vTableLength
				# group is a dict of (yMax, yMin) tuples keyed by yPelHeight
				group[vTable['yPelHeight']] = (vTable['yMax'], vTable['yMin'])
			# make sure startsz and endsz match the calculated values
			minSize = min(group.keys())
			maxSize = max(group.keys())
			assert startsz == minSize, \
				"startsz (%s) must equal min yPelHeight (%s): group %d" % \
				(group.startsz, minSize, groupIndex)
			assert endsz == maxSize, \
				"endsz (%s) must equal max yPelHeight (%s): group %d" % \
				(group.endsz, maxSize, groupIndex)
			self.groups.append(group)
			# match the defined offsets with the current group's offset
			for offsetIndex, offsetValue in enumerate(_offsets):
				# when numRecs < numRatios there can more than one ratio range
				# sharing the same VDMX group
				if currOffset == offsetValue:
					# map the group with the ratio range thas has the same
					# index as the offset to that group (it took me a while..)
					self.ratRanges[offsetIndex]['groupIndex'] = groupIndex
		# check that all ratio ranges have a group
		for i in range(self.numRatios):
			ratio = self.ratRanges[i]
			if ratio['groupIndex'] is None:
				from fontTools import ttLib
				raise ttLib.TTLibError(
					"no group defined for ratRange %d" % i)
Ejemplo n.º 5
0
 def decompile(self, data, ttFont, version=2.0):
     if version >= 3.0:
         _, data = sstruct.unpack2(Silf_part1_format_v3, data, self)
         self.ruleVersion = float(
             floatToFixedToStr(self.ruleVersion, precisionBits=16))
     _, data = sstruct.unpack2(Silf_part1_format, data, self)
     for jlevel in range(self.numJLevels):
         j, data = sstruct.unpack2(Silf_justify_format, data, _Object())
         self.jLevels.append(j)
     _, data = sstruct.unpack2(Silf_part2_format, data, self)
     if self.numCritFeatures:
         self.critFeatures = struct.unpack_from(
             ('>%dH' % self.numCritFeatures), data)
     data = data[self.numCritFeatures * 2 + 1:]
     (numScriptTag, ) = struct.unpack_from('B', data)
     if numScriptTag:
         self.scriptTags = [
             struct.unpack("4s", data[x:x + 4])[0].decode("ascii")
             for x in range(1, 1 + 4 * numScriptTag, 4)
         ]
     data = data[1 + 4 * numScriptTag:]
     (self.lbGID, ) = struct.unpack('>H', data[:2])
     if self.numPasses:
         self.oPasses = struct.unpack(('>%dL' % (self.numPasses + 1)),
                                      data[2:6 + 4 * self.numPasses])
     data = data[6 + 4 * self.numPasses:]
     (numPseudo, ) = struct.unpack(">H", data[:2])
     for i in range(numPseudo):
         if version >= 3.0:
             pseudo = sstruct.unpack(Silf_pseudomap_format,
                                     data[8 + 6 * i:14 + 6 * i], _Object())
         else:
             pseudo = sstruct.unpack(Silf_pseudomap_format_h,
                                     data[8 + 4 * i:12 + 4 * i], _Object())
         self.pMap[pseudo.unicode] = ttFont.getGlyphName(pseudo.nPseudo)
     data = data[8 + 6 * numPseudo:]
     currpos = (sstruct.calcsize(Silf_part1_format) +
                sstruct.calcsize(Silf_justify_format) * self.numJLevels +
                sstruct.calcsize(Silf_part2_format) +
                2 * self.numCritFeatures + 1 + 1 + 4 * numScriptTag + 6 +
                4 * self.numPasses + 8 + 6 * numPseudo)
     if version >= 3.0:
         currpos += sstruct.calcsize(Silf_part1_format_v3)
     self.classes = Classes()
     self.classes.decompile(data, ttFont, version)
     for i in range(self.numPasses):
         p = Pass()
         self.passes.append(p)
         p.decompile(
             data[self.oPasses[i] - currpos:self.oPasses[i + 1] - currpos],
             ttFont, version)
Ejemplo n.º 6
0
 def decompile(self, data, ttFont):
     headerSize = sstruct.calcsize(META_HEADER_FORMAT)
     header = sstruct.unpack(META_HEADER_FORMAT, data[0:headerSize])
     if header["version"] != 1:
         raise TTLibError("unsupported 'meta' version %d" %
                          header["version"])
     dataMapSize = sstruct.calcsize(DATA_MAP_FORMAT)
     for i in range(header["numDataMaps"]):
         dataMapOffset = headerSize + i * dataMapSize
         dataMap = sstruct.unpack(
             DATA_MAP_FORMAT,
             data[dataMapOffset:dataMapOffset + dataMapSize])
         tag = dataMap["tag"]
         offset = dataMap["dataOffset"]
         self.data[tag] = data[offset:offset + dataMap["dataLength"]]
Ejemplo n.º 7
0
 def decompile(self, data, ttFont):
     headerSize = sstruct.calcsize(META_HEADER_FORMAT)
     header = sstruct.unpack(META_HEADER_FORMAT, data[0 : headerSize])
     if header["version"] != 1:
         raise TTLibError("unsupported 'meta' version %d" %
                          header["version"])
     dataMapSize = sstruct.calcsize(DATA_MAP_FORMAT)
     for i in range(header["numDataMaps"]):
         dataMapOffset = headerSize + i * dataMapSize
         dataMap = sstruct.unpack(
             DATA_MAP_FORMAT,
             data[dataMapOffset : dataMapOffset + dataMapSize])
         tag = dataMap["tag"]
         offset = dataMap["dataOffset"]
         self.data[tag] = data[offset : offset + dataMap["dataLength"]]
Ejemplo n.º 8
0
 def compile(self, ttFont):
     header = {
         "version": 0x00010000,
         "offsetToData": sstruct.calcsize(FVAR_HEADER_FORMAT),
         "countSizePairs": 2,
         "axisCount": len(self.axes),
         "axisSize": sstruct.calcsize(FVAR_AXIS_FORMAT),
         "instanceCount": len(self.instances),
         "instanceSize": sstruct.calcsize(FVAR_INSTANCE_FORMAT) + len(self.axes) * 4
     }
     result = [sstruct.pack(FVAR_HEADER_FORMAT, header)]
     result.extend([axis.compile() for axis in self.axes])
     axisTags = [axis.axisTag for axis in self.axes]
     result.extend([instance.compile(axisTags) for instance in self.instances])
     return bytesjoin(result)
Ejemplo n.º 9
0
 def decompile(self, data, axisTags):
     sstruct.unpack2(FVAR_INSTANCE_FORMAT, data, self)
     pos = sstruct.calcsize(FVAR_INSTANCE_FORMAT)
     for axis in axisTags:
         value = struct.unpack(">l", data[pos:pos + 4])[0]
         self.coordinates[axis] = fixedToFloat(value, 16)
         pos += 4
Ejemplo n.º 10
0
 def decompile(self, data, axisTags):
     sstruct.unpack2(FVAR_INSTANCE_FORMAT, data, self)
     pos = sstruct.calcsize(FVAR_INSTANCE_FORMAT)
     for axis in axisTags:
         value = struct.unpack(">l", data[pos : pos + 4])[0]
         self.coordinates[axis] = fixedToFloat(value, 16)
         pos += 4
 def __init__(self, refNum):
     self.__fileName = array.array("c", "\0" * 64)
     sstruct.unpack(_FCBPBFormat, "\0" * sstruct.calcsize(_FCBPBFormat),
                    self)
     self.ioNamePtr = self.__fileName.buffer_info()[0]
     self.ioRefNum = refNum
     self.ioVRefNum = GetVRefNum(refNum)
     self.__haveInfo = 0
Ejemplo n.º 12
0
	def __init__(self, refNum):
		self.__fileName = array.array("c", "\0" * 64)
		sstruct.unpack(_FCBPBFormat, 
				"\0" * sstruct.calcsize(_FCBPBFormat), self)
		self.ioNamePtr = self.__fileName.buffer_info()[0]
		self.ioRefNum = refNum
		self.ioVRefNum = GetVRefNum(refNum)
		self.__haveInfo = 0
Ejemplo n.º 13
0
 def compile(self, ttFont):
     instanceSize = sstruct.calcsize(FVAR_INSTANCE_FORMAT) + (len(self.axes) * 4)
     includePostScriptNames = any(instance.postscriptNameID != 0xFFFF for instance in self.instances)
     if includePostScriptNames:
         instanceSize += 2
     header = {
         "version": 0x00010000,
         "offsetToData": sstruct.calcsize(FVAR_HEADER_FORMAT),
         "countSizePairs": 2,
         "axisCount": len(self.axes),
         "axisSize": sstruct.calcsize(FVAR_AXIS_FORMAT),
         "instanceCount": len(self.instances),
         "instanceSize": instanceSize,
     }
     result = [sstruct.pack(FVAR_HEADER_FORMAT, header)]
     result.extend([axis.compile() for axis in self.axes])
     axisTags = [axis.axisTag for axis in self.axes]
     for instance in self.instances:
         result.append(instance.compile(axisTags, includePostScriptNames))
     return bytesjoin(result)
Ejemplo n.º 14
0
 def decompile(self, data, axisTags):
     sstruct.unpack2(FVAR_INSTANCE_FORMAT, data, self)
     pos = sstruct.calcsize(FVAR_INSTANCE_FORMAT)
     for axis in axisTags:
         value = struct.unpack(">l", data[pos : pos + 4])[0]
         self.coordinates[axis] = fixedToFloat(value, 16)
         pos += 4
     if pos + 2 <= len(data):
         self.postscriptNameID = struct.unpack(">H", data[pos : pos + 2])[0]
     else:
         self.postscriptNameID = 0xFFFF
Ejemplo n.º 15
0
 def decompile(self, data, axisTags):
     sstruct.unpack2(FVAR_INSTANCE_FORMAT, data, self)
     pos = sstruct.calcsize(FVAR_INSTANCE_FORMAT)
     for axis in axisTags:
         value = struct.unpack(">l", data[pos:pos + 4])[0]
         self.coordinates[axis] = fixedToFloat(value, 16)
         pos += 4
     if pos + 2 <= len(data):
         self.postscriptNameID = struct.unpack(">H", data[pos:pos + 2])[0]
     else:
         self.postscriptNameID = 0xFFFF
Ejemplo n.º 16
0
	def decompile(self, data, ttFont):
		dummy, data = sstruct.unpack2(OS2_format_0, data, self)
		# workarounds for buggy fonts (Apple, mona)
		if not data:
			self.version = 0
		elif len(data) == sstruct.calcsize(OS2_format_1_addition):
			self.version = 1
		elif len(data) == sstruct.calcsize(OS2_format_2_addition):
			if self.version not in (2, 3, 4):
				self.version = 1
		else:
			from fontTools import ttLib
			raise ttLib.TTLibError, "unknown format for OS/2 table (incorrect length): version %s" % (self.version, len(data))
		if self.version == 1:
			sstruct.unpack2(OS2_format_1_addition, data, self)
		elif self.version in (2, 3, 4):
			sstruct.unpack2(OS2_format_2_addition, data, self)
		elif self.version <> 0:
			from fontTools import ttLib
			raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
		self.panose = sstruct.unpack(panoseFormat, self.panose, Panose())
Ejemplo n.º 17
0
 def compile(self, ttFont):
     instanceSize = sstruct.calcsize(FVAR_INSTANCE_FORMAT) + (len(self.axes) * 4)
     includePostScriptNames = any(instance.postscriptNameID != 0xFFFF
                                  for instance in self.instances)
     if includePostScriptNames:
         instanceSize += 2
     header = {
         "version": 0x00010000,
         "offsetToData": sstruct.calcsize(FVAR_HEADER_FORMAT),
         "countSizePairs": 2,
         "axisCount": len(self.axes),
         "axisSize": sstruct.calcsize(FVAR_AXIS_FORMAT),
         "instanceCount": len(self.instances),
         "instanceSize": instanceSize,
     }
     result = [sstruct.pack(FVAR_HEADER_FORMAT, header)]
     result.extend([axis.compile() for axis in self.axes])
     axisTags = [axis.axisTag for axis in self.axes]
     for instance in self.instances:
         result.append(instance.compile(axisTags, includePostScriptNames))
     return bytesjoin(result)
Ejemplo n.º 18
0
    def decompile(self, data, ttFont):
        sstruct.unpack2(Silf_hdr_format, data, self)
        if self.version >= 5.0:
            (data, self.scheme) = grUtils.decompress(data)
            sstruct.unpack2(Silf_hdr_format_3, data, self)
            base = sstruct.calcsize(Silf_hdr_format_3)
        elif self.version < 3.0:
            self.numSilf = struct.unpack('>H', data[4:6])
            self.scheme = 0
            self.compilerVersion = 0
            base = 8
        else:
            self.scheme = 0
            sstruct.unpack2(Silf_hdr_format_3, data, self)
            base = sstruct.calcsize(Silf_hdr_format_3)

        silfoffsets = struct.unpack_from(('>%dL' % self.numSilf), data[base:])
        for offset in silfoffsets:
            s = Silf()
            self.silfs.append(s)
            s.decompile(data[offset:], ttFont, self.version)
Ejemplo n.º 19
0
    def decompile(self, data, ttFont):
        sstruct.unpack2(Silf_hdr_format, data, self)
        if self.version >= 5.0:
            (data, self.scheme) = grUtils.decompress(data)
            sstruct.unpack2(Silf_hdr_format_3, data, self)
            base = sstruct.calcsize(Silf_hdr_format_3)
        elif self.version < 3.0:
            self.numSilf = struct.unpack('>H', data[4:6])
            self.scheme = 0
            self.compilerVersion = 0
            base = 8
        else:
            self.scheme = 0
            sstruct.unpack2(Silf_hdr_format_3, data, self)
            base = sstruct.calcsize(Silf_hdr_format_3)

        silfoffsets = struct.unpack_from(('>%dL' % self.numSilf), data[base:])
        for offset in silfoffsets:
            s = Silf()
            self.silfs.append(s)
            s.decompile(data[offset:], ttFont, self.version)
Ejemplo n.º 20
0
 def decompile(self, data, ttFont, version=2.0):
     if version >= 3.0 :
         _, data = sstruct.unpack2(Silf_part1_format_v3, data, self)
     _, data = sstruct.unpack2(Silf_part1_format, data, self)
     for jlevel in range(self.numJLevels):
         j, data = sstruct.unpack2(Silf_justify_format, data, _Object())
         self.jLevels.append(j)
     _, data = sstruct.unpack2(Silf_part2_format, data, self)
     if self.numCritFeatures:
         self.critFeatures = struct.unpack_from(('>%dH' % self.numCritFeatures), data)
     data = data[self.numCritFeatures * 2 + 1:]
     (numScriptTag,) = struct.unpack_from('B', data)
     if numScriptTag:
         self.scriptTags = [struct.unpack("4s", data[x:x+4])[0] for x in range(1, 1 + 4 * numScriptTag, 4)]
     data = data[1 + 4 * numScriptTag:]
     (self.lbGID,) = struct.unpack('>H', data[:2])
     if self.numPasses:
         self.oPasses = struct.unpack(('>%dL' % (self.numPasses+1)), data[2:6+4*self.numPasses])
     data = data[6 + 4 * self.numPasses:]
     (numPseudo,) = struct.unpack(">H", data[:2])
     for i in range(numPseudo):
         if version >= 3.0:
             pseudo = sstruct.unpack(Silf_pseudomap_format, data[8+6*i:14+6*i], _Object())
         else:
             pseudo = sstruct.unpack(Silf_pseudomap_format_h, data[8+4*i:12+4*i], _Object())
         self.pMap[pseudo.unicode] = ttFont.getGlyphName(pseudo.nPseudo)
     data = data[8 + 6 * numPseudo:]
     currpos = (sstruct.calcsize(Silf_part1_format)
                 + sstruct.calcsize(Silf_justify_format) * self.numJLevels
                 + sstruct.calcsize(Silf_part2_format) + 2 * self.numCritFeatures
                 + 1 + 1 + 4 * numScriptTag + 6 + 4 * self.numPasses + 8 + 6 * numPseudo)
     if version >= 3.0:
         currpos += sstruct.calcsize(Silf_part1_format_v3)
     self.classes = Classes()
     self.classes.decompile(data, ttFont, version)
     for i in range(self.numPasses):
         p = Pass()
         self.passes.append(p)
         p.decompile(data[self.oPasses[i]-currpos:self.oPasses[i+1]-currpos],
                     ttFont, version)
Ejemplo n.º 21
0
 def compile(self, ttFont):
     header = {
         "version":
         0x00010000,
         "offsetToData":
         sstruct.calcsize(FVAR_HEADER_FORMAT),
         "countSizePairs":
         2,
         "axisCount":
         len(self.axes),
         "axisSize":
         sstruct.calcsize(FVAR_AXIS_FORMAT),
         "instanceCount":
         len(self.instances),
         "instanceSize":
         sstruct.calcsize(FVAR_INSTANCE_FORMAT) + len(self.axes) * 4
     }
     result = [sstruct.pack(FVAR_HEADER_FORMAT, header)]
     result.extend([axis.compile() for axis in self.axes])
     axisTags = [axis.axisTag for axis in self.axes]
     result.extend(
         [instance.compile(axisTags) for instance in self.instances])
     return bytesjoin(result)
Ejemplo n.º 22
0
 def compile(self, ttFont, base, version=2.0):
     # build it all up backwards
     oActions = reduce(lambda a, x: (a[0] + len(x), a[1] + [a[0]]),
                       self.actions + [b""], (0, []))[1]
     oConstraints = reduce(lambda a, x: (a[0] + len(x), a[1] + [a[0]]),
                           self.ruleConstraints + [b""], (1, []))[1]
     constraintCode = b"\000" + b"".join(self.ruleConstraints)
     transes = []
     for t in self.stateTrans:
         if sys.byteorder != "big": t.byteswap()
         transes.append(t.tobytes())
         if sys.byteorder != "big": t.byteswap()
     if not len(transes):
         self.startStates = [0]
     oRuleMap = reduce(lambda a, x: (a[0] + len(x), a[1] + [a[0]]),
                       self.rules + [[]], (0, []))[1]
     passRanges = []
     gidcolmap = dict([(ttFont.getGlyphID(x[0]), x[1])
                       for x in self.colMap.items()])
     for e in grUtils.entries(gidcolmap, sameval=True):
         if e[1]:
             passRanges.append((e[0], e[0] + e[1] - 1, e[2][0]))
     self.numRules = len(self.actions)
     self.fsmOffset = (sstruct.calcsize(Silf_pass_format) + 8 +
                       len(passRanges) * 6 + len(oRuleMap) * 2 +
                       2 * oRuleMap[-1] + 2 + 2 * len(self.startStates) +
                       3 * self.numRules + 3 + 4 * self.numRules + 4)
     self.pcCode = self.fsmOffset + 2 * self.numTransitional * self.numColumns + 1 + base
     self.rcCode = self.pcCode + len(self.passConstraints)
     self.aCode = self.rcCode + len(constraintCode)
     self.oDebug = 0
     # now generate output
     data = sstruct.pack(Silf_pass_format, self)
     data += grUtils.bininfo(len(passRanges), 6)
     data += b"".join(struct.pack(">3H", *p) for p in passRanges)
     data += struct.pack((">%dH" % len(oRuleMap)), *oRuleMap)
     flatrules = reduce(lambda a, x: a + x, self.rules, [])
     data += struct.pack((">%dH" % oRuleMap[-1]), *flatrules)
     data += struct.pack("BB", self.minRulePreContext,
                         self.maxRulePreContext)
     data += struct.pack((">%dH" % len(self.startStates)),
                         *self.startStates)
     data += struct.pack((">%dH" % self.numRules), *self.ruleSortKeys)
     data += struct.pack(("%dB" % self.numRules), *self.rulePreContexts)
     data += struct.pack(">BH", self.collisionThreshold,
                         len(self.passConstraints))
     data += struct.pack((">%dH" % (self.numRules + 1)), *oConstraints)
     data += struct.pack((">%dH" % (self.numRules + 1)), *oActions)
     return data + b"".join(transes) + struct.pack("B", 0) + \
             self.passConstraints + constraintCode + b"".join(self.actions)
Ejemplo n.º 23
0
	def _getOffsets(self):
		"""
		Calculate offsets to VDMX_Group records.
		For each ratRange return a list of offset values from the beginning of
		the VDMX table to a VDMX_Group.
		"""
		lenHeader = sstruct.calcsize(VDMX_HeaderFmt)
		lenRatRange = sstruct.calcsize(VDMX_RatRangeFmt)
		lenOffset = struct.calcsize('>H')
		lenGroupHeader = sstruct.calcsize(VDMX_GroupFmt)
		lenVTable = sstruct.calcsize(VDMX_vTableFmt)
		# offset to the first group
		pos = lenHeader + self.numRatios*lenRatRange + self.numRatios*lenOffset
		groupOffsets = []
		for group in self.groups:
			groupOffsets.append(pos)
			lenGroup = lenGroupHeader + len(group) * lenVTable
			pos += lenGroup  # offset to next group
		offsets = []
		for ratio in self.ratRanges:
			groupIndex = ratio['groupIndex']
			offsets.append(groupOffsets[groupIndex])
		return offsets
Ejemplo n.º 24
0
    def compile(self, ttFont, version=2.0):
        self.numPasses = len(self.passes)
        self.numJLevels = len(self.jLevels)
        self.numCritFeatures = len(self.critFeatures)
        numPseudo = len(self.pMap)
        data = b""
        if version >= 3.0:
            hdroffset = sstruct.calcsize(Silf_part1_format_v3)
        else:
            hdroffset = 0
        data += sstruct.pack(Silf_part1_format, self)
        for j in self.jLevels:
            data += sstruct.pack(Silf_justify_format, j)
        data += sstruct.pack(Silf_part2_format, self)
        if self.numCritFeatures:
            data += struct.pack((">%dH" % self.numCritFeaturs),
                                *self.critFeatures)
        data += struct.pack("BB", 0, len(self.scriptTags))
        if len(self.scriptTags):
            tdata = [
                struct.pack("4s", x.encode("ascii")) for x in self.scriptTags
            ]
            data += b"".join(tdata)
        data += struct.pack(">H", self.lbGID)
        self.passOffset = len(data)

        data1 = grUtils.bininfo(numPseudo, 6)
        currpos = hdroffset + len(data) + 4 * (self.numPasses + 1)
        self.pseudosOffset = currpos + len(data1)
        for u, p in sorted(self.pMap.items()):
            data1 += struct.pack((">LH" if version >= 3.0 else ">HH"), u,
                                 ttFont.getGlyphID(p))
        data1 += self.classes.compile(ttFont, version)
        currpos += len(data1)
        data2 = b""
        datao = b""
        for i, p in enumerate(self.passes):
            base = currpos + len(data2)
            datao += struct.pack(">L", base)
            data2 += p.compile(ttFont, base, version)
        datao += struct.pack(">L", currpos + len(data2))

        if version >= 3.0:
            data3 = sstruct.pack(Silf_part1_format_v3, self)
        else:
            data3 = b""
        return data3 + data + datao + data1 + data2
Ejemplo n.º 25
0
 def decompile(self, data, ttFont):
     axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
     header = {}
     headerSize = sstruct.calcsize(AVAR_HEADER_FORMAT)
     header = sstruct.unpack(AVAR_HEADER_FORMAT, data[0:headerSize])
     majorVersion = header["majorVersion"]
     if majorVersion != 1:
         raise TTLibError("unsupported 'avar' version %d" % majorVersion)
     pos = headerSize
     for axis in axisTags:
         segments = self.segments[axis] = {}
         numPairs = struct.unpack(">H", data[pos:pos+2])[0]
         pos = pos + 2
         for _ in range(numPairs):
             fromValue, toValue = struct.unpack(">hh", data[pos:pos+4])
             segments[fixedToFloat(fromValue, 14)] = fixedToFloat(toValue, 14)
             pos = pos + 4
Ejemplo n.º 26
0
 def decompile(self, data, ttFont):
     axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
     header = {}
     headerSize = sstruct.calcsize(AVAR_HEADER_FORMAT)
     header = sstruct.unpack(AVAR_HEADER_FORMAT, data[0:headerSize])
     if header["version"] != 0x00010000:
         raise TTLibError("unsupported 'avar' version %04x" % header["version"])
     pos = headerSize
     for axis in axisTags:
         segments = self.segments[axis] = {}
         numPairs = struct.unpack(">H", data[pos:pos+2])[0]
         pos = pos + 2
         for _ in range(numPairs):
             fromValue, toValue = struct.unpack(">hh", data[pos:pos+4])
             segments[fixedToFloat(fromValue, 14)] = fixedToFloat(toValue, 14)
             pos = pos + 4
     self.fixupSegments_(warn=warnings.warn)
Ejemplo n.º 27
0
 def decompile(self, data, ttFont):
     axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
     header = {}
     headerSize = sstruct.calcsize(AVAR_HEADER_FORMAT)
     header = sstruct.unpack(AVAR_HEADER_FORMAT, data[0:headerSize])
     majorVersion = header["majorVersion"]
     if majorVersion != 1:
         raise TTLibError("unsupported 'avar' version %d" % majorVersion)
     pos = headerSize
     for axis in axisTags:
         segments = self.segments[axis] = {}
         numPairs = struct.unpack(">H", data[pos:pos + 2])[0]
         pos = pos + 2
         for _ in range(numPairs):
             fromValue, toValue = struct.unpack(">hh", data[pos:pos + 4])
             segments[fi2fl(fromValue, 14)] = fi2fl(toValue, 14)
             pos = pos + 4
Ejemplo n.º 28
0
	def compile(self, ttFont):
		packed = sstruct.pack(DSIG_HeaderFormat, self)
		headers = [packed]
		offset = len(packed) + self.usNumSigs * sstruct.calcsize(DSIG_SignatureFormat)
		data = []
		for sigrec in self.signatureRecords:
			# first pack signature block
			sigrec.cbSignature = len(sigrec.pkcs7)
			packed = sstruct.pack(DSIG_SignatureBlockFormat, sigrec) + sigrec.pkcs7
			data.append(packed)
			# update redundant length field
			sigrec.ulLength = len(packed)
			# update running table offset
			sigrec.ulOffset = offset
			headers.append(sstruct.pack(DSIG_SignatureFormat, sigrec))
			offset += sigrec.ulLength
		return ''.join(headers+data)
Ejemplo n.º 29
0
    def compile(self, ttFont, version=2.0):
        self.numPasses = len(self.passes)
        self.numJLevels = len(self.jLevels)
        self.numCritFeatures = len(self.critFeatures)
        numPseudo = len(self.pMap)
        data = b""
        if version >= 3.0:
            hdroffset = sstruct.calcsize(Silf_part1_format_v3)
        else:
            hdroffset = 0
        data += sstruct.pack(Silf_part1_format, self)
        for j in self.jLevels:
            data += sstruct.pack(Silf_justify_format, j)
        data += sstruct.pack(Silf_part2_format, self)
        if self.numCritFeatures:
            data += struct.pack((">%dH" % self.numCritFeaturs), *self.critFeatures)
        data += struct.pack("BB", 0, len(self.scriptTags))
        if len(self.scriptTags):
            tdata = [struct.pack("4s", x) for x in self.scriptTags]
            data += "".join(tdata)
        data += struct.pack(">H", self.lbGID)
        self.passOffset = len(data)

        data1 = grUtils.bininfo(numPseudo, 6)
        currpos = hdroffset + len(data) + 4 * (self.numPasses + 1)
        self.pseudosOffset = currpos + len(data1)
        for u, p in sorted(self.pMap.items()):
            data1 += struct.pack((">LH" if version >= 3.0 else ">HH"),
                                u, ttFont.getGlyphID(p))
        data1 += self.classes.compile(ttFont, version)
        currpos += len(data1)
        data2 = b""
        datao = b""
        for i, p in enumerate(self.passes):
            base = currpos + len(data2)
            datao += struct.pack(">L", base)
            data2 += p.compile(ttFont, base, version)
        datao += struct.pack(">L", currpos + len(data2))

        if version >= 3.0:
            data3 = sstruct.pack(Silf_part1_format_v3, self)
        else:
            data3 = b""
        return data3 + data + datao + data1 + data2
Ejemplo n.º 30
0
 def compile(self, ttFont, base, version=2.0):
     # build it all up backwards
     oActions = reduce(lambda a, x: (a[0]+len(x), a[1]+[a[0]]), self.actions + [b""], (0, []))[1]
     oConstraints = reduce(lambda a, x: (a[0]+len(x), a[1]+[a[0]]), self.ruleConstraints + [b""], (1, []))[1]
     constraintCode = b"\000" + b"".join(self.ruleConstraints)
     transes = []
     for t in self.stateTrans:
         if sys.byteorder != "big": t.byteswap()
         transes.append(t.tostring())
         if sys.byteorder != "big": t.byteswap()
     if not len(transes):
         self.startStates = [0]
     oRuleMap = reduce(lambda a, x: (a[0]+len(x), a[1]+[a[0]]), self.rules+[[]], (0, []))[1]
     passRanges = []
     gidcolmap = dict([(ttFont.getGlyphID(x[0]), x[1]) for x in self.colMap.items()])
     for e in grUtils.entries(gidcolmap, sameval = True):
         if e[1]:
             passRanges.append((e[0], e[0]+e[1]-1, e[2][0]))
     self.numRules = len(self.actions)
     self.fsmOffset = (sstruct.calcsize(Silf_pass_format) + 8 + len(passRanges) * 6
                 + len(oRuleMap) * 2 + 2 * oRuleMap[-1] + 2
                 + 2 * len(self.startStates) + 3 * self.numRules + 3
                 + 4 * self.numRules + 4)
     self.pcCode = self.fsmOffset + 2*self.numTransitional*self.numColumns + 1 + base
     self.rcCode = self.pcCode + len(self.passConstraints)
     self.aCode = self.rcCode + len(constraintCode)
     self.oDebug = 0
     # now generate output
     data = sstruct.pack(Silf_pass_format, self)
     data += grUtils.bininfo(len(passRanges), 6)
     data += b"".join(struct.pack(">3H", *p) for p in passRanges)
     data += struct.pack((">%dH" % len(oRuleMap)), *oRuleMap)
     flatrules = reduce(lambda a,x: a+x, self.rules, [])
     data += struct.pack((">%dH" % oRuleMap[-1]), *flatrules)
     data += struct.pack("BB", self.minRulePreContext, self.maxRulePreContext)
     data += struct.pack((">%dH" % len(self.startStates)), *self.startStates)
     data += struct.pack((">%dH" % self.numRules), *self.ruleSortKeys)
     data += struct.pack(("%dB" % self.numRules), *self.rulePreContexts)
     data += struct.pack(">BH", self.collisionThreshold, len(self.passConstraints))
     data += struct.pack((">%dH" % (self.numRules+1)), *oConstraints)
     data += struct.pack((">%dH" % (self.numRules+1)), *oActions)
     return data + b"".join(transes) + struct.pack("B", 0) + \
             self.passConstraints + constraintCode + b"".join(self.actions)
Ejemplo n.º 31
0
 def decompile(self, data, ttFont):
     axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
     header = {}
     headerSize = sstruct.calcsize(AVAR_HEADER_FORMAT)
     header = sstruct.unpack(AVAR_HEADER_FORMAT, data[0:headerSize])
     if header["version"] != 0x00010000:
         raise TTLibError("unsupported 'avar' version %04x" %
                          header["version"])
     pos = headerSize
     for axis in axisTags:
         segments = self.segments[axis] = {}
         numPairs = struct.unpack(">H", data[pos:pos + 2])[0]
         pos = pos + 2
         for _ in range(numPairs):
             fromValue, toValue = struct.unpack(">hh", data[pos:pos + 4])
             segments[fixedToFloat(fromValue,
                                   14)] = fixedToFloat(toValue, 14)
             pos = pos + 4
     self.fixupSegments_()
Ejemplo n.º 32
0
 def decompile(self, data, ttFont):
     header = {}
     headerSize = sstruct.calcsize(FVAR_HEADER_FORMAT)
     header = sstruct.unpack(FVAR_HEADER_FORMAT, data[0:headerSize])
     if header["version"] != 0x00010000:
         raise TTLibError("unsupported 'fvar' version %04x" % header["version"])
     pos = header["offsetToData"]
     axisSize = header["axisSize"]
     for _ in range(header["axisCount"]):
         axis = Axis()
         axis.decompile(data[pos:pos+axisSize])
         self.axes.append(axis)
         pos += axisSize
     instanceSize = header["instanceSize"]
     axisTags = [axis.axisTag for axis in self.axes]
     for _ in range(header["instanceCount"]):
         instance = NamedInstance()
         instance.decompile(data[pos:pos+instanceSize], axisTags)
         self.instances.append(instance)
         pos += instanceSize
Ejemplo n.º 33
0
 def decompile(self, data, ttFont):
     header = {}
     headerSize = sstruct.calcsize(FVAR_HEADER_FORMAT)
     header = sstruct.unpack(FVAR_HEADER_FORMAT, data[0:headerSize])
     if header["version"] != 0x00010000:
         raise TTLibError("unsupported 'fvar' version %04x" % header["version"])
     pos = header["offsetToData"]
     axisSize = header["axisSize"]
     for _ in range(header["axisCount"]):
         axis = Axis()
         axis.decompile(data[pos : pos + axisSize])
         self.axes.append(axis)
         pos += axisSize
     instanceSize = header["instanceSize"]
     axisTags = [axis.axisTag for axis in self.axes]
     for _ in range(header["instanceCount"]):
         instance = NamedInstance()
         instance.decompile(data[pos : pos + instanceSize], axisTags)
         self.instances.append(instance)
         pos += instanceSize
Ejemplo n.º 34
0
	def compile(self, ttFont):
		packed = sstruct.pack(DSIG_HeaderFormat, self)
		headers = [packed]
		offset = len(packed) + self.usNumSigs * sstruct.calcsize(DSIG_SignatureFormat)
		data = []
		for sigrec in self.signatureRecords:
			# first pack signature block
			sigrec.cbSignature = len(sigrec.pkcs7)
			packed = sstruct.pack(DSIG_SignatureBlockFormat, sigrec) + sigrec.pkcs7
			data.append(packed)
			# update redundant length field
			sigrec.ulLength = len(packed)
			# update running table offset
			sigrec.ulOffset = offset
			headers.append(sstruct.pack(DSIG_SignatureFormat, sigrec))
			offset += sigrec.ulLength
		if offset % 2:
			# Pad to even bytes
			data.append(b'\0')
		return bytesjoin(headers+data)
Ejemplo n.º 35
0
	def compile(self, ttFont):
		if not hasattr(self, "names"):
			# only happens when there are NO name table entries read
			# from the TTX file
			self.names = []
		self.names.sort()  # sort according to the spec; see NameRecord.__lt__()
		stringData = b""
		format = 0
		n = len(self.names)
		stringOffset = 6 + n * sstruct.calcsize(nameRecordFormat)
		data = struct.pack(">HHH", format, n, stringOffset)
		lastoffset = 0
		done = {}  # remember the data so we can reuse the "pointers"
		for name in self.names:
			if name.string in done:
				name.offset, name.length = done[name.string]
			else:
				name.offset, name.length = done[name.string] = len(stringData), len(name.string)
				stringData = stringData + name.string
			data = data + sstruct.pack(nameRecordFormat, name)
		return data + stringData
 def compile(self, ttFont):
     if not hasattr(self, "names"):
         # only happens when there are NO name table entries read
         # from the TTX file
         self.names = []
     self.names.sort(
     )  # sort according to the spec; see NameRecord.__lt__()
     stringData = b""
     format = 0
     n = len(self.names)
     stringOffset = 6 + n * sstruct.calcsize(nameRecordFormat)
     data = struct.pack(">HHH", format, n, stringOffset)
     lastoffset = 0
     done = {}  # remember the data so we can reuse the "pointers"
     for name in self.names:
         if name.string in done:
             name.offset, name.length = done[name.string]
         else:
             name.offset, name.length = done[name.string] = len(
                 stringData), len(name.string)
             stringData = stringData + name.string
         data = data + sstruct.pack(nameRecordFormat, name)
     return data + stringData
Ejemplo n.º 37
0
from collections.abc import Sequence
from dataclasses import dataclass, astuple
from io import BytesIO
import struct
import logging

log = logging.getLogger(__name__)

SVG_format_0 = """
	>   # big endian
	version:                  H
	offsetToSVGDocIndex:      L
	reserved:                 L
"""

SVG_format_0Size = sstruct.calcsize(SVG_format_0)

doc_index_entry_format_0 = """
	>   # big endian
	startGlyphID:             H
	endGlyphID:               H
	svgDocOffset:             L
	svgDocLength:             L
"""

doc_index_entry_format_0Size = sstruct.calcsize(doc_index_entry_format_0)


class table_S_V_G_(DefaultTable.DefaultTable):
    def decompile(self, data, ttFont):
        self.docList = []
Ejemplo n.º 38
0
the number of <colorParamUINameID> elements.

"""

XML = ET.XML
XMLElement = ET.Element
xmlToString = ET.tostring

SVG_format_0 = """
	>   # big endian
	version:                  H
	offsetToSVGDocIndex:      L
	offsetToColorPalettes:    L
"""

SVG_format_0Size = sstruct.calcsize(SVG_format_0)

SVG_format_1 = """
	>   # big endian
	version:                  H
	numIndicies:              H
"""

SVG_format_1Size = sstruct.calcsize(SVG_format_1)

doc_index_entry_format_0 = """
	>   # big endian
	startGlyphID:             H
	endGlyphID:               H
	svgDocOffset:             L
	svgDocLength:             L
sbixStrikeHeaderFormat = """
	>
	ppem:            H    # The PPEM for which this strike was designed (e.g., 9,
	                      # 12, 24)
	resolution:      H    # The screen resolution (in dpi) for which this strike
	                      # was designed (e.g., 72)
"""

sbixGlyphDataOffsetFormat = """
	>
	glyphDataOffset: L    # Offset from the beginning of the strike data record
                        # to data for the individual glyph
"""

sbixStrikeHeaderFormatSize = sstruct.calcsize(sbixStrikeHeaderFormat)
sbixGlyphDataOffsetFormatSize = sstruct.calcsize(sbixGlyphDataOffsetFormat)


class Strike(object):
	def __init__(self, rawdata=None, ppem=0, resolution=72):
		self.data = rawdata
		self.ppem = ppem
		self.resolution = resolution
		self.glyphs = {}

	def decompile(self, ttFont):
		if self.data is None:
			from fontTools import ttLib
			raise ttLib.TTLibError
		if len(self.data) < sbixStrikeHeaderFormatSize:
Ejemplo n.º 40
0
from fontTools.misc.textTools import safeEval
from fontTools.misc.encodingTools import getEncoding
from . import DefaultTable
import struct

nameRecordFormat = """
		>	# big endian
		platformID:	H
		platEncID:	H
		langID:		H
		nameID:		H
		length:		H
		offset:		H
"""

nameRecordSize = sstruct.calcsize(nameRecordFormat)


class table__n_a_m_e(DefaultTable.DefaultTable):
	
	def decompile(self, data, ttFont):
		format, n, stringOffset = struct.unpack(">HHH", data[:6])
		expectedStringOffset = 6 + n * nameRecordSize
		if stringOffset != expectedStringOffset:
			# XXX we need a warn function
			print("Warning: 'name' table stringOffset incorrect. Expected: %s; Actual: %s" % (expectedStringOffset, stringOffset))
		stringData = data[stringOffset:]
		data = data[6:]
		self.names = []
		for i in range(n):
			if len(data) < 12:
Ejemplo n.º 41
0
import logging


log = logging.getLogger(__name__)

# Apple's documentation of 'avar':
# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6avar.html

AVAR_HEADER_FORMAT = """
    > # big endian
    majorVersion:  H
    minorVersion:  H
    reserved:      H
    axisCount:     H
"""
assert sstruct.calcsize(AVAR_HEADER_FORMAT) == 8, sstruct.calcsize(AVAR_HEADER_FORMAT)


class table__a_v_a_r(DefaultTable.DefaultTable):

    dependencies = ["fvar"]

    def __init__(self, tag=None):
        DefaultTable.DefaultTable.__init__(self, tag)
        self.segments = {}

    def compile(self, ttFont):
        axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
        header = {
            "majorVersion": 1,
            "minorVersion": 0,
Ejemplo n.º 42
0

# -- sfnt directory helpers and cruft

ttcHeaderFormat = """
		> # big endian
		TTCTag:                  4s # "ttcf"
		Version:                 L  # 0x00010000 or 0x00020000
		numFonts:                L  # number of fonts
		# OffsetTable[numFonts]: L  # array with offsets from beginning of file
		# ulDsigTag:             L  # version 2.0 only
		# ulDsigLength:          L  # version 2.0 only
		# ulDsigOffset:          L  # version 2.0 only
"""

ttcHeaderSize = sstruct.calcsize(ttcHeaderFormat)

sfntDirectoryFormat = """
		> # big endian
		sfntVersion:    4s
		numTables:      H    # number of tables
		searchRange:    H    # (max2 <= numTables)*16
		entrySelector:  H    # log2(max2 <= numTables)
		rangeShift:     H    # numTables*16-searchRange
"""

sfntDirectorySize = sstruct.calcsize(sfntDirectoryFormat)

sfntDirectoryEntryFormat = """
		> # big endian
		tag:            4s
Ejemplo n.º 43
0
			return
		absNameOffset = reader.absNameListOffset + self.nameOffset
		nameLength, = struct.unpack('B', reader._read(1, absNameOffset))
		name, = struct.unpack('>%ss' % nameLength, reader._read(nameLength))
		self.name = tostr(name, encoding='mac-roman')


ResourceForkHeader = """
		> # big endian
		dataOffset:     L
		mapOffset:      L
		dataLen:        L
		mapLen:         L
"""

ResourceForkHeaderSize = sstruct.calcsize(ResourceForkHeader)

ResourceMapHeader = """
		> # big endian
		attr:              H
		typeListOffset:    H
		nameListOffset:    H
"""

ResourceMapHeaderSize = sstruct.calcsize(ResourceMapHeader)

ResourceTypeItem = """
		> # big endian
		type:              4s
		numRes:            H
		refListOffset:     H
Ejemplo n.º 44
0
import array

postFormat = """
	>
	formatType:			16.16F
	italicAngle:		16.16F		# italic angle in degrees			
	underlinePosition:	h
	underlineThickness:	h
	isFixedPitch:		L
	minMemType42:		L			# minimum memory if TrueType font is downloaded
	maxMemType42:		L			# maximum memory if TrueType font is downloaded
	minMemType1:		L			# minimum memory if Type1 font is downloaded
	maxMemType1:		L			# maximum memory if Type1 font is downloaded
"""

postFormatSize = sstruct.calcsize(postFormat)


class table__p_o_s_t(DefaultTable.DefaultTable):
    def decompile(self, data, ttFont):
        sstruct.unpack(postFormat, data[:postFormatSize], self)
        data = data[postFormatSize:]
        if self.formatType == 1.0:
            self.decode_format_1_0(data, ttFont)
        elif self.formatType == 2.0:
            self.decode_format_2_0(data, ttFont)
        elif self.formatType == 3.0:
            self.decode_format_3_0(data, ttFont)
        elif self.formatType == 4.0:
            self.decode_format_4_0(data, ttFont)
        else:
Ejemplo n.º 45
0

# -- sfnt directory helpers and cruft

ttcHeaderFormat = """
		> # big endian
		TTCTag:                  4s # "ttcf"
		Version:                 L  # 0x00010000 or 0x00020000
		numFonts:                L  # number of fonts
		# OffsetTable[numFonts]: L  # array with offsets from beginning of file
		# ulDsigTag:             L  # version 2.0 only
		# ulDsigLength:          L  # version 2.0 only
		# ulDsigOffset:          L  # version 2.0 only
"""

ttcHeaderSize = sstruct.calcsize(ttcHeaderFormat)

sfntDirectoryFormat = """
		> # big endian
		sfntVersion:    4s
		numTables:      H    # number of tables
		searchRange:    H    # (max2 <= numTables)*16
		entrySelector:  H    # log2(max2 <= numTables)
		rangeShift:     H    # numTables*16-searchRange
"""

sfntDirectorySize = sstruct.calcsize(sfntDirectoryFormat)

sfntDirectoryEntryFormat = """
		> # big endian
		tag:            4s
Ejemplo n.º 46
0
except ImportError:
    from UserDict import DictMixin as MutableMapping

# Apple's documentation of 'trak':
# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html

TRAK_HEADER_FORMAT = """
	> # big endian
	version:     16.16F
	format:      H
	horizOffset: H
	vertOffset:  H
	reserved:    H
"""

TRAK_HEADER_FORMAT_SIZE = sstruct.calcsize(TRAK_HEADER_FORMAT)

TRACK_DATA_FORMAT = """
	> # big endian
	nTracks:         H
	nSizes:          H
	sizeTableOffset: L
"""

TRACK_DATA_FORMAT_SIZE = sstruct.calcsize(TRACK_DATA_FORMAT)

TRACK_TABLE_ENTRY_FORMAT = """
	> # big endian
	track:      16.16F
	nameIndex:       H
	offset:          H
Ejemplo n.º 47
0

bitmap:

ULONG         reserved                 00 00 00 00
char[4]       format                   data type, e.g. "png "
(Variable)    bitmap data
"""

sbixHeaderFormat = """
	>
	usVal1:          H    # 00 01
	usVal2:          H    #       00 01
	numSets:         L    # 00 00 00 02 # number of bitmap sets
"""
sbixHeaderFormatSize = sstruct.calcsize(sbixHeaderFormat)


sbixBitmapSetOffsetFormat = """
	>
	offset:          L    # 00 00 00 10 # offset from table start to each bitmap set
"""
sbixBitmapSetOffsetFormatSize = sstruct.calcsize(sbixBitmapSetOffsetFormat)


class table__s_b_i_x(DefaultTable.DefaultTable):
	def __init__(self, tag):
		self.tableTag = tag
		self.usVal1 = 1
		self.usVal2 = 1
		self.numSets = 0
Ejemplo n.º 48
0
sbixStrikeHeaderFormat = """
	>
	ppem:          H	# The PPEM for which this strike was designed (e.g., 9,
						# 12, 24)
	resolution:    H	# The screen resolution (in dpi) for which this strike
						# was designed (e.g., 72)
"""

sbixGlyphDataOffsetFormat = """
	>
	glyphDataOffset:   L	# Offset from the beginning of the strike data record
							# to data for the individual glyph
"""

sbixStrikeHeaderFormatSize = sstruct.calcsize(sbixStrikeHeaderFormat)
sbixGlyphDataOffsetFormatSize = sstruct.calcsize(sbixGlyphDataOffsetFormat)


class Strike(object):
    def __init__(self, rawdata=None, ppem=0, resolution=72):
        self.data = rawdata
        self.ppem = ppem
        self.resolution = resolution
        self.glyphs = {}

    def decompile(self, ttFont):
        if self.data is None:
            from fontTools import ttLib
            raise ttLib.TTLibError
        if len(self.data) < sbixStrikeHeaderFormatSize:
Ejemplo n.º 49
0
	def compile(self, ttFont):

		dataList = []
		self.numSizes = len(self.strikes)
		dataList.append(sstruct.pack(eblcHeaderFormat, self))

		# Data size of the header + bitmapSizeTable needs to be calculated
		# in order to form offsets. This value will hold the size of the data
		# in dataList after all the data is consolidated in dataList.
		dataSize = len(dataList[0])

		# The table will be structured in the following order:
		# (0) header
		# (1) Each bitmapSizeTable [1 ... self.numSizes]
		# (2) Alternate between indexSubTableArray and indexSubTable
		#     for each bitmapSizeTable present.
		#
		# The issue is maintaining the proper offsets when table information
		# gets moved around. All offsets and size information must be recalculated
		# when building the table to allow editing within ttLib and also allow easy
		# import/export to and from XML. All of this offset information is lost
		# when exporting to XML so everything must be calculated fresh so importing
		# from XML will work cleanly. Only byte offset and size information is
		# calculated fresh. Count information like numberOfIndexSubTables is
		# checked through assertions. If the information in this table was not
		# touched or was changed properly then these types of values should match.
		#
		# The table will be rebuilt the following way:
		# (0) Precompute the size of all the bitmapSizeTables. This is needed to
		#     compute the offsets properly.
		# (1) For each bitmapSizeTable compute the indexSubTable and
		#    	indexSubTableArray pair. The indexSubTable must be computed first
		#     so that the offset information in indexSubTableArray can be
		#     calculated. Update the data size after each pairing.
		# (2) Build each bitmapSizeTable.
		# (3) Consolidate all the data into the main dataList in the correct order.

		for curStrike in self.strikes:
			dataSize += sstruct.calcsize(bitmapSizeTableFormatPart1)
			dataSize += len(('hori', 'vert')) * sstruct.calcsize(sbitLineMetricsFormat)
			dataSize += sstruct.calcsize(bitmapSizeTableFormatPart2)

		indexSubTablePairDataList = []
		for curStrike in self.strikes:
			curTable = curStrike.bitmapSizeTable
			curTable.numberOfIndexSubTables = len(curStrike.indexSubTables)
			curTable.indexSubTableArrayOffset = dataSize

			# Precompute the size of the indexSubTableArray. This information
			# is important for correctly calculating the new value for
			# additionalOffsetToIndexSubtable.
			sizeOfSubTableArray = curTable.numberOfIndexSubTables * indexSubTableArraySize
			lowerBound = dataSize
			dataSize += sizeOfSubTableArray
			upperBound = dataSize

			indexSubTableDataList = []
			for indexSubTable in curStrike.indexSubTables:
				indexSubTable.additionalOffsetToIndexSubtable = dataSize - curTable.indexSubTableArrayOffset
				glyphIds = list(map(ttFont.getGlyphID, indexSubTable.names))
				indexSubTable.firstGlyphIndex = min(glyphIds)
				indexSubTable.lastGlyphIndex = max(glyphIds)
				data = indexSubTable.compile(ttFont)
				indexSubTableDataList.append(data)
				dataSize += len(data)
			curTable.startGlyphIndex = min(ist.firstGlyphIndex for ist in curStrike.indexSubTables)
			curTable.endGlyphIndex = max(ist.lastGlyphIndex for ist in curStrike.indexSubTables)

			for i in curStrike.indexSubTables:
				data = struct.pack(indexSubHeaderFormat, i.firstGlyphIndex, i.lastGlyphIndex, i.additionalOffsetToIndexSubtable)
				indexSubTablePairDataList.append(data)
			indexSubTablePairDataList.extend(indexSubTableDataList)
			curTable.indexTablesSize = dataSize - curTable.indexSubTableArrayOffset

		for curStrike in self.strikes:
			curTable = curStrike.bitmapSizeTable
			data = sstruct.pack(bitmapSizeTableFormatPart1, curTable)
			dataList.append(data)
			for metric in ('hori', 'vert'):
				metricObj = vars(curTable)[metric]
				data = sstruct.pack(sbitLineMetricsFormat, metricObj)
				dataList.append(data)
			data = sstruct.pack(bitmapSizeTableFormatPart2, curTable)
			dataList.append(data)
		dataList.extend(indexSubTablePairDataList)

		return bytesjoin(dataList)
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
from . import DefaultTable
import struct

nameRecordFormat = """
		>	# big endian
		platformID:	H
		platEncID:	H
		langID:		H
		nameID:		H
		length:		H
		offset:		H
"""

nameRecordSize = sstruct.calcsize(nameRecordFormat)


class table__n_a_m_e(DefaultTable.DefaultTable):
    def decompile(self, data, ttFont):
        format, n, stringOffset = struct.unpack(">HHH", data[:6])
        expectedStringOffset = 6 + n * nameRecordSize
        if stringOffset != expectedStringOffset:
            # XXX we need a warn function
            print(
                "Warning: 'name' table stringOffset incorrect. Expected: %s; Actual: %s"
                % (expectedStringOffset, stringOffset))
        stringData = data[stringOffset:]
        data = data[6:]
        self.names = []
        for i in range(n):
Ejemplo n.º 51
0

sbixGlyphHeaderFormat = """
	>
	originOffsetX: h	# The x-value of the point in the glyph relative to its
						# lower-left corner which corresponds to the origin of
						# the glyph on the screen, that is the point on the
						# baseline at the left edge of the glyph.
	originOffsetY: h	# The y-value of the point in the glyph relative to its
						# lower-left corner which corresponds to the origin of
						# the glyph on the screen, that is the point on the
						# baseline at the left edge of the glyph.
	graphicType:  4s	# e.g. "png "
"""

sbixGlyphHeaderFormatSize = sstruct.calcsize(sbixGlyphHeaderFormat)


class Glyph(object):
	def __init__(self, glyphName=None, referenceGlyphName=None, originOffsetX=0, originOffsetY=0, graphicType=None, imageData=None, rawdata=None, gid=0):
		self.gid = gid
		self.glyphName = glyphName
		self.referenceGlyphName = referenceGlyphName
		self.originOffsetX = originOffsetX
		self.originOffsetY = originOffsetY
		self.rawdata = rawdata
		self.graphicType = graphicType
		self.imageData = imageData

		# fix self.graphicType if it is null terminated or too short
		if self.graphicType is not None:
Ejemplo n.º 52
0
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import readHex
import struct


sbixBitmapHeaderFormat = """
	>
	usReserved1:     H    # 00 00
	usReserved2:     H    #       00 00
	imageFormatTag:  4s   # e.g. "png "
"""

sbixBitmapHeaderFormatSize = sstruct.calcsize(sbixBitmapHeaderFormat)


class Bitmap(object):
	def __init__(self, glyphName=None, referenceGlyphName=None, usReserved1=0, usReserved2=0, imageFormatTag=None, imageData=None, rawdata=None, gid=0):
		self.gid = gid
		self.glyphName = glyphName
		self.referenceGlyphName = referenceGlyphName
		self.usReserved1 = usReserved1
		self.usReserved2 = usReserved2
		self.rawdata = rawdata
		self.imageFormatTag = imageFormatTag
		self.imageData = imageData

	def decompile(self, ttFont):
		self.glyphName = ttFont.getGlyphName(self.gid)
		if self.rawdata is None:
Ejemplo n.º 53
0
# FreeType2 source code for parsing 'gvar':
# http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/truetype/ttgxvar.c

GVAR_HEADER_FORMAT = """
	> # big endian
	version:			H
	reserved:			H
	axisCount:			H
	sharedTupleCount:		H
	offsetToSharedTuples:		I
	glyphCount:			H
	flags:				H
	offsetToGlyphVariationData:	I
"""

GVAR_HEADER_SIZE = sstruct.calcsize(GVAR_HEADER_FORMAT)


class table__g_v_a_r(DefaultTable.DefaultTable):
	dependencies = ["fvar", "glyf"]

	def __init__(self, tag=None):
		DefaultTable.DefaultTable.__init__(self, tag)
		self.version, self.reserved = 1, 0
		self.variations = {}

	def compile(self, ttFont):
		axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
		sharedTuples =  tv.compileSharedTuples(
			axisTags, itertools.chain(*self.variations.values()))
		sharedTupleIndices = {coord:i for i, coord in enumerate(sharedTuples)}
Ejemplo n.º 54
0
    def compile(self, ttFont):

        dataList = []
        self.numSizes = len(self.strikes)
        dataList.append(sstruct.pack(eblcHeaderFormat, self))

        # Data size of the header + bitmapSizeTable needs to be calculated
        # in order to form offsets. This value will hold the size of the data
        # in dataList after all the data is consolidated in dataList.
        dataSize = len(dataList[0])

        # The table will be structured in the following order:
        # (0) header
        # (1) Each bitmapSizeTable [1 ... self.numSizes]
        # (2) Alternate between indexSubTableArray and indexSubTable
        #     for each bitmapSizeTable present.
        #
        # The issue is maintaining the proper offsets when table information
        # gets moved around. All offsets and size information must be recalculated
        # when building the table to allow editing within ttLib and also allow easy
        # import/export to and from XML. All of this offset information is lost
        # when exporting to XML so everything must be calculated fresh so importing
        # from XML will work cleanly. Only byte offset and size information is
        # calculated fresh. Count information like numberOfIndexSubTables is
        # checked through assertions. If the information in this table was not
        # touched or was changed properly then these types of values should match.
        #
        # The table will be rebuilt the following way:
        # (0) Precompute the size of all the bitmapSizeTables. This is needed to
        #     compute the offsets properly.
        # (1) For each bitmapSizeTable compute the indexSubTable and
        #    	indexSubTableArray pair. The indexSubTable must be computed first
        #     so that the offset information in indexSubTableArray can be
        #     calculated. Update the data size after each pairing.
        # (2) Build each bitmapSizeTable.
        # (3) Consolidate all the data into the main dataList in the correct order.

        for _ in self.strikes:
            dataSize += sstruct.calcsize(bitmapSizeTableFormatPart1)
            dataSize += len(
                ('hori', 'vert')) * sstruct.calcsize(sbitLineMetricsFormat)
            dataSize += sstruct.calcsize(bitmapSizeTableFormatPart2)

        indexSubTablePairDataList = []
        for curStrike in self.strikes:
            curTable = curStrike.bitmapSizeTable
            curTable.numberOfIndexSubTables = len(curStrike.indexSubTables)
            curTable.indexSubTableArrayOffset = dataSize

            # Precompute the size of the indexSubTableArray. This information
            # is important for correctly calculating the new value for
            # additionalOffsetToIndexSubtable.
            sizeOfSubTableArray = curTable.numberOfIndexSubTables * indexSubTableArraySize
            lowerBound = dataSize
            dataSize += sizeOfSubTableArray
            upperBound = dataSize

            indexSubTableDataList = []
            for indexSubTable in curStrike.indexSubTables:
                indexSubTable.additionalOffsetToIndexSubtable = dataSize - curTable.indexSubTableArrayOffset
                glyphIds = list(map(ttFont.getGlyphID, indexSubTable.names))
                indexSubTable.firstGlyphIndex = min(glyphIds)
                indexSubTable.lastGlyphIndex = max(glyphIds)
                data = indexSubTable.compile(ttFont)
                indexSubTableDataList.append(data)
                dataSize += len(data)
            curTable.startGlyphIndex = min(ist.firstGlyphIndex
                                           for ist in curStrike.indexSubTables)
            curTable.endGlyphIndex = max(ist.lastGlyphIndex
                                         for ist in curStrike.indexSubTables)

            for i in curStrike.indexSubTables:
                data = struct.pack(indexSubHeaderFormat, i.firstGlyphIndex,
                                   i.lastGlyphIndex,
                                   i.additionalOffsetToIndexSubtable)
                indexSubTablePairDataList.append(data)
            indexSubTablePairDataList.extend(indexSubTableDataList)
            curTable.indexTablesSize = dataSize - curTable.indexSubTableArrayOffset

        for curStrike in self.strikes:
            curTable = curStrike.bitmapSizeTable
            data = sstruct.pack(bitmapSizeTableFormatPart1, curTable)
            dataList.append(data)
            for metric in ('hori', 'vert'):
                metricObj = vars(curTable)[metric]
                data = sstruct.pack(sbitLineMetricsFormat, metricObj)
                dataList.append(data)
            data = sstruct.pack(bitmapSizeTableFormatPart2, curTable)
            dataList.append(data)
        dataList.extend(indexSubTablePairDataList)

        return bytesjoin(dataList)
Ejemplo n.º 55
0
    > # big endian
    signature:      4s
    flavor:         4s
    length:         L
    numTables:      H
    reserved:       H
    totalSFNTSize:  L
    majorVersion:   H
    minorVersion:   H
    metaOffset:     L
    metaLength:     L
    metaOrigLength: L
    privOffset:     L
    privLength:     L
"""
woffHeaderSize = sstruct.calcsize(woffHeaderFormat)


class WOFFReader(object):
    def __init__(self, file, checkChecksums=1):
        self.file = file
        self.checkChecksums = checkChecksums
        # unpack the header
        self.file.seek(0)
        bytes = self.file.read(woffHeaderSize)
        if len(bytes) != woffHeaderSize:
            raise WOFFLibError("Not a properly formatted WOFF file.")
        sstruct.unpack(woffHeaderFormat, bytes, self)
        if self.signature != "wOFF":
            raise WOFFLibError("Not a properly formatted WOFF file.")
        # unpack the directory
Ejemplo n.º 56
0
import struct
import logging

log = logging.getLogger(__name__)

# Apple's documentation of 'avar':
# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6avar.html

AVAR_HEADER_FORMAT = """
    > # big endian
    majorVersion:  H
    minorVersion:  H
    reserved:      H
    axisCount:     H
"""
assert sstruct.calcsize(AVAR_HEADER_FORMAT) == 8, sstruct.calcsize(
    AVAR_HEADER_FORMAT)


class table__a_v_a_r(DefaultTable.DefaultTable):

    dependencies = ["fvar"]

    def __init__(self, tag=None):
        DefaultTable.DefaultTable.__init__(self, tag)
        self.segments = {}

    def compile(self, ttFont):
        axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
        header = {
            "majorVersion": 1,
Ejemplo n.º 57
0
		sfntVersion:         4s
		length:              L    # total woff2 file size
		numTables:           H    # number of tables
		reserved:            H    # set to 0
		totalSfntSize:       L    # uncompressed size
		totalCompressedSize: L    # compressed size
		majorVersion:        H    # major version of WOFF file
		minorVersion:        H    # minor version of WOFF file
		metaOffset:          L    # offset to metadata block
		metaLength:          L    # length of compressed metadata
		metaOrigLength:      L    # length of uncompressed metadata
		privOffset:          L    # offset to private data block
		privLength:          L    # length of private data block
"""

woff2DirectorySize = sstruct.calcsize(woff2DirectoryFormat)

woff2KnownTags = ("cmap", "head", "hhea", "hmtx", "maxp", "name", "OS/2",
                  "post", "cvt ", "fpgm", "glyf", "loca", "prep", "CFF ",
                  "VORG", "EBDT", "EBLC", "gasp", "hdmx", "kern", "LTSH",
                  "PCLT", "VDMX", "vhea", "vmtx", "BASE", "GDEF", "GPOS",
                  "GSUB", "EBSC", "JSTF", "MATH", "CBDT", "CBLC", "COLR",
                  "CPAL", "SVG ", "sbix", "acnt", "avar", "bdat", "bloc",
                  "bsln", "cvar", "fdsc", "feat", "fmtx", "fvar", "gvar",
                  "hsty", "just", "lcar", "mort", "morx", "opbd", "prop",
                  "trak", "Zapf", "Silf", "Glat", "Gloc", "Feat", "Sill")

woff2FlagsFormat = """
		> # big endian
		flags: B  # table type and flags
"""
Ejemplo n.º 58
0
# FreeType2 source code for parsing 'gvar':
# http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/truetype/ttgxvar.c

GVAR_HEADER_FORMAT = """
	> # big endian
	version:		H
	reserved:		H
	axisCount:		H
	sharedCoordCount:	H
	offsetToCoord:		I
	glyphCount:		H
	flags:			H
	offsetToData:		I
"""

GVAR_HEADER_SIZE = sstruct.calcsize(GVAR_HEADER_FORMAT)

TUPLES_SHARE_POINT_NUMBERS = 0x8000
TUPLE_COUNT_MASK = 0x0fff

EMBEDDED_TUPLE_COORD = 0x8000
INTERMEDIATE_TUPLE = 0x4000
PRIVATE_POINT_NUMBERS = 0x2000
TUPLE_INDEX_MASK = 0x0fff

DELTAS_ARE_ZERO = 0x80
DELTAS_ARE_WORDS = 0x40
DELTA_RUN_COUNT_MASK = 0x3f

POINTS_ARE_WORDS = 0x80
POINT_RUN_COUNT_MASK = 0x7f
Ejemplo n.º 59
0
			return
		absNameOffset = reader.absNameListOffset + self.nameOffset
		nameLength, = struct.unpack('B', reader._read(1, absNameOffset))
		name, = struct.unpack('>%ss' % nameLength, reader._read(nameLength))
		self.name = tostr(name, encoding='mac-roman')


ResourceForkHeader = """
		> # big endian
		dataOffset:     L
		mapOffset:      L
		dataLen:        L
		mapLen:         L
"""

ResourceForkHeaderSize = sstruct.calcsize(ResourceForkHeader)

ResourceMapHeader = """
		> # big endian
		attr:              H
		typeListOffset:    H
		nameListOffset:    H
"""

ResourceMapHeaderSize = sstruct.calcsize(ResourceMapHeader)

ResourceTypeItem = """
		> # big endian
		type:              4s
		numRes:            H
		refListOffset:     H