# Source code for fontTools.ttLib.tables.sbixGlyph

    from fontTools.misc import sstruct
    from fontTools.misc.textTools import readHex, safeEval
    import struct

    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:
                if self.graphicType[-1] == "\0":
                    self.graphicType = self.graphicType[:-1]
                if len(self.graphicType) > 4:
                    from fontTools import ttLib

                    raise ttLib.TTLibError(
                        "Glyph.graphicType must not be longer than 4 characters."
                    )
                elif len(self.graphicType) < 4:
                    # pad with spaces
                    self.graphicType += "    "[: (4 - len(self.graphicType))]

        def is_reference_type(self):
            """Returns True if this glyph is a reference to another glyph's image data."""
            return self.graphicType == "dupe" or self.graphicType == "flip"

        def decompile(self, ttFont):
            self.glyphName = ttFont.getGlyphName(self.gid)
            if self.rawdata is None:
                from fontTools import ttLib

                raise ttLib.TTLibError("No table data to decompile")
            if len(self.rawdata) > 0:
                if len(self.rawdata) < sbixGlyphHeaderFormatSize:
                    from fontTools import ttLib

                    # print "Glyph %i header too short: Expected %x, got %x." % (self.gid, sbixGlyphHeaderFormatSize, len(self.rawdata))
                    raise ttLib.TTLibError("Glyph header too short.")

                sstruct.unpack(
                    sbixGlyphHeaderFormat, self.rawdata[:sbixGlyphHeaderFormatSize], self
                )

                if self.is_reference_type():
                    # this glyph is a reference to another glyph's image data
                    (gid,) = struct.unpack(">H", self.rawdata[sbixGlyphHeaderFormatSize:])
                    self.referenceGlyphName = ttFont.getGlyphName(gid)
                else:
                    self.imageData = self.rawdata[sbixGlyphHeaderFormatSize:]
                    self.referenceGlyphName = None
            # clean up
            del self.rawdata
            del self.gid

        def compile(self, ttFont):
            if self.glyphName is None:
                from fontTools import ttLib

                raise ttLib.TTLibError("Can't compile Glyph without glyph name")
                # TODO: if ttFont has no maxp, cmap etc., ignore glyph names and compile by index?
                # (needed if you just want to compile the sbix table on its own)
            self.gid = struct.pack(">H", ttFont.getGlyphID(self.glyphName))
            if self.graphicType is None:
                rawdata = b""
            else:
                rawdata = sstruct.pack(sbixGlyphHeaderFormat, self)
                if self.is_reference_type():
                    rawdata += struct.pack(">H", ttFont.getGlyphID(self.referenceGlyphName))
                else:
                    assert self.imageData is not None
                    rawdata += self.imageData
            self.rawdata = rawdata

        def toXML(self, xmlWriter, ttFont):
            if self.graphicType is None:
                # TODO: ignore empty glyphs?
                # a glyph data entry is required for each glyph,
                # but empty ones can be calculated at compile time
                xmlWriter.simpletag("glyph", name=self.glyphName)
                xmlWriter.newline()
                return
            xmlWriter.begintag(
                "glyph",
                graphicType=self.graphicType,
                name=self.glyphName,
                originOffsetX=self.originOffsetX,
                originOffsetY=self.originOffsetY,
            )
            xmlWriter.newline()
            if self.is_reference_type():
                # this glyph is a reference to another glyph id.
                xmlWriter.simpletag("ref", glyphname=self.referenceGlyphName)
            else:
                xmlWriter.begintag("hexdata")
                xmlWriter.newline()
                xmlWriter.dumphex(self.imageData)
                xmlWriter.endtag("hexdata")
            xmlWriter.newline()
            xmlWriter.endtag("glyph")
            xmlWriter.newline()

        def fromXML(self, name, attrs, content, ttFont):
            if name == "ref":
                # this glyph i.e. a reference to another glyph's image data.
                # in this case imageData contains the glyph id of the reference glyph
                # get glyph id from glyphname
                glyphname = safeEval("'''" + attrs["glyphname"] + "'''")
                self.imageData = struct.pack(">H", ttFont.getGlyphID(glyphname))
                self.referenceGlyphName = glyphname
            elif name == "hexdata":
                self.imageData = readHex(content)
            else:
                from fontTools import ttLib

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