[PyQt] SVG Glyphs in PyQt

Kyle Covington kyle at red-r.org
Mon Sep 13 19:24:29 BST 2010


Recently I found that svg files generated by Cairo do not plot properly in
pyqt.  The error comes from the use of glyphs which seem not to be shown in
pyqt (this might be wrong but I couldn't find any way of getting glyphs to
render).

I ended up writing a set of functions that will convert the glyphs to svg
paths so the file will render normally.

These could still use some improvements for rendering color and other style
elements (which are locked in the functions that I wrote).

These functions will need to be embedded in a class or have self removed to
be used elsewhere.

I just wanted people to have these so they wouldn't have to search high and
low like I did to find a way to render glyphs in pyqt.

Hope for the best,
Kyle

    def convertSVG(self, file):
        dom = self._getsvgdom(file)
        print dom
        self._switchGlyphsForPaths(dom)
        self._commitSVG(file, dom)
    def _commitSVG(self, file, dom):
        f = open(file, 'w')
        dom.writexml(f)
        f.close()
    def _getsvgdom(self, file):
        print 'getting DOM model'
        import xml.dom
        import xml.dom.minidom as mini
        f = open(file, 'r')
        svg = f.read()
        f.close()
        dom = mini.parseString(svg)
        return dom
    def _getGlyphPaths(self, dom):
        symbols = dom.getElementsByTagName('symbol')
        glyphPaths = {}
        for s in symbols:
            pathNode = [p for p in s.childNodes if 'tagName' in dir(p) and
p.tagName == 'path']
            glyphPaths[s.getAttribute('id')] =
pathNode[0].getAttribute('d')
        return glyphPaths
    def _switchGlyphsForPaths(self, dom):
        glyphs = self._getGlyphPaths(dom)
        use = self._getUseTags(dom)
        for glyph in glyphs.keys():
            print glyph
            nl = self.makeNewList(glyphs[glyph].split(' '))
            u = self._matchUseGlyphs(use, glyph)
            for u2 in u:
                print u2, 'brefore'
                self._convertUseToPath(u2, nl)
                print u2, 'after'

    def _getUseTags(self, dom):
        return dom.getElementsByTagName('use')
    def _matchUseGlyphs(self, use, glyph):
        matches = []
        for i in use:
            print i.getAttribute('xlink:href')
            if i.getAttribute('xlink:href') == '#'+glyph:
                matches.append(i)
        print matches
        return matches
    def _convertUseToPath(self, use, strokeD):
        ## strokeD is a list of lists of strokes to make the glyph
        newD = self.nltostring(self.resetStrokeD(strokeD,
use.getAttribute('x'), use.getAttribute('y')))
        use.tagName = 'path'
        use.removeAttribute('xlink:href')
        use.removeAttribute('x')
        use.removeAttribute('y')
        use.setAttribute('style', 'fill: rgb(0%,0%,0%); stroke-width: 0.5;
stroke-linecap: round; stroke-linejoin: round; stroke: rgb(0%,0%,0%);
stroke-opacity: 1;stroke-miterlimit: 10; ')
        use.setAttribute('d', newD)
    def makeNewList(self, inList):
        i = 0
        nt = []
        while i < len(inList):
            start = i + self.listFind(inList[i:], ['M', 'L', 'C', 'Z'])
            end = start + self.listFind(inList[start+1:], ['M', 'L', 'C',
'Z', '', ' '])
            nt.append(inList[start:end+1])
            i = end + 1
        return nt
    def listFind(self, x, query):
        for i in range(len(x)):
            if x[i] in query:
                return i
        return len(x)
    def resetStrokeD(self, strokeD, x, y):
        nsd = []
        for i in strokeD:
            nsd.append(self.resetXY(i, x, y))
        return nsd
    def resetXY(self, nl, x, y): # convert a list of strokes to xy coords
        nl2 = []
        for i in range(len(nl)):
            if i == 0:
                nl2.append(nl[i])
            elif i%2: # it's odd
                nl2.append(float(nl[i]) + float(x))
            elif not i%2: # it's even
                nl2.append(float(nl[i]) + float(y))
            else:
                print i, nl[i], 'error'
        return nl2
    def nltostring(self, nl): # convert a colection of nl's to a string
        col = []
        for l in nl:
            templ = []
            for c in l:
                templ.append(str(c))
            templ = ' '.join(templ)
            col.append(templ)
        return ' '.join(col)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20100913/6e43c5df/attachment.html>


More information about the PyQt mailing list