11ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbodfrom __future__ import print_function, division, absolute_import 21b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom fontTools.misc.py23 import * 31b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom fontTools.misc import sstruct 4f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbodfrom fontTools.misc.textTools import readHex 51b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodimport struct 61b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbod 7f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod 8f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad EsfahbodsbixBitmapHeaderFormat = """ 9f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod > 10f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod usReserved1: H # 00 00 11f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod usReserved2: H # 00 00 12f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod imageFormatTag: 4s # e.g. "png " 13f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod""" 14f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod 15f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad EsfahbodsbixBitmapHeaderFormatSize = sstruct.calcsize(sbixBitmapHeaderFormat) 16f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod 17f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod 18f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbodclass Bitmap(object): 19f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod def __init__(self, glyphName=None, referenceGlyphName=None, usReserved1=0, usReserved2=0, imageFormatTag=None, imageData=None, rawdata=None, gid=0): 20f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.gid = gid 21f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.glyphName = glyphName 22f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.referenceGlyphName = referenceGlyphName 23f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.usReserved1 = usReserved1 24f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.usReserved2 = usReserved2 25f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.rawdata = rawdata 26f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.imageFormatTag = imageFormatTag 27f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.imageData = imageData 284801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 29f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod def decompile(self, ttFont): 30f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.glyphName = ttFont.getGlyphName(self.gid) 31f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if self.rawdata is None: 32f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod from fontTools import ttLib 33de85e4599f192055569542b90da96773d4140661Behdad Esfahbod raise ttLib.TTLibError("No table data to decompile") 34f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if len(self.rawdata) > 0: 35f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if len(self.rawdata) < sbixBitmapHeaderFormatSize: 36f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod from fontTools import ttLib 37f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod #print "Bitmap %i header too short: Expected %x, got %x." % (self.gid, sbixBitmapHeaderFormatSize, len(self.rawdata)) 38de85e4599f192055569542b90da96773d4140661Behdad Esfahbod raise ttLib.TTLibError("Bitmap header too short.") 394801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 40f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod sstruct.unpack(sbixBitmapHeaderFormat, self.rawdata[:sbixBitmapHeaderFormatSize], self) 414801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 42f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if self.imageFormatTag == "dupe": 43f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # bitmap is a reference to another glyph's bitmap 44f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod gid, = struct.unpack(">H", self.rawdata[sbixBitmapHeaderFormatSize:]) 45f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.referenceGlyphName = ttFont.getGlyphName(gid) 46f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod else: 47f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.imageData = self.rawdata[sbixBitmapHeaderFormatSize:] 48f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.referenceGlyphName = None 49f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # clean up 50f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod del self.rawdata 51f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod del self.gid 524801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 53f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod def compile(self, ttFont): 54f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if self.glyphName is None: 55f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod from fontTools import ttLib 56de85e4599f192055569542b90da96773d4140661Behdad Esfahbod raise ttLib.TTLibError("Can't compile bitmap without glyph name") 57f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # TODO: if ttFont has no maxp, cmap etc., ignore glyph names and compile by index? 58f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # (needed if you just want to compile the sbix table on its own) 59f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.gid = struct.pack(">H", ttFont.getGlyphID(self.glyphName)) 60f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if self.imageFormatTag is None: 61f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.rawdata = "" 62f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod else: 63f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.rawdata = sstruct.pack(sbixBitmapHeaderFormat, self) + self.imageData 644801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 65f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod def toXML(self, xmlWriter, ttFont): 66f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if self.imageFormatTag == None: 67f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # TODO: ignore empty bitmaps? 68f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # a bitmap entry is required for each glyph, 69f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # but empty ones can be calculated at compile time 70f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.simpletag("bitmap", glyphname=self.glyphName) 71f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.newline() 72f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod return 73f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.begintag("bitmap", format=self.imageFormatTag, glyphname=self.glyphName) 74f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.newline() 75f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod #xmlWriter.simpletag("usReserved1", value=self.usReserved1) 76f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod #xmlWriter.newline() 77f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod #xmlWriter.simpletag("usReserved2", value=self.usReserved2) 78f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod #xmlWriter.newline() 79f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if self.imageFormatTag == "dupe": 80f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # format == "dupe" is apparently a reference to another glyph id. 81f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.simpletag("ref", glyphname=self.referenceGlyphName) 82f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod else: 83f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.begintag("hexdata") 84f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.newline() 85f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.dumphex(self.imageData) 86f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.endtag("hexdata") 87f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.newline() 88f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.endtag("bitmap") 89f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod xmlWriter.newline() 90f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod 91de85e4599f192055569542b90da96773d4140661Behdad Esfahbod def fromXML(self, name, attrs, content, ttFont): 92f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod #if name in ["usReserved1", "usReserved2"]: 93f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # setattr(self, name, int(attrs["value"])) 94f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod #elif 95f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod if name == "ref": 96f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # bitmap is a "dupe", i.e. a reference to another bitmap. 97f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # in this case imageData contains the glyph id of the reference glyph 98f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod # get glyph id from glyphname 99f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.imageData = struct.pack(">H", ttFont.getGlyphID(attrs["glyphname"])) 100f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod elif name == "hexdata": 101f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod self.imageData = readHex(content) 102f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod else: 103f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod from fontTools import ttLib 104de85e4599f192055569542b90da96773d4140661Behdad Esfahbod raise ttLib.TTLibError("can't handle '%s' element" % name) 105