The built-in $txt->text_justify scales the text involved. It squeezes and stretches. Unless your column is nice and wide, the results are noticably crappy.
This example uses character spacing to get a nice clean justify like you would find in a newspaper.
#!/usr/local/bin/perl use PDF::API2; my $pdf = PDF::API2->new(-file => "$$.pdf"); delete $pdf->{forcecompress}; $pdf->mediabox(612,792); ## 8.5 x 11 at 72 point thingies/inch. $page = $pdf->page; ## Create a new page. $gfx = $page->gfx; ## Graphics layer for lines and such. my $txt = $page->text; ## Text Layer $txt->compress; ## Create all needed font references. my $times = $pdf->corefont('Times-Roman'); my $y; my $xcol; my $yStart = 792; my $summary = "This is the text that will be split out into the various thingees. This is paragraph one, and it has too much text in it. This is paragraph two, and it also has more than one line of text."; my @allLines = split/\n+/, $summary; my $para; foreach $para (@allLines){ $txt->font($times, 7); $y -= 9; my $indent = 1; my $check = 1; while ($check){ my ($charspace, $text, $over); if ($indent){ $txt->translate($xcol-52,$y); ($charspace, $text, $over) = newspaper_line($para, 124); $txt->charspace($charspace); $txt->text($text); $indent = 0; } else { $txt->translate($xcol-72,$y); ($charspace, $text, $over) = newspaper_line($para, 144); $txt->charspace($charspace); $txt->text($text); } if ($over){ $para = $over; $y -= 10; } else { $check = 0; } } } $pdf->finishobjects($page,$gfx,$txt); $pdf->saveas; $pdf->end(); sub newspaper_line { my $text = shift; my $width = shift; $txt->charspace(0); ## Accepts FONT, SIZE, TEXT, WIDTH ## Returns CHARSPACE, RENDERTEXT, REMAINDERTEXT ## Start out by splitting the TEXT on spaces into a big array. my @words = split/ +/, $text; my $i = 0; my $tempLine; ## Now go through progressively larger strings until it no longer fits. ## for ($i = 0; $i <= $#words; ++$i){ do { $tempLine .= "$words[$i] "; ++$i; } until ( ( $txt->advancewidth($tempLine) > $width ) || ($i > $#words ) ); if (($i > $#words) && !( $txt->advancewidth($tempLine) > $width )){ return(0, $tempLine, ""); } --$i; ## then decrement so it DOES fit. ## warn "We are taking $i words."; my $k; ## another looper for segmenting the word array.... my $run; my $overrun; for ($k = 0; $k <= $#words; ++$k){ if ($k < $i) { $run .= "$words[$k] " } else { $overrun .= "$words[$k] " } } ## Set up the control. $txt->charspace(0); my $nominal = $txt->advancewidth($run); ## Now the experiment. $txt->charspace(1); my $experiment = $txt->advancewidth($run); ## SINCE 0 -> $nominal AND 1 -> $experiment if (!($nominal)) {return 0} my $diff = $experiment - $nominal; my $min = $width - $nominal; my $target = $min / $diff; $txt->charspace($target); my $final = $txt->advancewidth($run); $txt->charspace(0); return($target, $run, $overrun); }