>>>>> "Eric" == Eric Jardim <[EMAIL PROTECTED]> writes:

    Eric> Hi, Is there, in PyGTK, a way to have a simple label widget
    Eric> where the text is +/- 90 degree rotated from the horizontal
    Eric> position?  If not, is that too difficult to implement? How
    Eric> could I do it? GDK, Styles... Any ideas?

Here is the code we use in matplotlib to draw vertical text -- note
the comments which give information about other options in recent
versions of pango and gtk

    def _draw_rotated_text(self, gc, x, y, s, prop, angle):
        """
        Draw the text rotated 90 degrees, other angles are not supported
        """
        # this function (and its called functions) is a bottleneck
        # Pango 1.6 supports rotated text, but pygtk 2.4.0 does not yet have 
wrapper functions
        # GTK+ 2.6 pixbufs support rotation

        gdrawable = self.gdkDrawable
        ggc = gc.gdkGC

        layout, inkRect, logicalRect = self._get_pango_layout(s, prop)
        l, b, w, h = inkRect
        x = int(x-h)
        y = int(y-w)

        if x < 0 or y < 0: # window has shrunk and text is off the edge
            return

        key = (x,y,s,angle,hash(prop))
        imageVert = self.rotated.get(key)
        if imageVert != None:
            gdrawable.draw_image(ggc, imageVert, 0, 0, x, y, h, w)
            return

        imageBack = gdrawable.get_image(x, y, w, h)
        imageVert = gdrawable.get_image(x, y, h, w)
        #imageFlip = gtk.gdk.Image(type=gdk.IMAGE_NORMAL,
        imageFlip = gtk.gdk.Image(type=gdk.IMAGE_FASTEST,
                                  visual=gdrawable.get_visual(),
                                  width=w, height=h)
        if imageFlip == None or imageBack == None or imageVert == None:
            warnings.warn("Could not renderer vertical text")
            return
        imageFlip.set_colormap(self._cmap)
        for i in range(w):
            for j in range(h):
                imageFlip.put_pixel(i, j, imageVert.get_pixel(j,w-i-1) )

        gdrawable.draw_image(ggc, imageFlip, 0, 0, x, y, w, h)
        gdrawable.draw_layout(ggc, x, y-b, layout)

        imageIn  = gdrawable.get_image(x, y, w, h)
        for i in range(w):
            for j in range(h):
                imageVert.put_pixel(j, i, imageIn.get_pixel(w-i-1,j) )

        gdrawable.draw_image(ggc, imageBack, 0, 0, x, y, w, h)
        gdrawable.draw_image(ggc, imageVert, 0, 0, x, y, h, w)
        self.rotated[key] = imageVert


Here is a closely related standalone example

import pygtk
pygtk.require('2.0')
import gtk
import pango

win = gtk.Window()
win.show()
vbox = gtk.VBox()
vbox.show()
win.add(vbox)

