#!/usr/bin/env python import gtk import cairo def shift(x,sz): return 0.5-(x*sz)%1 def lineshift(x1,y1,x2,y2,sz): dx1 = shift(x1,sz) dy1 = shift(y1,sz) dx2 = shift(x2,sz) dy2 = shift(y2,sz) dx = max(dx1,dx2) dy = max(dy1,dy2) return dx,dy class MainWindow(gtk.Window): def __init__(self, parent=None): gtk.Window.__init__(self) try: self.set_screen(parent.get_screen()) except AttributeError: self.connect('destroy', lambda *w: gtk.main_quit()) self.zoom = 1 self.set_title("pycairo test") self.set_default_size(400, 300) self.da = gtk.DrawingArea() self.da.connect("button_press_event",self.on_button_press) self.da.set_events(gtk.gdk.BUTTON_PRESS_MASK) self.add(self.da) self.da.connect('expose_event', self.expose) self.show_all() def expose (self,da,event): ctx = da.window.cairo_create() sz = self.zoom ctx.set_line_width(1) ## red 'x' starts here ctx.save() ## coords of the 1st stem x1,y1,x2,y2 = 30,10,50,30 ctx.set_source_rgb(1,0,0) m = cairo.Matrix(self.zoom,0,0,self.zoom,0,0) ctx.transform(m) ctx.move_to(x1,y1) ctx.line_to(x2,y2) ctx.stroke() ctx.restore() ctx.save() x1,y1,x2,y2 = 50,10,30,30 ## coords of the 2nd stem ctx.set_source_rgb(1,0,0) m = cairo.Matrix(self.zoom,0,0,self.zoom,0,0) ctx.transform(m) ctx.move_to(x1,y1) ctx.line_to(x2,y2) ctx.stroke() ctx.restore() ## black '+' starts here ctx.save() x1,y1,x2,y2 = 10,20,20,20 ## calculate 0.5 shift dx,dy = lineshift(x1,y1,x2,y2,sz) m = cairo.Matrix(self.zoom,0,0,self.zoom,dx,dy) ctx.transform(m) ctx.move_to(x1,y1) ctx.line_to(x2,y2) ## do not stroke it inside of save()/restore() ctx.restore() ctx.save() x1,y1,x2,y2 = 15,15,15,25 ## calculate 0.5 shift dx,dy = lineshift(x1,y1,x2,y2,sz) m = cairo.Matrix(self.zoom,0,0,self.zoom,dx,dy) ctx.transform(m) ctx.move_to(x1,y1) ctx.line_to(x2,y2) ## do not stroke it inside of save()/restore() ctx.restore() ## now stroke both black '+' stems ctx.stroke() def on_button_press(self,da,event): if event.button == 1: self.zoom*=1.4 if event.button == 3: self.zoom/=1.4 ## I'm lazy to send 'expose' signal, so I just hide/show drawing area here da.hide() da.show() def main(): MainWindow() gtk.main() if __name__ == '__main__': main()