#!/usr/bin/perl -w
# Rotated Text
#
# This demo shows how to use GDK and Pango to draw rotated and transformed
# text. The use of GdkPangoRenderer in this example is a somewhat advanced
# technique; most applications can simply use gdk_draw_layout(). We use
# it here mostly because that allows us to work in user coordinates - that is,
# coordinates prior to the application of the transformation matrix, rather
# than device coordinates.
#
# As of GTK+-2.6, the ability to draw transformed and anti-aliased graphics
# as shown in this example is only present for text. With GTK+-2.8, a new
# graphics system called "Cairo" will be introduced that provides these
# capabilities and many more for all types of graphics.
#
package rotated_text;
use strict;
use Glib qw(TRUE FALSE);
use Gtk2;
use Gtk2::Pango; # constants
my $window = undef;
sub min { $_[0] < $_[1] ? $_[0] : $_[1] }
sub rotated_text_expose_event {
my ($widget, $event) = @_;
use constant RADIUS => 150;
use constant N_WORDS => 10;
use constant FONT => "Sans Bold 27";
use constant M_PI => 3.141526;
my $matrix = Gtk2::Pango::Matrix->new; # all defaults
my $width = $widget->allocation->width;
my $height = $widget->allocation->height;
# Get the default renderer for the screen, and set it up for drawing
my $renderer = Gtk2::Gdk::PangoRenderer->get_default ($widget->get_screen);
$renderer->set_drawable ($widget->window);
$renderer->set_gc ($widget->style->black_gc);
# Set up a transformation matrix so that the user space coordinates for
# the centered square where we draw are [-RADIUS, RADIUS], [-RADIUS, RADIUS]
# We first center, then change the scale
my $device_radius = min ($width, $height) / 2.;
$matrix->translate ($device_radius + ($width - 2 * $device_radius) / 2,
$device_radius + ($height - 2 * $device_radius) / 2);
$matrix->scale ($device_radius / RADIUS, $device_radius / RADIUS);
# Create a PangoLayout, set the font and text
my $context = $widget->create_pango_context;
my $layout = Gtk2::Pango::Layout->new ($context);
$layout->set_text ("Text");
my $desc = Gtk2::Pango::FontDescription->from_string (FONT);
$layout->set_font_description ($desc);
# Draw the layout N_WORDS times in a circle
foreach my $i (0..N_WORDS-1) {
my $rotated_matrix = $matrix->copy;
my $angle = (360. * $i) / N_WORDS;
# Gradient from red at angle == 60 to blue at angle == 300
my $red = 65535 * (1 + cos (($angle - 60) * M_PI / 180.)) / 2;
my $green = 0;
my $blue = 65535 - $red;
my $color = Gtk2::Gdk::Color->new ($red, $green, $blue);
$renderer->set_override_color ('foreground', $color);
$rotated_matrix->rotate ($angle);
$context->set_matrix ($rotated_matrix);
# Inform Pango to re-layout the text with the new transformation matrix
$layout->context_changed;
my ($width, $height) = $layout->get_size;
$renderer->draw_layout ($layout, - $width / 2, - RADIUS * PANGO_SCALE);
}
# Clean up default renderer, since it is shared
$renderer->set_override_color ('foreground', undef);
$renderer->set_drawable (undef);
$renderer->set_gc (undef);
return FALSE;
}
sub do {
my $do_widget = shift;
if (!$window) {
my $white = Gtk2::Gdk::Color->new (0xffff, 0xffff, 0xffff);
$window = Gtk2::Window->new;
$window->set_screen ($do_widget->get_screen);
$window->set_title ("Rotated Text");
$window->signal_connect (destroy => sub { $window = undef; });
my $drawing_area = Gtk2::DrawingArea->new;
$window->add ($drawing_area);
# This overrides the background color from the theme
$drawing_area->modify_bg ('normal', $white);
$drawing_area->signal_connect
(expose_event => \&rotated_text_expose_event);
$window->set_default_size (2 * RADIUS, 2 * RADIUS);
}
if (! $window->visible) {
$window->show_all;
} else {
$window->destroy;
$window = undef;
}
return $window;
}
1;