NAME

Imager::DTP::Textbox - multi-byte text handling module with text wrapping and line alignment, for use with Imager.

SYNOPSIS

use Imager::DTP::Textbox::Horizontal;  # or Vertical

# first, define font & text string
my $font  = Imager::Font->new(file=>'path/to/foo.ttf',type=>'ft2',
            size=>14);
my $text  = 'This year\'s Thrash Domination Tour here in ';
   $text .= 'Japan was great.';
   $text .= "\n\n";
   $text .= 'With Testament, Kreator, Destruction, and '; 
   $text .= 'Laaz Rockit all gathered at one place.';
# with multi-byte characters, encode it to UTF8, with internal
# utf-8 flag enabled (using utf8::decode()).

# create instance - basic way
my $tb = Imager::DTP::Textbox::Horizontal->new();
$tb->setText(text=>$text,font=>$font); # set text with font
$tb->setWspace(pixel=>5); # set space between letters
$tb->setLeading(percent=>180); # set space between lines
$tb->setAlign(halign=>'left',valign=>'top'); # set text alignment
$tb->setWrap(width=>200,height=>150); # set text wrapping

# create instance - or the shorcut way
my $tb = Imager::DTP::Textbox::Horizontal->new(text=>$text,
         font=>$font, wspace=>5, leading=>180, halign=>'left',
         valign=>'top', wrapWidth=>200, wrapHeight=>180);

# and draw the text string on target image
my $target = Imager->new(xsize=>250,ysize=>250);
$tb->draw(target=>$target,x=>10,y=>10);

CLASS RELATION

Imager::DTP::Textbox is an ABSTRACT CLASS. The extended class would be Imager::DTP::Textbox::Horizontal and Imager::DTP::Textbox::Vertical. (Yes, I know the package name is much longer than it should be... I took the advantage of comprehension). So you must "use" the extended class (either of Horizonal or Vertical), and not the Imager::DTP::Textbox itself. The difference between Horizontal and Vertical is as follows:

Imager::DTP::Textbox::Horizontal

letters are drawn from left to right, line stacks from top to bottom.

Imager::DTP::Textbox::Vertical

letters are drawn from top to bottom, line stacks from right to left.

DESCRIPTION

Imager::DTP::Textbox is a module intended for handling sentences and paragraphs consisted with multi-byte characters, such as Japanese and Chinese. It supports text wrapping and line alignment, and is able to draw text string vertically from top to bottom as well. All the text string provided (by setText() method) will be splitted by "\n", and each chunk will be turned into Imager::DTP::Line instance internally. So in another words, Imager::DTP::Textbox can be described as "a big box to put lines and letters in order". It's like WWW Browser's textarea input, or Adobe Illustrator's textbox tool.

METHODS

new

Can be called with or without options.

use Imager::DTP::Textbox::Horizontal;
my $tb = Imager::DTP::Textbox::Horizontal->new();

# or set all/any options at the same time
my $font  = Imager::Font->new(file=>'path/to/foo.ttf',type=>'ft2',
            size=>14);
my $text  = "Hello me... meet the real me.\n";
   $text .= "And my misfits way of life.";
my $tb = Imager::DTP::Textbox::Horizontal->new(text=>$text,
         font=>$font, wspace=>5, leading=>150, halign=>'left',
         valign=>'top', wrapWidth=>200, wrapHeight=>180);

setText

Set text string to the instance. Text must not be undef or '', and font option is not optional either. For multi-byte letters/characters, text must be encoded to utf8, with it's internal utf8-flag ENABLED (This could be done by using utf8::decode() method).

my $font  = Imager::Font->new(file=>'path/to/foo.ttf',type=>'ft2',
            size=>14);
my $text  = 'Smashing through the boundaries,';
   $text .= 'Lunacy has found me...';
$tb->setText(text=>$text,font=>$font);

By default, each time the method is called, it replaces the previous text with the provided new text. But by putting the "add" option, it will add new text to the end of the current text.

my $moreText = 'Cannot stop the battery!';
$tb->setText(text=>$moreText,add=>1);

Font is optional this time. If there is any previous text set, the new text will automatically inherit the font preference of last line, last letter's font preference.

The following characters will be translated to corresponding string internally:

\r => \n
\r\n => \n

