The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl
#
# This examples shows how to print a (lined) buffer, wrapping lines if they are
# too long for the page boundaries. (ebassi)

use strict;
use warnings;

use Gtk2 '-init';
use Gnome2::Print;

use constant FONT_NAME => 'Bitstream Vera Sans Roman';
use constant FONT_SIZE => 16.0;

use constant LEFT_BORDER => 100;
use constant BOTTOM_BORDER  => 100;

our $d = create_dialog();
$d->show;

Gtk2->main;

0;

sub render_job
{
	my $job = shift;
	my $conf = $job->get_config;
	my $pc = $job->get_context;
		
	my $buffer = [
		"Twinkle Twinkle",
		"Little Star",
		"Twinkle Twinkle",
		"Where You Are",
		"",
		"This is some text created just for testing purposes. It's longer than a single line, and it's wider than the page margin, in order to verify that the text wrapping mechanism is working properly.",
		"",
		"Hope it'll all go well.",
	];
	
	my $font = Gnome2::Print::Font->find_closest(FONT_NAME, FONT_SIZE);
	
	my $font_height = $font->get_descender + $font->get_ascender;
	my $line_spacing = 1.2 * $font->get_size;
	my @adv = $font->get_glyph_stadvance($font->lookup_default(ord(' ')));
	my $space_advance = $adv[0];
	
	my ($width, $height) = $job->get_page_size;
	
	my $font_name = $font->get_name;
	printf "Found: %s (%.1f)\n", $font_name, $font->get_size;
	
	# start cursor.
	my $cur_x = LEFT_BORDER;
	my $cur_y = $height - BOTTOM_BORDER;

	# begin page
	my $page_n = 1;
	print "(cur_x, cur_y) = $cur_x, $cur_y\n";
	
	# init
	$pc->beginpage(sprintf("%d", $page_n++));
	$pc->moveto($cur_x, $cur_y);
	$pc->setfont($font);
	
	foreach my $line (@$buffer)
	{
		# fetch line width
		my $line_width = $font->get_width_utf8($line);
		print "line width: $line_width\n";
		
		if ($line_width < ($width - 2 * LEFT_BORDER - 1))
		{
			# fastpath for lines smaller than page width
			$pc->show($line);
			$cur_y -= ($font_height + $line_spacing);
			
			# start a new page if we hit this page's bottom border
			if ($cur_y < BOTTOM_BORDER)
			{
				$cur_y = $height - BOTTOM_BORDER;
				$pc->showpage;
				$pc->beginpage(sprintf("%d", $page_n++));
				$pc->setfont($font);
			}
			
			print "(cur_x, cur_y) = $cur_x, $cur_y\n";
			$pc->moveto($cur_x, $cur_y);
		}
		else
		{
			# word wrapping at word boundaries.
			my @words = split /\s/, $line;
			foreach my $w (@words)
			{
				my $word_width = $font->get_width_utf8($w);
				printf "*** word (%s[%d]) width: %d\n", $w, length($w), $word_width;
				
				if ($cur_x < ($width - 2 * LEFT_BORDER - 1))
				{
					# word still inside page boundary; remember the space!
					$cur_x += ($word_width + $space_advance);
					$pc->show(sprintf("%s ", $w));
					$pc->moveto($cur_x, $cur_y);
				}
				else
				{
					# wrapping
					print "*** wrapping at '$w'!\n";
					$cur_x = LEFT_BORDER;
					$cur_y -= ($font_height + $line_spacing);
					
					# start a new page if we hit this page's bottom border
					if ($cur_y < BOTTOM_BORDER)
					{
						$cur_y = $height - BOTTOM_BORDER;
						$pc->showpage;
						$pc->beginpage(sprintf("%d", $page_n++));
						$pc->setfont($font);
					}
					
					$pc->show(sprintf("%s", $w));
					$pc->moveto($cur_x, $cur_y);
				}
				
				print "(cur_x, cur_y) = $cur_x, $cur_y\n";
			}
			
			# move to next line
			$cur_x = LEFT_BORDER;
			$cur_y -= ($font_height + $line_spacing);
			$pc->moveto($cur_x, $cur_y);
		}
	}
	
	$pc->showpage;
	$job->close;
}

sub create_dialog
{
	my $job = Gnome2::Print::Job->new;
	my $dialog = Gnome2::Print::Dialog->new($job, "Sample print dialog", 0);

	$dialog->signal_connect(delete_event => sub { $dialog->destroy; });
	$dialog->signal_connect(destroy      => sub { Gtk2->main_quit;  });

	$dialog->signal_connect(response     => sub {
			my ($d, $response_id, $job) = @_;
			my $conf = $d->get_config;
			my $j = Gnome2::Print::Job->new($conf);

			if    (1 eq $response_id)
			{
				render_job($j);

				my $pc = Gnome2::Print::Context->new($conf);
				$j->render($pc);
				$pc->close;

				$d->destroy;
			}
			elsif (2 eq $response_id)
			{
				render_job($j);

				my $preview = Gnome2::Print::JobPreview->new($j, "Sample preview dialog");
				$preview->set_property("allow-grow" => 1);
				$preview->set_property("allow-shrink" => 1);
				$preview->set_transient_for($d);
				$preview->show_all;
			}
			else
			{
				$d->destroy;
			}
		}, $job);

	return $dialog;
}