0

I'm working on a Python+Gtk+Cairo app. My application needs to do some very complex (and expensive)drawings.

For performance reasons, I draw first on an ImageSurface(offscreen), then I would draw the ImageSurface content on my DrawingArea object.

NB: I need to scale / translate my drawings to make them visible; otherwise, large drawings would fall out of the window.

Unfortunately, something goes wrong: as you can see, I'm unable to paint the entire content of ImageSurface. By using the "canonical" Context.set_source_surface(imageSurface, xCoord, yCoord) Context.paint()

I only get this wrong output:

This is the result I want to achieve:

How can I force the painting of entire imagesurface?

A sample code below:

import gtk
import cairo

def main():
    w = gtk.Window()
    w.add(RubberTest())
    w.show_all()
    gtk.main()


class RubberTest(gtk.DrawingArea):
    def __init__(self, model=None):
        gtk.DrawingArea.__init__(self)
        self.set_size_request(800, 500)
        self.connect("expose-event", self._expose, self.create_basic_image())
        self.add_events(gtk.gdk.EXPOSURE_MASK
                      | gtk.gdk.BUTTON_PRESS_MASK
                      | gtk.gdk.BUTTON_RELEASE_MASK
                      | gtk.gdk.POINTER_MOTION_MASK)

    def create_basic_image(self):
        img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 24, 24)
        cr = cairo.Context(img)

        # due to large coordinates, the drawing fall out of the window
        self.points = [(10000, 10000), (790000, 10000), (790000, 490000), (10000, 490000)]

        xMax, yMax, xMin, yMin = max([c[0] for c in self.points]), max([c[1] for c in self.points]), min([c[0] for c in self.points]), min([c[1] for c in self.points])
        maxRectWidth = xMax - xMin
        maxRectHeight = yMax - yMin

        w = 800
        h = 500
        width_ratio = float(w) / maxRectWidth
        height_ratio = float(h) / maxRectHeight

        # scale factor
        scaleFactor = min(height_ratio, width_ratio)

        cr.set_line_width(4)
        cr.set_source_rgb(1, 0, 0)

        cr.save()

        # scale + translate
        cr.scale(scaleFactor, scaleFactor)
        cr.translate(-xMin, -yMin)

        for i in range(0, len(self.points)):
            currPoint = self.points[i]
            currX = float(currPoint[0])
            currY = float(currPoint[1])
            nextIndex = i + 1
            if (nextIndex == len(self.points)):
                nextIndex = 0
            nextPoint = self.points[nextIndex]
            nextX = nextPoint[0]
            nextY = nextPoint[1]
            cr.move_to(currX, currY)
            cr.line_to(nextX, nextY)
        cr.restore()
        cr.close_path()
        cr.stroke_preserve()
        return img

    def _expose(self, sender, event, img):
        cr = self.window.cairo_create()
        cr.set_source_surface(img, 0, 0)
        cr.paint()
        return True

if __name__ == '__main__':
    main()

Thanks, IT

IT.
  • 311
  • 1
  • 5
  • 24
  • That code creates an ImageSurface of size 24x24. That ImageSurface is displayed completely. The "missing drawing" happens while drawing to this ImageSurface, not when in _expose(). Also, why do you need create_basic_image()? Can't you do all of this drawing in _expose()? – Uli Schlachter Apr 24 '13 at 16:51
  • Thank you very much!! :-) I figured it was a stupid mistake like this. Yes, normally, I draw all directly in expose() body; Now, due to increasing complexity of the drawings, someone suggested me to draw anything - at once -, offscreen. In expose(), I limit to copy this ImageSource from memory to destination surface, to avoid time-consuming recalculation and redrawing. This may result in increasing of performance. Can you confirm this? – IT. Apr 25 '13 at 11:33
  • That depends on how often your content changes and how often you have to redraw. However, I think that GTK already remembers what you draw, so this wouldn't help much. You can try adding print("foo") to your _expose()-function so that you see when it is called. I guess that your ImageSurface wouldn't help... – Uli Schlachter Apr 26 '13 at 15:23

0 Answers0