"\n" will be used as a delimiter for splitting text string to each line object, and "\t" will stay the same until the time of draw() method call (see description of Imager::DTP::Line->draw() method for what will happen then).

setWspace

Set size for blank spaces inserted in between each letters. See Imager::DTP::Line->setWspace() for more description.

# setting a 5 pixel word space
$tb->setWspace(pixel=>5);

setLeading

The word "leading" in DTP application means "space between two consecutive lines". Thus, by setting some value (in percentage) here will affect the distance between each line. The default value is 150%, so setting any value greater than this will widen the distance, and setting smaller value (like 50%) will make the lines come closer (and with 50%, it will probably end up with two lines overlapping a little).

# set leading to 180%
$tb->setLeading(percent=>180);

The percentage is based on the ascent value of a letter, which has the maximum value out of all the letters held inside.

setAlign

Set horizontal and vertical alignment of lines, as if viewed from draw() method's x and y point.

$tb->setAlign(halign=>'right',valign=>'bottom');

Available options are:

halign (horizontal alignment)

left / center / right

valign (vertical alignment)

top / center / bottom

The default alignment for each extended class is as follows:

Imager::DTP::Textbox::Horizontal

halign => 'left' valign => 'top'

Imager::DTP::Textbox::Vertical

halign => 'right' valign => 'top'

setWrap

Set the maximum width and height of the bounding box, for the lines and letters to be wrapped inside. By setting these values to 0 will disable text wrapping (which is the default setting). Width will always be the horizontal measure, and height will be the vertical measure, no matter which extended class you choose (Imager::DTP::Textbox::Horizontal or Vertical).

# set x axis bounding to 200 pixels
$tb->setWrap(width=>200);

# set both x/y axis bounding to 100 pixels
$tb->setWrap(width=>100,height=>100);

Wrapping logic is letter-based, meaning text may be wrapped right in the middle of a "word", which is a normal wrapping rule for multi-byte texts (at least for Japanese, yes) in DTP applications. But with single-byte character word, this logic will make the sentence look ugly, so I've added some logic for single-byte character words to "always wrap at the beginning of the word". With it, alphabetical sentences and paragraphs will look OK, although hyphenation is not implemented (yet).

draw

Draw all the lines and letters held with-in, to the target image (Imager object).

my $target = Imager->new(xsize=>250,ysize=>250);
$tb->draw(target=>$target,x=>10,y=>10);

Each letter is drawn with Imager::DTP::Letter->draw() method, which internally is using Imager->String() method, so you can pass any extra Imager::String options to it by setting in 'others' option (See more details in Imager::DTP::Letter->draw() method description).

# passing Imager::String options
$tb->draw(target=>$target,x=>10,y=>10,others=>{aa=>1});

There is an extra debug option, which will draw a 'width x height' dark gray box underneath the textbox, a light grax box underneath each line, and a black bounding box for each letters. Handy for checking each object's bounding size/position.

# debug mode
$tb->draw(target=>$target,x=>10,y=>10,debug=>1);

Obtaining text drawn image

By NOT passing any target option, the method will return an Imager object, with all the lines and letters drawn to it. This is usefull when you want to perform some transformation (such as X/Y scaling, cropping, color filtering) to these text string.

# obtaining text drawn image
# x/y position will be forced at (0,0)
my $newimg = $tb->draw();

# apply some Imager's transformation method
my $scaled = $newimg->scaleX(pixels=>100);

GETTER METHODS

Calling these methods will return a property value corresponding to the method name.

getLines

Returns a reference (pointer) to an array containing all the Imager::DTP::Line object held internally.

getLeading

Returns the current value of leading.

getWidth

Return the actuall width of textbox. Actuall here means "not the wrapping width", but the precise width of the lines and letters held inside.

getHeight

Return the actuall height of textbox. Actuall here means "not the wrapping height", but the precise height of the lines and letters held inside.

getHalign

Returns the current value of horizontal alignment.

getValign

Returns the current value of vertical alignment.

getWrapWidth

Returns the current value of horizontal text wrap bounding.

getWrapHeight

Returns the current value of vertical text wrap bounding.

TODO

  • hyphenation with single-byte characters.

  • change Carp-only error handling to something more elegant.

AUTHOR

Toshimasa Ishibashi <iandeth99@ybb.ne.jp>

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

Imager, Imager::DTP