Esempio n. 1
0
    def parse_line(self, line):
        line = line.strip()  # get rid of eol characters
        parts = line.split(";")  # split by the ;s
        parts = filter(lambda s: s != "", parts)  # remove whitespace

        name = None
        char_parts_num = None
        char_parts = []
        for part in parts:
            elements = part.split()
            elements = list(filter(lambda s: s != "",
                                   elements))  # remove whitespace

            try:
                key = elements[0]
                if len(elements) < 2:
                    msg = "Composit definition key without data: %s" % repr(
                        line)
                    raise ParseError(msg)
                else:
                    elements = elements[1:]
                    data = " ".join(elements)

                if key == "CC":
                    name = elements[0]
                    char_parts_num = float(elements[1])

                elif key == "PCC":
                    name = elements[0]
                    delta_x = int(elements[1])
                    delta_y = int(elements[2])

                    char_parts.append((
                        name,
                        delta_x,
                        delta_y,
                    ))
                else:
                    raise ParseError("Unknown element in composit: %s" % \
                                                                   repr(line))
            except IndexError:
                msg = "Illegal number of elements in composit char: %s" % \
                                                                   repr(line)
                raise ParseError(msg)

        if name is None:
            raise ParseError("Character name missing from composit char: %s"%\
                                                                   repr(line))

        if char_parts_num != len(char_parts):
            warn("Composit char parts count mismatch: %s (not %i elements)" %\
                                                 (repr(line), char_part_num,))

        self.set(name, char_parts)
Esempio n. 2
0
    def __init__(self, line_iterator, info, parent, implicit_keyword=False):
        """
        @param line_iterator: Line iterator (see below)
          seek()) with the file pointer at the beginning of the first line
          for this section
        @param info: The rest of the section keyword's line (in a line
          'StartDirection 0' it would be ' 0'
        @param implicit_keyword: Boolean indicating whether this section
          started without a keyword. True implies that this section ends with
          the end of file.
        """
        keyword.__init__(self, info)
        self._all = []

        try:
            if self.info is not None:
                self.info = self.info_cls(self.info)
        except ValueError:
            raise ParseError("Can't parse %s as %s" % \
                            ( repr(info), self.info_cls.__name__, ))

        self.implicit_keyword = implicit_keyword

        self.parse(line_iterator, parent)
        self.check()
Esempio n. 3
0
 def __init__(self, info):
     if "true" in info.lower():
         self.info = True
     elif "false" in info.lower():
         self.info = False
     else:
         raise ParseError("%s needs boolean argument" % \
                          ( self.__class__.__name__, ))
Esempio n. 4
0
    def cls(self, keyword):
        if keyword.startswith("Start"):
            keyword = keyword[5:]

        for a in self:
            if a.__name__ == keyword:
                return a

        raise ParseError("Unknown keyword: %s" % repr(keyword))
Esempio n. 5
0
 def add_keyword(self, keyword, info):
     if keyword in self:
         tpl = (
             self.__class__.__name__,
             keyword,
         )
         raise ParseError("Section %s already has keyword %s" % tpl)
     else:
         cls = self.keywords.cls(keyword)
         obj = cls(info)
         self.set(keyword, obj.value())
Esempio n. 6
0
    def __init__(self, info):
        parts = info.split()
        info = []

        for part in parts:
            info.append(float(part))

        if len(info) != self.tuple_size:
            raise ParseError("%s needs %i number arguments" % \
                             ( self.__class__.__name__, self.tuple_size, ))

        self.info = tuple(info)
Esempio n. 7
0
def ps_hex_int(data):
    """
    Return integer value of a PostScript hexadecimal literal. They look like
    <12AB> und so.
    """
    match = ps_hex_int_re.match(data)
    if match is None:
        raise ParseError("Illegal hexadecimal representation: %s" % repr(data))
    else:
        data = match.group(1)

    return int(data, 16)
Esempio n. 8
0
    def add_subsection(self,
                       line_iterator,
                       keyword,
                       info,
                       implicit_start_stop=False):
        subsection_class = self.subsections.cls(keyword)
        section_object = subsection_class(line_iterator, info, self,
                                          implicit_start_stop)

        if keyword.startswith("Start"):
            keyword = keyword[5:]

        if section_object.multiple == 0:
            if keyword in self:
                tpl = (
                    keyword,
                    self.__class__.__name__,
                )
                raise ParseError("Multiple %s sections in %s" % tpl)
            self.set(keyword, section_object)
        else:
            try:
                if info is None:
                    idx = 0
                else:
                    idx = int(info)

                if keyword not in self:
                    l = []
                    for a in range(section_object.multiple):
                        l.append(None)

                    self.set(keyword, l)
                else:
                    l = self.get(keyword)

                l[idx] = section_object
                #subsection_class(line_iterator, info, self)
            except ValueError:
                raise ParseError("Can't parse %s into int" % repr(info))
