Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Rotating text in perl tk

by karlj (Initiate)
on Nov 07, 2011 at 23:47 UTC ( [id://936614]=perlquestion: print w/replies, xml ) Need Help??

karlj has asked for the wisdom of the Perl Monks concerning the following question:

I know this question has been asked before, but I cant find an answer that I like ;-) So here it is again. How do I create vertical text in perl tk? Im looking for a solution that involves changing the text to an image and rotating the image. Is there a way to do that? I know I could use Zinc or other extensions, but it has to work on a bunch of machines across a network, and trying to maintain the zinc installation has a host of problems on our setup. So I want to do it with straight perl tk. I can also stack the letters vertically, but that looks realy bad. Not sure if any rotated fonts exist, but again that involves installing the font on a bunch of systems, which is problematic for me. Can a rotated font be created on the fly from an existing font? thanks for any ideas! Karl

Replies are listed 'Best First'.
Re: Rotating text in perl tk
by zentara (Archbishop) on Nov 08, 2011 at 10:41 UTC
    Here is a package written by eserte, who is the current Tk maintainer and guru. If you can figure it out, ;-)

    Otherwise, without Tk::Zinc you are stuck using Cairo , look at the text-rotate.pl example in the Cairo module source.

    #!/usr/bin/perl -w # -*- *perl* -*- package main; use vars qw($x11); package Tk::RotX11Font; # $Id: RotX11Font.pm,v 1.13 1999/01/22 00:38:27 eserte Exp eserte $ # Author: Slaven Rezic # # Copyright (C) 1998, 1999 Slaven Rezic. All rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as *Perl* itself. # # Mail: ese... #</groups/unlock?msg=a8e2ebe3c5c85dc4&_done=/group/comp.lang.perl.tk/b +rowse_thread/thread/a128e86f32629886/a8e2ebe3c5c85dc4%3Flnk%3Dst%26q% +3DX11%253A%253AProtocol%2BPerl%26rnum%3D2>@cs.tu-berlin.de # WWW: http://user.cs.tu-berlin.de/~eserte/ use Tk; use Tk::Font; use strict; use vars qw(%font_cache); sub new { my($pkg, $text, $f_sub, $size, $rad) = @_; my $self = {}; ($self->{Font}, $self->{'Xadd'}, $self->{'Yadd'}) = get_font_attrib($text, $f_sub, $size, $rad); $self->{Text} = $text; bless $self, $pkg; } sub writeCanvas { my($rotfont, $c, $x, $y, $tags, $text) = @_; my $xadd_ref = $rotfont->{Xadd}; my $yadd_ref = $rotfont->{Yadd}; $text = $rotfont->{Text} if !defined $text; for(split(//, $text)) { my $item = $c->createText ($x, $y, -text => $_, -font => $rotfont->{Font}, -anchor => 'w', (defined $tags ? (-tags => $tags) : ())); $x+=$xadd_ref->[ord($_)]; $y+=$yadd_ref->[ord($_)]; } ($x, $y); } # Arguments: # $c - canvas # $x, $y - start coordinates # $f_sub - template for font as a sub reference, something like: # sub { "-adobe-helvetica-medium-r-normal--0-" . $_[0] ."-0-0 +-p-0-iso8859-1" } # $size - point- (or pixel?)size # $rad - angle in radians # $text - text for output # $tags - (optional) tags # # Returns coordinate ($x, $y) of the position of textcursor after draw +ing. sub writeRot { my($c, $x, $y, $f_sub, $size, $rad, $text, $tags) = @_; my($f, $xadd_ref, $yadd_ref) = get_font_attrib($text, $f_sub, $siz +e, $rad); for(split(//, $text)) { my $item = $c->createText($x, $y, -text => $_, -font => $f, -anchor => 'w', (defined $tags ? (-tags => $tags) : +())); $x+=$xadd_ref->[ord($_)]; $y+=$yadd_ref->[ord($_)]; } ($x, $y); } # Returns an array with the generated X11 font name, and references # to the per-character X-Add- and Y-Add-arrays sub get_font_attrib { my($text, $f_sub, $size, $rad) = @_; my($mat) = get_matrix($size, $rad); my %chars_used = map { (ord($_), 1) } split(//, $text); my $chars_used = join(" ", sort {$a <=> $b } keys %chars_used); # X11R6- oder *X11::Protocol*-Bug? Font-Struktur muĂ&#159; mehr al +s ein # Zeichen enthalten! if (scalar keys %chars_used == 1) { $chars_used .= " " . ((keys(%chars_used))[0] == 32 ? 33 : 32); } my $f = $f_sub->($mat); $f .= "[$chars_used]"; my($xadd_ref, $yadd_ref) = get_x11font_resources($f, \%chars_used) +; ($f, $xadd_ref, $yadd_ref); } sub get_matrix { my($size, $r) = @_; my($mat); foreach ($size*cos($r), $size*sin($r), $size*-sin($r), $size*cos($ +r)) { s/-/~/g; if ($mat) { $mat .= " " } $mat .= $_; } "[" . $mat . "]"; } sub x_y_extent { my($rotfont, $text) = @_; my $x = 0; my $y = 0; my $xadd_ref = $rotfont->{Xadd}; my $yadd_ref = $rotfont->{Yadd}; $text = $rotfont->{Text} if !defined $text; foreach (split(//, $text)) { $x += $xadd_ref->[ord($_)]; $y += $yadd_ref->[ord($_)]; } ($x, $y); } sub get_x_y_extent { my($text, $f_sub, $size, $rad) = @_; my($f, $xadd_ref, $yadd_ref) = get_font_attrib($text, $f_sub, $siz +e, $rad); my $x = 0; my $y = 0; foreach (split(//, $text)) { $x += $xadd_ref->[ord($_)]; $y += $yadd_ref->[ord($_)]; } ($x, $y); } sub get_x11font_resources { my $font = shift; my $chars_used_ref = shift; my $fid = $main::x11->new_rsrc; $main::x11->OpenFont($fid, $font); my(%res) = $main::x11->QueryFont($fid); my @x; foreach (keys %{$res{'properties'}}) { if ($main::x11->atom_name($_) eq 'FONT') { my $realfont; $realfont = $main::x11->atom_name($res{'properties'}->{$_} +); my(@f) = split(/-/, $realfont); @x = split(/\s/, substr($f[7], 1, length($f[7])-2)); foreach (@x) { s/~/-/g } last; } } my(@font_xadd); my(@font_yadd); $#font_xadd = 255; $#font_yadd = 255; foreach (keys %$chars_used_ref) { my $attr = $res{'char_infos'}->[$_-$res{'min_char_or_byte2'}]- +>[5]; my($x, $y) = ($attr/1000*$x[0], -$attr/1000*$x[1]); $font_xadd[$_] = $x; $font_yadd[$_] = $y; } $main::x11->CloseFont($fid); $font_cache{$font} = [\@font_xadd, \@font_yadd]; # XXX create dup? (\@font_xadd, \@font_yadd); } return 1 if caller(); package main; use Tk; use X11::Protocol; MAIN: { my $top = new MainWindow; $x11 = X11::Protocol->new(); my $font = shift || "adobe-helvetica"; # $font = "arial"; my $size = shift || 24; my $f_sub = sub { "-$font-medium-r-normal--0-" . $_[0] . "-0-0-p-0 +-iso8859-1" }; my $c = $top->Canvas(-width => 500, -height => 500, -bg => 'white', )->pack; my $start = time; for(my $deg = -180; $deg <= 180; $deg+=15) { my $d = $deg; my $r = _deg2rad($d); my $text = " Some Rotated Text"; # my $rotfont = new Tk::RotX11Font $text, $f_sub, $size, $r; # $rotfont->writeCanvas($c, 250, 250); Tk::RotX11Font::writeRot($c, 250, 250, $f_sub, $size, $r, $tex +t); printf STDERR "(x/y) at %4d° = (" . join("/", Tk::RotX11Font::get_x_y_extent($text, $f_sub, $siz +e,$r)) . ")\n", $d; } warn "Time: " . (time-$start) . " seconds\n"; MainLoop; } sub _deg2rad { $_[0]/180*3.141592653; } __END__

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Rotating text in perl tk
by zentara (Archbishop) on Nov 08, 2011 at 10:56 UTC
    If you can move to Gtk2, the rotated fonts look way better than inTk.
    #! /usr/bin/perl -w use strict; use Glib qw/TRUE FALSE/; use Gtk2 '-init'; my $deg = 0; my $label; Glib::Timeout->add (200,sub{ &rotate_label() }); #standard window creation, placement, and signal connecting my $window = Gtk2::Window->new('toplevel'); $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); $window->set_border_width(5); $window->set_position('center_always'); #this vbox will geturn the bulk of the gui my $vbox = &ret_vbox(); #add and show the vbox $window->add($vbox); $window->show(); #our main event-loop Gtk2->main(); sub ret_vbox { #create a vbox to pack the following widgets my $vbox = Gtk2::VBox->new(FALSE,5); #this will be the label who gets rotated throughout the program $label = Gtk2::Label->new(); #start with it at 90deg to have max space alllocated to it $label->set_angle(90); $label->set_markup('<span foreground="DarkRed" size="x-large"><b>R +otating Label</b></span>'); $vbox->pack_start($label,FALSE,FALSE,4); #create table to pack the labels that will demo how mnemonic text +work my $table = Gtk2::Table->new (2, 2, FALSE); my $lbl_mnemonic_one = Gtk2::Label->new_with_mnemonic("Label _ +One:"); $lbl_mnemonic_one->set_alignment (1, 1); $table->attach_defaults ($lbl_mnemonic_one, 0, 1, 0, 1); my $ent_one = Gtk2::Entry->new(); $lbl_mnemonic_one->set_mnemonic_widget ($ent_one); $table->attach_defaults ($ent_one, 1, 2, 0, 1); my $lbl_mnemonic_two = Gtk2::Label->new(); $lbl_mnemonic_two->set_markup_with_mnemonic('<span foreground= +"maroon" size="x-large"><i>Label _Two</i></span>'); $lbl_mnemonic_two->set_alignment (0, 0); $table->attach_defaults ($lbl_mnemonic_two, 0, 1, 1, 2); my $ent_two = Gtk2::Entry->new(); $lbl_mnemonic_two->set_mnemonic_widget ($ent_two); $table->attach_defaults ($ent_two, 1, 2, 1, 2); $vbox->pack_end($table,FALSE,FALSE,4); $vbox->pack_end(Gtk2::HSeparator->new(),FALSE,FALSE,4); #create a label that will demo pango markup my $label_markup = Gtk2::Label->new(); $label_markup->set_markup("<span foreground=\"yellow1\" size=\"400 +00\">Label with</span><s><big> Tango </big></s> Pango<span background + = 'black' foreground= 'green' size ='30000'><i>markup</i></span>"); $vbox->pack_end($label_markup,FALSE,FALSE,4); $vbox->pack_end(Gtk2::HSeparator->new(),FALSE,FALSE,4); $vbox->show_all(); return $vbox; } sub rotate_label { $deg = $deg +5; ($deg==360)&&($deg =0); $label->set_angle($deg); return 1; }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Rotating text in perl tk
by Anonymous Monk on Nov 08, 2011 at 04:22 UTC

    Basically you're looking to create screenshots

    Good luck with that :)

    maintain the zinc installation has a host of problems on our setup.

    It has got to be a easier than reinventing every wheel :)

    Prima might work for you, its virtually as easy to install as Tk

    Heck, you could probably even turn it into a Tk extension (at least the interesting cavas-like parts)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://936614]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2024-04-24 01:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found