Beispiel #1
0
    def buildGlyphHashValue(self,
                            width,
                            outlineXML,
                            glyphName,
                            useDefaultGlyphDir,
                            level=0):
        """
        glyphData must be the official <outline> XML from a GLIF.
        We skip contours with only one point.
        """
        dataList = ["w%s" % norm_float(round(width, 9))]
        if level > 10:
            raise UFOParseError(
                "In parsing component, exceeded 10 levels of reference. "
                "'%s'. " % (glyphName))
        # <outline> tag is optional per spec., e.g. space glyph
        # does not necessarily have it.
        if outlineXML is not None:
            for childContour in outlineXML:
                if childContour.tag == "contour":
                    if len(childContour) < 2:
                        continue
                    for child in childContour:
                        if child.tag == "point":
                            ptType = child.get("type")
                            pointType = '' if ptType is None else ptType[0]
                            x = self._rd_val(child.get("x"))
                            y = self._rd_val(child.get("y"))
                            dataList.append("%s%s%s" % (pointType, x, y))

                elif childContour.tag == "component":
                    # append the component hash.
                    compGlyphName = childContour.get("base")

                    if compGlyphName is None:
                        raise UFOParseError(
                            "'%s' is missing the 'base' attribute in a "
                            "component." % glyphName)

                    dataList.append("%s%s" % ("base:", compGlyphName))

                    if useDefaultGlyphDir:
                        try:
                            componentPath = self.getGlyphDefaultPath(
                                compGlyphName)
                        except KeyError:
                            raise UFOParseError(
                                "'%s' component glyph is missing from "
                                "contents.plist." % (compGlyphName))
                    else:
                        # If we are not necessarily using the default layer
                        # for the main glyph, then a missing component may not
                        # have been processed, and may just be in the default
                        # layer. We need to look for component glyphs in the
                        # src list first, then in the defualt layer.
                        try:
                            componentPath = self.getGlyphSrcPath(compGlyphName)
                            if not os.path.exists(componentPath):
                                componentPath = self.getGlyphDefaultPath(
                                    compGlyphName)
                        except KeyError:
                            try:
                                componentPath = self.getGlyphDefaultPath(
                                    compGlyphName)
                            except KeyError:
                                raise UFOParseError(
                                    "'%s' component glyph is missing from "
                                    "contents.plist." % (compGlyphName))

                    if not os.path.exists(componentPath):
                        raise UFOParseError(
                            "'%s' component file is missing: '%s'." %
                            (compGlyphName, componentPath))

                    etRoot = ET.ElementTree()

                    # Collect transform values
                    for trans_key, flbk_val in COMP_TRANSFORM.items():
                        value = childContour.get(trans_key, flbk_val)
                        dataList.append(self._rd_val(value))

                    componentXML = etRoot.parse(componentPath)
                    componentOutlineXML = componentXML.find("outline")
                    _, componentDataList = self.buildGlyphHashValue(
                        width, componentOutlineXML, glyphName,
                        useDefaultGlyphDir, level + 1)
                    dataList.extend(componentDataList)
        data = "".join(dataList)
        if len(data) >= 128:
            data = hashlib.sha512(data.encode("ascii")).hexdigest()
        return data, dataList
Beispiel #2
0
 def _rd_val(str_val):
     """Round and normalize a (string) GLIF value"""
     return repr(norm_float(round(ast.literal_eval(str_val), 9)))