Beispiel #1
0
    def decompileCoordinates(self, data):
        endPtsOfContours = array.array("h")
        endPtsOfContours.fromstring(data[:2 * self.numberOfContours])
        if sys.byteorder <> "big":
            endPtsOfContours.byteswap()
        self.endPtsOfContours = endPtsOfContours.tolist()

        data = data[2 * self.numberOfContours:]

        instructionLength, = struct.unpack(">h", data[:2])
        data = data[2:]
        self.program = ttProgram.Program()
        self.program.fromBytecode(data[:instructionLength])
        data = data[instructionLength:]
        nCoordinates = self.endPtsOfContours[-1] + 1
        flags, xCoordinates, yCoordinates = \
          self.decompileCoordinatesRaw(nCoordinates, data)

        # fill in repetitions and apply signs
        coordinates = numpy.zeros((nCoordinates, 2), numpy.int16)
        xIndex = 0
        yIndex = 0
        for i in range(nCoordinates):
            flag = flags[i]
            # x coordinate
            if flag & flagXShort:
                if flag & flagXsame:
                    x = xCoordinates[xIndex]
                else:
                    x = -xCoordinates[xIndex]
                xIndex = xIndex + 1
            elif flag & flagXsame:
                x = 0
            else:
                x = xCoordinates[xIndex]
                xIndex = xIndex + 1
            # y coordinate
            if flag & flagYShort:
                if flag & flagYsame:
                    y = yCoordinates[yIndex]
                else:
                    y = -yCoordinates[yIndex]
                yIndex = yIndex + 1
            elif flag & flagYsame:
                y = 0
            else:
                y = yCoordinates[yIndex]
                yIndex = yIndex + 1
            coordinates[i] = (x, y)
        assert xIndex == len(xCoordinates)
        assert yIndex == len(yCoordinates)
        # convert relative to absolute coordinates
        self.coordinates = numpy.add.accumulate(coordinates)
        # discard all flags but for "flagOnCurve"
        self.flags = numpy.bitwise_and(flags, flagOnCurve).astype(numpy.int8)
Beispiel #2
0
 def decompileComponents(self, data, glyfTable):
     self.components = []
     more = 1
     haveInstructions = 0
     while more:
         component = GlyphComponent()
         more, haveInstr, data = component.decompile(data, glyfTable)
         haveInstructions = haveInstructions | haveInstr
         self.components.append(component)
     if haveInstructions:
         numInstructions, = struct.unpack(">h", data[:2])
         data = data[2:]
         self.program = ttProgram.Program()
         self.program.fromBytecode(data[:numInstructions])
         data = data[numInstructions:]
         assert len(data) < 4, "bad composite data"
Beispiel #3
0
class table__f_p_g_m(DefaultTable.DefaultTable):
    def decompile(self, data, ttFont):
        program = ttProgram.Program()
        program.fromBytecode(data)
        self.program = program

    def compile(self, ttFont):
        return self.program.getBytecode()

    def toXML(self, writer, ttFont):
        self.program.toXML(writer, ttFont)
        writer.newline()

    def fromXML(self, (name, attrs, content), ttFont):
        program = ttProgram.Program()
        program.fromXML((name, attrs, content), ttFont)
        self.program = program
Beispiel #4
0
 def decompile(self, data, ttFont):
     program = ttProgram.Program()
     program.fromBytecode(data)
     self.program = program
Beispiel #5
0
class Glyph:
    def __init__(self, data=""):
        if not data:
            # empty char
            self.numberOfContours = 0
            return
        self.data = data

    def compact(self, glyfTable, recalcBBoxes=1):
        data = self.compile(glyfTable, recalcBBoxes)
        self.__dict__.clear()
        self.data = data

    def expand(self, glyfTable):
        if not hasattr(self, "data"):
            # already unpacked
            return
        if not self.data:
            # empty char
            self.numberOfContours = 0
            return
        dummy, data = sstruct.unpack2(glyphHeaderFormat, self.data, self)
        del self.data
        if self.isComposite():
            self.decompileComponents(data, glyfTable)
        else:
            self.decompileCoordinates(data)

    def compile(self, glyfTable, recalcBBoxes=1):
        if hasattr(self, "data"):
            return self.data
        if self.numberOfContours == 0:
            return ""
        if recalcBBoxes:
            self.recalcBounds(glyfTable)
        data = sstruct.pack(glyphHeaderFormat, self)
        if self.isComposite():
            data = data + self.compileComponents(glyfTable)
        else:
            data = data + self.compileCoordinates()
        # From the spec: "Note that the local offsets should be word-aligned"
        # From a later MS spec: "Note that the local offsets should be long-aligned"
        # Let's be modern and align on 4-byte boundaries.
        if len(data) % 4:
            # add pad bytes
            nPadBytes = 4 - (len(data) % 4)
            data = data + "\0" * nPadBytes
        return data

    def toXML(self, writer, ttFont):
        if self.isComposite():
            for compo in self.components:
                compo.toXML(writer, ttFont)
            if hasattr(self, "program"):
                writer.begintag("instructions")
                self.program.toXML(writer, ttFont)
                writer.endtag("instructions")
                writer.newline()
        else:
            last = 0
            for i in range(self.numberOfContours):
                writer.begintag("contour")
                writer.newline()
                for j in range(last, self.endPtsOfContours[i] + 1):
                    writer.simpletag("pt",
                                     [("x", self.coordinates[j][0]),
                                      ("y", self.coordinates[j][1]),
                                      ("on", self.flags[j] & flagOnCurve)])
                    writer.newline()
                last = self.endPtsOfContours[i] + 1
                writer.endtag("contour")
                writer.newline()
            if self.numberOfContours:
                writer.begintag("instructions")
                self.program.toXML(writer, ttFont)
                writer.endtag("instructions")
                writer.newline()

    def fromXML(self, (name, attrs, content), ttFont):
        if name == "contour":
            self.numberOfContours = self.numberOfContours + 1
            if self.numberOfContours < 0:
                raise ttLib.TTLibError, "can't mix composites and contours in glyph"
            coordinates = []
            flags = []
            for element in content:
                if type(element) <> TupleType:
                    continue
                name, attrs, content = element
                if name <> "pt":
                    continue  # ignore anything but "pt"
                coordinates.append(
                    [safeEval(attrs["x"]),
                     safeEval(attrs["y"])])
                flags.append(not not safeEval(attrs["on"]))
            coordinates = numpy.array(coordinates, numpy.int16)
            flags = numpy.array(flags, numpy.int8)
            if not hasattr(self, "coordinates"):
                self.coordinates = coordinates
                self.flags = flags
                self.endPtsOfContours = [len(coordinates) - 1]
            else:
                self.coordinates = numpy.concatenate(
                    (self.coordinates, coordinates))
                self.flags = numpy.concatenate((self.flags, flags))
                self.endPtsOfContours.append(len(self.coordinates) - 1)
        elif name == "component":
            if self.numberOfContours > 0:
                raise ttLib.TTLibError, "can't mix composites and contours in glyph"
            self.numberOfContours = -1
            if not hasattr(self, "components"):
                self.components = []
            component = GlyphComponent()
            self.components.append(component)
            component.fromXML((name, attrs, content), ttFont)
        elif name == "instructions":
            self.program = ttProgram.Program()
            for element in content:
                if type(element) <> TupleType:
                    continue
                self.program.fromXML(element, ttFont)