GDTextUtil-0.86/0040755000022200001440000000000007674205463012340 5ustar mgjvusersGDTextUtil-0.86/Text.pm0100644000022200001440000004114407674200026013611 0ustar mgjvusers# $Id: Text.pm,v 1.37 2003/06/19 00:13:10 mgjv Exp $ package GD::Text; ($GD::Text::prog_version) = '$Revision: 1.37 $' =~ /\s([\d.]+)/; $GD::Text::VERSION = '0.86'; =head1 NAME GD::Text - Text utilities for use with GD =head1 SYNOPSIS use GD; use GD::Text; my $gd_text = GD::Text->new() or die GD::Text::error(); $gd_text->set_font('funny.ttf', 12) or die $gd_text->error; $gd_text->set_font(gdTinyFont); $gd_text->set_font(GD::Font::Tiny); ... $gd_text->set_text($string); my ($w, $h) = $gd_text->get('width', 'height'); if ($gd_text->is_ttf) { ... } Or alternatively my $gd_text = GD::Text->new( text => 'Some text', font => 'funny.ttf', ptsize => 14, ); =head1 DESCRIPTION This module provides a font-independent way of dealing with text in GD, for use with the GD::Text::* modules and GD::Graph. =head1 NOTES As with all Modules for Perl: Please stick to using the interface. If you try to fiddle too much with knowledge of the internals of this module, you could get burned. I may change them at any time. You can only use TrueType fonts with version of GD > 1.20, and then only if compiled with support for this. If you attempt to do it anyway, you will get errors. If you want to refer to builtin GD fonts by their short name (C, C), you will need to C the GD module as well as one the GD::Text modules, because it is GD that exports those names into your name space. If you don't like that, use the longer alternatives (CGiant>) instead. =head1 METHODS =cut use strict; use GD; use Carp; use Cwd; use vars qw($FONT_PATH @FONT_PATH $OS); BEGIN { $FONT_PATH = $ENV{FONT_PATH} || $ENV{TTF_FONT_PATH} || $ENV{TT_FONT_PATH} || ''; unless ($OS = $^O) { require Config; $OS = $Config::Config{'os_name'}; } } my $ERROR; =head2 GD::Text->new( attrib => value, ... ) Create a new object. See the C method for attributes. =cut sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = { type => 'builtin', font => gdSmallFont, ptsize => 10, }; bless $self => $class; $self->set(@_) or return; return $self } =head2 GD::Text::error() or $gd_text->error(); Return the last error that occured in the class. This may be imperfect. =cut # XXX This sucks! fix it sub error { $ERROR }; sub _set_error { $ERROR = shift }; =head2 $gd_text->set_font( font, size ) Set the font to use for this string. The arguments are either a GD builtin font (like gdSmallFont or GD::Font->Small) or the name of a TrueType font file and the size of the font to use. See also L<"font_path">. If you are not using an absolute path to the font file, you can leave of the .ttf file extension, but you have to append it for absolute paths: $gd_text->set_font('arial', 12); # but $gd_text->set_font('/usr/fonts/arial.ttf', 12); The first argument can be a reference to an array of fonts. The first font from the array that can be found will be used. This allows you to do something like $gd_text->font_path( '/usr/share/fonts:/usr/fonts'); $gd_text->set_font( ['verdana', 'arial', gdMediumBoldFont], 14); if you'd prefer verdana to be used, would be satisfied with arial, but if none of that is available just want to make sure you can fall back on something that will be available. Returns true on success, false on error. =cut sub set_font { my $self = shift; my $fonts = shift; my $size = shift; # Make sure we have a reference to an array $fonts = [$fonts] unless ref($fonts) eq 'ARRAY'; foreach my $font (@{$fonts}) { my $rc = ref($font) && $font->isa('GD::Font') ? $self->_set_builtin_font($font) : $self->_set_TTF_font($font, $size || $self->{ptsize}) ; return $rc if $rc; } return; } sub _set_builtin_font { my $self = shift; my $font = shift; $self->{type} = 'builtin'; $self->{font} = $font; $self->{ptsize} = 0; $self->_recalc(); return 1; } sub _find_TTF { my $font = shift || return; local $FONT_PATH = $FONT_PATH; # XXX MOVE A LOT OF THIS INTO THE font_path SUB, filling the # @FONT_PATH array my ($psep, $dsep); if ($OS =~ /^MS(DOS|Win)/i) { # Fix backslashes $font =~ s#\\#/#g; # Check for absolute path $font =~ m#^([A-Za-z]:|/)# and return $font; $FONT_PATH =~ s#\\#/#g; # XXX move to set_font_path? $psep = '/'; $dsep = ';'; } =pod elsif ($OS =~ /^MacOS/i) { # Check for absolute path $font =~ /:/ and $font !~ /^:/ and return $font; $psep = ':'; $dsep = ','; } elsif ($OS =~ /^AmigaOS/i) { # What's an absolute path here? $psep = '/'; $dsep = ':'; # XXX ? } elsif ($OS =~ /^VMS/i) { # What's an absolute path here? $psep = '/'; $dsep = ':'; } =cut else { # Default to Unix # Check for absolute path substr($font, 0, 1) eq '/' and return $font; $psep = '/'; $dsep = ':'; } # If we don't have a font path set, we look in the current directory # only. if ($FONT_PATH) { # We have a font path, and a relative path to the font file. # Let's see if the current directory is in the font path. If # not, put it at the front. $FONT_PATH = ".$dsep$FONT_PATH" unless $FONT_PATH eq '.' || $FONT_PATH =~ /^\.$dsep/ || $FONT_PATH =~ /$dsep\.$/ || $FONT_PATH =~ /$dsep\.$dsep/; } else { # XXX what about MacOS? It doesn't work like this on MacOS. $FONT_PATH = '.'; } # Let's search for it # TODO Maybe truncate base name at 8 characters for dos-like # installations? for my $path (split /$dsep/, $FONT_PATH) { # XXX Can I use File::Basename for this? my $file = "$path$psep$font"; -f $file and return $file; # See if we can find one with an extension at the end for my $ext (qw/ ttf TTF /) { -f "$file.$ext" and return "$file.$ext"; } } return; } sub _set_TTF_font { my $self = shift; my $font = shift; my $size = shift; $ERROR = "TrueType fonts require a point size", return unless (defined $size && $size > 0); return unless $self->can_do_ttf; my $font_file = _find_TTF($font) or $ERROR = "Cannot find TTF font: $font", return; # XXX Fix for Freetype 2.0x bug, where relative paths to a font file # no longer work. if (substr($font_file, 0, 1) eq '.') { # This is a relative path. Replace ./path/file with # $cwd/path/file my $oldpath = $ENV{PATH}; $ENV{PATH} = "/bin:/usr/bin"; # Keep -T happy require Cwd; substr($font_file, 0, 1) = Cwd::cwd; $ENV{PATH} = $oldpath; } # Check that the font exists and is a real TTF font my @bb = GD::Image->stringTTF(0, $font_file, $size, 0, 0, 0, "foo"); $ERROR = "$@", return unless @bb; $self->{type} = 'ttf'; $self->{font} = $font_file; $self->{ptsize} = $size; $self->_recalc(); return 1; } =head2 $gd_text->set_text('some text') Set the text to operate on. Returns true on success and false on error. =cut sub set_text { my $self = shift; my $text = shift; $ERROR = "No text set", return unless defined $text; $self->{text} = $text; $self->_recalc_width(); } =head2 $gd_text->set( attrib => value, ... ) The set method provides a convenience replacement for the various other C methods. Valid attributes are: =over 4 =item text The text to operate on, see also C. =item font, ptsize The font to use and the point size. The point size is only used for TrueType fonts. Also see C. =back Returns true on success, false on any error, even if it was partially successful. When an error is returned, no guarantees are given about the correctness of the attributes. =cut # We use this to save a few CPU cycles my $recalc = 1; sub set { my $self = shift; $ERROR = "Incorrect attribute list", return if @_%2; my %args = @_; $ERROR = ''; $recalc = 0; foreach (keys %args) { /^text$/i and do { $self->set_text($args{$_}); next; }; /^font$/i and do { $self->set_font($args{$_}, $self->{ptsize}) or return; next; }; /^ptsize$/i and do { $self->{ptsize} = $args{$_}; next; }; $ERROR .= " '$_'"; } $recalc = 1; $self->_recalc(); if ($ERROR ne '') { $ERROR = "Illegal attribute(s):$ERROR"; return; } return 1; } =head2 $gd_text->get( attrib, ... ) Get the value of an attribute. Return a list of the attribute values in list context, and the value of the first attribute in scalar context. The attributes that can be retrieved are all the ones that can be set, and: =over 4 =item width, height The width (height) of the string in pixels =item space The width of a space in pixels =item char_up, char_down The number of pixels that a character can stick out above and below the baseline. Note that this is only useful for TrueType fonts. For builtins char_up is equal to height, and char_down is always 0. =back Note that some of these parameters (char_up, char_down and space) are generic font properties, and not necessarily a property of the text that is set. =cut sub get { my $self = shift; my @wanted = map $self->{$_}, @_; wantarray ? @wanted : $wanted[0]; } =head2 $gd_text->width('string') Return the length of a string in pixels, without changing the current value of the text. Returns the width of 'string' rendered in the current font and size. On failure, returns undef. The use of this method is vaguely deprecated. =cut sub width { my $self = shift; my $string = shift; my $save = $self->get('text'); my $len = $self->set_text($string); return unless defined $len; my $w = $self->get('width'); $self->set_text($save); return $w; } # Here we do the real work. See the documentation for the get method to # find out which attributes need to be set and/or reset sub _recalc_width { my $self = shift; return unless $recalc; return unless (defined $self->{text} && $self->{font}); if ($self->is_builtin) { $self->{'width'} = $self->{font}->width() * length($self->{text}); } elsif ($self->is_ttf) { my @bb1 = GD::Image->stringTTF(0, $self->{font}, $self->{ptsize}, 0, 0, 0, $self->{text}); $self->{'width'} = $bb1[2] - $bb1[0]; } else { confess "Impossible error in GD::Text::_recalc."; } } my ($test_string, $space_string, $n_spaces); BEGIN { # Build a string of all characters that are printable, and that are # not whitespace. my @test_chars = map chr, 0x01 .. 0xff; my $isprintable_sub; if ($] >= 5.008) { # We have to do this at run time, otherwise 5.005_03 will # whinge about [[::]] syntax being reserved, and this cannot # be shut up with $^W #$^W = 0; eval '$isprintable_sub = sub { $_[0] =~ /^[[:graph:]]$/ }' } else { eval { local $SIG{'__WARN__'}; require POSIX }; if ($@) { @test_chars = map chr, 0x21..0x7e, 0xa1..0xff; $isprintable_sub = sub { 1 } } else { $isprintable_sub = sub { POSIX::isgraph($_[0]) } } } $test_string = join '', grep $isprintable_sub->($_), @test_chars; # Put a space every 5 characters, and count how many there are $space_string = $test_string; $n_spaces = $space_string =~ s/(.{5})(.{5})/$1 $2/g; } sub _recalc { my $self = shift; return unless $recalc; return unless $self->{font}; if ($self->is_builtin) { $self->{height} = $self->{char_up} = $self->{font}->height(); $self->{char_down} = 0; $self->{space} = $self->{font}->width(); } elsif ($self->is_ttf) { my @bb1 = GD::Image->stringTTF(0, $self->{font}, $self->{ptsize}, 0, 0, 0, $test_string) or return; my @bb2 = GD::Image->stringTTF(0, $self->{font}, $self->{ptsize}, 0, 0, 0, $space_string); $self->{char_up} = -$bb1[7]; $self->{char_down} = $bb1[1]; $self->{height} = $self->{char_up} + $self->{char_down}; # XXX Should we really round this? $self->{space} = sprintf "%.0f", (($bb2[2]-$bb2[0]) - ($bb1[2]-$bb1[0]))/$n_spaces; } else { confess "Impossible error in GD::Text::_recalc."; } $self->_recalc_width() if defined $self->{text}; return 1; } =head2 $gd_text->is_builtin Returns true if the current object is based on a builtin GD font. =cut sub is_builtin { my $self = shift; return $self->{type} eq 'builtin'; } =head2 $gd_text->is_ttf Returns true if the current object is based on a TrueType font. =cut sub is_ttf { my $self = shift; return $self->{type} eq 'ttf'; } =head2 $gd_text->can_do_ttf() or GD::Text->can_do_ttf() Return true if this object can handle TTF fonts. This depends on whether your version of GD is newer than 1.19 and has TTF support compiled into it. =cut sub can_do_ttf { my $proto = shift; # Just see whether there is a stringTTF method at all GD::Image->can('stringTTF') or return; # Let's check whether TTF support has been compiled in. We don't # need to worry about providing a real font. The following will # always fail, but we'll check the message to see why it failed GD::Image->stringTTF(0, 'foo', 10, 0, 0, 0, 'foo'); # Error message: libgd was not built with TrueType font support $@ =~ /not built with.*font support/i and return; # Well.. It all seems to be fine return 1; } =head2 $gd_text->font_path(path_spec), GD::Text->font_path(path_spec) This sets the font path for the I (i.e. not just for the object). The C method will search this path to find the font specified if it is a TrueType font. It should contain a list of paths. The current directory is always searched first, unless '.' is present in FONT_PATH. Examples: GD::Text->font_path('/usr/ttfonts'); # Unix GD::Text->font_path('c:/fonts'); # MS-OS Any font name that is not an absolute path will first be looked for in the current directory, and then in /usr/ttfonts (c:\fonts). GD::Text->font_path('/usr/ttfonts:.:lib/fonts'); # Unix GD::Text->font_path('c:/fonts;.;f:/fonts'); # MS-OS Any font name that is not an absolute path will first be looked for in /usr/ttfonts (c:\fonts), then in the current directory. and then in lib/fonts (f:\fonts), relative to the current directory. GD::Text->font_path(undef); Font files are only looked for in the current directory. FONT_PATH is initialised at module load time from the environment variables FONT_PATH or, if that's not present, TTF_FONT_PATH, or TT_FONT_PATH. Returns the value the font path is set to. If called without arguments C returns the current font path. Note: This currently only works for unices, and (hopefully) for Microsoft based OS's. If anyone feels the urge to have a look at the code, and send me patches for their OS, I'd be most grateful) =cut sub font_path { my $proto = shift; if (@_) { $FONT_PATH = shift; if ($FONT_PATH) { # clean up a bit $FONT_PATH =~ s/^:+//; $FONT_PATH =~ s/:+$//; } } $FONT_PATH; } =head1 BUGS This module has only been tested with anglo-centric 'normal' fonts and encodings. Fonts that have other characteristics may not work well. If that happens, please let me know how to make this work better. The font height gets estimated by building a string with all printable characters (with an ordinal value between 0 and 255) that pass the POSIX::isprint() test (and not the isspace() test). If your system doesn't have POSIX, I make an approximation that may be false. Under Perl 5.8.0 the [[:print:]] character class is used, since the POSIX is*() functions don't seem to work correctly. The whole font path thing works well on Unix, but probably not very well on other OS's. This is only a problem if you try to use a font path. If you don't use a font path, there should never be a problem. I will try to expand this in the future, but only if there's a demand for it. Suggestions welcome. =head1 COPYRIGHT copyright 1999 Martien Verbruggen (mgjv@comdyn.com.au) =head1 SEE ALSO GD(3), GD::Text::Wrap(3), GD::Text::Align(3) =cut 1; GDTextUtil-0.86/t/0040755000022200001440000000000007674205463012603 5ustar mgjvusersGDTextUtil-0.86/t/align.t0100644000022200001440000000727007626513523014061 0ustar mgjvusers# $Id: align.t,v 1.19 2003/02/21 03:07:10 mgjv Exp $ use lib ".", ".."; BEGIN{ require "t/lib.pl" } use Test::More tests => 21; use GD; BEGIN { use_ok "GD::Text::Align" }; use constant PI => 4 * atan2(1,1); # Create an image $gd = GD::Image->new(200,200); ok (defined $gd, "GD returns an object"); $gd->colorAllocate(255,255,255); $black = $gd->colorAllocate(0,0,0); is ($gd->colorsTotal, 2, "Colors allocation"); # Test the default setup $t = GD::Text::Align->new($gd); ok (defined $t, "GD::Text::Align returns object") or diag($@); $t->set_text('A string'); ($w, $h, $cu, $cd) = $t->get(qw(width height char_up char_down)); ok ($w==48 && $h==13 && $cu==13 && $cd==0, "string returns right dim"); # Some alignments $t->set_align('top', 'left'); $t->draw(100,10); ($x, $y) = $t->get(qw(x y)); ok ($x==100 && $y==10, "top left"); $t->set_align('center', 'right'); $t->draw(100,10); ($x, $y) = $t->get(qw(x y)); ok ($x==52 && $y==3.5, "center right"); $t->set_align('bottom','center'); $t->draw(100,20); ($x, $y) = $t->get(qw(x y)); ok ($x==76 && $y==7, "bottom center"); # Test loading of other builtin font $t->set_font(gdGiantFont); $t->set_align('bottom', 'right'); $t->draw(100,40); ($x, $y) = $t->get(qw(x y)); ok ($x==28 && $y==25, "builtin font"); # Test some angles, this method is not meant to be used by anyone but # me :) # This first test used to check for PI/4 exactly, but some installations # of Perl on some platforms, with some flags would round that just # slightly differently from what I expect and want. $t->draw(100,40,PI/4 - 0.0001); ok (!$t->_builtin_up, "angles test"); $t->draw(100,40,PI/4 + 0.0001); ok ($t->_builtin_up, "angles test 2"); # And some bounding boxes $t->set_align('bottom', 'left'); @bb = $t->bounding_box(100,100); is ("@bb", "100 100 172 100 172 85 100 85", "bounding boxes"); @bb = $t->bounding_box(100,100,PI/2); is ("@bb", "100 100 100 28 85 28 85 100", "bounding boxes 2"); # Constructor test $t = GD::Text::Align->new($gd, valign => 'top', halign => 'left', text => 'Banana Boat', colour => $black, font => gdGiantFont, ); @bb = $t->draw(10,10); is ("@bb", "10 25 109 25 109 10 10 10", "constructor test"); # Test a '0' string $t = GD::Text::Align->new($gd, text => '0', font => gdLargeFont, valign => 'bottom', halign => 'center', colour => $black); @bb = $t->draw(100, 200); is ("@bb", "96 200 104 200 104 184 96 184", "false string"); # TTF fonts SKIP: { # skip skip "No ttf", 6 unless ($t->can_do_ttf); $t = GD::Text::Align->new($gd, valign => 'top', halign => 'left', text => 'Banana Boat', colour => 1, ptsize => 18, ); ok ($t->set_font('Dustismo_Sans'), "ttf font Dustismo Sans") or diag($t->error); skip "Some TTF tests disabled: Freetype inconsistent", 5; @bb = $t->draw(10,40); ok (aeq(\@bb, [qw"11 57 137 57 137 41 11 41"], 1), "drawing") or diag("bb = @bb"); ok ($t->set_font('Dustismo_Sans', 12), "ttf Dustismo Sans 12pt") or diag($t->error); $t->set_align('bottom', 'left'); @bb = $t->bounding_box(100,100); ok (aeq(\@bb, [qw"101 97 190 97 190 86 101 86"], 1), "bottom left align") or diag("bb = @bb"); $t->set_align('top', 'center'); @bb = $t->bounding_box(100,100, 4*PI/3); ok (aeq(\@bb, [qw"111 55 67 132 77 137 120 60"], 1), "top center align") or diag("bb = @bb"); @bb = $t->draw(140,100,4*PI/3); ok (aeq(\@bb, [qw"151 55 107 132 117 137 160 60"], 1), "last drawing") or diag("bb = @bb"); } __END__ # only during testing of the test scripts $gd->colorAllocate(127,127,127); $gd->line(100,0,100,200,2); $gd->line(0,100,200,100,2); open(GD, ">/tmp/align.png") or die $!; binmode GD; print GD $gd->png; close(GD) GDTextUtil-0.86/t/lib.pl0100644000022200001440000000103307674205360013674 0ustar mgjvusers# allow a 2 pixel difference between the values in array ref 1 and array # ref 2 eval { local $SIG{'__WARN__'}; require Test::More }; if ($@) { # Test::More is not available print "1..1\n"; print "ok 1 # skip Skipping all tests: No Test::More\n"; exit 0; } sub main::aeq { my ($a1, $a2, $e) = @_; $e = 0 unless $e; return 0 if @$a1 != @$a2; for (my $i = 0; $i < @$a1; $i++) { return 0 if $a1->[$i] > $a2->[$i] + $e || $a1->[$i] < $a2->[$i] - $e; } return 1; } 1; GDTextUtil-0.86/t/text.t0100644000022200001440000000724307626513523013753 0ustar mgjvusers# $Id: text.t,v 1.17 2003/02/21 00:10:28 mgjv Exp $ use lib ".", ".."; BEGIN { require "t/lib.pl" } use Test::More tests => 20; use GD; BEGIN { use_ok "GD::Text" } # Test the default setup $t = GD::Text->new(); ok ($t->is_builtin, "default font is builtin"); # Check some size parameters $t->set_text("Some text"); ($w, $h, $cu, $cd) = $t->get(qw(width height char_up char_down)); ok ($w==54 && $h==13 && $cu==13 && $cd==0, "default size params") or diag("w=$w, h=$h, cu=$cu, cd=$cd"); # Change the text $t->set_text("Some other text"); $w = $t->get('width'); ok ($w==90 && $h==13 && $cu==13 && $cd==0, "default size params 2") or diag("w=$w, h=$h, cu=$cu, cd=$cd"); # Test loading of other builtin font $t->set_font(gdGiantFont); ok ($t->is_builtin, "gdGiantFont builtin"); # Test the width method $w = $t->width("Foobar Banana"); is ($w, 117, "width method"); # And make sure it did not change the text in the object $text = $t->get('text'); is ($text, "Some other text", "text did not change"); # Now check the Giant Font parameters ($w, $h, $cu, $cd) = $t->get(qw(width height char_up char_down)); ok ($w==135 && $h==15 && $cu==15 && $cd==0, "Giant font size") or diag("w=$w, h=$h, cu=$cu, cd=$cd"); # Check that constructor with argument works $t = GD::Text->new(text => 'FooBar Banana', font => gdGiantFont); ($w) = $t->get(qw(width)) if defined $t; is ($w, 117, "constructor with args") or diag("t=$t"); # Check multiple fonts in one go, number 1 $rc = $t->set_font(['foo', gdGiantFont, 'bar', gdTinyFont]); ok ($rc, "multiple fonts"); SKIP: { skip "No TTF support", 6 unless ($t->can_do_ttf); unless (ok (-d "t", "correct directory")) { diag("Running in incorrect directory: No 't' subdirectory."); skip "Test script ran from incorrect directory", 5; } # Test loading of TTF $rc = $t->set_font('Dustismo_Sans.ttf', 18); ok ($rc && $t->is_ttf, "ttf set_font") or diag("Your GD module incorrectly claims valid TTF support"); # Check multiple fonts in one go, number 2 $rc = $t->set_font(['Dustismo_Sans', gdGiantFont, 'bar'], 24); like ($t->get('font'), qr/Dustismo_Sans.ttf$/, "ttf multiple fonts") or diag("Font is '".$t->get('font')."'"); is ($t->get('ptsize'), 24, "ttf multiple fonts"); skip "Some TTF tests disabled: Freetype inconsistent", 2; # Check some size parameters @p = $t->get(qw(width height char_up char_down space)); is ("@p", "210 29 23 6 11", "ttf size param"); # Check that constructor with argument works $t = GD::Text->new(text => 'FooBar', font =>'Dustismo_Sans'); @p = $t->get(qw(width height char_up char_down space)) if defined $t; ok (defined $t && "@p" eq "38 12 10 2 5", "ttf constructor arg") or diag("p = @p"); } # Font Path tests # # Only do this if we have TTF font support, and if we're on a unix-like # OS. Will adapt this once I have support for other OS's for the font # path. SKIP : { skip "no tff/nonunix", 4 unless ($t->can_do_ttf && $^O && $^O !~ /^MS(DOS|Win)/i && $^O !~ /VMS/i && $^O !~ /^MacOS/i && $^O !~ /os2/i && $^O !~ /^AmigaOS/i); # Font Path $t->font_path('demo/..:/tmp'); $rc = GD::Text::_find_TTF('Dustismo_Sans', 18); is($rc,'./Dustismo_Sans.ttf', "font path no ttf"); $t->font_path('demo/..:.:/tmp'); $rc = GD::Text::_find_TTF('Dustismo_Sans', 18); is($rc,'demo/../Dustismo_Sans.ttf', "font path multi"); $rc = GD::Text::_find_TTF('/usr/foo/font.ttf', 18); is($rc,'/usr/foo/font.ttf', "font path abs"); $t->font_path(undef); $rc = GD::Text::_find_TTF('Dustismo_Sans.ttf', 18); is($rc,'./Dustismo_Sans.ttf', "named"); } GDTextUtil-0.86/t/wrap.t0100644000022200001440000000362107626513523013734 0ustar mgjvusers# $Id: wrap.t,v 1.14 2003/02/20 12:23:32 mgjv Exp $ use lib ".", ".."; BEGIN { require "t/lib.pl" } use Test::More tests => 14; use GD; BEGIN { use_ok "GD::Text::Wrap" }; $text = <new(170,150); ok (defined $gd, "GD::Image object"); # Allocate colours $gd->colorAllocate(255,255,255); $gd->colorAllocate( 0, 0, 0); is($gd->colorsTotal,2, "color allocation"); # Create a GD::Text::Wrap object $wp = GD::Text::Wrap->new($gd, text => $text); ok ($wp, "GD::Text::Wrap object"); $wp->set(align => 'left', width => 130); # Get the bounding box @bb = $wp->get_bounds(20,10); is ("@bb", "20 10 150 128", "bounding box"); # Draw, and check that the result is the same @bb2 = $wp->draw(20,10); is("@bb", "@bb2", "drawing bounding box"); $wp->set(align => 'left'); @bb2 = $wp->draw(20,10); is ("@bb", "@bb2", "left align"); $wp->set(align => 'justified'); @bb2 = $wp->draw(20,10); is ("@bb", "@bb2", "justified"); $wp->set(align => 'right'); @bb2 = $wp->draw(20,10); is ("@bb", "@bb2", "right align"); @bb = "20 10 150 143"; $wp->set(preserve_nl => 1); @bb2 = $wp->draw(20,10); is ("@bb", "@bb2", "preserve_nl"); $wp->set(preserve_nl => 0); SKIP: { skip "No TTF Support", 3 unless ($wp->can_do_ttf); $rc = $wp->set_font('Dustismo_Sans', 10); ok ($rc, "ttf font set"); skip "Some TTF tests disabled: Freetype inconsistent", 2; # Get the bounding box @bb = $wp->get_bounds(20,10); ok (aeq(\@bb, [qw'20 10 150 113'], 1), "ttf bounding box") or diag("bb = @bb"); @bb2 = $wp->draw(20,10); ok (aeq(\@bb, \@bb2, 0), "ttf drawing") or diag("bb2 = @bb2"); } ok (1, "end"); __END__ #Only here to test the test. open(GD, '>/tmp/wrap.png') or die $!; binmode GD; print GD $gd->png(); close GD; GDTextUtil-0.86/demo/0040755000022200001440000000000007674205463013264 5ustar mgjvusersGDTextUtil-0.86/demo/GDWrap.pl0100644000022200001440000000311207626513523014733 0ustar mgjvusers#!/usr/bin/perl -w use strict; use GD; use GD::Text::Wrap; my $outfile = shift || "GDWrap.png"; my $gd = GD::Image->new(400,240); my $white = $gd->colorAllocate(255,255,255); my $black = $gd->colorAllocate( 0, 0, 0); my $blue = $gd->colorAllocate(127,127,255); my $red = $gd->colorAllocate(127, 0, 0); #print "No colours: $black ", $gd->colorsTotal, "\n"; my $text = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.'; my $wp = GD::Text::Wrap->new($gd, width => 180, line_space => 4, color => $black, text => $text, ); $wp->set(align => 'left'); $gd->rectangle($wp->get_bounds(10,10), $blue); $wp->draw(10,10); $gd->rectangle($wp->get_bounds(210,10), $blue); $wp->set(para_space => 5, preserve_nl => 1); $wp->set_font('Dustismo_Sans', 10); $wp->set(align => 'justified', line_space => 0); $wp->draw(210,10); $wp->set(para_space => 10, preserve_nl => 0); # Assume the user has set FONT_PATH or TTF_FONT_PATH #$wp->font_path('/usr/share/fonts/ttfonts'); $wp->set_font(['arial', 'Dustismo_Sans'], 10); $wp->set(align => 'right'); $gd->rectangle($wp->get_bounds(10,120), $blue); $wp->draw(10,120); $text =~ tr/\n//d; $wp->set(text => $text); $wp->set(colour => $white, align => 'center', line_space => 2); $wp->set_font(gdMediumBoldFont, 12); $gd->filledRectangle($wp->get_bounds(210,120), $red); $wp->draw(210,120); print "Writing $outfile\n"; open(GD, ">$outfile") or die "Cannot open '$outfile' for write: $!"; binmode GD ; print GD $gd->png(); close GD; GDTextUtil-0.86/demo/GDWrap.ref.png0100644000022200001440000001006507422214755015663 0ustar mgjvusersPNG  IHDR/PLTE???__PIDATx]Kr8.V9"t)uvD`H(Zr1˒HD @!T..|7dTrdP9ĕWIi6MN"D,m^^]kiT2OG(V.b;:xǧ)ΟB`Nll~È/Æ eR X^(O%Y8~9t"sc-ho*I,GEeudwb"'gbFDGE V:ddj@ *#@l+5|@Il 7t-ՂrN[I kIpLp$3+bg42-MjajS6>UeQbd_Z C?Sä.ݻ:Z2UrUɵ*:V2TWrt;;%JE@z/.e\z2V%J֒r*ޫ]\vР%/` (Xw@ +jZB9@^A "3 [D oaw@biux#<H^`JV2b3WNsͮ)2qF- e֡z Q ȷMvnWnWnWrK*Z 7וu)OԭCk%o*+RW^Zײ.e JauWђlBwe]ve]Pقko&d(%eC,jt@FHX H]@Kb]D.43cj仏=}Orv j:,`F25Nk9o?ӹs ^y:Y:pȀ` @B=Ox{{sivW7p$qVk9j &~%Fq_N{~xLIH7752$HcDеe@Ú:gbGo] 4es  c#7`?nb9oصE%,@51 8W pFWZs-t-iE\ZՀT̏ ȟG)ke? HuPVc2|H7O Lv< ֔a 42 IGe_c@`ۿ0D!7LH$_>3"sv c @ t*Q D}p׳xd( IrO|Hya2 DD>$\ hO<}t姀Ёv-&@|W7n = 4XH G r\~kyIIq;-dUo\[/z^l`~cH}"囃=5vqRcy݁W, q1l Ij:y{wg$偐#0ju_diJ>@8~,zwP;'⒜Ko a+ 3ĴF :qc } wŹnz* P)}haBҮrdw-bLjajD[1y/M !zG a@h]+BpZ<;c]< Wpa_0e%!wx1I%D\:!zXp7att1; $>(6 z\H jL1 O"h1ݏ3={"]2d '+q2n-bsH5^%RΔ4_!@0x08F&#4Lp ~ |CP!8.1Ajn2EŁKs<$oCnٍ]@fV׺ CX,=e_8p"|Q\!Hf>L}:ۺu41H—xOyw pY?_{fO{eΛHw H|cF !>i?D{2 CӉF;"-"5 Yz c򵴺yL%dywh'"cO{( $R tem%dH&8X,1x+1/n'҃ !~i3Z4=wj9\t1}?H(>ŋgQ' .#m&Rg n1B9)n#~|s s"YuV Թkўl-DԦ i3ddSN}.1#]+yy$Bl˔@]30N!6k)YY7i܁|C `>89|L s X|0@jWp^@ݱoN dd8#"=/2!7B%QF?zdBA51QϾx=BQ}"UnuNb":V'RwH(Lg@oz=E; i'=iG. 5so: 5֘H]ZVd ! 'zΔ|{*Ӗ9gL{S L y0 dO1{ӄ@k }Il}4 "%Cv )6B^}:h~<ƟI#>r"c@&3E... @IENDB`GDTextUtil-0.86/MANIFEST0100644000022200001440000000026207626513523013462 0ustar mgjvusersChanges README Makefile.PL MANIFEST Dustismo_Sans.ttf Dustismo.LICENSE demo/GDWrap.pl demo/GDWrap.ref.png t/lib.pl t/text.t t/align.t t/wrap.t Text.pm Text/Wrap.pm Text/Align.pm GDTextUtil-0.86/Makefile.PL0100644000022200001440000000346007674205210014300 0ustar mgjvusersuse ExtUtils::MakeMaker; use strict; use Config; my %extras; eval { local $SIG{'__WARN__'}; require Test::More }; if ($@) { print "Test::More is not installed: All tests will be skipped\n"; # XXX Why can't I reset this to not do any tests? $extras{test} = {TESTS => undef}; } # Check that the current GD has TTF support, and that it works. eval { local $SIG{'__WARN__'}; require GD; require File::Spec; require Cwd; GD::Image->can('stringTTF') or die "One"; GD::Image->stringTTF(0, 'foo', 10, 0, 0, 0, 'foo'); $@ =~ /TrueType font support/i and die "Two"; my $test_font = File::Spec->catfile(Cwd::cwd(), "Dustismo_Sans.ttf"); GD::Image->stringTTF(0, $test_font, 10, 0, 0, 0, 'foo') or die "Three: $@"; }; if ($@ && $@ =~ /^Three/) { # We seem to have one of those rare GD installations that claims it # can do TTF, but that fails when we try. warn < 'GDTextUtil', 'NAME' => 'GD::Text', 'VERSION_FROM' => 'Text.pm', 'PREREQ_PM' => { 'GD' => 1 }, ($] >= 5.005 ? ( 'ABSTRACT' => 'text utilities for GD', 'AUTHOR' => 'Martien Verbruggen (mgjv@comdyn.com.au)', ):() ), clean => {FILES => "GDWrap.png"}, %extras, ); sub MY::postamble { qq( .PHONY: demo demo: pure_all GDWrap.png GDWrap.png: demo/GDWrap.pl \@$Config{'perlpath'} -Mblib demo/GDWrap.pl demo/GDWrap.png ) } # $Id: Makefile.PL,v 1.14 2003/06/19 00:57:44 mgjv Exp $ GDTextUtil-0.86/Dustismo_Sans.ttf0100644000022200001440000017310007625144340015641 0ustar mgjvusers LTSHyOS/2UNVVDMXkIr`cmapxzcvt tm@fpgmɌqvgasp glyf<9hdmx>b"heado,6hhea Bzd$hmtx{SHkernGloca8fmaxp^ nameD}post &prepr @?_<9jEWkk2Wuu[e@[fJADBE@ Kqc ">T"dX 1,9e L \ s#w    >  "   X 0   V . v   F Copyright (c) Dustin Norlander, 2002. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later DustismoRegularDustinNorlander: Dustismo: 2002DustismoVersion 1.4; 2002DustismoDustismo is a trademark of Dustin Norlander.Copyright (c) Dustin Norlander, 2002. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later DustismoRegularDustinNorlander: Dustismo: 2002DustismoVersion 1.06 2003DustismoDustismo is a trademark of Dustin Norlander.Dustin Norlander, . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version of the License, or any laterDustin Norlanderhttp://www.dustismo.comCopyright (C) 2002 Dustin Norlander This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version.http://www.gnu.org/licenses/gpl.txtCopyright (c) Dustin Norlander, 2002. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later DustismoRegularDustinNorlander: Dustismo: 2002DustismoVersion 1.06 2003DustismoDustismo is a trademark of Dustin Norlander.Dustin Norlander, . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version of the License, or any laterDustin Norlanderhttp://www.dustismo.comCopyright (C) 2002 Dustin Norlander This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version.http://www.gnu.org/licenses/gpl.txt "  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ƂʈǫJ@ ~!7~     " & 0 : D !""" "9     & 0 9 D !"""7r~pc0hޒHZ\bh 4bcdefghjikmlnoqprsutvwxzy{}|~ #$    %&'()*`aKLMN\[GHIJOPQRSTUVWXYZCD]bc?@ABEF^_;<=> !"qonrstH@~!7~     " & 0 : D !""" "9     & 0 9 D !"""7r~pc0hޒFXZ`f2bcdefghjikmlnoqprsutvwxzy{}|~ #$    %&'()*`aKLMN\[GHIJOPQRSTUVWXYZCD]bc?@ABEF^_;<=> !"qonrstu ++ E}iD@ EhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDF+F+EhDEhD@,vE %E#ah#h`D- ,KPXYD_^- , EiD`- , *!- , F%FRX#Y Id F had%F hadRX#eY/ SXi TX!@Yi TX!@eYY:-, F%FRX#Y F jad%F jadRX#Y/-,K &PXQXD@DY!! EPXD!YY-, EiD` E}iD`-,*-,K &SX@Y &SX#!#Y &SX#!#Y &SX#!@#Y &SX%EPX#!#!%E#!#!Y!YD-,KSXED!!Y-sKKWZbZb*qKwlil!k!(:hsJ8 @)hEHHY;5D( F"$ 1(\CLHn%~9`JP9IJJJs9Jd1=JsHHl9$Hs9IHe5$~A9!5i91H]X=0Ha*arH<3Ye4!L/J/ LHcV J]Je4YJLYH9dC9!<=P!DGq c,p9p9B9JH^9pAWzWzWzWzWzWz3R0R0R0R0`iOJW4W4W4W4W4CCCC.!b[G=5p%..9v:7 !._:k%{s26D~9p9^92ADH0.8<b$b0 B!!A!HH4h5<1p9Jp9JJV1V VV^9^9^9pApApAJL,OT=@h- =DTRYMa,(e<@1D/Q B!>L<D~9*aydaU`JrH`JrH`JrHP93YHIHYHIHYHIHe4l9$d~ACe59e59e59~AC~AC~AC~9*a~9*aP93P93H]Jdd@!d1~-J1D1D5<P!~9*aP93P93IJPJe4Je4Je4Je4Je4s9L/s9L/s9L/~AC~ACl9e4l9e4H]J$ddd1/s9L/Jx/1/=LHJJJH]JW$dI0uQ\AAC~9*adBl9e4~AC9#/`JR8x                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         V@ @ Fv/7?Y0134632#"&x)**).))))iKQ +/ /ܸܸи///EX/>YEX/>Y01#3#3΂7!D@ @!            Fv/7?YEX/>Y +( +( +иик)9 и!и(+012654&#"32##5"&'33"&54767532#&^e\gU]`53\%2WQN/GK9YEX/>YEX///>YEX/>YEX / >Y01 #2#"&546"32654&2#"&546"32654&irnnqo6NN66OO{poomZ" N87RTKKmnopK66JJ66KėnomnO8JL65K:q*#,{ +& +&A&&&&&&&]A &&&&6&F&V&qAe&u&qEX / >Y +016&6'3'.547'.7632267z u2g=o6/I%LOssGD?'_sd lAW27fpOIE%_k+GEMJrmC(4%7o\j sK$ + +/EX/>Y01#3JqK + +A]A &6FVqAeuqEX/>YEX / >Y017&Je``ef#m*]]*m#f8oI | + +AjzqA]A )9IYqEX / >YEX/>Y0156'5e``e#m*33*m#@1Q + / /// + 9ик  9  901''7#53'773ag``gakgllgk<  +//0172'67.6,CVyC9@A,w:/DqmHS + +01!!H H# + +AjzqA]A )9IYqEX / >YA]A '7GWqAfvq0174632#"&H@./>@-.@m/@A..?@*KQ@@Fv/7?YEX/>Y AiyqA]A (8HXqA]A '7GWqAfvq01#"&=46324&#"3265jjjji^ݘޙhd^d5U Q + + и EX/>YEX/>Yܸ и 01526733!5358EZFXb/4łvD + + и и /EX/>YEX/>YAiyqA]A (8HXq01)56$65&!"#4$32!~s[egHyH`IvA;(})} +$ +Aj$z$qA$$$$$$$]A $$)$9$I$Y$q$9/AjzqA]A )9IYqܸ+EX/>YEX/>YEX/>YEX/>YEX/>Y + 9'Ai'y'qA''''''']A ''('8'H'X'q01'67632#"&5332654>56&#" m$1_mx=}[jiHK#5ƥk*Á|HܧNrrqMf< q" w + +и иEX/>YEX/>YEX/>YEX / >Yܸи01% 3##!5<^$dd_;łq;Fq# +//и/ܸ ܸи/ AjzqA]A )9IYqEX/>YEX/>Y + ܺ 99A]A '7GWqAfvq01"#!!632#"'532654'&[khpŖ5il`|[1ޑ^}׎PG"I + +AjzqA]A )9IYq EX/>YEX/>Y +9ܸA]A '7GWqAfvq01632#".!"";2654& nn.8nѽns|u$q^@%@Fv/7?YEX/>Y  + %AiyqA]A (8HXqA]A '7GWqAfvq  9* 9014&#"326&#"3265&#"$'47&54632Ғ[[[[X ЋޑދWWjrrIoiioj`si̔is(o + +A]A &6FVqAeuqEX/>YEX/>Y +9ܸAiyqA]A (8HXq01#"$54$32!52%2654&+"z3Țz,nѽwasy|u\7  + +AjzqA]A )9IYq ииEX/>Y +014632#"&4632#"&\A,-A@..??..@A-.?U-@A,.BBJ.BB..?@CA<  + +AjzqA]A )9IYqи//EX/>Y014632#"&2'67.6]B,,CB-.@o,CVyC9@U-@A,.BBA,w:/DqmL'k@-@Fv/7?/.ć........10IhIha@RX878Y 5'q%osHB + + +01!!!!H}}ĂnI +/EX/>Y015 n%q%K#// +0/1/0и/*ܸи/1ܸ Aj z qA ]A  ) 9 I Y q*и/*и/ и/*!и!/$и$/EX/>YEX-/->YAiyqA]A (8HXq01#7676767654'&#"#46324632#"&t7(N)M5:4a6ʍ8"=657 )**),]C/-&=w71z%@ĉzB)[0Uw))))` AP +&5 +&F +F@ +@5@9Aj z qA ]A  ) 9 I Y q и /5@95@9 5@9A&&&&&&&]A &&&&6&F&V&qAe&u&qAFFFFFFF]A FF&F6FFFVFqAeFuFq@R*/ +*:" +:J +JB +B9Jи/и/ B901;27654#"'&'#"&54763273&! 327#"'&'&547632#"32654'&@!2H}ULyS-'ڣӬTfǶAߡZc⮟bkT4D5*@TyЩvh8/DڠأkżxvXZflsPQB@9K @B @        Fv/7?YEX$/$>Y + $ܸ ܺ 901!27654'&#!27654'&#'2#!e_TU^+ZTUZSLyQTO3SHQSDJz MIdaKNiookz^V&K9c#۸ + +EX/>YEX/>YAiyqA]A (8HXqA]A '7GWqAfvq014632#&'&#"327673#"&59jjL1GdșdG1LjjSnnV_iNnۣnNi_VnnJK a +//и/ܸܸܸи/EX / >YEX/>Yܸ 017!2654&#!%2#!(Ę(zs7$V+߂]X`kڙKJaK U + +EX/>YEX / >Y +ܸ 01!!!!!akKTKJaK M + +EX/>YEX/>Y +01!!!#akKXeK9c): +*/+/)ܸܸ* и /)и/и ܸ и /EX/>YEX/>YEX/>Y% +%9AiyqA]A (8HXqA]A '7GWqAfvq01!5#"&54632#4&#"3265!6&7!};KqjjᘘjjᘂșșhG%7nYnnۣ۩ A JK W +EX/>YEX/>YEX/>YEX / >Y +01!3#!#:ƂK<K1K l@0 @       Fv/7?YEX/>YA]A '7GWqAfvq01!#"'&=33265#F$3w{%MlKJLl~rv~-5EXkX=K @B @     Fv/7?YEX/>Y01!!T*K7KHK @> @     Fv/7?YEX/>YA]A '7GWqAfvq Ai y qA ]A   ( 8 H X q0132654&#"#"&54632șșDjjᘘjjۣyۣnnYnnHK  +//и/ܸܸ иAjzqA]A )9IYqEX/>YEX/>Y +  01#!2#32654'&#̄؛JXKx|D9c8, +9/:/9,и,/:ܺ,9ܸ,ܸи7EX2/2>YEX/>YEX'/'>Y292 Ai y qA ]A   ( 8 H X q'A]A '7GWqAfvq01654'&#"327'%#.'#"&'&547632 @ 9ddddddzXL 2[1%)pjjLLpqjjLL#F#]{ymnnmnmE6]47nY77nHK߸ +// и / ܸиܸAjzqA]A )9IYq 99EX / >YEX / >YEX/>Y + ܺ 901!2654&##!2#؛nl)y~8Kx|rn!5d7Z +8/9/8и/ܸи9 ܸ!Aj!z!qA!!!!!!!]A !!)!9!I!Y!q(и 2и!3EX-/->YEX/>Y-AiyqA]A (8HXqA]A '7GWqAfvq01"#".'332>'4.$.54>36#4.Q[11YDR_aM2[NNa74`AMckH-Z!gcQ^e;9eaGZ@$&AXD6UCidMLa9:fM3lB&KE + +EX/>YEX/>Yܸи01#!5!.i7ɂAK +//и/ܸ ܸܸ и /EX/>YEX/>YEX/>YA]A '7GWqAfvq0132653#"'&'&5ʒ̂Ɩzs6%Kۥ_ٚ]X`kQ!Kl@/@Fv/7?m^W1K o@. @    Fv/7?Y017!!Hba?K +/EX/>Y01 3? aLy +M/N/7ܸܸMHиH/A]A &6FVqAeuq и+и+/H,и,/EX1/1>YEX=/=>YEXC/C>YA]A '7GWqAfvqC191&Ai&y&qA&&&&&&&]A &&(&8&H&X&q:01%2>76=>=4.#"'>32.''".54>@^A'!0L^aY /"3M\$itt\93N[(1^RA~NqKBwM3O?XLsF/Cl$ %,/29 @ 6' &D7IhB#@\9 A -'-,=kU$MF=HK } +//и/ܸи/ܸ Aj z qA ]A  ) 9 I Y qк9EX/>YEX / >YEX/>Y AiyqA]A (8HXqA]A '7GWqAfvq9901"32654&'2#"'#36#ǐ2܀{Q⑓㏒ĮK3: +  + A ]A   & 6 F V qAe u qEX/>YEX/>Y9 Ai y qA ]A   ( 8 H X qA]A '7GWqAfvq9012#&'&#"327673#"54Ǎ5! gˑf !2ә9@p⒓p ;50.Ky +//ܸܸи и / 9A]A &6FVqAeuqи/EX/>YEX/>YEX / >Y 9 9AiyqA]A (8HXq A]A '7GWqAfvq0123#5#"54"32654&{2ǐߓ<-0ᒏߓ4۸ +EX/>YEX / >Y + A]A '7GWqAfvqAiyqA]A (8HXq013267#"5432"!.юh+5  o)#ϊـ[/.hj!Ks + +и  EX/>YEX/>YEX / >YEX/>Yܸ и 01"3###535463YcNNcDb;b}/v & +'/(/ܸܸи/'и/ A ]A   & 6 F V qAe u qи/ и/$к%9EX/>YEX / >YEX/>Y! +! A]A '7GWqAfvqAiyqA]A (8HXq 9% 901%2654&#""543253#"&'7326= w z|lߓ⑓߂,ɳ֦{ǔ[JKԸ +//и/ܸܸ ܸEX/>YEX/>YEX/>YEX/>Y9 Ai y qA ]A   ( 8 H X q013632#4&#"#J~վ炙Kޘ"/>Mf + +и/и/EX/>YEX/>YEX/>Y014>32#".!##  ..  r , , C; qYKZ + +и/!EX/>YEX/>YEX/>Y014>32#".#5!#52765#  ..  pWVZ12| , , L~WX21DHK @@ @     Fv/7?YEX/>Y013#VKJs +  +  + + к99!EX/>YEX/>YEX/>YEX/>YEX / >YEX/>YAiyqA]A (8HXq к9901"#6&#"#3632632#4&xyfvzZM7𹤂_Qҡ"ޡҡ"j"ޡJԸ +//и/ܸܸ ܸEX/>YEX/>YEX/>YEX/>Y9 Ai y qA ]A   ( 8 H X q013632#4&#"#Jsꄲ޽"4  +//и/A]A &6FVqAeuqܸ Aj z qA ]A  ) 9 I Y qEX / >YEX/>Y AiyqA]A (8HXqA]A '7GWqAfvq01"32654&'2#"54ˑΑQ⒓0.Jq  +//ܸAjzqA]A )9IYqи/ܸ и /к9EX/>YEX/>YEX/>YEX / >YA]A '7GWqAfvqAiyqA]A (8HXq9901%2654&#""'#3632'̐Ɛl㏒⑓߂LLq +//и/ ܸ ܸ к  9 и/A]A &6FVqAeuqEX / >YEX/>YEX / >YEX/>Y 9 9A]A '7GWqAfvqAiyqA]A (8HXq01"543253#'2654&#"*ܐĒ-0Į=ĂߓᒏH + + EX/>YEX / >YEX / >Y 9 9AiyqA]A (8HXq016;&#"#3̀g^DŽ,̑"9C>764&'.'.67>.'.&'.',4+aa\'9X+0a0.G<2(4?.N<(~)2,ff`%0I,0c/Exa5~?.N<(0$ #x9 ;FT)/*:L2!1# 't: bD)/*:L2#r + +и /EX/>YEX/>YEX / >Yܸ ܸи013#;#"&5#52=328,b,:aSblC̸ +//ܸܸи/ ܸEX/>YEX/>YEX/>YEX/>Y9 A ]A   ' 7 G W qAf v q01!#5#"&5332653m悛 ؚ!l@/@Fv/7?YEX/>YEX/>YEX/>YEX / >YEX / >Y99901!33 3# ]}H= @O @            Fv/7?YEX/>Y0173 3'{(g$6NM|!Dp o@. @    Fv/7?YEX/>Y 9016567.4'GiMs6(::(6sMiHSI++++ISHq}K?@@Fv/7?YEX/>Y 901'>67.&'7iMs6(::(6sMiHSJI՜++IJSH,1 +//EX/>YEX / >Y012767#"&"'>@w)&%{>Nn"0{%iVP/[T3g@9{&$9j&$(9c&&""Ja&(!kH&19v&2Ar&8zK&DHzK&DCYzJ&Dz &Dz&Dzx&D.-3&F@0K&HA0K&HCS0K&H0&HwQ&fS&Cf`K&i&/rJ&Q4K&RA4K&RC!4K&R4 &R4&RCK&XCK&XCQCN&XC&Xx.@DK - +/EX/>YEX/>Y012#"&546"32654&7ponm6ON78RTKnomnK58JK76J!>" + +" +"A]A &6FVqAeuqܸ и"иии"/EX/>Y 9 90167#5&'&54676753&'yHKLIwRvmrpIUlMQSw{SPkw}9% cթ![09̸ +1 +1и/ и1,и13и3/%/EX / >YEX/>Y  + -и/и 5A5555555]A 55'575G5W5qAf5v5q01%&#"32!#"'#"'&54763265#5347632&#"3#327677D0!3vYix6YX4/16[92V6=*27ii V{X!<bb($56'+)NIg5.~HM(O! G?uK<Hh +I/J/Iи/ܸи/Jܸ и /&Aj&z&qA&&&&&&&]A &&)&9&I&Y&qи/9+к/92и8и&9и9/&;и=и=/&C/EX5/5>YAiyqA]A (8HXq5959/5901"#"&53327654'%&54767'&54632#67632767&#"[O#c${$(H~ $NR%HH<2V|HK%H$)%A*IS*7{I f7Y=&,,$E277{dC8`8o|~y#:% 5b  +/ /014632#"&5XYWXXz{WWxy%)r + +  +  ܸ EX/>YEX / >YEX/>Yܸ и 01476763!####.%F +0+{d~\+;?.vD (1K + + + +A]A &6FVqAeuqAjzqA]A )9IYq& 9)и3EX/>Y +A]A '7GWqAfvq01 ! "3254#%6#/32654&'rwJLFBa_IilODux}EE^hd^ɆwMOr .vD%3 ++# ++ +1 +A]A &6FVqAeuq #9#9A+++++++]A ++&+6+F+V+qAe+u+qAj1z1qA1111111]A 11)191I1Y1q5EX / >Y& + + + .A.......]A ..'.7.G.W.qAf.v.q01"3267#"'&5432. ! "3254j*ƃ Ĺ+urwJLFB䷍n`y~y]q`ux}EE9q-K@U@        Fv/7??))99)*>?))99tK@M@      Fv/7?YEX*/*>YEX/>YEX / >Yܺ 9* ܺ901%;2654'%"&#%+"'#7&5476;27BLXMVUYJrgEZa4F:4#-+v՜n:|ؙ==+C,!E! @;@          Fv/7/YEX/>Y 9 901%#"' '633273#&YY O1b2GzOOz .ZTr?rV:EZm +EX&/&>YEX,/,>YEX / >YEX?/?>YQ +0 +,AiyqA]A (8HXqQ9и/ии"и"/* &9?7A7777777]A 77'777G7W7qAf7v7qDиD/FиQMиM/QOиO/FZ01"!.+"'&'&547676;2767.#!"#463!2632!32767#"'&#"276=#"'#"3l'&ok\`0D?fCJNmL5H_DDbzY$#.hf\`,307iIE,cH^#gFBBEh;eg'b25[;EgSL%DXdC|bPYEX/>YEX/>YEX/>YA]A '7GWqAfvqAiyqA]A (8HXq01%32654/"&'273#"'#7&54+Km{jG@]k HkP<̐bc̑fP,,q%%b%K / +0/1/0.и./и/./ܸи/1ܸ%Aj%z%qA%%%%%%%]A %%)%9%I%Y%qи//и//!и!/EX/>YEX/>Y!A!!!!!!!]A !!'!7!G!W!qAf!v!q014632#"&#"&53327654'&'&'&/3)**) 756="8̍ʅ6a4:5M)N(7))))U0[)Bz¢@%z17w=&-/C]sG @ +  + и/ и//EX / >Y014632#"&#s)**)))))2: M@ @    Fv/7/YEX/>YEX!/!>Y A]A '7GWqAfvqи0174632#"&%4632#"&%4632#"&D@..AB-.@@./?A-.@A./?A--Bm/@A.-@@-/@A..?@-.AA..?@9&$CHm9&$9&2AK0 +1/2/1!и!/ܸ2ܸܸ и /и,EX'/'>YEX/>Y +./ +. +'ܸܺ9,/.901#";2654&!!!!5+"'&5476;25!!& Ӑ XBZ`d ōZa d`ZBlը+RxuQ/2+C,2/QmxD.5t +" +A]A &6FVqAeuqEX%/%>YEX)/)>YEX/>YEX/>Y/ +/%AiyqA]A (8HXqA]A '7GWqAfvqк%9'%9401"32654&'&327#"'!"&'&543 632%!&'&#" ]Xn`?^8ru3"Ƃ~ c&OSj;hc̐k+RSWch>@HG=@@Fv/7/YEX$/$>YEX/>YEX/>Y01+.54674+.5467 b *9PI$`! a ,9QI'c_?)Z  0@8_>,[=0=<<TL1K +EX/>YEX/>YEX / >YEX"/">Y01632&'&7676754&5456%>32&'&5476754&5456| ^.@#Pu K% `=*,BO u`c=-=C &-@4*9A+] -=:;$K) +EX / >YEX/>Y01+.5467#4` *;O K$ `_>*Y&3=80)1 +/ /EX / >YEX/>Y01>32&'&54367675&5O=).@Q H& _*;@-] #.B4 e  + +A]A &6FVqAeuq и/ / +01%4632#"&4632#"&!!A--BB-.@A--BB-.@~-AB,.BB.?@--BBɂ!k&\!p&<>KQ@@Fv/7?YEX/>YEX/>Yܸ01"32654&'76327'#"''7&54ZxzXZ{wE_D\dh\D_E99E_DZjgYD_E9,{YYz{X]wE_E99E_E\ef\D_D88D_DXji*>@@Fv/7?/......10IhIha@RX878Y J H*>@@Fv/7?/......10IhIha@RX878Y 5HL854 n + +AjzqA]A )9IYq  +014632#"&4@./>@-.@%/@A..?@5K.  +//0172'67.6,CVyC9@A,w:/Dqm32&'&7676754&5456%>32&'&54356754&5456|;*.@#Pu K% `>),BO u`*:=.=D &-@4*:A,] -=:;1K'4@L +EX/>YEX/>YEX///>YEX/>YEX / >YEX;/;>Y5A +5;9и/Aи/ A]A '7GWqAfvqG01 #2#"&546"32654&2#"&546"32654&2#"&546"32654&prnnom6NN66PQ|poomZ" N88QS}ompo6PP66PQKKmnnoK66JK55LėnomnO8JK76J?mnnpL67IK55M9&$hJa&(et9&$yrJap&(^Ja&(Ck1&,l 5&,n-u&,&,Cn9&24e9&2t9&2CkA&8oA&8nAS&8CJK) +EX/>YEX/>Y01!##JC;L<vK?@@Fv/7//-I. {$A+TQ..R1h&K +EX/>Y01!!KTK  +/EX/>Y012#"&546"32654&C`aB@__@ /.!!23K\BB[]@A]P. !,,! .=v +//EX/>Y01654'&'3#'6K)C62%sDD$F(*C\q<&K7 +/EX/>YEX/>Y901373#qq§K@\mF-ɸ +./и/ܸA]AqA@P`qA]A qAqܸܸи/ ܸи/и/%и &и -и-/ //%/01".#4.56.#5>.537m054)!  M  !)450 BJuouJJuouJd/=>;;>=/hEG +=< +=и/=и/<и/<+и+/3'&#4>.52>'6.#5>.53?054))450 054))450 "_/=>;;>=//=>;;>=/-}=' + +/ +01!#!-S3=@:GC + +и // +и013265#53546;#"3#+DcNN|Dc|cDcb}cDb} 5J-S + + +AjzqA]A )9IYq и /*9*/Aj*z*qA*******]A **)*9*I*Y*q"ܺ "9/EX/>YEX/>YEX/>YEX$/$>Y- +ܸܺ -9&и'012654.#3#'5346;2#53>54&#1So=Ddo|\yFCvO3ZE(QR`};fPok}i=vG@D;(  +/ / +01267.'7@x&i9``9i&x55JNTTNJ55TZ +////0173%73T9YM"I8LMcK"I,O,K A +EX/>YEX/>Y9ܺ 9017!!'7'7G*K=~L>}H(yK U + +и EX/>YEX/>Y99017#'7&邻+K=~L/>}H<&6p@K&Vı1&=hDpT&]ķ Q}K4 + +и/EX/>Y013#3Q}6K  + /!/ܸܸ и/ ܸиEX/>YEX/>Y + ܸܸ и 01%2654&#!3#2#!#535ӓ(zs7$T~+) ]X`kڙrS&<h!kK&\ e + / / ܸܸ и/EX/>YEX / >Y +и01!##5!##syxl( +  + и/  и /и/"и"/ +% +% +  + и ии!01.#"3#3#32673#".'#535#53632m<@ }g"}$ROx愋ΆWԵN愧vy  +////017''7'!\\]l]\]L@4Ÿ +5/6/5)и)/ܸ6 ܸ ܺ) 90) 9EX&/&>Y +. +.&A]A '7GWqAfvq0.901";27654'&#&+5327#"$547>36&''>6QYJ\l228WY#5pl#8߀|8ElEJ6.CizXvHQGpA>RIp ^݀Zz<p & + +  + AjzqA]A )9IYq9/!ܸ и /!и/и/и/и/ ( + + +# +#и012654&#"#"'3!53##5!#632͐j~swwns~č͏̑jщ . :  +//01"&54632,Ò:ɓ˒Dx7 &θ +'/(/ ܸAjzqA]A )9IYq'и/ܸ и /и/и/!и!// +# +# +012654&#"#"'3!53##53#632͐j~swwX~č͏̑jщl9nK&$,^a&Dd  + +01!!dYa>l + +01!!a U0 J&%HK&EsDJK&%HK&EqJK&%n HK&E 9&&'I{g3B&F'qIHK&UH&5bH&UHK&5HK&UH&5l4&R93&2sK&7j g&W AK&8G@C&XGq@5&6]q9K&V5&6{9K&V5d&69&VSA&8C!&XA1&8qC&XA&8!C}&X291&$qa&D9K&$G<@a&DG@9&&gq3K&F59&&{3K&FH&1PoJK&Qp^&,x&a#/&,o!,&T1&,f&-/p-qW&MlpJ &/p`&O>+p1&=nDp@&]1&=3Dp&]'=5-&:Jn<-K&ZV&<n!kK&\9&$ta(&D9&&a3&FW=9&& s3K&FJ&'sPzf&GR<Ja1&(dq4&HJa&({4(&HJa&(4&HgAJaK&(G@4&HG@Ja&(q4K&H9&*{/vK&J9&*{/v2&Jc 9&*g/v&J5AA&8pC(&XWA&8CD&XW9&2n4(&R9 &24Q&RH&10{JK&Q&7{/#&W i&,n('1K&,G@/vM&LG@9c&*/v&JJ&+nx&K,z1K&,-o/qM&LMr=K&.HK&NJ K&/K&O>`J e&/aT&O>#~J K&/#WK&O>4HK&1TJ&QeK&K%S +// ܸܸи/ܸиии иии/ //EX/>YEX/>Y + + и ии01!!533##!##537:ggƂa]RĔ5Wp&QK&7_,&WK&'"0K&G2WQK +//ܸ ܸи/и/EX / >YEX / >YEX/>YEX/>YEX/>Y + 9  901>5##33'F c !Ff'oKj>lA + /!/ܸܸ  и / ܸ ии/ 9и/EX/>YEX / >YEX/>YEX/>YAiyqA]A (8HXq 9014'&#"#36323'5>767UYY\\suuĖKݽ[[qq"ć>lD/%=AZd&8C&X9&$ naK&D;&,n/K&; 9&2n4K&RA&8nCK&X9K$#>&`'l/7 +8/9/ܸ80и0/ 09AjzqA]A )9IYq0!A!!!!!!!]A !!&!6!F!V!qAe!u!q+09 + +и&и(и*0123!53>76.&3!53.7>7>|Tm# 8N.$9bG)DzcczD'E`9$.L6 "n3]LEKAxn0!e{G`XX`G{e!0nxAKEL]3;&pJK%R(0 + +EX/>Y +013!!R  +/EX/>Y01% 3!ow7|M(4^@@@@~v .FVR l  \ ` < ZD\jTNZXZD*b (P< !!"#|#$2$$%|&&'()L)* **+F++,8,|,,-&-2->-J-V-b-n-z-----------. .."...:.F.R.^.j.v...../|041R1p1234n445F56N67:8t9:b::;0;;;<<==>>p>??\???@@A,A^AAB&CCC&C2C>CJCVCbCnCzCCCCCCCDDHDdDDDDEF.FRFGGGGGGH4HxHHHHHIJIVIbIIJ.JTKKKLLLLLLLLLLMMMM*M:MFMRM^MjMvMMMMMMMMMMMN NN"N.N:NFNRN^NjNvNNNNNNNNNNNO OO"O.O:OFORO^OjOvOOOOOOOOOOOPPPP*P6PBPNP\PjPvPPPPPPPPPPPQQQQ*Q6QBQNQZQfQrQQQQQQQQQQQRRR R,R8RDRPR\RRRSSSST?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.nulluni00A0uni0192uni00DFuni20ACmacronperiodcenteredrcaronRcaronuni0157uni0156racuteRacuteomacronOmacronuni0162uni0163UogonekuogonekSacutesacute Scircumflex scircumflexUtildeutildeUmacronumacronUringuringAmacronamacronAogonekaogonek Ccircumflex ccircumflexNacutenacuteItildeitildeImacronimacronuni0130 Jcircumflex jcircumflexLacutelacuteZacutezacuteuni017Buni017C Wcircumflex wcircumflex Ycircumflex ycircumflexAbreveabreveuni010Auni010BDcarondcaronEmacronemacronEbreveebreveuni0116uni0117EogonekeogonekEcaronecaron Gcircumflex gcircumflexuni0120uni0121Ubreveubreveuni0170uni0171Obreveobreveuni0150uni0151NcaronncaronTcarontcaronIbreveibreveIogonekiogonekuni0122uni0123 Hcircumflex hcircumflexIJijuni0136uni0137uni013Buni013CLcaronlcaronLdotldotuni0145uni0146hbarHbaruni0149Tbartbaruni0110uni0111EngengUhornuhornuni01CDuni01CEuni01CFuni01D0uni01D1uni01D2uni01D3uni01D4Alphauni0390uni038FBetaGammaDelta`<$@$*$2$62$92DWD\HYHZKHLMNHQ pRZUDUHUJUQ8URUUVGAYHYRZR[H      !"#$% &!'!(")#*$+%,&-&.'/(0)1*2+3,4,5-6.7/8091:1;2<3=4>5?6@6A7B8C9D:E;F<G<H=I>J?K@LAMANBOCPDQERFSFTGUHVIWJXKYLZL[M\N]O^P_Q`QaRbScTdUeVfWgWhXiYjZk[l\m\n]o^p_q`rasatbucvdwexfygzg{h|i}j~kllmnopqqrstuvwwxyz{||}~GDTextUtil-0.86/Text/0040755000022200001440000000000007674205463013264 5ustar mgjvusersGDTextUtil-0.86/Text/Wrap.pm0100644000022200001440000002757507626513523014544 0ustar mgjvusers# $Id: Wrap.pm,v 1.20 2003/02/20 12:51:29 mgjv Exp $ package GD::Text::Wrap; ($GD::Text::Wrap::VERSION) = '$Revision: 1.20 $' =~ /\s([\d.]+)/; =head1 NAME GD::Text::Wrap - Wrap strings in boxes =head1 SYNOPSIS use GD; use GD::Text::Wrap; my $gd = GD::Image->new(800,600); # allocate colours, do other things. my $text = <new( $gd, line_space => 4, color => $black, text => $text, ); $wrapbox->set_font(gdMediumBoldFont); $wrapbox->set_font('arial', 12); $wrapbox->set(align => 'left', width => 120); $wrapbox->draw(10,140); $gd->rectangle($wrap_box->get_bounds(10,140), $color); =head1 DESCRIPTION GD::Text::Wrap provides an object that draws a formatted paragraph of text in a box on a GD::Image canvas, using either a builtin GD font or a TrueType font. =head1 METHODS This class doesn't inherit from GD::Text directly, but delegates most of its work to it (in fact to a GD::Text::Align object. That means that most of the GD::Text::Align methods are available for this class, specifically C and C. Other methods and methods with a different interface are described here: =cut use strict; # XXX add version number to GD use GD; use GD::Text::Align; use Carp; my %attribs = ( width => undef, height => undef, line_space => 2, para_space => 0, align => 'justified', text => undef, preserve_nl => 0, ); =head2 GD::Text::Wrap->new( $gd_object, attribute => value, ... ) Create a new object. The first argument to new has to be a valid GD::Image object. The other arguments will be passed to the set() method for initialisation of the attributes. =cut sub new { my $proto = shift; my $class = ref($proto) || $proto; my $gd = shift; ref($gd) and $gd->isa('GD::Image') or croak "Not a GD::Image object"; my $self = { gd => $gd }; bless $self => $class; $self->_init(); $self->set(@_); return $self } sub _init { my $self = shift; $self->{render} = GD::Text::Align->new($self->{gd}, text => 'Foo'); croak "Cannot allocate GD::Text::Align object" unless $self->{render}; # XXX 5.004_04 doesn't like foreach as a modifier #$self->set($_, $attribs{$_}) foreach (keys %attribs); foreach (keys %attribs) { $self->set($_, $attribs{$_}) }; # XXX SET DEFAULTS $self->set( colour => $self->{gd}->colorsTotal - 1, width => ($self->{gd}->getBounds())[0] - 1, ); } =head2 $wrapbox->set( attribute => value, ... ) set the value for an attribute. Valid attributes are: =over 4 =item width The width of the box to draw the text in. If unspecified, they will default to the width of the GD::Image object. =item line_space The number of pixels between lines. Defaults to 2. =item para_space, paragraph_space The number of extra pixels between paragraphs, above line_space. Defaults to 0. =item color, colour Synonyms. The colour to use when drawing the font. Will be initialised to the last colour in the GD object's palette. =item align, alignment Synonyms. One of 'justified' (the default), 'left', 'right' or 'center'. =item text The text to draw. This is the only attribute that you absolutely have to set. =item preserve_nl If set to a true value, newlines in the text will cause a line break. Note that lines will still be justified. If only one word appears on the line, it could get ugly. Defaults to 0. =back As with the methods, attributes unknown to this class get delegated to the GD::Text::Align class. =cut sub _attrib_name { my $attrib = shift; $attrib = 'colour' if $attrib eq 'color'; $attrib = 'align' if $attrib =~ /^align/; $attrib = 'para_space' if $attrib eq 'paragraph_space'; $attrib; } sub set { my $self = shift; my %args = @_; while (my ($attrib, $val) = each %args) { # This spelling problem keeps bugging me. SWITCH: for (_attrib_name($attrib)) { exists $attribs{$_} and $self->{$_} = $val, last SWITCH; # If we don't have this attribute, maybe the GD::Text::Align # object can use it (for colour mainly at the moment) $self->{render}->set($_ => $val) and last SWITCH; carp "No attribute $attrib"; } } } =head2 $wrapbox->get( attribute ); Get the current value of an attribute. All attributes mentioned under the C method can be retrieved =cut sub get { my $self = shift; my $attrib = shift; $self->{_attrib_name($attrib)} } =head2 $wrapbox->get_bounds() Returns the bounding box of the box that will be drawn with the current attribute settings as a list. The values returned are the coordinates of the upper left and lower right corner. ($left, $top, $right, $bottom) = $wrapbox->get_bounds(); Returns an empty list on error. NOTE: The return list of this method may change in a future implementation that allows angled boxes. =cut my $dry_run = 0; sub get_bounds { my $self = shift; $dry_run = 1; return $self->draw(@_); } # # Vertical movement and state # sub _move_to_top { my $self = shift; $self->{_y_pos} = $self->{top} + $self->{render}->get('char_up'); } sub _at_top { my $self = shift; $self->{_y_pos} == $self->{top} + $self->{render}->get('char_up'); } sub _set_bottom { my $self = shift; $self->{bottom} = $self->{_y_pos} + $self->{render}->get('char_down'); } sub _crlf { my $self = shift; $self->{_y_pos} += $self->{render}->get('height') + $self->{line_space} } sub _new_paragraph { my $self = shift; $self->_crlf; $self->{_y_pos} += $self->{para_space}; } sub _undo_new_paragraph { my $self = shift; $self->{_y_pos} -= $self->{render}->get('height') + $self->{line_space} + $self->{para_space}; } =head2 $wrapbox->draw(x, y) Draw the box, with (x,y) as the top right corner. Returns the same values as the C method. NOTE: The return list of this method may change in a future implementation that allows angled boxes. =cut sub draw { my $self = shift; $self->{left} = shift; defined($self->{left}) or return; $self->{top} = shift; defined($self->{top}) or return; $self->{angle} = shift || 0; #unused return unless $self->{text}; $self->{right} = $self->{left} + $self->{width}; $self->_move_to_top; # FIXME We need a better paragraph separation RE foreach my $paragraph (split '\n\n+', $self->{text}) #foreach my $paragraph ($self->{text}) { $self->_draw_paragraph($paragraph); $self->_new_paragraph; } $self->_undo_new_paragraph; # FIXME Yuck # Reset dry_run $dry_run = 0; $self->_set_bottom; return ( $self->{left}, $self->{top}, $self->{right}, $self->{bottom} ) } sub _draw_paragraph { my $self = shift; my $text = shift; my @line = (); foreach my $word (split /(\s+)/, $text) { # Number of newlines my $nnl = $self->{preserve_nl} ? $word =~ y/\n// : 0; # Length of the whole line with this new word my $len = $nnl ? 0 : $self->{render}->width(join(' ', @line, $word)); # If this is a separator without newlines, continue with next next if !$nnl && $word =~ /^\s+$/; if (($len > $self->{right} - $self->{left} || $nnl) && @line) { $self->_draw_line(@line) unless $dry_run; @line = (); $self->_crlf; # XXX 5.004 compatibility #$self->_crlf for (2..$nnl); for (2..$nnl) { $self->_crlf } } # Store the new word, unless it's just newlines push @line, $word unless $nnl; } # Take care of the last line $self->_draw_last_line(@line) unless $dry_run; } sub _draw_line { my $self = shift; $self->__draw_line(0, @_); } sub _draw_last_line { my $self = shift; $self->__draw_line(1, @_); } sub __draw_line { my $self = shift; # We need the following for justification only my $last = shift; for ($self->{align}) { /^just/i and !$last and do { $self->_draw_justified_line(@_); last; }; /^right/i and do { $self->{render}->set_text(join(' ', @_)); $self->{render}->set_halign('right'); $self->{render}->draw($self->{right}, $self->{_y_pos}); last; }; /^center/i and do { $self->{render}->set_text(join(' ', @_)); $self->{render}->set_halign('left'); my $x = ($self->{right} + $self->{left} - $self->{render}->get('width')) / 2; $self->{render}->draw($x, $self->{_y_pos}); last; }; # default action, left justification $self->{render}->set_text(join(' ', @_)); $self->{render}->set_halign('left'); $self->{render}->draw($self->{left}, $self->{_y_pos}); } } sub _draw_justified_line { my $self = shift; my $y = $self->{_y_pos}; my $x = $self->{left}; $self->{render}->set_halign('left'); my @lengths = (); my $length = 0; # first, calculate the lengths of the individual words foreach my $word (@_) { $self->{render}->set_text($word); my $len = $self->{render}->get('width'); push @lengths, $len; $length += $len; } # Calculate the average space between words my $space = ($self->{right} - $self->{left} - $length)/($#_ || 1); # Draw all the words, except the last one for (my $i = 0; $i < $#_; $i++) { $self->{render}->set_text($_[$i]); $self->{render}->draw($x, $y); $x += $lengths[$i] + $space; } # Draw the last word # XXX This will make a single word that's too long stick out the # right side of the box. is that what we want? $self->{render}->set_halign('right'); $self->{render}->set_text($_[-1]); $self->{render}->draw($self->{right}, $y); } # # Delegate all the other methods to the GD::Text::Align method use vars qw($AUTOLOAD); sub AUTOLOAD { my $self = shift; my ($method) = $AUTOLOAD =~ /.*::(.*)$/; $self->{render}->$method(@_) if ($method ne 'DESTROY'); } =head1 NOTES As with all Modules for Perl: Please stick to using the interface. If you try to fiddle too much with knowledge of the internals of this module, you may get burned. I may change them at any time. You can only use TrueType fonts with version of GD > 1.20, and then only if compiled with support for this. If you attempt to do it anyway, you will get errors. Even though this module lives in the GD::Text namespace, it is not a GD::Text. It does however delegate a lot of its functionality to a contained object that is one (GD::Text::Align). =head1 BUGS None that I know of, but that doesn't mean much. There may be some problems with exotic fonts, or locales and character encodings that I am not used to. =head1 TODO Angled boxes. At the moment, the only bit of the box that is allowed to be unspecified and in fact must be unspecified, is the bottom. If there is enough need for it, I might implement more flexibility, in that that you need to only specify three of the four sides of the box, and the fourth will be calculated. Automatic resizing of a TrueType font to fit inside a box when four sides are specified, or maybe some other nifty things. More flexibility in the interface. Especially draw needs some thought. More and better error handling. Warnings for lines that are too long and stick out of the box. Warning for emptyish lines? =head1 COPYRIGHT copyright 1999 Martien Verbruggen (mgjv@comdyn.com.au) =head1 SEE ALSO L, L, L =cut 1; GDTextUtil-0.86/Text/Align.pm0100644000022200001440000002663107626513523014655 0ustar mgjvusers# $Id: Align.pm,v 1.18 2003/02/21 00:10:26 mgjv Exp $ package GD::Text::Align; ($GD::Text::Align::VERSION) = '$Revision: 1.18 $' =~ /\s([\d.]+)/; =head1 NAME GD::Text::Align - Draw aligned strings =head1 SYNOPSIS use GD; use GD::Text::Align; my $gd = GD::Image->new(800,600); # allocate colours, do other things. my $align = GD::Text::Align->new($gd valign => 'top', halign => 'right', ); $align->set_font('arial', 12); $align->set_text('some string'); @bb = $align->bounding_box(200, 400, PI/3); # you can do things based on the bounding box here $align->draw(200, 400, PI/3); =head1 DESCRIPTION GD::Text::Align provides an object that draws a string aligned to a coordinate at an angle. For builtin fonts only two angles are valid: 0 and PI/2. All other angles will be converted to one of these two. =head1 METHODS This class inherits everything from GD::Text. I will only discuss the methods and attributes here that are not discussed there, or that have a different interface or behaviour. Methods directly inherited include C and C. =cut use strict; # XXX add version number to GD use GD; use GD::Text; use Carp; @GD::Text::Align::ISA = qw(GD::Text); =head2 GD::Text::Align->new($gd_object, attrib => value, ...) Create a new object. The first argument to new has to be a valid GD::Image object. The other arguments will be passed on to the set method. =cut sub new { my $proto = shift; my $class = ref($proto) || $proto; my $gd = shift; ref($gd) and $gd->isa('GD::Image') or croak "Not a GD::Image object"; my $self = $class->SUPER::new() or return; $self->{gd} = $gd; $self->_init(); $self->set(@_); bless $self => $class; } my %defaults = ( halign => 'left', valign => 'base', ); sub _init { my $self = shift; while (my ($k, $v) = each(%defaults)) { $self->{$k} = $v; } $self->{colour} = $self->{gd}->colorsTotal - 1, } =head2 $align->set(attrib => value, ...) Set an attribute. Valid attributes are the ones discussed in L and: =over 4 =item valign, halign Vertical and horizontal alignment of the string. See also set_valign and set_halign. =item colour, color Synonyms. The colour to use to draw the string. This should be the index of the colour in the GD::Image object's palette. The default value is the last colour in the GD object's palette at the time of the creation of C<$align>. =back =cut sub set { my $self = shift; $@ = "Incorrect attribute list", return if @_%2; my %args = @_; my @super; foreach (keys %args) { /^valign/ and do { $self->set_valign($args{$_}); next; }; /^halign/ and do { $self->set_halign($args{$_}); next; }; /^colou?r$/ and do { $self->{colour} = $args{$_}; next; }; # Save anything unknown to pass off to SUPER class push @super, $_, $args{$_}; } $self->SUPER::set(@super); } =head2 $align->get(attribute) Get the value of an attribute. Valid attributes are all the attributes mentioned in L, the attributes mentioned under the C method and =over 4 =item x, y and angle The x and y coordinate and the angle to be used. You can only do this after a call to the draw or bounding_box methods. Note that these coordinates are not necessarily the same ones that were passed in. Instead, they are the coordinates from where the GD methods will start drawing. I doubt that this is very useful to anyone. =back Note that while you can set the colour with both 'color' and 'colour', you can only get it as 'colour'. Sorry, but such is life in Australia. =cut # get is inherited unchanged =head2 $align->set_valign(value) Set the vertical alignment of the string to one of 'top', 'center', 'base' or 'bottom'. For builtin fonts the last two are the same. The value 'base' denotes the baseline of a TrueType font. Returns true on success, false on failure. =cut sub set_valign { my $self = shift; local $_ = shift or return; if (/^top/ || /^center/ || /^bottom/ || /^base/) { $self->{valign} = $_; return $_; } else { carp "Illegal vertical alignment: $_"; return; } } =head2 $align->set_halign(value) Set the horizontal alignment of the string to one of 'left', 'center', or 'right'. Returns true on success, false on failure. =cut sub set_halign { my $self = shift; local $_ = shift or return; if (/^left/ || /^center/ || /^right/) { $self->{halign} = $_; return $_; } else { carp "Illegal horizontal alignment: $_"; return; } } =head2 $align->set_align(valign, halign) Set the vertical and horizontal alignment. Just here for convenience. See also C and C. Returns true on success, false on failure. =cut sub set_align { my $self = shift; $self->set_valign(shift) or return; $self->set_halign(shift) or return; } # # Determine whether a builtin font string should be drawn with the # string or stringUp method. It will use the stringUp method for any # angles between PI/4 and 3PI/4, 5PI/4 and 7PI/4, and all equivalents. # # return # true for stringUp # false for string # sub _builtin_up { my $self = shift; return sin($self->{angle}) > 0.5 * sqrt(2) || sin($self->{angle}) < -0.5 * sqrt(2) } # # Calculates the x and y coordinate that should be passed # to the GD::Image drawing routines, and set them as attributes # sub _align { my $self = shift; my ($x, $y, $angle) = @_; defined $x && defined $y or carp "Need X and Y coordinates", return; $self->{angle} = $angle || 0; if ($self->is_builtin) { return $self->_align_builtin($x, $y); } elsif ($self->is_ttf) { return $self->_align_ttf($x, $y); } else { confess "Impossible error in GD::Text::Align::_align"; } } # # calculate the alignment for a builtin font # sub _align_builtin { my $self = shift; my ($x, $y) = @_; # Swap coordinates and make sure to keep the sign right, since left # becomes _down_ (larger) and right becomes _up_ (smaller) ($x, $y) = (-$y, $x) if ($self->_builtin_up); for ($self->{halign}) { #/^left/ and $x = $x; /^center/ and $x -= $self->{width}/2; /^right/ and $x -= $self->{width}; } for ($self->{valign}) { #/^top/ and $y = $y; /^center/ and $y -= $self->{height}/2; /^bottom/ and $y -= $self->{height}; /^base/ and $y -= $self->{height}; } ($x, $y) = ($y, -$x) if ($self->_builtin_up); $self->{'x'} = $x; $self->{'y'} = $y; return 1; } # # calculate the alignment for a TrueType font # sub _align_ttf { my $self = shift; my ($x, $y) = @_; my $phi = $self->{angle}; for ($self->{halign}) { #/^left/ and $x = $x; /^center/ and do { $x -= cos($phi) * $self->{width}/2; $y += sin($phi) * $self->{width}/2; }; /^right/ and do { $x -= cos($phi) * $self->{width}; $y += sin($phi) * $self->{width}; }; } for ($self->{valign}) { /^top/ and do { $x += sin($phi) * $self->{char_up}; $y += cos($phi) * $self->{char_up}; }; /^center/ and do { $x -= sin($phi) * ($self->{char_down} - $self->{height}/2); $y -= cos($phi) * ($self->{char_down} - $self->{height}/2); }; /^bottom/ and do { $x -= sin($phi) * $self->{char_down}; $y -= cos($phi) * $self->{char_down}; }; #/^base/ and $y = $y; } $self->{'x'} = $x; $self->{'y'} = $y; return 1; } =head2 $align->draw(x, y, angle) Draw the string at coordinates I, I at an angle I in radians. The x and y coordinate become the pivot around which the string rotates. Note that for the builtin GD fonts the only two valid angles are 0 and PI/2. Returns the bounding box of the drawn string (see C). =cut sub draw { my $self = shift; my ($x, $y, $angle) = @_; $@ = "No text set", return unless defined $self->{text}; $@ = "No colour set", return unless defined $self->{colour}; $self->_align($x, $y, $angle) or return; if ($self->is_builtin) { if ($self->_builtin_up) { $self->{gd}->stringUp($self->{font}, $self->{'x'}, $self->{'y'}, $self->{text}, $self->{colour}); } else { $self->{gd}->string($self->{font}, $self->{'x'}, $self->{'y'}, $self->{text}, $self->{colour}); } } elsif ($self->is_ttf) { $self->{gd}->stringTTF($self->{colour}, $self->{font}, $self->{ptsize}, $self->{angle}, $self->{'x'}, $self->{'y'}, $self->{text}); } else { confess "impossible error in GD::Text::Align::draw"; } return $self->bounding_box($x, $y, $angle); } =head2 $align->bounding_box(x, y, angle) Return the bounding box of the string to draw. This returns an eight-element list (exactly like the GD::Image->stringTTF method): (x1,y1) lower left corner (x2,y2) lower right corner (x3,y3) upper right corner (x4,y4) upper left corner Note that upper, lower, left and right are relative to the string, not to the canvas. The bounding box can be used to make decisions about whether to move the string or change the font size prior to actually drawing the string. =cut sub bounding_box { my $self = shift; my ($x, $y, $angle) = @_; $@ = "No text set", return unless defined $self->{text}; $self->_align($x, $y, $angle) or return; if ($self->is_builtin) { if ($self->_builtin_up) { return ( $self->{'x'} + $self->{height}, $self->{'y'}, $self->{'x'} + $self->{height}, $self->{'y'} - $self->{width}, $self->{'x'} , $self->{'y'} - $self->{width}, $self->{'x'} , $self->{'y'}, ) } else { return ( $self->{'x'} , $self->{'y'} + $self->{height}, $self->{'x'} + $self->{width}, $self->{'y'} + $self->{height}, $self->{'x'} + $self->{width}, $self->{'y'}, $self->{'x'} , $self->{'y'}, ) } } elsif ($self->is_ttf) { return GD::Image->stringTTF($self->{colour}, $self->{font}, $self->{ptsize}, $self->{angle}, $self->{'x'}, $self->{'y'}, $self->{text}); } else { confess "impossible error in GD::Text::Align::draw"; } } =head1 NOTES As with all Modules for Perl: Please stick to using the interface. If you try to fiddle too much with knowledge of the internals of this module, you may get burned. I may change them at any time. You can only use TrueType fonts with version of GD > 1.20, and then only if compiled with support for this. If you attempt to do it anyway, you will get errors. In the following, terms like 'top', 'upper', 'left' and the like are all relative to the string to be drawn, not to the canvas. =head1 BUGS Any bugs inherited from GD::Text. =head1 COPYRIGHT copyright 1999 Martien Verbruggen (mgjv@comdyn.com.au) =head1 SEE ALSO L, L, L =cut 1; GDTextUtil-0.86/Changes0100644000022200001440000000341007674200035013614 0ustar mgjvusersRevision history for Perl extension GDTextUtil. Thu Jun 19 2003 - Fixed check for TTF font support. The libgd error message changed between 1.8 and 2.0 - Release patched version Thu Feb 20 2003 - Removed cetus.ttf from distribution because of copyright uncertainties - Fixed font search, slightly Thu Jun 15 2002 - Fixed GD::Text, use Cwd. For some reason, this was only a problem under Perls before 5.6.0. Sat Jan 19 2002 - Added demo/GDWrap.ref.png - Changed demo/GDWrap.pl - Fixes so that set_font always uses absolute path for TTF. This to circumvent some bug/misfeature in the freetype 2.0.x library. - Fixed up tests, to include approximate checking of bounds, instead of requiring absolute match. Sun Oct 22 2000 - Fixed draw(0,0) problem in GD::Text::Wrap Mon Sep 18 2000 - Added paragraph and newline preservation Sun Apr 30 2000 - Corrected GD::Wrap::AUTOLOAD not to call DESTROY in the wrong package (5.6.0 introduced this problem) - Changed Makefile.PL for 5.6.0 Tue Feb 29 2000 - Modified for/foreach constructs to workin 5.004_04 - Quoted many hash keys to make 5.004_04 happy Sun Jan 9 2000 - Added append of '.ttf' when searching for TTF font files. Sun Jan 9 2000 - Added font path tests. - Allow first argument to set_font to be an array reference to various font names that may or may not be present. - GD::Text::Wrap now uses autoloader to delegate methods to GD::Text::Align Release of 0.65 Sat Jan 8 2000 - Added font path. - Changed test string to include all printable characters between 0x00 and 0xff. Was only using 0x21 to 0x7e before, but some capitals with umlauts are outside of the ASCII range. Before Jan 01 2000 - Original module - Release of 0.61 0.01 Sat Dec 4 15:21:17 1999 - original version; created by h2xs 1.19 GDTextUtil-0.86/Dustismo.LICENSE0100644000022200001440000004522707625144303015151 0ustar mgjvusersDustismo is Copyright (C) 2002 Dustin Norlander Homepage: http://www.cheapskatefonts.com email: nutso@cheapskatefonts.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. GDTextUtil-0.86/README0100644000022200001440000001133707626530177013222 0ustar mgjvusersThe GDTextUtil package contains text utilities for use with the GD drawing package. This package provides three modules that make it possible to work with internal GD fonts as well as TrueType fonts, without having to worry about different interface functions to call. Apart from an abstract interface to all font types and strings for GD, this library also provides some utility in aligning and wrapping your string. GD::Text: Provides information about a font, irrespective of whether the font is a TTF or builtin font. GD::Text::Align Align a string around a coordinate, left, right, center, top, bottom or center. GD::Text::Wrap Wrap a long string between a right and left margin, starting at a certain y coordinate. Layout the text flush left, flush right, center, or justified. Requirements: perl 5.005_03 or higher. It may (and probably will) work on older versions, but it has not been tested, and I won't spend a lot of time trying to support it. GD 1.20 or up, if possible built with TTF (freetype) support. GD 2.* has not been tested yet. Please note that the freetype version 2 libraries should be at the latest level. Especially version 2.0.3 has an annoying bug that rotates text twice. Later versions of freetype (2.1.2 currently) don't render as nicely anymore as earlier ones. Hopefully that will be fixed, because it is _ugly_ right now. If you want 'make test' to do something useful, you will need to have Test::More installed. If you don't, all tests will be skipped. Installation: perl Makefile.PL make make test make demo make install Demo(s) can be found in the demo directory. DO NOT PANIC when the tests fail. The various Freetype libraries often have a slightly different implementation of their rendering algorithms, resulting in slightly different bounding boxes for strings, and slightly different looking images. If your tests fail, try a 'make demo', and visually compare demo/GDWrap.png (freshly generated image) and demo/GDWrap.ref.png (reference image). If they look reasonably similar, you can call the tests successful. Even if they don't look entirely similar, it may simply be because your font files are different from the ones I used to create GDWrap.ref.png. Please see the sources. Currently, some of the TTF tests in t/* are disabled, specifically because every version of the freetype library seems to render differently enough for sizing to be wrong all the time. I don't think I'll ever re-enable them anymore. Bug Reports: When you report a bug, please include as much information as possible (unless you also supply a patch :)). The minimum set of information I need to be able to correctly assess a bug is: GD::Text version Perl version and OS GD version If the bug relates to TrueType font rendering, I'll also need to know which version freetype library you linked in. If at all possible, submit a small program that demonstrates the problem, together with the output _you_ get on your system (remember that it all works fine on mine). If you're using Redhat, and have their freetype 2.0.3 library RPM installed, do not report bugs until you have upgraded to a later version. CYGWIN If you try to install the GD::Text modules on cygwin, you may see error messages like the following: C:\cygwin\bin\cygperl.exe: *** unable to remap C:\cygwin\usr\X11R6\bin\libfreetype.dll to same address as parent(0x720000) != 0x74000064 [main] cygperl 4296 sync_with_child: child 4364(0xFC) died before initialization with status code 0x1 It has been brought to my attention (by Michael West) that in this case it is necessary to "rebase" the used libraries (Don't ask me, I don't know what that means). There is some more info on the cygwin mailing list: http://sources.redhat.com/ml/cygwin/2003-02/msg01484.html http://sources.redhat.com/ml/cygwin/2003-02/msg01789.html http://sources.redhat.com/ml/cygwin/2003-02/msg01833.html Todo: - Make the interface more flexible - Alignment for the wrap boxes as a whole - More demo code COPYRIGHT Copyright (c) 1999 Martien Verbruggen mgjv@comdyn.com.au This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Enclosed fonts: Dustismo Sans and Dustismo Roman http://www.cheapskatefonts.com/ see Dustismo,LICENSE for original (GPL) license Cetus by Greg Meronek is no longer enclosed, since its copyright status has become unclear (the status is simply not known). http://fontastic.i-n.net/fontastic/greg.htm