Algunas pruebas con pygtk+cairo y svg
authordanigm <danigm>
Thu, 10 Dec 2009 19:14:29 +0000 (19:14 +0000)
committerdanigm <danigm@aa302d1f-72b1-406a-902b-8593ca2b2744>
Thu, 10 Dec 2009 19:14:29 +0000 (19:14 +0000)
git-svn-id: https://forja.rediris.es/svn/cusl4-tbo@2 aa302d1f-72b1-406a-902b-8593ca2b2744

test/cairo1.py [new file with mode: 0644]
test/cairotest.py [new file with mode: 0644]
test/ejemplo_2.py [new file with mode: 0644]
test/globo.svg [new file with mode: 0644]
test/rsvgtest.py [new file with mode: 0644]

diff --git a/test/cairo1.py b/test/cairo1.py
new file mode 100644 (file)
index 0000000..e3e5a2e
--- /dev/null
@@ -0,0 +1,42 @@
+#! /usr/bin/env python
+import pygtk
+pygtk.require('2.0')
+import gtk, gobject, cairo
+
+# Create a GTK+ widget on which we will draw using Cairo
+class Screen(gtk.DrawingArea):
+
+    # Draw in response to an expose-event
+    __gsignals__ = { "expose-event": "override" }
+
+    # Handle the expose-event by drawing
+    def do_expose_event(self, event):
+
+        # Create the cairo context
+        cr = self.window.cairo_create()
+
+        # Restrict Cairo to the exposed area; avoid extra work
+        cr.rectangle(event.area.x, event.area.y,
+                event.area.width, event.area.height)
+        cr.clip()
+
+        self.draw(cr, *self.window.get_size())
+
+    def draw(self, cr, width, height):
+        # Fill the background with gray
+        cr.set_source_rgb(0.5, 0.5, 0.5)
+        cr.rectangle(0, 0, width, height)
+        cr.fill()
+
+# GTK mumbo-jumbo to show the widget in a window and quit when it's closed
+def run(Widget):
+    window = gtk.Window()
+    window.connect("delete-event", gtk.main_quit)
+    widget = Widget()
+    widget.show()
+    window.add(widget)
+    window.present()
+    gtk.main()
+
+if __name__ == "__main__":
+    run(Screen)
diff --git a/test/cairotest.py b/test/cairotest.py
new file mode 100644 (file)
index 0000000..e3ef384
--- /dev/null
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+import pygtk
+pygtk.require('2.0')
+import gtk, gobject, cairo
+import math
+import rsvg
+pi = math.pi
+
+BLACK = (0.0,0.0,0.0)
+WHITE = (1.0,1.0,1.0)
+
+class TBObject:
+    def __init__(self, x=0, y=0, w=0, h=0):
+        self.width = w
+        self.height = h
+        self.x = x
+        self.y = y
+
+    def scale(self, w=0, h=0):
+        self.width = w
+        self.height = h
+
+    def move(self, x, y):
+        self.x = x
+        self.y = y
+
+class Text(TBObject):
+    def __init__(self, text, color=BLACK, font="Sans", fontsize=12, **kwargs):
+        TBObject.__init__(self, **kwargs)
+        self.text = text.split("\n")
+        self.color = color
+        self.font = font
+        self.fontsize = fontsize
+
+    def draw(self, cr):
+        x, y = self.x, self.y
+        for line in self.text:
+            cr.set_source_rgb(*self.color)
+            cr.select_font_face(self.font, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
+            cr.set_font_size(self.fontsize)
+            x_bearing, y_bearing, width, height = cr.text_extents(line)[:4]
+            cr.move_to(x - width / 2 - x_bearing, y - height / 2 - y_bearing)
+            cr.show_text(line)
+            y -= y_bearing - 5
+
+class SVG(TBObject):
+    def __init__(self, file, **kwargs):
+        TBObject.__init__(self, **kwargs)
+        self.file = file 
+        self.svg = rsvg.Handle(file)
+
+    def draw(self, cr):
+        x, y = self.x, self.y
+        ws, hs = self.scale_svg()
+        cr.translate(x, y)
+        cr.scale(ws, hs)
+        self.svg.render_cairo(cr)
+        cr.scale(1/ws,1/hs)
+        cr.translate(-x, -y)
+
+    def scale_svg(self):
+        w, h = self.svg.props.width, self.svg.props.height
+        if not self.width or not self.height:
+            self.width, self.height = w, h
+
+        w_scale = self.width / float(w)
+        h_scale = self.height / float(h)
+        return w_scale, h_scale
+
+class Rectangle(TBObject):
+    def __init__(self, color=BLACK, fill=WHITE, line_width=1, **kwargs):
+        TBObject.__init__(self, **kwargs)
+        self.color = color
+        self.fill = fill
+        self.line_width = line_width
+
+    def draw(self, cr):
+        cr.set_line_width(self.line_width)
+        cr.set_source_rgb(*self.color)
+        cr.rectangle(self.x, self.y, self.width, self.height)
+        cr.stroke()
+        cr.set_source_rgb(*self.fill)
+        cr.rectangle(self.x, self.y, self.width, self.height)
+        cr.fill()
+
+class DArea(gtk.DrawingArea):
+    def __init__(self):
+        gtk.DrawingArea.__init__(self)
+        self.connect("expose-event", self.expose)
+
+        self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
+                        gtk.gdk.BUTTON1_MOTION_MASK)
+
+        self.connect("expose_event", self.expose)
+        self.connect("button_press_event", self.pressing)
+        self.connect("motion_notify_event", self.moving)
+
+    def expose(self, widget, event):
+        self.context = self.window.cairo_create()
+
+        self.context.rectangle(event.area.x, event.area.y,
+                        event.area.width, event.area.height)
+        self.context.clip()
+
+        self.draw(self.context, *self.window.get_size())
+    
+    def draw(self, cr, width, height):
+        r = Rectangle(x=10, y=10, w=width-20, h=height-20, line_width=10)
+        r.draw(cr)
+
+        # draw lines
+        cr.set_source_rgb(0.0, 0.0, 0.8)
+        cr.move_to(width / 3.0, height / 3.0)
+        cr.rel_line_to(0, height / 6.0)
+        cr.move_to(2 * width / 3.0, height / 3.0)
+        cr.rel_line_to(0, height / 6.0)
+        cr.stroke()
+
+        # and a circle
+        cr.set_source_rgb(1.0, 0.0, 0.0)
+        radius = min(width, height)
+        cr.arc(width / 2.0, height / 2.0, radius / 2.0 - 20, 0, 2 * pi)
+        cr.stroke()
+        cr.arc(width / 2.0, height / 2.0, radius / 3.0 - 10, pi / 3, 2 * pi / 3)
+        cr.stroke()
+
+        globo = SVG("globo.svg", x=width-300, y=40, w=200, h=120)
+        globo.draw(cr)
+
+        text = '''
+este texto
+está escrito
+en varias
+líneas
+        '''
+
+        tbotext = Text(text, x=width-200, y=60, fontsize=12, font="Kid Kosmic")
+        tbotext.draw(cr)
+
+    def pressing(self, widget, event):
+        print "pressing", event.x, event.y
+
+    def moving(self, widget, event):
+        print "moving", event.x, event.y
+
+def main():
+    w = gtk.Window()
+    w.set_title("TBO")
+    w.set_default_size(800, 500)
+    darea = DArea()
+    w.add(darea)
+    w.show_all()
+    w.connect('destroy', gtk.main_quit)
+    gtk.main()
+
+if __name__ == '__main__':
+    main()
diff --git a/test/ejemplo_2.py b/test/ejemplo_2.py
new file mode 100644 (file)
index 0000000..a77048d
--- /dev/null
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+import gtk
+import gtk.gdk
+import math
+
+class SemiCirculo(gtk.DrawingArea):
+       def __init__(self):
+               gtk.DrawingArea.__init__(self)
+               self.connect("expose-event", self.expose)
+       
+       def expose(self, widget, event):
+               #Creamos un contexto de dibujo cairo
+               self.context = widget.window.cairo_create()
+               
+               #Ajustamos el tamaño del contexto al del widget
+               self.context.rectangle(event.area.x, event.area.y,
+                               event.area.width, event.area.height)
+               self.context.clip()
+       
+               #Llamamos a la función de dibujado
+               self.draw(self.context)
+               return False    
+
+       def draw(self, context):
+               #Adquirimos las coordenadas de origen
+               #y el tamaño del rectangulo del widget,
+               #situando en las variable x e y
+               #el centro del rectangulo.
+               rect = self.get_allocation()
+               x = rect.x + rect.width / 2
+               y = rect.y + rect.height / 2
+
+               #hallamos el radio
+               radius = min(rect.width / 2, rect.height / 2) - 5
+
+               #Dibujamos un arco
+               context.arc(x, y, radius, 0,(1 * math.pi))
+
+               #Elegimos el color de relleno y lo vertemos
+               context.set_source_rgb(0.7, 0.8, 0.1)
+               context.fill_preserve()
+
+               #Elegimos el color del borde y lo dibujamos
+               context.set_source_rgb(0, 0, 0)
+               context.stroke()
+
+def main():
+       window = gtk.Window()
+       semicirculo = SemiCirculo()
+
+       # Añadimos nuestro widget a la ventana
+       window.add(semicirculo)         
+       # Conectamos el evento destroy con la salida del bucle de eventos
+       window.connect("destroy", gtk.main_quit)
+       # Dibujamos toda la ventana
+       window.show_all()
+
+       # Comenzamos el bucle de eventos
+       gtk.main()
+
+if __name__ == "__main__":
+       main()
diff --git a/test/globo.svg b/test/globo.svg
new file mode 100644 (file)
index 0000000..651a32e
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="400"
+   height="400"
+   viewBox="0 0 200 200"
+   version="1.0"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="globo.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <metadata
+     id="metadata8">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs6">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 125 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="250 : 125 : 1"
+       inkscape:persp3d-origin="125 : 83.333333 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     inkscape:window-height="553"
+     inkscape:window-width="1024"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     guidetolerance="10.0"
+     gridtolerance="10.0"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     showgrid="false"
+     inkscape:zoom="0.63"
+     inkscape:cx="111.11111"
+     inkscape:cy="125"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:current-layer="svg2" />
+  <g
+     id="surface0" />
+  <path
+     style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.20000005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+     d="M 99.999998,1.6000005 C 45.683698,1.6000005 1.5999999,42.568493 1.5999999,93.03344 C 1.5999999,127.12528 21.740146,156.84899 51.540705,172.56656 L 47.181932,198.4 L 67.29496,179.2155 C 77.532444,182.57134 88.531428,184.42454 99.999998,184.42454 C 154.31629,184.42454 198.39998,143.4984 198.39999,93.03344 C 198.39999,42.568493 154.3163,1.600004 99.999998,1.6000005 z"
+     id="path2383" />
+</svg>
diff --git a/test/rsvgtest.py b/test/rsvgtest.py
new file mode 100644 (file)
index 0000000..0c87955
--- /dev/null
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+import cairo, gtk, rsvg, sys
+
+class myApp:
+    def __init__(self, filename):
+        mw = gtk.Window(gtk.WINDOW_TOPLEVEL)
+        mw.connect("delete_event", gtk.main_quit)
+
+        svg = rsvg.Handle(filename)
+        
+        da = gtk.DrawingArea()
+        da.set_size_request(svg.props.width, svg.props.height)
+        da.connect("expose_event", self.expose, svg)
+
+        mw.add(da)
+        mw.show_all()
+
+
+    def expose(self, da, event, svg):
+        ctx = da.window.cairo_create()
+        ctx.scale(2, 2)
+        svg.render_cairo(ctx)
+
+
+if __name__ == "__main__":
+    if len(sys.argv) != 2:
+        print "Uso: %s fichero.svg" % sys.argv[0]
+    else:
+        try:
+            app = myApp(sys.argv[1])
+            gtk.main()
+        except KeyboardInterrupt:
+            pass
+