Esempio n. 9
0
    def parse_line(self, line):
        elements = line.split()
        elements = filter(lambda a: a != "", elements)

        if len(elements) != 6:
            raise ParseError("Illegal TrackKern dataset: %s" % repr(line))

        degree = int(elements[0])
        rest = elements[1:]
        rest = map(float, rest)

        tpl = tuple([degree] + rest)
        self.set(degree, tpl)
Esempio n. 10
0
    def parse(self, line_iterator, parent):
        while True:
            line = line_iterator.readline()

            if line == "":
                raise ParseError("Unexpected end of file")
            elif line.strip().startswith("End%s" % self.__class__.__name__):
                return  # end of section
            elif line.strip() == "":
                continue  # empty line
            else:
                # pass the line
                self.parse_line(line)
Esempio n. 11
0
def parse_afm(fp):
    """
    Parse afm file pointed to by fp. Return a FontMetrics object.
    """
    lines = line_iterator(fp)
    first_line = lines.readline()
    parts = first_line.split()

    if parts[0] != "StartFontMetrics" or len(parts) != 2:
        raise ParseError("Not a valid AFM file!")

    version = float(parts[1])
    if version > 4.1:
        warn("This parser only knows AFM specification v. 4.1.")

    try:
        return FontMetrics(lines, None, parts[1])
    except ParseError as e:
        e.args = (e.args[0] + (" (line: %i)" % lines.line_number), )
        raise
Esempio n. 12
0
    def parse_line(self, line):
        line = line.strip()  # get rid of eol characters
        parts = line.split(";")  # split by the ;s
        parts = filter(lambda s: s != "", parts)  # remove whitespace

        info = {}
        for part in parts:
            elements = part.split()

            key = elements[0]
            if len(elements) < 2:
                raise ParseError("KernPairs key without data: %s" % repr(line))
            else:
                elements = elements[1:]
                data = " ".join(elements)

            try:
                if key == "KP":
                    key = (
                        elements[0],
                        elements[1],
                    )
                    value = (
                        "KP",
                        float(elements[2]),
                        float(elements[3]),
                    )
                elif key == "KPH":
                    key = (
                        ps_hex_int(elements[0]),
                        ps_hex_int(elements[1]),
                    )
                    value = (
                        "KPH",
                        float(elements[2]),
                        float(elements[3]),
                    )
                elif "KPX":
                    key = (
                        elements[0],
                        elements[1],
                    )
                    value = (
                        "KPX",
                        float(elements[2]),
                        0,
                    )
                elif "KPY":
                    key = (
                        elements[0],
                        elements[1],
                    )
                    value = (
                        "KPY",
                        0,
                        float(elements[2]),
                    )
                else:
                    raise ParseError("Unknown data key in KernPairs line %s" %\
                                                                    repr(line))

                self.set(key, value)
            except IndexError:
                msg = "Illegel number of data elements in KernPairs line %s" %\
                                                                     repr(line)
                raise ParseError(msg)
