0

I am writing a python program to do graphic animations, I am using the python cairo/rsvg libraries. I have reached a speed issue and wanted to accelerate some parts of the code by moving some of the rendering code in a cython library.

Ideally I would like to augment the cairo library methods to add a few that are optimized for my needs.

For example i have a function that draws an svg on screen centered at a point with a bounding box that forces its size, usually this function is called by an external loop which draws tens of svgs, and this function is one of the most expensive in my code:

def svg(ctx, path, pos, angle, width, height):
    """Draws an svg file at coordinates pos with at a specific angle, and a
    maximum bounding box of size width x height"""
    if width == 0 or height == 0:
        return

    svg = rsvg.Handle(file=path) #any svg file

    ctx.save()

    #put in position
    ctx.translate(pos.x, pos.y)

    #rotate
    ctx.rotate(angle)

    #resize
    if svg.props.width != width or svg.props.height != height:
        ratiow = (width *1.0) / (svg.props.width*1.0)
        ratioh = (height * 1.0) / (svg.props.height * 1.0)
        ctx.scale(ratiow, ratioh)

    #move center to 0,0 of image
    ctx.translate(-svg.props.width / 2, - svg.props.height / 2)

    #draw image
    svg.render_cairo(ctx)
    ctx.restore()

What I would like to do is to write a cython function that given the list of svgs will draw them all at once on the screen.

Could this kind of optimization be done with cython? For what I understand it would be extremely beneficial to define a type for the cairo context object (ctx), but how is the correct way to do it?

yann.kmm
  • 827
  • 7
  • 21
  • My suspicion is that most of the work is being done in the C code that you're calling rather than the Python code in the function (which looks pretty light) therefore I doubt Cython will do a lot. – DavidW May 19 '17 at 09:22
  • @Davidw it is possible, but I'd like to give it a shot, even if it is only to undertand better how to do such a wrapping. – yann.kmm May 19 '17 at 09:26
  • The first thing to try would be to try compiling it with Cython unchanged (the vast majority of Python code should work in Cython). That'll probably give you something like a 20-50% speed up. If it barely gives you anything that probably suggests the slowdown in the the Cairo code, not the Python code. – DavidW May 19 '17 at 09:44
  • 1
    I have tried to compile that function with cython, and using it instead of the original python one leads to a *slower* speeds, which I suspect is due to the conversion of the ctx python object to a cython one. – yann.kmm May 19 '17 at 10:35
  • 1
    It can sometimes happen that you get lower speeds. I doubt if it's due to changing the type of the `ctx` object (since it doesn't actually become a Cython object unless you change the code) but I don't know what it is due to. In any case, I personally can't see anything that I think will give much benefit, but maybe someone else can... – DavidW May 19 '17 at 13:17
  • Several months late, but the way you would go about doing this is writing a `.pxd` wrapper file for the c cairo library to directly interface with it. Simply calling a library like pycairo from your cython code will not give you any speed benefits as you correctly surmised. I am in the process of wrapping a few functions myself and can add a copy of what I have wrapped so far (at least for the cairo part, haven't touched rsvg yet). – CodeSurgeon Nov 18 '17 at 08:45
  • I'm still working on this so your comment isn't late at all =) I will try your suggestion of writing a .pxd wrapper and I would be interested in seeing what you have written. – yann.kmm Nov 23 '17 at 19:19

0 Answers0