>>>>> "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/