Esempio n. 13
0
    def parse_line(self, line):
        """Parse a CharMetrics line info a dict as { 'KEY': info }"""
        line = line.strip()  # get rid of eol characters
        parts = line.split(";")  # split by the ;s
        parts = filter(lambda s: s != "", parts)  # remove whitespace

        info = {}
        for part in parts:
            elements = part.split()

            key = elements[0]
            if len(elements) < 2:
                raise ParseError("CharMetrics key without data")
            else:
                elements = elements[1:]
                data = " ".join(elements)

            # For these codes see Adobe Font Metrics File Format Specification
            # 3d. edition, pp. 31ff (section 8).

            if key == "C":  # character code
                info["C"] = int(data)
                info["CH"] = int(data)

            elif key == "CH":  # character code (hex)
                data = ps_hex_int(data)
                info["C"] = data
                info["CH"] = data

            elif key == "WX" or key == "W0X":  # character width direction 0
                data = float(data)

                info["WX"] = data
                info["W0X"] = data

            elif key == "W1X":  # character width direction 1
                info["W1X"] = float(data)

            elif key == "WY" or key == "W0Y":  # character height direction 0
                data = float(data)

                info["WY"] = data
                info["W0Y"] = data

            elif key == "W1Y":  # character height direction 1
                info["W1Y"] = float(data)

            elif key == "W" or key == "W0":  # character width vector (wri dir 0
                wx, wy = float_pair(elements)
                info["W"] = (
                    wx,
                    wy,
                )
                info["W0"] = (
                    wx,
                    wy,
                )

            elif key == "W1":  # character width vector (writing direction 1)
                wx, wy = float_pair(elements)
                info["W1"] = (
                    wx,
                    wy,
                )

            elif key == "W1":  # character width vector (writing direction 1)
                wx, wy = float_pair(elements)
                info["W1"] = (
                    wx,
                    wy,
                )

            elif key == "N":  # postscript character name
                info["N"] = data

            elif key == "B":  # character bounding box
                info["B"] = float_tuple(elements, 4)

            elif key == "L":  # Ligature
                if len(elements) != 2:
                    raise ParseError(
                        "CharMetrics key L must be L successor ligature")
                if "L" not in info:
                    info["L"] = {}
                info["L"][elements[0]] = elements[1]
            else:
                raise ParseError("Unknown CharMetric line: %s" % repr(line))

        if "C" not in info:
            raise ParseError("Illegal CharMetrics line: Either C or CH key" +
                             "must be present! (%s)" % repr(line))

        if info["C"] != -1:
            self[info["C"]] = info

        try:
            glyph_name = info["N"]
            if glyph_name != '.notdef':
                self.by_glyph_name[glyph_name] = info
        except KeyError:
            raise ParseError(
                "No glyph name specified for character code {}".format(
                    info["C"]))
Esempio n. 14
0
    def parse(self, line_iterator, parent):
        while True:
            line = line_iterator.readline()
            if line == "":
                if self.implicit_keyword:
                    break
                else:
                    raise ParseError("Unexpected end of file")

            if line.strip() == "":  # empty line
                continue

            parts = line.split()
            keyword = parts[0]

            if len(parts) > 1:
                info = " ".join(parts[1:])
            else:
                info = ""

            if keyword in self.keywords.keywords():
                self.add_keyword(keyword, info)
            elif keyword in self.subsections.start_keywords():
                self.add_subsection(line_iterator, keyword, info)
            elif keyword.startswith("End%s" % self.__class__.__name__):
                return  # Finished this section
            elif parent is not None and keyword in parent.keywords.keywords():
                # It seems that if the subsection's keywords are omited
                # section and subsection keywords may be mixed freely.
                # No word of that in the specification but as Adobe's own
                # files do it, it must be "standard" complient, I guess.
                # This format suks.
                parent.add_keyword(keyword, info)
            elif parent is not None and keyword \
                                   in parent.subsections.start_keywords():
                parent.add_subsection(line_iterator, keyword, info)
            elif parent is not None and \
                     keyword.startswith("End%s" % parent.__class__.__name__):
                # We'v run into the parent's End line, rewind the file buffer
                # so that the parent sees the line and pass control back
                # to 'him'.
                line_iterator.rewind()
                return
            elif keyword in (
                    "",
                    "Comment",
            ):
                continue  # An empty line
            elif keyword[0] in "abcdefghijklmnopqrstuvwxyz":
                continue  # keywords that start with a lower char are user
                # defined and supposed to be ignored
            else:
                # Check the subsection's keyword lists: If it is a keyword
                # from an implicit subsection rewind the filepointer to the
                # beginning of the line and create a new section.
                found = False
                for cls in self.subsections:
                    if cls.implicit_start_stop and \
                       keyword in cls.keywords.keywords():
                        line_iterator.rewind()
                        found = True
                        self.add_subsection(line_iterator,
                                            cls.__name__,
                                            None,
                                            implicit_start_stop=True)

                if not found:
                    tpl = (
                        self.__class__.__name__,
                        repr(line),
                    )
                    raise ParseError("Unknown line in %s section: %s " % tpl)
Esempio n. 15
0
 def __init__(self, value):
     try:
         py_float.__init__(self, value)
     except ValueError:
         raise ParseError("Illegal representation of a float: %s" %
                          repr(value))
Esempio n. 16
0
 def __init__(self, value, base=10):
     try:
         py_int.__init__(self, value, base)
     except ValueError:
         raise ParseError("Illegal representation of an integer: %s" %
                          repr(value))