Rendering SVG with libRSVG,Python and c-types

Back to cookbook

Normally it's easier to use librsvg Python bindings from PyGTK, so you can import rsvg. When that's not an option, you may be able to bind just enough of it using the ctypes module to use it. Example for win32 follows.

# Very primitive librsvg bindings for win32
# no error checking, etc.
# but hey it works!

from ctypes import *
import cairo

l=CDLL('librsvg-2-2.dll')
g=CDLL('libgobject-2.0-0.dll')
g.g_type_init()    


class PycairoContext(Structure):
    _fields_ = [("PyObject_HEAD", c_byte * object.__basicsize__),
                ("ctx", c_void_p),
                ("base", c_void_p)]



class RsvgDimensionData(Structure):
    _fields_ = [("width", c_int),
                ("height", c_int),
                ("em",c_double),
                ("ex",c_double)]


svghandlecache = {}


def renderSVG(ctx,filename,x,y):  

    if not filename in svghandlecache:  
        error=''
        handle1 = l.rsvg_handle_new_from_file(filename,error)
        svghandlecache[filename] = handle1
    else:
        handle1 = svghandlecache[filename]
    #print error
    #print handle1    

    #svgDim = RsvgDimensionData()

    #l.rsvg_handle_get_dimensions(handle1,byref(svgDim))

    #print 'SVG Dimensions: ',svgDim.width,'x',svgDim.height

    #scaleX = float(WIDTH) / float(svgDim.width)
    #scaleY = float(HEIGHT) / float(svgDim.height)
    #scaleY = scaleX
    #scaleX = 1
    #scaleY = 1

    #print scaleY

    ctx.save()
    #ctx.scale(scaleX, scaleY)
    ctx.translate(x,y)

    z = PycairoContext.from_address(id(ctx))
    #print z.ctx

    #print '>>',l.rsvg_handle_render_cairo(handle1, z.ctx)
    l.rsvg_handle_render_cairo(handle1, z.ctx)
    ctx.restore()    



WIDTH, HEIGHT = 400, 400

# Setup Cairo
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
ctx = cairo.Context(surface)

#bg
bg = WebColour('#FFFFFF')
ctx.set_source_rgb(bg[0],bg[1],bg[2])
ctx.paint()

renderSVG(ctx,'ball.svg',0,0)

surface.write_to_png("test.png")