class C:

    def __init__(self, text):
        self.text = text
        
    def realize(self, drawingArea):
        self.drawingArea = drawingArea
        self.drawable = drawingArea.window

        cmap = self.drawable.get_colormap()

        # the background and foreground colors
        self.cBack = cmap.alloc_color(30000, 30000, 30000) 
        self.cFore = cmap.alloc_color(0, 65025, 0) 

            
        # text properties
        context = self.drawingArea.create_pango_context()
        self.layout  = self.drawingArea.create_pango_layout(self.text)
        desc = pango.FontDescription('Sans 14')
        self.layout.set_font_description(desc)    


    def draw_text(self, drawable=None, x=100, y=100):
        if drawable is None: drawable=self.drawable
        
        # draw some text in the foreground color
        w, h = self.drawable.get_size()
        gc = self.drawable.new_gc()
        gc.foreground = self.cBack
        self.drawable.draw_rectangle(gc, 1, 0, 0, w, h)

        gc = drawable.new_gc()
        drawable.draw_layout(gc, x=x, y=y, layout=self.layout)
        

    def draw_text_rotated(self, x=50, y=100):
        """
        Draw the text rotated 90 degrees
        """

        gc = self.drawable.new_gc()

        inkRect, logicalRect = self.layout.get_pixel_extents()
        rect = inkRect
        l, b, w, h = rect

        # save the background
        imageBack = self.drawable.get_image(x, y, w, h)
        imageVert = self.drawable.get_image(x, y, h, w)

        # transform the vertical image, write it onto the renderer,
        # and draw the layout onto it
        imageFlip = gtk.gdk.Image(type=gtk.gdk.IMAGE_NORMAL,
                                  visual=self.drawable.get_visual(),
                                  width=w, height=h)
        if imageFlip is None or imageBack is None or imageVert is None:
            print >> sys.stderr, "Could not renderer vertical text", s
            return
        imageFlip.set_colormap(self.drawable.get_colormap())
        for i in range(w):
            for j in range(h):
                imageFlip.put_pixel(i, j, imageVert.get_pixel(j,w-i-1) )

        self.drawable.draw_image(gc, imageFlip, 0, 0, x, y, w, h)
        self.drawable.draw_layout(gc, x, y-b, self.layout)

        # now get that image and flip it vertical
        imageIn = self.drawable.get_image(x, y, w, h)
        imageOut = gtk.gdk.Image(type=gtk.gdk.IMAGE_NORMAL,
                                 visual=self.drawable.get_visual(),
                                 width=h, height=w)
        imageOut.set_colormap(self.drawable.get_colormap())
        for i in range(w):
            for j in range(h):
                imageOut.put_pixel(j, i, imageIn.get_pixel(w-i-1,j) )

        # draw the old background and the flipped text
        self.drawable.draw_image(gc, imageBack, 0, 0, x, y, w, h)
        self.drawable.draw_image(gc, imageOut, 0, 0, x, y, h, w)

        return True

    def _draw_text_rotated(self):
        """
        draw the text to a pixmap, rotate the image, fill a pixbuf
        and draw from the pixbuf
        """

        inkRect, logicalRect = self.layout.get_pixel_extents()
        x, y, w, h = logicalRect
        pixmap = gtk.gdk.Pixmap(self.drawable, w, h)
        gc = pixmap.new_gc()
        gc.foreground = self.cBack
        pixmap.draw_rectangle(gc, 1, 0, 0, w, h)

        self.draw_text(drawable=pixmap, x=0, y=0)


        if 0:
            # These lines test that the pixmap was drawn to ok
            pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, w, h)
            pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(),
                                     0, 0, 0, 0, w, h)
            pixbuf.render_to_drawable(self.drawable, gc, 0, 0, 0, 0, w, h, 0, 
0, 0)
            return 


        imageIn = pixmap.get_image(x=0, y=0, width=w, height=h)
        imageOut = gtk.gdk.Image(type=0,
                                 visual=pixmap.get_visual(),
                                 width=h, height=w)
        imageOut.set_colormap(imageIn.get_colormap())
        for i in range(w):
            for j in range(h):
                imageOut.put_pixel(j, i, imageIn.get_pixel(w-i-1,j) )


        pixbuf = gtk.gdk.Pixbuf(colorspace=gtk.gdk.COLORSPACE_RGB,
                                has_alpha=0, bits_per_sample=8,
                                width=h, height=w)
        pixbuf.get_from_image(src=imageOut, cmap=imageIn.get_colormap(),
                              src_x=0, src_y=0, dest_x=0, dest_y=0,
                              width=h, height=w)
        pixbuf.render_to_drawable(self.drawable, gc,
                                  src_x=0, src_y=0,
                                  dest_x=50, dest_y=100,
                                  width=h, height=w,
                                  dither=0, x_dither=0, y_dither=0)


        
        
        
        
c = C('Some text')

da = gtk.DrawingArea()
da.connect('realize', c.realize)
da.set_size_request(300,300)


da.show()
vbox.pack_start(da, gtk.TRUE, gtk.TRUE)

hbox = gtk.HBox()
hbox.show()
vbox.pack_start(hbox, gtk.FALSE, gtk.FALSE)

button = gtk.Button('Draw')
button.show()
button.connect('clicked', lambda b: c.draw_text())
hbox.pack_start(button, gtk.TRUE, gtk.TRUE)

button = gtk.Button('Rotate')
button.show()
button.connect('clicked', lambda b: c.draw_text_rotated())
hbox.pack_start(button, gtk.TRUE, gtk.TRUE)

button = gtk.Button('Quit')
button.show()
button.connect('clicked', lambda b: gtk.mainquit())
hbox.pack_start(button, gtk.TRUE, gtk.TRUE)

gtk.mainloop()
_______________________________________________
pygtk mailing list   [email protected]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to