Daniel RuosoPublicado em 23/12/2006
r3 - 23 Dec 2006 - DanielRuoso
Às vezes é necessário desenhar um texto qualquer na tela com Gtk2, como parte de um gráfico. Como este tema em especial tem pouquíssima documentação, segue aqui o caminho das pedras para conseguir escrever um texto qualquer com Gtk2 e Pango.
O Gtk2 é um toolkit poderoso. Muito mais poderoso do que muitos julgam, e, justamente por isso, as vezes não é tão simples utilizá-lo. Por exemplo, eu cheguei na questão desse artigo quando estava precisando desenhar um texto qualquer utilizando um Gtk2::DrawingArea. Eu poderia ter utilizado o draw_text, mas este método está obsoleto e não colabora muito com UTF8 e coisas assim. Eu já sabia que o Gtk2 tem um ótimo suporte a UTF8 e por isso queria fazer o negócio direito.
Pois bem, sabia que o engodo começava no Pango, mas a única documentação que existe são as APIs, então, bem, fui à tentativa e erro.
Não pretendo aqui passar todos os passos de erro, mas quero sim explicar como ficou o resultado final.
O Pango Context é um elemento chave para tudo funcionar. Você não consegue fazer praticamente nada sem ter um contexto válido. O segredo é saber que qualquer widget implementa o método get_pango_context. Com esse método você tem o contexto no seu estado ideal, uma vez que você chama ele do próprio widget onde voce vai pintar alguma coisa.
A outra coisa que voce precisa é conseguir um FontDescription, ou seja, para definir com qual fonte voce vai escrever. A classe Gtk2::Pango::FontDescription tem o método from_string que serve para construir a fonte a partir de uma descrição amigável. Algo como "Sans 10".
Por fim, o último elemento que voce precisa ter antes de mandar pintar o texto é o Layout. Como estamos falando em internacionalização, UTF-8 e coisa e tal, não existe a noção de "coloque o texto aqui". Um conjunto maior de variáveis influencia nisso, mas felizmente o Pango cuida disso, a única coisa que voce precisa é criar um layout, o resto ele faz. Para criar um layout basta chamar o método new da classe Gtk2::Pango::Layout, que recebe o Pango Context. Depois basta passar a string (em UTF8, mas você realmente não precisa se preocupar com isso) utilizando o método set_text do layout e dizer a fonte usando o set_font_description.
Aqui está a parte ainda mais obscura. Por causa do conjunto gigantesco de possibilidades de onde e como o texto vai aparecer, voce não diz tem os métodos de pintura de texto no GdkWindow, mas sim, surpreendentemente, no GdkStyle, que é acessível em qualquer widget pelo método homonimo style.
O método de pintura do texto é, por fim, o paint_layout, que vai fazer toda a magia negra necessária para fazer o texto aparecer com os glyphs específicos (mesmo que voce escreva em japonês).
#!/usr/bin/perl
use strict;
use warnings;
use Gtk2 qw(-init -threads-init);
my $canvas_width = 0;
my $canvas_height = 0;
my $mainwindow = Gtk2::Window->new("toplevel");
my $draw = Gtk2::DrawingArea->new();
$draw->signal_connect(expose_event => \&drawit);
$draw->signal_connect(configure_event => \&configureit);
$mainwindow->add($draw);
$mainwindow->show_all();
Gtk2->main();
sub configureit {
my $draw = shift;
my $event = shift;
$canvas_width = $event->width;
$canvas_height = $event->height;
}
sub drawit {
my $draw = shift;
my $event = shift;
my ($x,$y,$w,$h) = ($event->area->x, $event->area->y, $event->area->width, $event->area->height);
# Obtendo o Graphic Context do widget.
my $gc = $draw->style->fg_gc($draw->state);
# Limpando a área a ser pintada.
$draw->window->clear_area($x, $y, $w, $h);
# Vou mexer só na parte que precisa ser atualizada
$gc->set_clip_rectangle(Gtk2::Gdk::Rectangle->new($x, $y, $w, $h));
# Pintar o fundo de branco.
$gc->set_rgb_fg_color(Gtk2::Gdk::Color->new(255*257,255*257,255*257));
$draw->window->draw_rectangle($gc,1,0,0,$canvas_width,$canvas_height);
$gc->set_rgb_fg_color(Gtk2::Gdk::Color->new(0,0,0));
# obter o Pango Context
my $pangoc = $draw->get_pango_context();
# criar o Font Description
my $fontdesc = Gtk2::Pango::FontDescription->from_string("Sans 10");
# Criar o layout
my $layout = Gtk2::Pango::Layout->new($pangoc);
# definir a fonte
$layout->set_font_description($fontdesc);
# definir o texto
$layout->set_text("Algum Texto áæß");
# Desenhar...
my $rect = Gtk2::Gdk::Rectangle->new(int($canvas_width/2)-75+2,int($canvas_height/2)-100+2,146,20);
$draw->style->paint_layout($draw->window,$draw->state,1,$rect,undef,undef,$rect->x,$rect->y,$layout);
# Desfazendo o clip
$gc->set_clip_rectangle(undef);
}
Daniel Ruoso