diff options
Diffstat (limited to 'Lib/fontTools/ttLib/tables/V_D_M_X_.py')
-rw-r--r-- | Lib/fontTools/ttLib/tables/V_D_M_X_.py | 385 |
1 files changed, 197 insertions, 188 deletions
diff --git a/Lib/fontTools/ttLib/tables/V_D_M_X_.py b/Lib/fontTools/ttLib/tables/V_D_M_X_.py index ba8593f1..0632173c 100644 --- a/Lib/fontTools/ttLib/tables/V_D_M_X_.py +++ b/Lib/fontTools/ttLib/tables/V_D_M_X_.py @@ -37,196 +37,205 @@ VDMX_vTableFmt = """ class table_V_D_M_X_(DefaultTable.DefaultTable): + 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 - 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) + raise ttLib.TTLibError("no group defined for ratRange %d" % i) - 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 + 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 - def compile(self, ttFont): - if not(self.version == 0 or self.version == 1): - from fontTools import ttLib - raise ttLib.TTLibError( - "unknown format for VDMX table: version %s" % self.version) - data = sstruct.pack(VDMX_HeaderFmt, self) - for ratio in self.ratRanges: - data += sstruct.pack(VDMX_RatRangeFmt, ratio) - # recalculate offsets to VDMX groups - for offset in self._getOffsets(): - data += struct.pack('>H', offset) - for group in self.groups: - recs = len(group) - startsz = min(group.keys()) - endsz = max(group.keys()) - gHeader = {'recs': recs, 'startsz': startsz, 'endsz': endsz} - data += sstruct.pack(VDMX_GroupFmt, gHeader) - for yPelHeight, (yMax, yMin) in sorted(group.items()): - vTable = {'yPelHeight': yPelHeight, 'yMax': yMax, 'yMin': yMin} - data += sstruct.pack(VDMX_vTableFmt, vTable) - return data + def compile(self, ttFont): + if not (self.version == 0 or self.version == 1): + from fontTools import ttLib - def toXML(self, writer, ttFont): - writer.simpletag("version", value=self.version) - writer.newline() - writer.begintag("ratRanges") - writer.newline() - for ratio in self.ratRanges: - groupIndex = ratio['groupIndex'] - writer.simpletag( - "ratRange", - bCharSet=ratio['bCharSet'], - xRatio=ratio['xRatio'], - yStartRatio=ratio['yStartRatio'], - yEndRatio=ratio['yEndRatio'], - groupIndex=groupIndex - ) - writer.newline() - writer.endtag("ratRanges") - writer.newline() - writer.begintag("groups") - writer.newline() - for groupIndex in range(self.numRecs): - group = self.groups[groupIndex] - recs = len(group) - startsz = min(group.keys()) - endsz = max(group.keys()) - writer.begintag("group", index=groupIndex) - writer.newline() - writer.comment("recs=%d, startsz=%d, endsz=%d" % - (recs, startsz, endsz)) - writer.newline() - for yPelHeight, (yMax, yMin) in sorted(group.items()): - writer.simpletag( - "record", - [('yPelHeight', yPelHeight), ('yMax', yMax), ('yMin', yMin)]) - writer.newline() - writer.endtag("group") - writer.newline() - writer.endtag("groups") - writer.newline() + raise ttLib.TTLibError( + "unknown format for VDMX table: version %s" % self.version + ) + data = sstruct.pack(VDMX_HeaderFmt, self) + for ratio in self.ratRanges: + data += sstruct.pack(VDMX_RatRangeFmt, ratio) + # recalculate offsets to VDMX groups + for offset in self._getOffsets(): + data += struct.pack(">H", offset) + for group in self.groups: + recs = len(group) + startsz = min(group.keys()) + endsz = max(group.keys()) + gHeader = {"recs": recs, "startsz": startsz, "endsz": endsz} + data += sstruct.pack(VDMX_GroupFmt, gHeader) + for yPelHeight, (yMax, yMin) in sorted(group.items()): + vTable = {"yPelHeight": yPelHeight, "yMax": yMax, "yMin": yMin} + data += sstruct.pack(VDMX_vTableFmt, vTable) + return data - def fromXML(self, name, attrs, content, ttFont): - if name == "version": - self.version = safeEval(attrs["value"]) - elif name == "ratRanges": - if not hasattr(self, "ratRanges"): - self.ratRanges = [] - for element in content: - if not isinstance(element, tuple): - continue - name, attrs, content = element - if name == "ratRange": - if not hasattr(self, "numRatios"): - self.numRatios = 1 - else: - self.numRatios += 1 - ratio = { - "bCharSet": safeEval(attrs["bCharSet"]), - "xRatio": safeEval(attrs["xRatio"]), - "yStartRatio": safeEval(attrs["yStartRatio"]), - "yEndRatio": safeEval(attrs["yEndRatio"]), - "groupIndex": safeEval(attrs["groupIndex"]) - } - self.ratRanges.append(ratio) - elif name == "groups": - if not hasattr(self, "groups"): - self.groups = [] - for element in content: - if not isinstance(element, tuple): - continue - name, attrs, content = element - if name == "group": - if not hasattr(self, "numRecs"): - self.numRecs = 1 - else: - self.numRecs += 1 - group = {} - for element in content: - if not isinstance(element, tuple): - continue - name, attrs, content = element - if name == "record": - yPelHeight = safeEval(attrs["yPelHeight"]) - yMax = safeEval(attrs["yMax"]) - yMin = safeEval(attrs["yMin"]) - group[yPelHeight] = (yMax, yMin) - self.groups.append(group) + def toXML(self, writer, ttFont): + writer.simpletag("version", value=self.version) + writer.newline() + writer.begintag("ratRanges") + writer.newline() + for ratio in self.ratRanges: + groupIndex = ratio["groupIndex"] + writer.simpletag( + "ratRange", + bCharSet=ratio["bCharSet"], + xRatio=ratio["xRatio"], + yStartRatio=ratio["yStartRatio"], + yEndRatio=ratio["yEndRatio"], + groupIndex=groupIndex, + ) + writer.newline() + writer.endtag("ratRanges") + writer.newline() + writer.begintag("groups") + writer.newline() + for groupIndex in range(self.numRecs): + group = self.groups[groupIndex] + recs = len(group) + startsz = min(group.keys()) + endsz = max(group.keys()) + writer.begintag("group", index=groupIndex) + writer.newline() + writer.comment("recs=%d, startsz=%d, endsz=%d" % (recs, startsz, endsz)) + writer.newline() + for yPelHeight, (yMax, yMin) in sorted(group.items()): + writer.simpletag( + "record", + [("yPelHeight", yPelHeight), ("yMax", yMax), ("yMin", yMin)], + ) + writer.newline() + writer.endtag("group") + writer.newline() + writer.endtag("groups") + writer.newline() + + def fromXML(self, name, attrs, content, ttFont): + if name == "version": + self.version = safeEval(attrs["value"]) + elif name == "ratRanges": + if not hasattr(self, "ratRanges"): + self.ratRanges = [] + for element in content: + if not isinstance(element, tuple): + continue + name, attrs, content = element + if name == "ratRange": + if not hasattr(self, "numRatios"): + self.numRatios = 1 + else: + self.numRatios += 1 + ratio = { + "bCharSet": safeEval(attrs["bCharSet"]), + "xRatio": safeEval(attrs["xRatio"]), + "yStartRatio": safeEval(attrs["yStartRatio"]), + "yEndRatio": safeEval(attrs["yEndRatio"]), + "groupIndex": safeEval(attrs["groupIndex"]), + } + self.ratRanges.append(ratio) + elif name == "groups": + if not hasattr(self, "groups"): + self.groups = [] + for element in content: + if not isinstance(element, tuple): + continue + name, attrs, content = element + if name == "group": + if not hasattr(self, "numRecs"): + self.numRecs = 1 + else: + self.numRecs += 1 + group = {} + for element in content: + if not isinstance(element, tuple): + continue + name, attrs, content = element + if name == "record": + yPelHeight = safeEval(attrs["yPelHeight"]) + yMax = safeEval(attrs["yMax"]) + yMin = safeEval(attrs["yMin"]) + group[yPelHeight] = (yMax, yMin) + self.groups.append(group) |