diff options
Diffstat (limited to 'Lib/fontTools/ttLib/tables/sbixStrike.py')
-rw-r--r-- | Lib/fontTools/ttLib/tables/sbixStrike.py | 277 |
1 files changed, 153 insertions, 124 deletions
diff --git a/Lib/fontTools/ttLib/tables/sbixStrike.py b/Lib/fontTools/ttLib/tables/sbixStrike.py index b367a99f..7614af4c 100644 --- a/Lib/fontTools/ttLib/tables/sbixStrike.py +++ b/Lib/fontTools/ttLib/tables/sbixStrike.py @@ -22,127 +22,156 @@ 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: - from fontTools import ttLib - raise(ttLib.TTLibError, "Strike header too short: Expected %x, got %x.") \ - % (sbixStrikeHeaderFormatSize, len(self.data)) - - # read Strike header from raw data - sstruct.unpack(sbixStrikeHeaderFormat, self.data[:sbixStrikeHeaderFormatSize], self) - - # calculate number of glyphs - firstGlyphDataOffset, = struct.unpack(">L", \ - self.data[sbixStrikeHeaderFormatSize:sbixStrikeHeaderFormatSize + sbixGlyphDataOffsetFormatSize]) - self.numGlyphs = (firstGlyphDataOffset - sbixStrikeHeaderFormatSize) // sbixGlyphDataOffsetFormatSize - 1 - # ^ -1 because there's one more offset than glyphs - - # build offset list for single glyph data offsets - self.glyphDataOffsets = [] - for i in range(self.numGlyphs + 1): # + 1 because there's one more offset than glyphs - start = i * sbixGlyphDataOffsetFormatSize + sbixStrikeHeaderFormatSize - current_offset, = struct.unpack(">L", self.data[start:start + sbixGlyphDataOffsetFormatSize]) - self.glyphDataOffsets.append(current_offset) - - # iterate through offset list and slice raw data into glyph data records - for i in range(self.numGlyphs): - current_glyph = Glyph(rawdata=self.data[self.glyphDataOffsets[i]:self.glyphDataOffsets[i+1]], gid=i) - current_glyph.decompile(ttFont) - self.glyphs[current_glyph.glyphName] = current_glyph - del self.glyphDataOffsets - del self.numGlyphs - del self.data - - def compile(self, ttFont): - self.glyphDataOffsets = b"" - self.bitmapData = b"" - - glyphOrder = ttFont.getGlyphOrder() - - # first glyph starts right after the header - currentGlyphDataOffset = sbixStrikeHeaderFormatSize + sbixGlyphDataOffsetFormatSize * (len(glyphOrder) + 1) - for glyphName in glyphOrder: - if glyphName in self.glyphs: - # we have glyph data for this glyph - current_glyph = self.glyphs[glyphName] - else: - # must add empty glyph data record for this glyph - current_glyph = Glyph(glyphName=glyphName) - current_glyph.compile(ttFont) - current_glyph.glyphDataOffset = currentGlyphDataOffset - self.bitmapData += current_glyph.rawdata - currentGlyphDataOffset += len(current_glyph.rawdata) - self.glyphDataOffsets += sstruct.pack(sbixGlyphDataOffsetFormat, current_glyph) - - # add last "offset", really the end address of the last glyph data record - dummy = Glyph() - dummy.glyphDataOffset = currentGlyphDataOffset - self.glyphDataOffsets += sstruct.pack(sbixGlyphDataOffsetFormat, dummy) - - # pack header - self.data = sstruct.pack(sbixStrikeHeaderFormat, self) - # add offsets and image data after header - self.data += self.glyphDataOffsets + self.bitmapData - - def toXML(self, xmlWriter, ttFont): - xmlWriter.begintag("strike") - xmlWriter.newline() - xmlWriter.simpletag("ppem", value=self.ppem) - xmlWriter.newline() - xmlWriter.simpletag("resolution", value=self.resolution) - xmlWriter.newline() - glyphOrder = ttFont.getGlyphOrder() - for i in range(len(glyphOrder)): - if glyphOrder[i] in self.glyphs: - self.glyphs[glyphOrder[i]].toXML(xmlWriter, ttFont) - # TODO: what if there are more glyph data records than (glyf table) glyphs? - xmlWriter.endtag("strike") - xmlWriter.newline() - - def fromXML(self, name, attrs, content, ttFont): - if name in ["ppem", "resolution"]: - setattr(self, name, safeEval(attrs["value"])) - elif name == "glyph": - if "graphicType" in attrs: - myFormat = safeEval("'''" + attrs["graphicType"] + "'''") - else: - myFormat = None - if "glyphname" in attrs: - myGlyphName = safeEval("'''" + attrs["glyphname"] + "'''") - elif "name" in attrs: - myGlyphName = safeEval("'''" + attrs["name"] + "'''") - else: - from fontTools import ttLib - raise ttLib.TTLibError("Glyph must have a glyph name.") - if "originOffsetX" in attrs: - myOffsetX = safeEval(attrs["originOffsetX"]) - else: - myOffsetX = 0 - if "originOffsetY" in attrs: - myOffsetY = safeEval(attrs["originOffsetY"]) - else: - myOffsetY = 0 - current_glyph = Glyph( - glyphName=myGlyphName, - graphicType=myFormat, - originOffsetX=myOffsetX, - originOffsetY=myOffsetY, - ) - for element in content: - if isinstance(element, tuple): - name, attrs, content = element - current_glyph.fromXML(name, attrs, content, ttFont) - current_glyph.compile(ttFont) - self.glyphs[current_glyph.glyphName] = current_glyph - else: - from fontTools import ttLib - raise ttLib.TTLibError("can't handle '%s' element" % name) + 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: + from fontTools import ttLib + + raise ( + ttLib.TTLibError, + "Strike header too short: Expected %x, got %x.", + ) % (sbixStrikeHeaderFormatSize, len(self.data)) + + # read Strike header from raw data + sstruct.unpack( + sbixStrikeHeaderFormat, self.data[:sbixStrikeHeaderFormatSize], self + ) + + # calculate number of glyphs + (firstGlyphDataOffset,) = struct.unpack( + ">L", + self.data[ + sbixStrikeHeaderFormatSize : sbixStrikeHeaderFormatSize + + sbixGlyphDataOffsetFormatSize + ], + ) + self.numGlyphs = ( + firstGlyphDataOffset - sbixStrikeHeaderFormatSize + ) // sbixGlyphDataOffsetFormatSize - 1 + # ^ -1 because there's one more offset than glyphs + + # build offset list for single glyph data offsets + self.glyphDataOffsets = [] + for i in range( + self.numGlyphs + 1 + ): # + 1 because there's one more offset than glyphs + start = i * sbixGlyphDataOffsetFormatSize + sbixStrikeHeaderFormatSize + (current_offset,) = struct.unpack( + ">L", self.data[start : start + sbixGlyphDataOffsetFormatSize] + ) + self.glyphDataOffsets.append(current_offset) + + # iterate through offset list and slice raw data into glyph data records + for i in range(self.numGlyphs): + current_glyph = Glyph( + rawdata=self.data[ + self.glyphDataOffsets[i] : self.glyphDataOffsets[i + 1] + ], + gid=i, + ) + current_glyph.decompile(ttFont) + self.glyphs[current_glyph.glyphName] = current_glyph + del self.glyphDataOffsets + del self.numGlyphs + del self.data + + def compile(self, ttFont): + self.glyphDataOffsets = b"" + self.bitmapData = b"" + + glyphOrder = ttFont.getGlyphOrder() + + # first glyph starts right after the header + currentGlyphDataOffset = ( + sbixStrikeHeaderFormatSize + + sbixGlyphDataOffsetFormatSize * (len(glyphOrder) + 1) + ) + for glyphName in glyphOrder: + if glyphName in self.glyphs: + # we have glyph data for this glyph + current_glyph = self.glyphs[glyphName] + else: + # must add empty glyph data record for this glyph + current_glyph = Glyph(glyphName=glyphName) + current_glyph.compile(ttFont) + current_glyph.glyphDataOffset = currentGlyphDataOffset + self.bitmapData += current_glyph.rawdata + currentGlyphDataOffset += len(current_glyph.rawdata) + self.glyphDataOffsets += sstruct.pack( + sbixGlyphDataOffsetFormat, current_glyph + ) + + # add last "offset", really the end address of the last glyph data record + dummy = Glyph() + dummy.glyphDataOffset = currentGlyphDataOffset + self.glyphDataOffsets += sstruct.pack(sbixGlyphDataOffsetFormat, dummy) + + # pack header + self.data = sstruct.pack(sbixStrikeHeaderFormat, self) + # add offsets and image data after header + self.data += self.glyphDataOffsets + self.bitmapData + + def toXML(self, xmlWriter, ttFont): + xmlWriter.begintag("strike") + xmlWriter.newline() + xmlWriter.simpletag("ppem", value=self.ppem) + xmlWriter.newline() + xmlWriter.simpletag("resolution", value=self.resolution) + xmlWriter.newline() + glyphOrder = ttFont.getGlyphOrder() + for i in range(len(glyphOrder)): + if glyphOrder[i] in self.glyphs: + self.glyphs[glyphOrder[i]].toXML(xmlWriter, ttFont) + # TODO: what if there are more glyph data records than (glyf table) glyphs? + xmlWriter.endtag("strike") + xmlWriter.newline() + + def fromXML(self, name, attrs, content, ttFont): + if name in ["ppem", "resolution"]: + setattr(self, name, safeEval(attrs["value"])) + elif name == "glyph": + if "graphicType" in attrs: + myFormat = safeEval("'''" + attrs["graphicType"] + "'''") + else: + myFormat = None + if "glyphname" in attrs: + myGlyphName = safeEval("'''" + attrs["glyphname"] + "'''") + elif "name" in attrs: + myGlyphName = safeEval("'''" + attrs["name"] + "'''") + else: + from fontTools import ttLib + + raise ttLib.TTLibError("Glyph must have a glyph name.") + if "originOffsetX" in attrs: + myOffsetX = safeEval(attrs["originOffsetX"]) + else: + myOffsetX = 0 + if "originOffsetY" in attrs: + myOffsetY = safeEval(attrs["originOffsetY"]) + else: + myOffsetY = 0 + current_glyph = Glyph( + glyphName=myGlyphName, + graphicType=myFormat, + originOffsetX=myOffsetX, + originOffsetY=myOffsetY, + ) + for element in content: + if isinstance(element, tuple): + name, attrs, content = element + current_glyph.fromXML(name, attrs, content, ttFont) + current_glyph.compile(ttFont) + self.glyphs[current_glyph.glyphName] = current_glyph + else: + from fontTools import ttLib + + raise ttLib.TTLibError("can't handle '%s' element" % name) |