GD-2.50/0000755000175100017510000000000012164636125011320 5ustar lsteinlsteinGD-2.50/README.unix0000644000175100017510000000425512164634363013172 0ustar lsteinlsteinTo: Thomas Schachner Subject: GD.pm In-Reply-To: <387B1B0E.653A6BA7@awd.at> References: <387B1B0E.653A6BA7@awd.at> X-Mailer: VM 6.71 under 21.1 "20 Minutes to Nikko" XEmacs Lucid (patch 2) Reply-To: lstein@cshl.org --text follows this line-- This problem has been reported under some versions of SuSE and RedHat Linux (it appears to be related to a partcular RPM distribution of Perl). Perl was built incorrectly, causing some but not all loadable modules to fail. The only solution I know of is to rebuild Perl correctly from scratch and reinstall all previously-installed modules. Lincoln Thomas Schachner writes: > HI! > > Sorry for writing directly, but > we have tried all to get GD-1.23 to work ( because we need it urgent ) > but the following: > > when run make NO! errors > > but when make test the following: > > PERL_DL_NONLAZY=1 /usr/bin/perl -Iblib/arch -Iblib/lib > -I/usr/lib/perl5/5.00502/ > i586-linux -I/usr/lib/perl5/5.00502 -e 'use Test::Harness qw(&runtests > $verbose) > ; $verbose=0; runtests @ARGV;' t/*.t > t/GD................Can't load './blib/arch/auto/GD/GD.so' for module > GD: ./blib > /arch/auto/GD/GD.so: undefined symbol: SetCPerlObj at > /usr/lib/perl5/5.00502/i58 > 6-linux/DynaLoader.pm line 168. > > at t/GD.t line 11 > BEGIN failed--compilation aborted at t/GD.t line 11. > dubious > Test returned status 2 (wstat 512, 0x200) > DIED. FAILED tests 1-9 > Failed 9/9 tests, 0.00% okay > Failed Test Status Wstat Total Fail Failed List of failed > ------------------------------------------------------------------------------- > t/GD.t 2 512 9 9 100.00% 1-9 > Failed 1/1 test scripts, 0.00% okay. 9/9 subtests failed, 0.00% okay. > make: *** [test_dynamic] Error 2 > > Any Hints? > > all nessecary libraries are compiled with the same compiler ( libpng & > libz )!! > > Thanks Thomas -- ======================================================================== Lincoln D. Stein Cold Spring Harbor Laboratory lstein@cshl.org Cold Spring Harbor, NY ======================================================================== GD-2.50/Makefile.PL0000644000175100017510000002677712164634363013317 0ustar lsteinlsteinuse ExtUtils::MakeMaker qw(prompt WriteMakefile); use Config; use strict; require 5.6.0; unless (@ARGV) { warn < PATHS: CHECK AND ADJUST <===== my (@INC,@LIBPATH,@LIBS); my $AUTOCONFIG = 0; # global set by try_to_autoconfigure() below my ($options,$lib_gd_path,$lib_ft_path,$lib_png_path,$lib_jpeg_path,$lib_xpm_path,$lib_zlib_path,$force); use Getopt::Long; GetOptions("ignore_missing_gd" => \$force); unless (try_to_autoconfigure(\$options,\$lib_gd_path,\@INC,\@LIBPATH,\@LIBS) || $force) { die < \$options, "lib_gd_path=s" => \$lib_gd_path, "lib_ft_path=s" => \$lib_ft_path, "lib_png_path=s" => \$lib_png_path, "lib_jpeg_path=s" => \$lib_jpeg_path, "lib_xpm_path=s" => \$lib_xpm_path, "lib_zlib_path=s" => \$lib_zlib_path, ); unless ($result) { print STDERR <.config.cache"; print F $DEFINES,"\n"; close F; WriteMakefile( 'NAME' => 'GD', 'VERSION_FROM' => 'GD.pm', 'PREREQ_PM' => { 'Math::Trig' => 0, }, 'PM' => { 'GD.pm' => '$(INST_LIBDIR)/GD.pm', 'GD/Polyline.pm' => '$(INST_LIBDIR)/GD/Polyline.pm', 'GD/Polygon.pm' => '$(INST_LIBDIR)/GD/Polygon.pm', 'GD/Simple.pm' => '$(INST_LIBDIR)/GD/Simple.pm', 'GD/Image.pm' => '$(INST_LIBDIR)/GD/Image.pm', 'GD/Group.pm' => '$(INST_LIBDIR)/GD/Group.pm', 'qd.pl' => '$(INST_LIBDIR)/qd.pl'}, 'dist' => {'COMPRESS'=>'gzip -9f', 'SUFFIX' => 'gz', 'ZIP'=>'/usr/bin/zip','ZIPFLAGS'=>'-rl'}, 'LIBS' => [join(' ',$ENV{'GD_LIBS'},@LIBPATH,@LIBS)], 'INC' => join(' ',$ENV{'GD_INC'},@INC), 'PL_FILES' => {'bdf_scripts/bdf2gdfont.PLS' => 'bdf_scripts/bdf2gdfont.pl', 'GD/Image.pm.PLS' => 'GD/Image.pm', }, 'CCFLAGS' => "$Config{ccflags} -Wformat=0", 'EXE_FILES' => ['bdf_scripts/bdf2gdfont.pl'], 'AUTHOR' => 'Lincoln Stein (lstein@cshl.org)', 'ABSTRACT' => 'Interface to Gd Graphics Library', $CAPI ? ('CAPI' => 'TRUE') : (), 'DEFINE' => $DEFINES, ); exit 0; sub try_to_autoconfigure { my ($options,$lib_gd_path,$INC,$LIBPATH,$LIBS) = @_; my $config = `gdlib-config --all`; return unless $config; $AUTOCONFIG++; my ($version) = $config =~ /^GD library\s+(\S+)/m; warn "Configuring for libgd version $version.\n"; my ($cflags) = $config =~ /^cflags:\s+(.+)/m; my ($ldflags) = $config =~ /^ldflags:\s+(.+)/m; my ($libs) = $config =~ /^libs:\s+(.+)/m; my ($libdir) = $config =~ /^libdir:\s+(.+)/m; my ($features) = $config =~ /^features:\s+(.+)/m; my ($includedir) = $config =~ /^includedir:\s+(.+)/m; @$INC = map {s/^-I// && "-I$_"} split /\s+/,$cflags; @$LIBPATH = map {s/^-L// && "-L$_"} split /\s+/,$ldflags; @$LIBS = split /\s+/,$libs; push @$LIBS,"-lgd"; push @$LIBPATH,"-L$libdir"; ($$lib_gd_path = $libdir) =~ s!/[^/]+$!!; $$options = $features; my ($minor) = $version =~ /^2\.\d+\.(\d+)$/; $$options .= " GD_UNCLOSEDPOLY GD_ANIMGIF GD_FTCIRCLE VERSION_33" if defined($minor) && $minor >= 33; my @correct_inc = map {s/^-I// && $_} split /\s+/,$cflags; check_for_stray_headers(@correct_inc); return 1; } sub check_for_stray_headers { my @official_libraries = @_; my %official_libraries = map {$_=>1} @official_libraries; print STDERR "Checking for stray libgd header files..."; my $cc = $Config{'cc'}; my $data = `$cc -print-search-dirs`; $data ||= ''; my ($libraries) = $data =~ /^libraries: =(.+)/m; my @cc_libs = split /:/,$libraries; foreach (@cc_libs) { s/\/$//; } my %libraries = map {$_=>1} (@cc_libs,'/include','/usr/include', '/usr/local/include','/opt/include', '/usr/X11R6/include'); my $problems; foreach (keys %libraries) { s/\blib\b/include/; next if $official_libraries{$_}; next unless -e "$_/gd.h"; warn "\n\n** WARNING: found gd.h header file in ${_}gd.h, but it is expected at $official_libraries[0]/gd.h. This may cause compile errors! **\n"; $problems++; } print STDERR $problems ? "** Possible problems found **\n" : "none found.\n"; print STDERR "\n"; } sub MY::postamble { my $postamble = <<'END'; html: GD.pm pod2html --outfile=GD.html GD.pm END $postamble; } package MY; sub processPL { my $inherited = shift->SUPER::processPL(@_); $inherited =~ s/(:: GD\/Image.pm.PLS)/$1 .config.cache/; $inherited; } GD-2.50/GD/0000755000175100017510000000000012164636125011612 5ustar lsteinlsteinGD-2.50/GD/Simple.pm0000644000175100017510000010656012164634363013413 0ustar lsteinlsteinpackage GD::Simple; =head1 NAME GD::Simple - Simplified interface to GD library =head1 SYNOPSIS use GD::Simple; # create a new image $img = GD::Simple->new(400,250); # draw a red rectangle with blue borders $img->bgcolor('red'); $img->fgcolor('blue'); $img->rectangle(10,10,50,50); # draw an empty rectangle with green borders $img->bgcolor(undef); $img->fgcolor('green'); $img->rectangle(30,30,100,100); # move to (80,80) and draw a green line to (100,190) $img->moveTo(80,80); $img->lineTo(100,190); # draw a solid orange ellipse $img->moveTo(110,100); $img->bgcolor('orange'); $img->fgcolor('orange'); $img->ellipse(40,40); # draw a black filled arc $img->moveTo(150,150); $img->fgcolor('black'); $img->arc(50,50,0,100,gdNoFill|gdEdged); # draw a string at (10,180) using the default # built-in font $img->moveTo(10,180); $img->string('This is very simple'); # draw a string at (280,210) using 20 point # times italic, angled upward 90 degrees $img->moveTo(280,210); $img->font('Times:italic'); $img->fontsize(20); $img->angle(-90); $img->string('This is very fancy'); # some turtle graphics $img->moveTo(300,100); $img->penSize(3,3); $img->angle(0); $img->line(20); # 20 pixels going to the right $img->turn(30); # set turning angle to 30 degrees $img->line(20); # 20 pixel line $img->line(20); $img->line(20); $img->turn(-90); # set turning angle to -90 degrees $img->line(50); # 50 pixel line # draw a cyan polygon edged in blue my $poly = new GD::Polygon; $poly->addPt(150,100); $poly->addPt(199,199); $poly->addPt(100,199); $img->bgcolor('cyan'); $img->fgcolor('blue'); $img->penSize(1,1); $img->polygon($poly); # convert into png data print $img->png; =head1 DESCRIPTION GD::Simple is a subclass of the GD library that shortens many of the long GD method calls by storing information about the pen color, size and position in the GD object itself. It also adds a small number of "turtle graphics" style calls for those who prefer to work in polar coordinates. In addition, the library allows you to use symbolic names for colors, such as "chartreuse", and will manage the colors for you. =head2 The Pen GD::Simple maintains a "pen" whose settings are used for line- and shape-drawing operations. The pen has the following properties: =over 4 =item fgcolor The pen foreground color is the color of lines and the borders of filled and unfilled shapes. =item bgcolor The pen background color is the color of the contents of filled shapes. =item pensize The pen size is the width of the pen. Larger sizes draw thicker lines. =item position The pen position is its current position on the canvas in (X,Y) coordinates. =item angle When drawing in turtle mode, the pen angle determines the current direction of lines of relative length. =item turn When drawing in turtle mode, the turn determines the clockwise or counterclockwise angle that the pen will turn before drawing the next line. =item font The font to use when drawing text. Both built-in bitmapped fonts and TrueType fonts are supported. =item fontsize The size of the font to use when drawing with TrueType fonts. =back One sets the position and properties of the pen and then draws. As the drawing progresses, the position of the pen is updated. =head2 Methods GD::Simple introduces a number of new methods, a few of which have the same name as GD::Image methods, and hence change their behavior. In addition to these new methods, GD::Simple objects support all of the GD::Image methods. If you make a method call that isn't directly supported by GD::Simple, it refers the request to the underlying GD::Image object. Hence one can load a JPEG image into GD::Simple and declare it to be TrueColor by using this call, which is effectively inherited from GD::Image: my $img = GD::Simple->newFromJpeg('./myimage.jpg',1); The rest of this section describes GD::Simple-specific methods. =cut use strict; use GD; use GD::Group; use Math::Trig; use Carp 'croak'; our @ISA = 'Exporter'; our @EXPORT = @GD::EXPORT; our @EXPORT_OK = @GD::EXPORT_OK; our $AUTOLOAD; my %COLORS; my $IMAGECLASS = 'GD::Image'; my $TRANSPARENT; sub AUTOLOAD { my $self = shift; my($pack,$func_name) = $AUTOLOAD=~/(.+)::([^:]+)$/; return if $func_name eq 'DESTROY'; if (ref $self && exists $self->{gd}) { $self->{gd}->$func_name(@_); } else { my @result = $IMAGECLASS->$func_name(@_); if (UNIVERSAL::isa($result[0],'GD::Image')) { return $self->new($result[0]); } else { return @result; } } } =over 4 =item $img = GD::Simple->new($x,$y [,$truecolor]) =item $img = GD::Simple->new($gd) Create a new GD::Simple object. There are two forms of new(). In the first form, pass the width and height of the desired canvas, and optionally a boolean flag to request a truecolor image. In the second form, pass a previously-created GD::Image object. =cut # dual-purpose code - beware sub new { my $pack = shift; unshift @_,(100,100) if @_ == 0; if (@_ >= 2) { # traditional GD::Image->new() call my $gd = $IMAGECLASS->new(@_); my $self = $pack->new($gd); $self->clear; return $self; } if (@_ == 1) { # initialize from existing image my $gd = shift; my $self = bless { gd => $gd, xy => [0,0], font => gdSmallFont, fontsize => 9, turningangle => 0, angle => 0, pensize => 1, },$pack; $self->{bgcolor} = $self->translate_color(255,255,255); $self->{fgcolor} = $self->translate_color(0,0,0); return $self; } } =item GD::Simple->class('GD'); =item GD::Simple->class('GD::SVG'); Select whether new() should use GD or GD::SVG internally. Call GD::Simple->class('GD::SVG') before calling new() if you wish to generate SVG images. If future GD subclasses are created, this method will subport them. =cut sub class { my $pack = shift; if (@_) { $IMAGECLASS = shift; eval "require $IMAGECLASS; 1" or die $@; $IMAGECLASS = "$IMAGECLASS\:\:Image" if $IMAGECLASS eq 'GD::SVG'; } $IMAGECLASS; } =item $img->moveTo($x,$y) This call changes the position of the pen without drawing. It moves the pen to position ($x,$y) on the drawing canvas. =cut sub moveTo { my $self = shift; croak 'Usage GD::Simple->moveTo($x,$y)' unless @_ == 2; my ($x,$y) = @_; $self->{xy} = [$x,$y]; } =item $img->move($dx,$dy) =item $img->move($dr) This call changes the position of the pen without drawing. When called with two arguments it moves the pen $dx pixels to the right and $dy pixels downward. When called with one argument it moves the pen $dr pixels along the vector described by the current pen angle. =cut sub move { my $self = shift; if (@_ == 1) { # polar coordinates -- this is r $self->{angle} += $self->{turningangle}; my $angle = deg2rad($self->{angle}); $self->{xy}[0] += $_[0] * cos($angle); $self->{xy}[1] += $_[0] * sin($angle); } elsif (@_ == 2) { # cartesian coordinates $self->{xy}[0] += $_[0]; $self->{xy}[1] += $_[1]; } else { croak 'Usage GD::Simple->move($dx,$dy) or move($r)'; } } =item $img->lineTo($x,$y) The lineTo() call simultaneously draws and moves the pen. It draws a line from the current pen position to the position defined by ($x,$y) using the current pen size and color. After drawing, the position of the pen is updated to the new position. =cut sub lineTo { my $self = shift; croak 'Usage GD::Simple->lineTo($x,$y)' unless @_ == 2; $self->gd->line($self->curPos,@_,$self->fgcolor); $self->moveTo(@_); } =item $img->line($x1,$y1,$x2,$y2 [,$color]) =item $img->line($dx,$dy) =item $img->line($dr) The line() call simultaneously draws and moves the pen. When called with two arguments it draws a line from the current position of the pen to the position $dx pixels to the right and $dy pixels down. When called with one argument, it draws a line $dr pixels long along the angle defined by the current pen angle. When called with four or five arguments, line() behaves like GD::Image->line(). =cut sub line { my $self = shift; if (@_ >= 4) { my ($x1,$x2,$y1,$y2,$color) = @_; $color ||= $self->fgcolor; return $self->gd->line($x1,$x2,$y1,$y2,$color); } croak 'Usage GD::Simple->line($dx,$dy) or line($r) or line($x1,$y1,$x2,$y2 [,$color])' unless @_ >= 1; my @curPos = $self->curPos; $self->move(@_); my @newPos = $self->curPos; return $self->gd->line(@curPos,@newPos,$self->fgcolor); } =item $img->clear This method clears the canvas by painting over it with the current background color. =cut sub clear { my $self = shift; $self->gd->filledRectangle(0,0,$self->getBounds,$self->bgcolor); } =item $img->rectangle($x1,$y1,$x2,$y2) This method draws the rectangle defined by corners ($x1,$y1), ($x2,$y2). The rectangle's edges are drawn in the foreground color and its contents are filled with the background color. To draw a solid rectangle set bgcolor equal to fgcolor. To draw an unfilled rectangle (transparent inside), set bgcolor to undef. =cut sub rectangle { my $self = shift; return $self->gd->rectangle(@_) if @_ == 5; croak 'Usage GD::Simple->rectangle($x1,$y1,$x2,$y2)' unless @_ == 4; my $gd = $self->gd; my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); $gd->filledRectangle(@_,$bg) if defined $bg; $gd->rectangle(@_,$fg) if defined $fg && (!defined $bg || $bg != $fg); } =item $img->ellipse($width,$height) This method draws the ellipse centered at the current location with width $width and height $height. The ellipse's border is drawn in the foreground color and its contents are filled with the background color. To draw a solid ellipse set bgcolor equal to fgcolor. To draw an unfilled ellipse (transparent inside), set bgcolor to undef. =cut sub ellipse { my $self = shift; return $self->gd->ellipse(@_) if @_ == 5; croak 'Usage GD::Simple->ellipse($width,$height)' unless @_ == 2; my $gd = $self->gd; my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); $gd->filledEllipse($self->curPos,@_,$bg) if defined $bg; $gd->ellipse($self->curPos,@_,$fg) if defined $fg && (!defined $bg || $bg != $fg); } =item $img->arc($cx,$cy,$width,$height,$start,$end [,$style]) This method draws filled and unfilled arcs. See L for a description of the arguments. To draw a solid arc (such as a pie wedge) set bgcolor equal to fgcolor. To draw an unfilled arc, set bgcolor to undef. =cut sub arc { my $self = shift; return $self->gd->arc(@_) if @_ == 7; croak 'Usage GD::Simple->arc($width,$height,$start,$end,$style)' unless @_ >= 4; my ($width,$height,$start,$end,$style) = @_; my $gd = $self->gd; my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); my ($cx,$cy) = $self->curPos; if ($bg) { my @args = ($cx,$cy,$width,$height,$start,$end,$bg); push @args,$style if defined $style; $gd->filledArc(@args); } else { my @args = ($cx,$cy,$width,$height,$start,$end,$fg); $gd->arc(@args); } } =item $img->polygon($poly) This method draws filled and unfilled polygon using the current settings of fgcolor for the polygon border and bgcolor for the polygon fill color. See L for a description of creating polygons. To draw a solid polygon set bgcolor equal to fgcolor. To draw an unfilled polygon, set bgcolor to undef. =cut sub polygon { my $self = shift; croak 'Usage GD::Simple->polygon($poly)' unless @_ == 1; my $gd = $self->gd; my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); $gd->filledPolygon(@_,$bg) if defined $bg; $gd->openPolygon(@_,$fg) if defined $fg && (!defined $bg || $bg != $fg); } =item $img->polyline($poly) This method draws polygons without closing the first and last vertices (similar to GD::Image->unclosedPolygon()). It uses the fgcolor to draw the line. =cut sub polyline { my $self = shift; croak 'Usage GD::Simple->polyline($poly)' unless @_ == 1; my $gd = $self->gd; my $fg = $self->fgcolor; $gd->unclosedPolygon(@_,$fg); } =item $img->string($string) This method draws the indicated string starting at the current position of the pen. The pen is moved to the end of the drawn string. Depending on the font selected with the font() method, this will use either a bitmapped GD font or a TrueType font. The angle of the pen will be consulted when drawing the text. For TrueType fonts, any angle is accepted. For GD bitmapped fonts, the angle can be either 0 (draw horizontal) or -90 (draw upwards). For consistency between the TrueType and GD font behavior, the string is always drawn so that the current position of the pen corresponds to the bottom left of the first character of the text. This is different from the GD behavior, in which the first character of bitmapped fonts hangs down from the pen point. This method returns a polygon indicating the bounding box of the rendered text. If an error occurred (such as invalid font specification) it returns undef and an error message in $@. =cut sub string { my $self = shift; return $self->gd->string(@_) if @_ == 5; my $string = shift; my $font = $self->font; my @bounds; if (ref $font && $font->isa('GD::Font')) { my ($x,$y) = $self->curPos; if ($self->angle == -90) { $x -= $font->height; $y -= $font->width; $self->gd->stringUp($font,$x,$y,$string,$self->fgcolor); $self->{xy}[1] -= length($string) * $font->width; @bounds = ( ($self->{xy}[0],$y), ($x,$y), ($x,$self->{xy}[1]-$font->width), ($self->{xy}[0],$self->{xy}[1]-$font->width) ); } else { $y -= $font->height; $self->gd->string($font,$x,$y,$string,$self->fgcolor); $self->{xy}[0] += length($string) * $font->width; @bounds = ( ($x,$self->{xy}[1]), ($self->{xy}[0],$self->{xy}[1]), ($self->{xy}[0],$y), ($x,$y) ); } } else { $self->useFontConfig(1); @bounds = $self->stringFT($self->fgcolor,$font, $self->fontsize,-deg2rad($self->angle), # -pi * $self->angle/180, $self->curPos,$string); return unless @bounds; my ($delta_x,$delta_y) = $self->_string_width(@bounds); $self->{xy}[0] += $delta_x; $self->{xy}[1] += $delta_y; } my $poly = GD::Polygon->new; while (@bounds) { $poly->addPt(splice(@bounds,0,2)); } return $poly; } =item $metrics = $img->fontMetrics =item ($metrics,$width,$height) = GD::Simple->fontMetrics($font,$fontsize,$string) This method returns information about the current font, most commonly a TrueType font. It can be invoked as an instance method (on a previously-created GD::Simple object) or as a class method (on the 'GD::Simple' class). When called as an instance method, fontMetrics() takes no arguments and returns a single hash reference containing the metrics that describe the currently selected font and size. The hash reference contains the following information: xheight the base height of the font from the bottom to the top of a lowercase 'm' ascent the length of the upper stem of the lowercase 'd' descent the length of the lower step of the lowercase 'j' lineheight the distance from the bottom of the 'j' to the top of the 'd' leading the distance between two adjacent lines =cut # return %$fontmetrics # keys: 'ascent', 'descent', 'lineheight', 'xheight', 'leading' sub fontMetrics { my $self = shift; unless (ref $self) { #class invocation -- create a scratch $self = $self->new; $self->font(shift) if defined $_[0]; $self->fontsize(shift) if defined $_[0]; } my $font = $self->font; my $metrics; if (ref $font && $font->isa('GD::Font')) { my $height = $font->height; $metrics = {ascent => 0, descent => 0, lineheight => $height, xheight => $height, leading => 0}; } else { $self->useFontConfig(1); my @mbounds = GD::Image->stringFT($self->fgcolor,$font, $self->fontsize,0, 0,0,'m'); my $xheight = $mbounds[3]-$mbounds[5]; my @jbounds = GD::Image->stringFT($self->fgcolor,$font, $self->fontsize,0, 0,0,'j'); my $ascent = $mbounds[7]-$jbounds[7]; my $descent = $jbounds[3]-$mbounds[3]; my @mmbounds = GD::Image->stringFT($self->fgcolor,$font, $self->fontsize,0, 0,0,"m\nm"); my $twolines = $mmbounds[3]-$mmbounds[5]; my $lineheight = $twolines - 2*$xheight; my $leading = $lineheight - $ascent - $descent; $metrics = {ascent => $ascent, descent => $descent, lineheight => $lineheight, xheight => $xheight, leading => $leading}; } if ((my $string = shift) && wantarray) { my ($width,$height) = $self->stringBounds($string); return ($metrics,abs($width),abs($height)); } return $metrics; } =item ($delta_x,$delta_y)= $img->stringBounds($string) This method indicates the X and Y offsets (which may be negative) that will occur when the given string is drawn using the current font, fontsize and angle. When the string is drawn horizontally, it gives the width and height of the string's bounding box. =cut sub stringBounds { my $self = shift; my $string = shift; my $font = $self->font; if (ref $font && $font->isa('GD::Font')) { if ($self->angle == -90) { return ($font->height,-length($string) * $font->width); } else { return (length($string) * $font->width,$font->height); } } else { $self->useFontConfig(1); my @bounds = GD::Image->stringFT($self->fgcolor,$font, $self->fontsize,-deg2rad($self->angle), $self->curPos,$string); return $self->_string_width(@bounds); } } =item $delta_x = $img->stringWidth($string) This method indicates the width of the string given the current font, fontsize and angle. It is the same as ($img->stringBounds($string))[0] =cut sub stringWidth { return ((shift->stringBounds(@_))[0]); } sub _string_width { my $self = shift; my @bounds = @_; my $delta_x = abs($bounds[2]-$bounds[0]); my $delta_y = abs($bounds[5]-$bounds[3]); my $angle = $self->angle % 360; if ($angle >= 0 && $angle < 90) { return ($delta_x,$delta_y); } elsif ($angle >= 90 && $angle < 180) { return (-$delta_x,$delta_y); } elsif ($angle >= 180 && $angle < 270) { return (-$delta_x,-$delta_y); } elsif ($angle >= 270 && $angle < 360) { return ($delta_x,-$delta_y); } } =item ($x,$y) = $img->curPos Return the current position of the pen. Set the current position using moveTo(). =cut sub curPos { @{shift->{xy}}; } =item $font = $img->font([$newfont] [,$newsize]) Get or set the current font. Fonts can be GD::Font objects, TrueType font file paths, or fontconfig font patterns like "Times:italic" (see L). The latter feature requires that you have the fontconfig library installed and are using libgd version 2.0.33 or higher. As a shortcut, you may pass two arguments to set the font and the fontsize simultaneously. The fontsize is only valid when drawing with TrueType fonts. =cut sub font { my $self = shift; $self->{font} = shift if @_; $self->{fontsize} = shift if @_; $self->{font}; } =item $size = $img->fontsize([$newfontsize]) Get or set the current font size. This is only valid for TrueType fonts. =cut sub fontsize { my $self = shift; $self->{fontsize} = shift if @_; $self->{fontsize}; } =item $size = $img->penSize([$newpensize]) Get or set the current pen width for use during line drawing operations. =cut sub penSize { my $self = shift; if (@_) { $self->{pensize} = shift; $self->gd->setThickness($self->{pensize}); } $self->{pensize}; } =item $angle = $img->angle([$newangle]) Set the current angle for use when calling line() or move() with a single argument. Here is an example of using turn() and angle() together to draw an octagon. The first line drawn is the downward-slanting top right edge. The last line drawn is the horizontal top of the octagon. $img->moveTo(200,50); $img->angle(0); $img->turn(360/8); for (1..8) { $img->line(50) } =cut sub angle { my $self = shift; $self->{angle} = shift if @_; $self->{angle}; } =item $angle = $img->turn([$newangle]) Get or set the current angle to turn prior to drawing lines. This value is only used when calling line() or move() with a single argument. The turning angle will be applied to each call to line() or move() just before the actual drawing occurs. Angles are in degrees. Positive values turn the angle clockwise. =cut # degrees, not radians sub turn { my $self = shift; $self->{turningangle} = shift if @_; $self->{turningangle}; } =item $color = $img->fgcolor([$newcolor]) Get or set the pen's foreground color. The current pen color can be set by (1) using an (r,g,b) triple; (2) using a previously-allocated color from the GD palette; or (3) by using a symbolic color name such as "chartreuse." The list of color names can be obtained using color_names(). The special color name 'transparent' will create a completely transparent color. =cut sub fgcolor { my $self = shift; $self->{fgcolor} = $self->translate_color(@_) if @_; $self->{fgcolor}; } =item $color = $img->bgcolor([$newcolor]) Get or set the pen's background color. The current pen color can be set by (1) using an (r,g,b) triple; (2) using a previously-allocated color from the GD palette; or (3) by using a symbolic color name such as "chartreuse." The list of color names can be obtained using color_names(). The special color name 'transparent' will create a completely transparent color. =cut sub bgcolor { my $self = shift; $self->{bgcolor} = $self->translate_color(@_) if @_; $self->{bgcolor}; } =item $index = $img->translate_color(@args) Translates a color into a GD palette or TrueColor index. You may pass either an (r,g,b) triple or a symbolic color name. If you pass a previously-allocated index, the method will return it unchanged. =cut sub translate_color { my $self = shift; return unless defined $_[0]; my ($r,$g,$b); if (@_ == 1 && $_[0] =~ /^-?\d+/) { # previously allocated index return $_[0]; } elsif (@_ == 3) { # (rgb triplet) ($r,$g,$b) = @_; } elsif (lc $_[0] eq 'transparent') { return $TRANSPARENT ||= $self->alphaColor('white',127); } else { $self->read_color_table unless %COLORS; die "unknown color" unless exists $COLORS{lc $_[0]}; ($r,$g,$b) = @{$COLORS{lc $_[0]}}; } return $self->colorResolve($r,$g,$b); } sub transparent { my $self = shift; my $index = $self->translate_color(@_); $self->gd->transparent($index); } =item $index = $img->alphaColor(@args,$alpha) Creates an alpha color. You may pass either an (r,g,b) triple or a symbolic color name, followed by an integer indicating its opacity. The opacity value ranges from 0 (fully opaque) to 127 (fully transparent). =cut sub alphaColor { my $self = shift; return unless defined $_[0]; my ($r,$g,$b,$a); if (@_ == 4) { # (rgb triplet) ($r,$g,$b,$a) = @_; } else { $self->read_color_table unless %COLORS; die "unknown color" unless exists $COLORS{lc $_[0]}; ($r,$g,$b) = @{$COLORS{lc $_[0]}}; $a = $_[1]; } return $self->colorAllocateAlpha($r,$g,$b,$a); } =item @names = GD::Simple->color_names =item $translate_table = GD::Simple->color_names Called in a list context, color_names() returns the list of symbolic color names recognized by this module. Called in a scalar context, the method returns a hash reference in which the keys are the color names and the values are array references containing [r,g,b] triples. =cut sub color_names { my $self = shift; $self->read_color_table unless %COLORS; return wantarray ? sort keys %COLORS : \%COLORS; } =item $gd = $img->gd Return the internal GD::Image object. Usually you will not need to call this since all GD methods are automatically referred to this object. =cut sub gd { shift->{gd} } sub read_color_table { my $class = shift; while () { chomp; last if /^__END__/; my ($name,$r,$g,$b) = split /\s+/; $COLORS{$name} = [hex $r,hex $g,hex $b]; } } sub setBrush { my $self = shift; my $brush = shift; if ($brush->isa('GD::Simple')) { $self->gd->setBrush($brush->gd); } else { $self->gd->setBrush($brush); } } =item ($red,$green,$blue) = GD::Simple->HSVtoRGB($hue,$saturation,$value) Convert a Hue/Saturation/Value (HSV) color into an RGB triple. The hue, saturation and value are integers from 0 to 255. =cut sub HSVtoRGB { my $self = shift; @_ == 3 or croak "Usage: GD::Simple->HSVtoRGB(\$hue,\$saturation,\$value)"; my ($h,$s,$v)=@_; my ($r,$g,$b,$i,$f,$p,$q,$t); if( $s == 0 ) { ## achromatic (grey) return ($v,$v,$v); } $h %= 255; $s /= 255; ## scale saturation from 0.0-1.0 $h /= 255; ## scale hue from 0 to 1.0 $h *= 360; ## and now scale it to 0 to 360 $h /= 60; ## sector 0 to 5 $i = $h % 6; $f = $h - $i; ## factorial part of h $p = $v * ( 1 - $s ); $q = $v * ( 1 - $s * $f ); $t = $v * ( 1 - $s * ( 1 - $f ) ); if($i<1) { $r = $v; $g = $t; $b = $p; } elsif($i<2){ $r = $q; $g = $v; $b = $p; } elsif($i<3){ $r = $p; $g = $v; $b = $t; } elsif($i<4){ $r = $p; $g = $q; $b = $v; } elsif($i<5){ $r = $t; $g = $p; $b = $v; } else { $r = $v; $g = $p; $b = $q; } return (int($r+0.5),int($g+0.5),int($b+0.5)); } =item ($hue,$saturation,$value) = GD::Simple->RGBtoHSV($hue,$saturation,$value) Convert a Red/Green/Blue (RGB) value into a Hue/Saturation/Value (HSV) triple. The hue, saturation and value are integers from 0 to 255. =back =cut sub RGBtoHSV { my $self = shift; my ($r, $g ,$bl) = @_; my ($min,undef,$max) = sort {$a<=>$b} ($r,$g,$bl); return (0,0,0) unless $max > 0; my $v = $max; my $s = 255 * ($max - $min)/$max; my $h; my $range = $max - $min; if ($range == 0) { # all colors are equal, so monochrome return (0,0,$max); } if ($max == $r) { $h = 60 * ($g-$bl)/$range; } elsif ($max == $g) { $h = 60 * ($bl-$r)/$range + 120; } else { $h = 60 * ($r-$g)/$range + 240; } $h = int($h*255/360 + 0.5); return ($h, $s, $v); } sub newGroup { my $self = shift; return $self->GD::newGroup(@_); } 1; __DATA__ white FF FF FF black 00 00 00 aliceblue F0 F8 FF antiquewhite FA EB D7 aqua 00 FF FF aquamarine 7F FF D4 azure F0 FF FF beige F5 F5 DC bisque FF E4 C4 blanchedalmond FF EB CD blue 00 00 FF blueviolet 8A 2B E2 brown A5 2A 2A burlywood DE B8 87 cadetblue 5F 9E A0 chartreuse 7F FF 00 chocolate D2 69 1E coral FF 7F 50 cornflowerblue 64 95 ED cornsilk FF F8 DC crimson DC 14 3C cyan 00 FF FF darkblue 00 00 8B darkcyan 00 8B 8B darkgoldenrod B8 86 0B darkgray A9 A9 A9 darkgreen 00 64 00 darkkhaki BD B7 6B darkmagenta 8B 00 8B darkolivegreen 55 6B 2F darkorange FF 8C 00 darkorchid 99 32 CC darkred 8B 00 00 darksalmon E9 96 7A darkseagreen 8F BC 8F darkslateblue 48 3D 8B darkslategray 2F 4F 4F darkturquoise 00 CE D1 darkviolet 94 00 D3 deeppink FF 14 100 deepskyblue 00 BF FF dimgray 69 69 69 dodgerblue 1E 90 FF firebrick B2 22 22 floralwhite FF FA F0 forestgreen 22 8B 22 fuchsia FF 00 FF gainsboro DC DC DC ghostwhite F8 F8 FF gold FF D7 00 goldenrod DA A5 20 gray 80 80 80 green 00 80 00 greenyellow AD FF 2F honeydew F0 FF F0 hotpink FF 69 B4 indianred CD 5C 5C indigo 4B 00 82 ivory FF FF F0 khaki F0 E6 8C lavender E6 E6 FA lavenderblush FF F0 F5 lawngreen 7C FC 00 lemonchiffon FF FA CD lightblue AD D8 E6 lightcoral F0 80 80 lightcyan E0 FF FF lightgoldenrodyellow FA FA D2 lightgreen 90 EE 90 lightgrey D3 D3 D3 lightpink FF B6 C1 lightsalmon FF A0 7A lightseagreen 20 B2 AA lightskyblue 87 CE FA lightslategray 77 88 99 lightsteelblue B0 C4 DE lightyellow FF FF E0 lime 00 FF 00 limegreen 32 CD 32 linen FA F0 E6 magenta FF 00 FF maroon 80 00 00 mediumaquamarine 66 CD AA mediumblue 00 00 CD mediumorchid BA 55 D3 mediumpurple 100 70 DB mediumseagreen 3C B3 71 mediumslateblue 7B 68 EE mediumspringgreen 00 FA 9A mediumturquoise 48 D1 CC mediumvioletred C7 15 85 midnightblue 19 19 70 mintcream F5 FF FA mistyrose FF E4 E1 moccasin FF E4 B5 navajowhite FF DE AD navy 00 00 80 oldlace FD F5 E6 olive 80 80 00 olivedrab 6B 8E 23 orange FF A5 00 orangered FF 45 00 orchid DA 70 D6 palegoldenrod EE E8 AA palegreen 98 FB 98 paleturquoise AF EE EE palevioletred DB 70 100 papayawhip FF EF D5 peachpuff FF DA B9 peru CD 85 3F pink FF C0 CB plum DD A0 DD powderblue B0 E0 E6 purple 80 00 80 red FF 00 00 rosybrown BC 8F 8F royalblue 41 69 E1 saddlebrown 8B 45 13 salmon FA 80 72 sandybrown F4 A4 60 seagreen 2E 8B 57 seashell FF F5 EE sienna A0 52 2D silver C0 C0 C0 skyblue 87 CE EB slateblue 6A 5A CD slategray 70 80 90 snow FF FA FA springgreen 00 FF 7F steelblue 46 82 B4 tan D2 B4 8C teal 00 80 80 thistle D8 BF D8 tomato FF 63 47 turquoise 40 E0 D0 violet EE 82 EE wheat F5 DE B3 whitesmoke F5 F5 F5 yellow FF FF 00 yellowgreen 9A CD 32 gradient1 00 ff 00 gradient2 0a ff 00 gradient3 14 ff 00 gradient4 1e ff 00 gradient5 28 ff 00 gradient6 32 ff 00 gradient7 3d ff 00 gradient8 47 ff 00 gradient9 51 ff 00 gradient10 5b ff 00 gradient11 65 ff 00 gradient12 70 ff 00 gradient13 7a ff 00 gradient14 84 ff 00 gradient15 8e ff 00 gradient16 99 ff 00 gradient17 a3 ff 00 gradient18 ad ff 00 gradient19 b7 ff 00 gradient20 c1 ff 00 gradient21 cc ff 00 gradient22 d6 ff 00 gradient23 e0 ff 00 gradient24 ea ff 00 gradient25 f4 ff 00 gradient26 ff ff 00 gradient27 ff f4 00 gradient28 ff ea 00 gradient29 ff e0 00 gradient30 ff d6 00 gradient31 ff cc 00 gradient32 ff c1 00 gradient33 ff b7 00 gradient34 ff ad 00 gradient35 ff a3 00 gradient36 ff 99 00 gradient37 ff 8e 00 gradient38 ff 84 00 gradient39 ff 7a 00 gradient40 ff 70 00 gradient41 ff 65 00 gradient42 ff 5b 00 gradient43 ff 51 00 gradient44 ff 47 00 gradient45 ff 3d 00 gradient46 ff 32 00 gradient47 ff 28 00 gradient48 ff 1e 00 gradient49 ff 14 00 gradient50 ff 0a 00 __END__ =head1 COLORS This script will create an image showing all the symbolic colors. #!/usr/bin/perl use strict; use GD::Simple; my @color_names = GD::Simple->color_names; my $cols = int(sqrt(@color_names)); my $rows = int(@color_names/$cols)+1; my $cell_width = 100; my $cell_height = 50; my $legend_height = 16; my $width = $cols * $cell_width; my $height = $rows * $cell_height; my $img = GD::Simple->new($width,$height); $img->font(gdSmallFont); for (my $c=0; $c<$cols; $c++) { for (my $r=0; $r<$rows; $r++) { my $color = $color_names[$c*$rows + $r] or next; my @topleft = ($c*$cell_width,$r*$cell_height); my @botright = ($topleft[0]+$cell_width,$topleft[1]+$cell_height-$legend_height); $img->bgcolor($color); $img->fgcolor($color); $img->rectangle(@topleft,@botright); $img->moveTo($topleft[0]+2,$botright[1]+$legend_height-2); $img->fgcolor('black'); $img->string($color); } } print $img->png; =head1 AUTHOR The GD::Simple module is copyright 2004, Lincoln D. Stein. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest versions of GD.pm are available at http://stein.cshl.org/WWW/software/GD =head1 SEE ALSO L, L, L, L =cut GD-2.50/GD/Polyline.pm0000644000175100017510000005372312164634363013757 0ustar lsteinlstein############################################################################ # # Polyline.pm # # Author: Dan Harasty # Email: harasty@cpan.org # Version: 0.2 # Date: 2002/08/06 # # For usage documentation: see POD at end of file # # For changes: see "Changes" file included with distribution # use strict; package GD::Polyline; ############################################################################ # # GD::Polyline # ############################################################################ # # What's this? A class with nothing but a $VERSION and and @ISA? # Below, this module overrides and adds several modules to # the parent class, GD::Polygon. Those updated/new methods # act on polygons and polylines, and sometimes those behaviours # vary slightly based on whether the object is a polygon or polyine. # use vars qw($VERSION @ISA); $VERSION = "0.2"; @ISA = qw(GD::Polygon); package GD::Polygon; ############################################################################ # # new methods on GD::Polygon # ############################################################################ use GD; use Carp 'croak','carp'; use vars qw($bezSegs $csr); $bezSegs = 20; # number of bezier segs -- number of segments in each portion of the spline produces by toSpline() $csr = 1/3; # control seg ratio -- the one possibly user-tunable parameter in the addControlPoints() algorithm sub rotate { my ($self, $angle, $cx, $cy) = @_; $self->offset(-$cx,-$cy) if $cx or $cy; $self->transform(cos($angle),sin($angle),-sin($angle),cos($angle),$cx,$cy); } sub centroid { my ($self, $scale) = @_; my ($cx,$cy); $scale = 1 unless defined $scale; map {$cx += $_->[0]; $cy += $_->[1]} $self->vertices(); $cx *= $scale / $self->length(); $cy *= $scale / $self->length(); return ($cx, $cy); } sub segLength { my $self = shift; my @points = $self->vertices(); my ($p1, $p2, @segLengths); $p1 = shift @points; # put the first vertex on the end to "close" a polygon, but not a polyline push @points, $p1 unless $self->isa('GD::Polyline'); while ($p2 = shift @points) { push @segLengths, _len($p1, $p2); $p1 = $p2; } return @segLengths if wantarray; my $sum; map {$sum += $_} @segLengths; return $sum; } sub segAngle { my $self = shift; my @points = $self->vertices(); my ($p1, $p2, @segAngles); $p1 = shift @points; # put the first vertex on the end to "close" a polygon, but not a polyline push @points, $p1 unless $self->isa('GD::Polyline'); while ($p2 = shift @points) { push @segAngles, _angle_reduce2(_angle($p1, $p2)); $p1 = $p2; } return @segAngles; } sub vertexAngle { my $self = shift; my @points = $self->vertices(); my ($p1, $p2, $p3, @vertexAngle); $p1 = $points[$#points]; # last vertex $p2 = shift @points; # current point -- the first vertex # put the first vertex on the end to "close" a polygon, but not a polyline push @points, $p2 unless $self->isa('GD::Polyline'); while ($p3 = shift @points) { push @vertexAngle, _angle_reduce2(_angle($p1, $p2, $p3)); ($p1, $p2) = ($p2, $p3); } $vertexAngle[0] = undef if defined $vertexAngle[0] and $self->isa("GD::Polyline"); return @vertexAngle if wantarray; } sub toSpline { my $self = shift; my @points = $self->vertices(); # put the first vertex on the end to "close" a polygon, but not a polyline push @points, [$self->getPt(0)] unless $self->isa('GD::Polyline'); unless (@points > 1 and @points % 3 == 1) { carp "Attempt to call toSpline() with invalid set of control points"; return undef; } my ($ap1, $dp1, $dp2, $ap2); # ap = anchor point, dp = director point $ap1 = shift @points; my $bez = new ref($self); $bez->addPt(@$ap1); while (@points) { ($dp1, $dp2, $ap2) = splice(@points, 0, 3); for (1..$bezSegs) { my ($t0, $t1, $c1, $c2, $c3, $c4, $x, $y); $t1 = $_/$bezSegs; $t0 = (1 - $t1); # possible optimization: # these coefficient could be calculated just once and # cached in an array for a given value of $bezSegs $c1 = $t0 * $t0 * $t0; $c2 = 3 * $t0 * $t0 * $t1; $c3 = 3 * $t0 * $t1 * $t1; $c4 = $t1 * $t1 * $t1; $x = $c1 * $ap1->[0] + $c2 * $dp1->[0] + $c3 * $dp2->[0] + $c4 * $ap2->[0]; $y = $c1 * $ap1->[1] + $c2 * $dp1->[1] + $c3 * $dp2->[1] + $c4 * $ap2->[1]; $bez->addPt($x, $y); } $ap1 = $ap2; } # remove the last anchor point if this is a polygon -- since it will autoclose without it $bez->deletePt($bez->length()-1) unless $self->isa('GD::Polyline'); return $bez; } sub addControlPoints { my $self = shift; my @points = $self->vertices(); unless (@points > 1) { carp "Attempt to call addControlPoints() with too few vertices in polyline"; return undef; } my $points = scalar(@points); my @segAngles = $self->segAngle(); my @segLengths = $self->segLength(); my ($prevLen, $nextLen, $prevAngle, $thisAngle, $nextAngle); my ($controlSeg, $pt, $ptX, $ptY, @controlSegs); # this loop goes about creating polylines -- here called control segments -- # that hold the control points for the final set of control points # each control segment has three points, and these are colinear # the first and last will ultimately be "director points", and # the middle point will ultimately be an "anchor point" for my $i (0..$#points) { $controlSeg = new GD::Polyline; $pt = $points[$i]; ($ptX, $ptY) = @$pt; if ($self->isa('GD::Polyline') and ($i == 0 or $i == $#points)) { $controlSeg->addPt($ptX, $ptY); # director point $controlSeg->addPt($ptX, $ptY); # anchor point $controlSeg->addPt($ptX, $ptY); # director point next; } $prevLen = $segLengths[$i-1]; $nextLen = $segLengths[$i]; $prevAngle = $segAngles[$i-1]; $nextAngle = $segAngles[$i]; # make a control segment with control points (director points) # before and after the point from the polyline (anchor point) $controlSeg->addPt($ptX - $csr * $prevLen, $ptY); # director point $controlSeg->addPt($ptX , $ptY); # anchor point $controlSeg->addPt($ptX + $csr * $nextLen, $ptY); # director point # note that: # - the line is parallel to the x-axis, as the points have a common $ptY # - the points are thus clearly colinear # - the director point is a distance away from the anchor point in proportion to the length of the segment it faces # now, we must come up with a reasonable angle for the control seg # first, "unwrap" $nextAngle w.r.t. $prevAngle $nextAngle -= 2*pi() until $nextAngle < $prevAngle + pi(); $nextAngle += 2*pi() until $nextAngle > $prevAngle - pi(); # next, use seg lengths as an inverse weighted average # to "tip" the control segment toward the *shorter* segment $thisAngle = ($nextAngle * $prevLen + $prevAngle * $nextLen) / ($prevLen + $nextLen); # rotate the control segment to $thisAngle about it's anchor point $controlSeg->rotate($thisAngle, $ptX, $ptY); } continue { # save the control segment for later push @controlSegs, $controlSeg; } # post process my $controlPoly = new ref($self); # collect all the control segments' points in to a single control poly foreach my $cs (@controlSegs) { foreach my $pt ($cs->vertices()) { $controlPoly->addPt(@$pt); } } # final clean up based on poly type if ($controlPoly->isa('GD::Polyline')) { # remove the first and last control point # since they are director points ... $controlPoly->deletePt(0); $controlPoly->deletePt($controlPoly->length()-1); } else { # move the first control point to the last control point # since it is supposed to end with two director points ... $controlPoly->addPt($controlPoly->getPt(0)); $controlPoly->deletePt(0); } return $controlPoly; } # The following helper functions are for internal # use of this module. Input arguments of "points" # refer to an array ref of two numbers, [$x, $y] # as is used internally in the GD::Polygon # # _len() # Find the length of a segment, passing in two points. # Internal function; NOT a class or object method. # sub _len { # my ($p1, $p2) = @_; # return sqrt(($p2->[0]-$p1->[0])**2 + ($p2->[1]-$p1->[1])**2); my $pt = _subtract(@_); return sqrt($pt->[0] ** 2 + $pt->[1] **2); } use Math::Trig; # _angle() # Find the angle of... well, depends on the number of arguments: # - one point: the angle from x-axis to the point (origin is the center) # - two points: the angle of the vector defined from point1 to point2 # - three points: # Internal function; NOT a class or object method. # sub _angle { my ($p1, $p2, $p3) = @_; my $angle = undef; if (@_ == 1) { return atan2($p1->[1], $p1->[0]); } if (@_ == 2) { return _angle(_subtract($p1, $p2)); } if (@_ == 3) { return _angle(_subtract($p2, $p3)) - _angle(_subtract($p2, $p1)); } } # _subtract() # Find the difference of two points; returns a point. # Internal function; NOT a class or object method. # sub _subtract { my ($p1, $p2) = @_; # print(_print_point($p2), "-", _print_point($p1), "\n"); return [$p2->[0]-$p1->[0], $p2->[1]-$p1->[1]]; } # _print_point() # Returns a string suitable for displaying the value of a point. # Internal function; NOT a class or object method. # sub _print_point { my ($p1) = @_; return "[" . join(", ", @$p1) . "]"; } # _angle_reduce1() # "unwraps" angle to interval -pi < angle <= +pi # Internal function; NOT a class or object method. # sub _angle_reduce1 { my ($angle) = @_; $angle += 2 * pi() while $angle <= -pi(); $angle -= 2 * pi() while $angle > pi(); return $angle; } # _angle_reduce2() # "unwraps" angle to interval 0 <= angle < 2 * pi # Internal function; NOT a class or object method. # sub _angle_reduce2 { my ($angle) = @_; $angle += 2 * pi() while $angle < 0; $angle -= 2 * pi() while $angle >= 2 * pi(); return $angle; } ############################################################################ # # new methods on GD::Image # ############################################################################ sub GD::Image::polyline { my $self = shift; # the GD::Image my $p = shift; # the GD::Polyline (or GD::Polygon) my $c = shift; # the color my @points = $p->vertices(); my $p1 = shift @points; my $p2; while ($p2 = shift @points) { $self->line(@$p1, @$p2, $c); $p1 = $p2; } } sub GD::Image::polydraw { my $self = shift; # the GD::Image my $p = shift; # the GD::Polyline or GD::Polygon my $c = shift; # the color return $self->polyline($p, $c) if $p->isa('GD::Polyline'); return $self->polygon($p, $c); } 1; __END__ =pod =head1 NAME GD::Polyline - Polyline object and Polygon utilities (including splines) for use with GD =head1 SYNOPSIS use GD; use GD::Polyline; # create an image $image = new GD::Image (500,300); $white = $image->colorAllocate(255,255,255); $black = $image->colorAllocate( 0, 0, 0); $red = $image->colorAllocate(255, 0, 0); # create a new polyline $polyline = new GD::Polyline; # add some points $polyline->addPt( 0, 0); $polyline->addPt( 0,100); $polyline->addPt( 50,125); $polyline->addPt(100, 0); # polylines can use polygon methods (and vice versa) $polyline->offset(200,100); # rotate 60 degrees, about the centroid $polyline->rotate(3.14159/3, $polyline->centroid()); # scale about the centroid $polyline->scale(1.5, 2, $polyline->centroid()); # draw the polyline $image->polydraw($polyline,$black); # create a spline, which is also a polyine $spline = $polyline->addControlPoints->toSpline; $image->polydraw($spline,$red); # output the png binmode STDOUT; print $image->png; =head1 DESCRIPTION B extends the GD module by allowing you to create polylines. Think of a polyline as "an open polygon", that is, the last vertex is not connected to the first vertex (unless you expressly add the same value as both points). For the remainder of this doc, "polyline" will refer to a GD::Polyline, "polygon" will refer to a GD::Polygon that is not a polyline, and "polything" and "$poly" may be either. The big feature added to GD by this module is the means to create splines, which are approximations to curves. =head1 The Polyline Object GD::Polyline defines the following class: =over 5 =item C A polyline object, used for storing lists of vertices prior to rendering a polyline into an image. =item C Cnew> I Create an empty polyline with no vertices. $polyline = new GD::Polyline; $polyline->addPt( 0, 0); $polyline->addPt( 0,100); $polyline->addPt( 50,100); $polyline->addPt(100, 0); $image->polydraw($polyline,$black); In fact GD::Polyline is a subclass of GD::Polygon, so all polygon methods (such as B and B) may be used on polylines. Some new methods have thus been added to GD::Polygon (such as B) and a few updated/modified/enhanced (such as B) I. See section "New or Updated GD::Polygon Methods" for more info. =back Note that this module is very "young" and should be considered subject to change in future releases, and/or possibly folded in to the existing polygon object and/or GD module. =head1 Updated Polygon Methods The following methods (defined in GD.pm) are OVERRIDDEN if you use this module. All effort has been made to provide 100% backward compatibility, but if you can confirm that has not been achieved, please consider that a bug and let the the author of Polyline.pm know. =over 5 =item C C<$poly-Escale($sx, $sy, $cx, $cy)> I Scale a polything in along x-axis by $sx and along the y-axis by $sy, about centery point ($cx, $cy). Center point ($cx, $cy) is optional -- if these are omitted, the function will scale about the origin. To flip a polything, use a scale factor of -1. For example, to flip the polything top to bottom about line y = 100, use: $poly->scale(1, -1, 0, 100); =back =head1 New Polygon Methods The following methods are added to GD::Polygon, and thus can be used by polygons and polylines. Don't forget: a polyline is a GD::Polygon, so GD::Polygon methods like offset() can be used, and they can be used in GD::Image methods like filledPolygon(). =over 5 =item C C<$poly-Erotate($angle, $cx, $cy)> I Rotate a polything through $angle (clockwise, in radians) about center point ($cx, $cy). Center point ($cx, $cy) is optional -- if these are omitted, the function will rotate about the origin In this function and other angle-oriented functions in GD::Polyline, positive $angle corrensponds to clockwise rotation. This is opposite of the usual Cartesian sense, but that is because the raster is opposite of the usual Cartesian sense in that the y-axis goes "down". =item C C<($cx, $cy) = $poly-Ecentroid($scale)> I Calculate and return ($cx, $cy), the centroid of the vertices of the polything. For example, to rotate something 180 degrees about it's centroid: $poly->rotate(3.14159, $poly->centroid()); $scale is optional; if supplied, $cx and $cy are multiplied by $scale before returning. The main use of this is to shift an polything to the origin like this: $poly->offset($poly->centroid(-1)); =item C C<@segLengths = $poly-EsegLength()> I In array context, returns an array the lengths of the segments in the polything. Segment n is the segment from vertex n to vertex n+1. Polygons have as many segments as vertices; polylines have one fewer. In a scalar context, returns the sum of the array that would have been returned in the array context. =item C C<@segAngles = $poly-EsegAngle()> I Returns an array the angles of each segment from the x-axis. Segment n is the segment from vertex n to vertex n+1. Polygons have as many segments as vertices; polylines have one fewer. Returned angles will be on the interval 0 <= $angle < 2 * pi and angles increase in a clockwise direction. =item C C<@vertexAngles = $poly-EvertexAngle()> I Returns an array of the angles between the segment into and out of each vertex. For polylines, the vertex angle at vertex 0 and the last vertex are not defined; however $vertexAngle[0] will be undef so that $vertexAngle[1] will correspond to vertex 1. Returned angles will be on the interval 0 <= $angle < 2 * pi and angles increase in a clockwise direction. Note that this calculation does not attempt to figure out the "interior" angle with respect to "inside" or "outside" the polygon, but rather, just the angle between the adjacent segments in a clockwise sense. Thus a polygon with all right angles will have vertex angles of either pi/2 or 3*pi/2, depending on the way the polygon was "wound". =item C C<$poly-EtoSpline()> I Create a new polything which is a reasonably smooth curve using cubic spline algorithms, often referred to as Bezier curves. The "source" polything is called the "control polything". If it is a polyline, the control polyline must have 4, 7, 10, or some number of vertices of equal to 3n+1. If it is a polygon, the control polygon must have 3, 6, 9, or some number of vertices of equal to 3n. $spline = $poly->toSpline(); $image->polydraw($spline,$red); In brief, groups of four points from the control polyline are considered "control points" for a given portion of the spline: the first and fourth are "anchor points", and the spline passes through them; the second and third are "director points". The spline does not pass through director points, however the spline is tangent to the line segment from anchor point to adjacent director point. The next portion of the spline reuses the previous portion's last anchor point. The spline will have a cusp (non-continuous slope) at an anchor point, unless the anchor points and its adjacent director point are colinear. In the current implementation, toSpline() return a fixed number of segments in the returned polyline per set-of-four control points. In the future, this and other parameters of the algorithm may be configurable. =item C C<$polyline-EaddControlPoints()> I So you say: "OK. Splines sound cool. But how can I get my anchor points and its adjacent director point to be colinear so that I have a nice smooth curves from my polyline?" Relax! For The Lazy: addControlPoints() to the rescue. addControlPoints() returns a polyline that can serve as the control polyline for toSpline(), which returns another polyline which is the spline. Is your head spinning yet? Think of it this way: =over 5 =item + If you have a polyline, and you have already put your control points where you want them, call toSpline() directly. Remember, only every third vertex will be "on" the spline. You get something that looks like the spline "inscribed" inside the control polyline. =item + If you have a polyline, and you want all of its vertices on the resulting spline, call addControlPoints() and then toSpline(): $control = $polyline->addControlPoints(); $spline = $control->toSpline(); $image->polyline($spline,$red); You get something that looks like the control polyline "inscribed" inside the spline. =back Adding "good" control points is subjective; this particular algorithm reveals its author's tastes. In the future, you may be able to alter the taste slightly via parameters to the algorithm. For The Hubristic: please build a better one! And for The Impatient: note that addControlPoints() returns a polyline, so you can pile up the the call like this, if you'd like: $image->polyline($polyline->addControlPoints()->toSpline(),$mauve); =back =head1 New GD::Image Methods =over 5 =item C C<$image-Epolyline(polyline,color)> I $image->polyline($polyline,$black) This draws a polyline with the specified color. Both real color indexes and the special colors gdBrushed, gdStyled and gdStyledBrushed can be specified. Neither the polyline() method or the polygon() method are very picky: you can call either method with either a GD::Polygon or a GD::Polyline. The I determines if the shape is "closed" or "open" as drawn, I the object type. =item C C<$image-Epolydraw(polything,color)> I $image->polydraw($poly,$black) This method draws the polything as expected (polygons are closed, polylines are open) by simply checking the object type and calling either $image->polygon() or $image->polyline(). =back =head1 Examples Please see file "polyline-examples.pl" that is included with the distribution. =head1 See Also For more info on Bezier splines, see http://www.webreference.com/dlab/9902/bezier.html. =head1 Future Features On the drawing board are additional features such as: - polygon winding algorithms (to determine if a point is "inside" or "outside" the polygon) - new polygon from bounding box - find bounding polygon (tightest fitting simple convex polygon for a given set of vertices) - addPts() method to add many points at once - clone() method for polygon - functions to interwork GD with SVG Please provide input on other possible features you'd like to see. =head1 Author This module has been written by Daniel J. Harasty. Please send questions, comments, complaints, and kudos to him at harasty@cpan.org. Thanks to Lincoln Stein for input and patience with me and this, my first CPAN contribution. =head1 Copyright Information The Polyline.pm module is copyright 2002, Daniel J. Harasty. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest version of Polyline.pm is available at your favorite CPAN repository and/or along with GD.pm by Lincoln D. Stein at http://stein.cshl.org/WWW/software/GD. =cut # future: # addPts # boundingPolygon # addControlPoints('method' => 'fitToSegments', 'numSegs' => 10) # toSpline('csr' => 1/4); # GD::Color # colorMap('x11' | 'svg' | ) # colorByName($image, 'orange'); # setImage($image); # cbn('orange'); # # # GD-2.50/GD/Image.pm.PLS0000644000175100017510000001265612164634363013643 0ustar lsteinlstein#!perl use Config; use File::Basename qw(&basename &dirname); use Cwd; my $DEFINES = ''; my $VERSION = ''; if (open F,".config.cache") { chomp($DEFINES = ); close F; } $origdir = cwd; chdir dirname($0); $file = basename($0, '.PL','.PLS'); open OUT,">$file" or die "Can't create $file: $!"; print "Extracting $file (with variable substitutions)\n"; print OUT <<"!GROK!THIS!"; # DO NOT EDIT! THIS FILE IS AUTOGENERATED BY $0 !GROK!THIS! print OUT << '!NO!SUBS!'; package GD::Image; use strict; use GD; use Symbol 'gensym','qualify_to_ref'; use vars '$VERSION'; $VERSION = '2.38'; =head1 NAME GD::Image - Image class for the GD image library =head1 SYNOPSIS See L =head1 DESCRIPTION See L =head1 AUTHOR The GD.pm interface is copyright 1995-2005, Lincoln D. Stein. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest versions of GD.pm are available on CPAN: http://www.cpan.org =head1 SEE ALSO L L, L, L, L =cut # Copyright 1995 Lincoln D. Stein. See accompanying README file for # usage information *stringTTF = \&GD::Image::stringFT; sub _make_filehandle { shift; # get rid of class no strict 'refs'; my $thing = shift; return $thing if defined(fileno $thing); # otherwise try qualifying it into caller's package my $fh; { local $^W = 0; # to avoid uninitialized variable warning from Symbol.pm $fh = qualify_to_ref($thing,caller(2)); } return $fh if defined(fileno $fh); # otherwise treat it as a file to open $fh = gensym; open($fh,$thing) || return; return $fh; } sub new { my $pack = shift; if (@_ == 1) { if (my $type = _image_type($_[0])) { my $method = "newFrom${type}Data"; return unless $pack->can($method); return $pack->$method($_[0]); } return unless my $fh = $pack->_make_filehandle($_[0]); my $magic; return unless read($fh,$magic,4); return unless my $type = _image_type($magic); seek($fh,0,0); my $method = "newFrom${type}"; return $pack->$method($fh); } return $pack->_new(@_); } sub newTrueColor { my $pack = shift; return $pack->_new(@_, 1); } sub newPalette { my $pack = shift; return $pack->_new(@_, 0); } sub newFromGd { croak("Usage: newFromGd(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGd($fh); } sub newFromGd2 { croak("Usage: newFromGd2(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGd2($fh); } sub newFromGd2Part { croak("Usage: newFromGd2(class,filehandle,srcX,srcY,width,height)") unless @_==6; my($class,$f) = splice(@_,0,2); my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGd2Part($fh,@_); } sub ellipse ($$$$$) { my ($self,$cx,$cy,$width,$height,$color) = @_; $self->arc($cx,$cy,$width,$height,0,360,$color); } # draws closed polygon with the specified color sub polygon { my $self = shift; my($p,$c) = @_; $self->openPolygon($p, $c); $self->line( @{$p->{'points'}->[0]}, @{$p->{'points'}->[$p->{'length'}-1]}, $c); } sub width { my $self = shift; my @bounds = $self->getBounds; $bounds[0]; } sub height { my $self = shift; my @bounds = $self->getBounds; $bounds[1]; } sub _image_type { my $data = shift; my $magic = substr($data,0,4); return 'Png' if $magic eq "\x89PNG"; return 'Jpeg' if $magic eq "\377\330\377\340"; return 'Jpeg' if $magic eq "\377\330\377\341"; return 'Jpeg' if $magic eq "\377\330\377\355"; return 'Jpeg' if $magic eq "\377\330\377\356"; return 'Gif' if $magic eq "GIF8"; return 'Gd2' if $magic eq "gd2\000"; return 'Xpm' if substr($data,0,9) eq "/* XPM */"; return; } sub clone { croak("Usage: clone(\$image)") unless @_ == 1; my $self = shift; my ($x,$y) = $self->getBounds; my $new = $self->new($x,$y); return unless $new; $new->copy($self,0,0,0,0,$x,$y); return $new; } !NO!SUBS! if ($DEFINES =~ /HAVE_PNG/) { print OUT <<'!NO!SUBS!' sub newFromPng { croak("Usage: newFromPng(class,filehandle,[truecolor])") unless @_>=2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromPng($fh,@_); } !NO!SUBS! } if ($DEFINES =~ /HAVE_JPEG/) { print OUT <<'!NO!SUBS!' sub newFromJpeg { croak("Usage: newFromJpeg(class,filehandle,[truecolor])") unless @_>=2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromJpeg($fh,@_); } !NO!SUBS! } if ($DEFINES =~ /HAVE_GIF/) { print OUT <<'!NO!SUBS!' sub newFromGif { croak("Usage: newFromGif(class,filehandle,[truecolor])") unless @_>=2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGif($fh,@_); } !NO!SUBS! } if ($DEFINES =~ /HAVE_DBM/) { print OUT <<'!NO!SUBS!' sub newFromXbm { croak("Usage: newFromXbm(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromXbm($fh); } !NO!SUBS! } print OUT <<'!NO!SUBS!'; # Autoload methods go after __END__, and are processed by the autosplit program. 1; __END__ !NO!SUBS! close OUT or die "Can't close $file: $!"; chdir $origdir; GD-2.50/GD/Polygon.pm0000644000175100017510000000766112164634363013613 0ustar lsteinlsteinpackage GD::Polygon; use strict; use Carp 'carp'; use GD; # old documentation error *GD::Polygon::delete = \&deletePt; =head1 NAME GD::Polygon - Polygon class for the GD image library =head1 SYNOPSIS See L =head1 DESCRIPTION See L =head1 AUTHOR The GD.pm interface is copyright 1995-2005, Lincoln D. Stein. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest versions of GD.pm are available on CPAN: http://www.cpan.org =head1 SEE ALSO L L, L, L, L =cut ### The polygon object ### # create a new polygon sub new { my $class = shift; return bless { 'length'=>0,'points'=>[] },$class; } # automatic destruction of the polygon sub DESTROY { my $self = shift; undef $self->{'points'}; } sub clear { my $self = shift; $self->{'points'} = []; } # add an x,y vertex to the polygon sub addPt { my($self,$x,$y) = @_; push(@{$self->{'points'}},[$x,$y]); $self->{'length'}++; } # get a vertex sub getPt { my($self,$index) = @_; return () unless ($index>=0) && ($index<$self->{'length'}); return @{$self->{'points'}->[$index]}; } # change the value of a vertex sub setPt { my($self,$index,$x,$y) = @_; unless (($index>=0) && ($index<$self->{'length'})) { carp "Attempt to set an undefined polygon vertex"; return undef; } @{$self->{'points'}->[$index]} = ($x,$y); 1; } # return the total number of vertices sub length { my $self = shift; return $self->{'length'}; } # return the array of vertices. # each vertex is an two-member (x,y) array sub vertices { my $self = shift; return @{$self->{'points'}}; } # return the bounding box of the polygon # (smallest rectangle that contains it) sub bounds { my $self = shift; my($top,$bottom,$left,$right) = @_; $top = 99999999; $bottom =-99999999; $left = 99999999; $right = -99999999; my $v; foreach $v ($self->vertices) { $left = $v->[0] if $left > $v->[0]; $right = $v->[0] if $right < $v->[0]; $top = $v->[1] if $top > $v->[1]; $bottom = $v->[1] if $bottom < $v->[1]; } return ($left,$top,$right,$bottom); } # delete a vertex, returning it, just for fun sub deletePt { my($self,$index) = @_; unless (($index>=0) && ($index<@{$self->{'points'}})) { carp "Attempt to delete an undefined polygon vertex"; return undef; } my($vertex) = splice(@{$self->{'points'}},$index,1); $self->{'length'}--; return @$vertex; } # translate the polygon in space by deltaX and deltaY sub offset { my($self,$dh,$dv) = @_; my $size = $self->length; my($i); for ($i=0;$i<$size;$i++) { my($x,$y)=$self->getPt($i); $self->setPt($i,$x+$dh,$y+$dv); } } # map the polygon from sourceRect to destRect, # translating and resizing it if necessary sub map { my($self,$srcL,$srcT,$srcR,$srcB,$destL,$destT,$destR,$destB) = @_; my($factorV) = ($destB-$destT)/($srcB-$srcT); my($factorH) = ($destR-$destL)/($srcR-$srcL); my($vertices) = $self->length; my($i); for ($i=0;$i<$vertices;$i++) { my($x,$y) = $self->getPt($i); $x = int($destL + ($x - $srcL) * $factorH); $y = int($destT + ($y - $srcT) * $factorV); $self->setPt($i,$x,$y); } } # These routines added by Winfriend Koenig. sub toPt { my($self, $dx, $dy) = @_; unless ($self->length > 0) { $self->addPt($dx,$dy); return; } my ($x, $y) = $self->getPt($self->length-1); $self->addPt($x+$dx,$y+$dy); } sub transform($$$$$$$) { # see PostScript Ref. page 154 my($self, $a, $b, $c, $d, $tx, $ty) = @_; my $size = $self->length; for (my $i=0;$i<$size;$i++) { my($x,$y)=$self->getPt($i); $self->setPt($i, $a*$x+$c*$y+$tx, $b*$x+$d*$y+$ty); } } sub scale { my($self, $sx, $sy, $cx, $cy) = @_; $self->offset(-$cx,-$cy) if defined $cx or defined $cy; $self->transform($sx,0,0,$sy,$cx,$cy); } 1; GD-2.50/GD/Group.pm0000644000175100017510000000116012164634363013244 0ustar lsteinlsteinpackage GD::Group; # Simple object for recursive grouping. Does absolutely nothing with GD, # but works nicely with GD::SVG. use strict; our $AUTOLOAD; our $VERSION = 1.00; sub AUTOLOAD { my ($pack,$func_name) = $AUTOLOAD =~ /(.+)::([^:]+)$/; my $this = shift; $this->{gd}->currentGroup($this->{group}); $this->{gd}->$func_name(@_); } sub new { my $this = shift; my ($gd,$group) = @_; return bless {gd => $gd, group => $group},ref $this || $this; } sub DESTROY { my $this = shift; my $gd = $this->{gd}; my $grp = $this->{group}; $gd->endGroup($grp); } 1; GD-2.50/META.yml0000664000175100017510000000074412164636125012600 0ustar lsteinlstein--- abstract: 'Interface to Gd Graphics Library' author: - 'Lincoln Stein (lstein@cshl.org)' build_requires: ExtUtils::MakeMaker: 0 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 6.68, CPAN::Meta::Converter version 2.112621' license: unknown meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: GD no_index: directory: - t - inc requires: Math::Trig: 0 version: 2.50 GD-2.50/t/0000755000175100017510000000000012164636125011563 5ustar lsteinlsteinGD-2.50/t/tile.jpeg0000644000175100017510000000067112164634363013375 0ustar lsteinlsteinJFIFHHC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222"* "1S!56as( a!145AQqr ?ROBqQhxZKhv;DtIM=k1mtK[ zt~, [T?+2tNJ~rS%dy ՟*>B8x+lGGD-2.50/t/test.out.4.png-10000644000175100017510000000041512164634363014360 0ustar lsteinlsteinPNG  IHDRd2[- PLTE3JIDAT8 0 E ̓z =0@6ʊD&?cۘKjGUOςx|pvrՑ3 9l`deVM2lh8ceB{"r{ܩ?Oy(k> S϶M(IENDB`GD-2.50/t/test.out.3.png0000644000175100017510000000623512164634363014227 0ustar lsteinlsteinPNG  IHDR,,TPLTE1tRNS@f 9IDATx[& g >7Ч70Y@UyVb!nnO?$ ǯ mǤL/6MJ_mش/ߦ?l6MٞB۟mm*i킏͟c¶uWC`ۮm/ `~Xo;wƦ`AcSz&l B~E~LmL-{c[mJǶ?mKېn6NE9g|uo{<ۚ{ͤۑYζFw yxhS(% PYa3َlʳiMr!uTAL8VjL8n/Ϲ)OϹ69 J97㕺u;u[ֻJܴ 877ҧ7o ݕ )7jo}ss fz?7B; v\ZDn%n[̾ESsktR n»n0`IsmdJL v[Ŝ[pW䶉9)鶉nӏW;B#m1=mg9f_ (;77oj仩%znsob-qt[Dnv^mp.Kƹ%p%vc^pnT%#tZF?v{dns27ILW8[^Qj$`P-ź$Xtw]˕W9׷{ȔylkTmw\ci2ćnSQԻQ5R*:8sJ[TӸ͇KyS[j!rSvVx77ylmdn?CM"s֍TMa7Ÿi.hn r-Uo#/즻uZ듛X-KQ[9: VI%*TsZ;EkU"i*S>B- Y0gj4UL h!c(}stN--,dV~JχUwք2˞v5٭ B m` Ǻ302JlY9Kk jh§HUxkeOH՝?^UZUghUejE*?c5}kS\}kZgVtRKT2-@ :fkR}ޏf-Z@*>dR|ڢS"'W:.jj opߏN&޶XCf2fZgsvZKk @ViO9/UZgr-lnR^i%]j׺ke{DT{xr'#-f?2X+߻Vw%jP!%ɴpT?|OMFHGjnZ!oR(׋D4H !}VNmϞ\JO_EZ|ZܵZ={ܚTXc4hiҳE+L| ZD_VXuժ :~J-觵7FZޫqhc.i-F ==L k%DosZL*eZ}UWk-٣Yg]t V!u`ma0%Ʋ 72D1e -ߍEm_}7V0Mk|X.%QR. &aSt@-~t%dknX_Z/ >j5'L.K9KOiŕNJlGre*Ł\9,EPQܹF<,d{=peh*ŝj,*(I/L cҋJЏ0rX8b2XڣJt E(2XdEQ<]i,v(.,?ݓ>ppX"N(&r1ExV6Ʈ V&CߋXϋ?brTQr+,5 nx'b,"D2߆x 0R?XpC,ocFXmXrlac62GF)uXz^!y  xkQr=/ؗ'q{ VY/H*⥻%Q 0]7C65_%M |\(Wcɦ .]Nrm>{ЃNUDÁO[sXwwQ|LX?V&;qX,9-&o F`1\8Xjl~p1V؄wNt[ϩ T5xZGyVhr呑6_$oR[dv7-? nJ{aխznX XfXK,XUW]ɱ*frfDՀ1V4٫OV;1]ðj^QK#V>QX]~<9X[(ao߃q[(V`ݾKb,+=CڣXuPW[ @2,Gjb`5E XEW `5EK ZXXQE9Gj0(|*VCaEK˱(ł(j+`Dq,VueXUEVL%jH(`a*>*c18]oaaQ?/R1s:zIENDB`GD-2.50/t/test.out.10.png-10000644000175100017510000000535512164634363014445 0ustar lsteinlsteinPNG  IHDR00` PLTE@LG32(0ߊIDATxmT \SvZ\O  e/>J&-h‡> 򤲕nVmKaVPKiYGYѤS~hKCGmC{?"^_/6{c̈́h!J\Q]]]G[M^ܡXVP4[.ϥ|Yrp0ppp O{jDj܎񢶈6[68X-OAoݻ-bUVk%;W<4[GiL EEHZUV`~j*isAU1 Y_VҿR+}g䐾Q4@*x^> T+4C8~XA*!ܢ}DhG-0C\) -ַ@3?aBTV"/\,YnK LVFN { |r[AX sq|bLE+O-!eq Bh+ -HW'NLġ OHH1 q\.7dpr/@˱N9a;ЯVpv8= :0%9_}ouXM\b "&e[O~-eRIv ׸ |G:aXEۄpȬ ,~}cmb1m$]qF oZ8gH[@LT) p# _ʅC6P 2ڈUl`߇/^#hj/-AaQU2 B8)]X]S4 /ρ;G;O] ByKmy g TL. ~ ;Y_wσ4dMthy&*8Y>;Y2/΁"Z*Goڸ\.P3p C=_Y2WgYsa(#wWq3)8^ N_N^9]2ɰ}v!ɇ 0ABQ`DXYY ~c=Q9_11`K@b>fl01secY QQ_,"99,D<,';;;M t(jŠ K smƌmuۧ[ @e\13o[÷ods變LL2W)G+ ^cr4~\a@*Z&bx4+pJ0bw)-wzm=IENDB`GD-2.50/t/test.out.3.gif0000644000175100017510000000561612164634363014212 0ustar lsteinlsteinGIF87a,,,,,0I8ͻ`(dihlp,tmx|pH$q)L:PsڌZX u[z^GzȮ4mK{}we d{DhV@C;xRb+› \ѓ} b}b[LSOߔ{D=* CoBk1A\P#%|=NHG%M&BR%-Q5S~ْNB1}ZP"JhSK*5UVv| W7_k֜fϚIko-۶Bn+7LO%k_D2ܔpaz|er2%l3ϼ*Ɗ9sB z5!5ڶ]޳?.unyc!G<5Sױ]Q}sy7Q}wSi iSHP"!c נQGFn]\hÃD;E/'[+؂lc~6Rx[d Chd)YbN8m*(>*kjj뤔º箩Iʨ^OjN8F+ʚj鵼>#♧JP R˒:K*Bn+CR0 Wo{oYW,mz_ȶJc/pr8 21O1, LW RRlHvzfO|sT\r@cLDb.o-C[-,O}0mh+ wt\ ݷvs т^7y(.C3SSM&8;^s>難py{:d-~+ /^)޵3|Ռs7?c_ޯOO!G&׃o>λpGK}' P{a_py. DU?eP3!jP$8A!~[ BNw2 kh bF ;RK 7djm$TH$ojEJQz!FE耱NJ\4`ZqMغ91v, 8.@ $H>EϏWb$G #r#Y$"B2,-7fg(Ir"(xJN`]Lܥ-I=J+ "0]X_ &+WeLIA3&5(2rN|3wtBB/\Dl)jf,f[nzLd Z@ ~F̔BLB/$NBR4EJH{*ZRQJ-JE4I%4SxiKEhHԧiCqjO:[rN*541QSӈTC5iQ-XkXźSALh'V g\sŮr[ٱ׫֯]a)fM$ _JNmլ]ݨFjIuc=M(eDGkXTuw]l+Y.浳iQ[T nB:WLo۟&Z.mT\Z=-f{N""wK^;0oy{^Ln{@],#{_7uo_OnQ'8 $`FpzOni9DI)jdLI]џؗ11D;fGm(c8q䥦ثd*9L.`<,k62u#k<w|f unDhH+iASZ̛==P+%e~OhzaEud^ k(upo\z<`5-G2djH{k5vbXC=Pkn j@{;s{NJfuyso[ߎPCgv:>qEi }nG3'׻n;=/O1>r@<杅t'=:K6Pa#>Dխ>jK]M/G׽3}c'clݽx=;}gn$nkt{>xT~p/|oZS[P˝xz#K.DgzԧDz<9{{;a~D{#'~no)a~z~7>S.=׻mk~Om}|o;[E57~gk2|~~z\  Ȁ 2VG~~8xe{_WE؂x)_Te'X7xi9 ({~(:SWWeH J؁vG7|FXA|"8xZ_^*8N\d=hQ+jhg88w7rXhhw@XDŽwiZ8'ElqXG>MZ򈖘~І$fL}'M&$ƈbA%`$A":Et"JEfπ抣ȋR!l⋛t(H؇mF ;GD-2.50/t/test.out.10.png0000644000175100017510000000473112164634363014304 0ustar lsteinlsteinPNG  IHDR00` PLTE@Ll ȖF CԦ|dD)H7gWFx.,G=(6&7)qU'8(hHhYRG32(JIDATxmT]H#Y2t=(! D_X4B Ch nA%IZi[3342 tDhFBb0 iK~gž[~wsnUH6e3U\^3?GF0_Z(,ԇbdqdϷTc P>L`=q*83!\0f q/wy>LHBtwwQ%Kx E|ϗHӾ~H^rBe 9<H&Lv230  Hwf4L C0"X?'bt4s sFg@7u 56ٱf #I9}vvgnP Jֱ~6l&bj?En -)W 覑BWLky|3}2T+qE/JvaEQ7[hq w!+cV0 C'+s$<=IX\ΡsBPZwwy?XH0,}yQ?+p쩅X4eNzFpdn\zWb]W-Pd #۝powx85 cv\u@VwG]j*(*9qi?^/X1=8YڒmlɪlMUSq-.g'O uĻ(ksx)&%-%pJq"O`@9.xi$t oO>"s#W&`3p [N4Ag6SpE8Ƙ ͷ 5) a]RRJk>zEŷ VJDTn(Bw"HɪIbg<˱ fbmOt۲n\;*ǜ>{L1Znys[tM]:6{=6X'x]E#jyD;<端ȫoܛy< OO. 1{m^Z*6|ٗ>p6tfU'!ZR]c:Tl6y gdb=R稥M,Vsy=xϚ"ߤ^Kx9Չc_ B p8JKU89-ÊRdӯwkFyD&-{v FOpUEXb ..`Y 3B  m pD^ ?ѓ`=dmJ(=nmQ7?;5|I}eSlwkQi4}t=p ݎRZ 4FƗ=aycRRJ&]}=k`C!AO/"!LF%IF:{ j;9lGHϷvtwL~ٽ'(h I wc`vct-4xA0@ d2<ߖ1zp6VG32(0ߊIDATmT XS>Ŀ:U~$2 hpg ▌ECb"nOhtZnSeb)86թ-s}}{~}<Zv}WIyV+y=|mV,l LaO N[:v6f;npjn7nhj˳4h_mOlX-]ugrlVr46]/"rsBP}˅!lq1ONˆgMC=77n$:yr[@!E|VVVkVA]yMúp&"ȠLN '5 VU&|{kVʦ[8}:y]ܼJ 궶ի>-b<ص!E6\w`iK9r:qۍZn0VmMujv!l=ޑv#7{7p3Zc-qn㍖~/۞(Ε46G{n7Yw{7n}w-їaa {7w3qjI D&9]uu/y'x/OsXtiX bO f4׮31Ղ׳'ZPa<&)b|T#ˉT=nt΄WɟffS8^!ݝ =j^$ǣ~9իǛ%8pv{{ཁ13PbԦj!0(ynNǯF C {` Ff2 L Ё+0yGH,bEqqTh&xAzRuzσpyU&65Cű9_I`c$l#  #r@e-ǎ5/<֘_HgI6l% ¬^V߯psv疔@% "4V4pK`J%'0QrSX3I#RL& KL$U_xU߈B` ȷW2`N. *6 @xL N:2 $=^Z"u(e b9?\^Nc~Cr/;^82)| N u2!׵x|ba7Ѝw}sW7pN%gIm oX*~,0!S|^4|( >Nu/0_T[/JaːX ݇K47'\c(dKSBWǒP 3p}2s_& /&)dnTsJpϰKv=^ܤ;QQ!$PoG}h<`ĥJ)tśVK\+ܷ&wŹm\wЮ{ S r0c0_)xR)1J R6EmUT5f؝ )йvsoc杊]ko5|pgެKe"Mt‚Ec VT_\P(hZϐд"D*+];?%.nE-rj E94]VUfPt33sپf`8RTԟ37tNΓxdeo\S54T4jhpUU`QE1:*)PH'$ ,*,^UV&eeejDkGi ͗Х,  PC(zE{/ZLW4tict4X*IMezTﺯ^7lY1i²KsB5?XTD2茜aQ.!!9Aij3,H$'FϠCREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?GD-2.50/t/GD.t0000644000175100017510000002267712164634363012262 0ustar lsteinlstein#!/usr/bin/perl -w use lib './blib/lib','./blib/arch','../blib/lib','../blib/arch'; use FileHandle; use FindBin qw($Bin); use constant FONT=>"$Bin/Generic.ttf"; use constant SKIP_TEST_8 => 1; my $loaded; my $suffix; BEGIN {$| = 1; $loaded = 0; print "1..12\n"; } END {print "not ok 1\n" unless $loaded;} use GD qw(:DEFAULT GD_CMP_IMAGE); use GD::Simple; $loaded++; if ($suffix = $ENV{GDIMAGETYPE}) { print STDERR "Testing using $suffix support.\n"; } elsif (GD::Image->can('newFromPng')) { print STDERR "Testing using png support.\n"; $suffix = "png"; } elsif (GD::Image->can('newFromJpeg')) { print STDERR "Testing using jpeg support.\n"; $suffix = "jpeg"; } elsif (GD::Image->can('newFromGif')) { print STDERR "Testing using gif support.\n"; $suffix = "gif"; } else { die "Regression tests require one or more of PNG, GIF or JPEG support in libgd."; } print "ok 1\n"; chdir 't' || die "Couldn't change to 't' directory: $!"; $arg = shift; if (defined $arg && $arg eq '--write') { warn "Writing regression files..."; compare(&test2,2,'write'); compare(&test3,3,'write'); compare(&test4,4,'write'); compare(&test5,5,'write'); compare(&test6,6,'write'); compare(&test7,7,'write'); compare(&test8,8,'write'); compare(&test9('frog.xpm'),9,'write') if GD::Image->can('newFromXpm'); compare(&test10('frog.jpg'),10,'write') if GD::Image->can('newFromJpeg'); } compare(test2(),2); compare(test3(),3); compare(test4(),4); compare(test5(),5); compare(test6(),6); compare(test7(),7); if (SKIP_TEST_8) { print "ok 8 # Skip, FreeType changes too frequently to be testable\n"; } elsif (GD::Image->stringTTF(0,FONT,12.0,0.0,20,20,"Hello world!")) { compare(test8(),8,undef); } elsif ($@ =~/not built with .+Type font support/) { print "ok ",8," # Skip, no FreeType font support\n"; } else { print "not ok ",8,"\n"; } if (GD::Image->newFromXpm('frog.xpm')) { compare(test9('frog.xpm'),9); } elsif ($@ =~/not built with xpm support/) { print "ok ",9," # Skip, no XPM support\n"; } else { print "not ok ",9,"\n"; } if (GD::Image->can('newFromJpeg')) { compare(test10('frog.jpg'),10); } else { print "ok ",10," # Skip, no JPEG support\n"; } my $image = GD::Image->new(300,300); $image->colorAllocate(255,255,255); $image->colorAllocate(0,0,0); $image->colorAllocate(255,0,0); $image->rectangle(0,0,300,300,0); $image->filledRectangle(10,10,50,50,2); my $gd = $image->gd; my $image2 = GD::Image->newFromGdData($gd); print ((image($image) eq image($image2)) ? "ok 11\n" : "not ok 11\n"); my $gd2 = $image->gd2; $image2 = GD::Image->newFromGd2Data($gd2); print ((image($image) eq image($image2)) ? "ok 12\n" : "not ok 12\n"); exit 0; sub compare { if (@_ < 2 && $@ =~ /not built with PNG/i) { print "ok $_[0] # Skip, no PNG support\n"; return; } my($imageData,$testNo,$fht) = @_; local($/); undef $/; my $regressdata; my $file = ($^O eq 'VMS')? "test.out_".$testNo."_$suffix" : "./test.out.$testNo.$suffix"; if (defined $fht and $fht eq 'write') { open (REGRESSFILE,">${file}_new") || die "Can't open regression file '${file}_new': $!\n"; print STDERR "Writing ${file}_new\n"; binmode REGRESSFILE; print REGRESSFILE $imageData; close REGRESSFILE; } else { my ($ok,$counter); my $fname = $file; while (-r "./$fname") { open (REGRESSFILE,"./$fname") || die "Can't open regression file './t/$fname': $!\n"; binmode REGRESSFILE; $regressdata = ; close REGRESSFILE; $ok = $imageData eq $regressdata; last if $ok; $fname = "$file-".++$counter; } print $ok ? "ok $testNo" : "not ok $testNo","\n"; } } sub test2 { my($im) = new GD::Image(300,300); my($white) = $im->colorAllocate(255, 255, 255); my($black) = $im->colorAllocate(0, 0, 0); my($red) = $im->colorAllocate(255, 0, 0); my($green) = $im->colorAllocate(0,255,0); my($yellow) = $im->colorAllocate(255,250,205); open (TILE,"./tile.$suffix") || die "Can't open tile file: $!"; my($tile) = $suffix eq 'png' ? GD::Image->newFromPng(TILE) : $suffix eq 'gif' ? GD::Image->newFromGif(TILE) : $suffix eq 'jpeg'? GD::Image->newFromJpeg(TILE) : die "Regression tests require PNG, GIF or JPEG support in libgd"; close TILE; return unless $tile; $im->setBrush($tile); $im->arc(100,100,100,150,0,360,gdBrushed); $im->setTile($tile); $im->filledRectangle(150,150,250,250,gdTiled); $im->rectangle(150,150,250,250,$black); $im->setStyle($green,$green,$green,gdTransparent,$red,$red,$red,gdTransparent); $im->line(0,280,300,280,gdStyled); return image($im) } sub test3 { my($im) = new GD::Image(300,300); my($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); my($brush) = new GD::Image(10,10); $brush->colorAllocate(255,255,255); # white $brush->colorAllocate(0,0,0); # black $brush->transparent($white); # white is transparent $brush->filledRectangle(0,0,5,2,$black); # a black rectangle $im->setBrush($brush); $im->arc(100,100,100,150,0,360,gdBrushed); my($poly) = new GD::Polygon; $poly->addPt(30,30); $poly->addPt(100,10); $poly->addPt(190,290); $poly->addPt(30,290); $im->polygon($poly,gdBrushed); $im->fill(132,62,$blue); $im->fill(100,70,$red); $im->fill(40,40,$yellow); $im->interlaced(1); $im->copy($im,150,150,20,20,50,50); $im->copyResized($im,10,200,20,20,100,100,50,50); return image($im) } sub test4 { my($im) = new GD::Image(100,50); my($black,$white,$red,$blue) = ( $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 255, 255), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255) ); $im->arc(50, 25, 98, 48, 0, 360, $white); $im->fill(50, 21, $red); return image($im) } sub test5 { my($im) = new GD::Image(225,180); my($black,$white,$red,$blue,$yellow) = ($im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 255, 255), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); my($poly) = new GD::Polygon; $poly->addPt(0,50); $poly->addPt(25,25); $poly->addPt(50,50); $im->filledPolygon($poly,$blue); $poly->offset(100,100); $im->filledPolygon($poly,$red); $poly->map(50,50,100,100,10,10,110,60); $im->filledPolygon($poly,$yellow); $poly->map($poly->bounds,50,20,80,160); $im->filledPolygon($poly,$white); return image($im) } sub test6 { my($im) = new GD::Image(300,300); my($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); $im->transparent($white); $im->interlaced(1); my($brush) = new GD::Image(10,10); $brush->colorAllocate(255,255,255); $brush->colorAllocate(0,0,0); $brush->transparent($white); $brush->filledRectangle(0,0,5,2,$black); $im->string(gdLargeFont,150,10,"Hello world!",$red); $im->string(gdSmallFont,150,28,"Goodbye cruel world!",$blue); $im->stringUp(gdTinyFont,280,250,"I'm climbing the wall!",$black); $im->charUp(gdMediumBoldFont,280,280,"Q",$black); $im->setBrush($brush); $im->arc(100,100,100,150,0,360,gdBrushed); $poly = new GD::Polygon; $poly->addPt(30,30); $poly->addPt(100,10); $poly->addPt(190,290); $poly->addPt(30,290); $im->polygon($poly,gdBrushed); $im->fill(132,62,$blue); $im->fill(100,70,$red); $im->fill(40,40,$yellow); return image($im) } sub test7 { my $dtor = 0.0174533; my $pi = 3.141592654; my $xsize = 500; my $ysize = 500; my $scale = 1; my $x_offset = $xsize/2; my $y_offset = $ysize/2; my $im = new GD::Image($xsize,$ysize); my $poly = new GD::Polygon; my $col_bg = $im->colorAllocate(0,0,0); my $col_fg = $im->colorAllocate(255,255,0); my $col_fill = $im->colorAllocate(255,0,0); my $r_0 = 100; my $theta_0 = 20; my $spring_factor = 30; for($theta=0;$theta<=360;$theta++) { my $r = $r_0 + $spring_factor*sin(2*$pi*$theta/$theta_0); my $x = int($r * cos($theta*$dtor))*$scale+$x_offset; my $y = int($r * sin($theta*$dtor))*$scale+$y_offset; $poly->addPt($x,$y); } $im->filledPolygon($poly,$col_fill); # Call gdImageFilledPolygon() return image($im) } sub test8 { my $im = GD::Image->new(400,250); if (!$im) { printf("Test7: no image");}; my($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); # Some TTFs $im->stringFT($black,FONT,12.0,0.0,20,20,"Hello world!") || warn $@; $im->stringFT($red,FONT,14.0,0.0,20,80,"Hello world!") || warn $@; $im->stringFT($blue,FONT,30.0,-0.5,60,100,"Goodbye cruel world!") || warn $@; return image($im) } sub test9 { my $fn = shift; my $im = GD::Image->newFromXpm($fn); return image($im) } sub test10 { my $fn = shift; my $im = GD::Image->newFromJpeg($fn); return image($im) } # not used sub test11 { my $fn = shift; my $im = GD::Image->newFromGif($fn); $im->gif; } sub image { my $gd = shift; return $suffix eq 'png' ? $gd->png :$suffix eq 'gif' ? $gd->gif :$suffix eq 'jpeg'? $gd->jpeg :undef; } GD-2.50/t/Generic.ttf0000644000175100017510000005420412164634363013665 0ustar lsteinlsteinpOS/2O7X4NPCLT=ͺ <6cmap9 Xcvt ;Tfpgmahglyf tJhead Y@6hhea X$hmtxSiVhkernCxlocaTmaxpVW name:P post x DprepsT=  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a>z "   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV[WYZ\]`a^_X $4U !JfP hP!wohB+'ym/+)fZ?+'oj=7^`T) omb!@ ,C b#BfV-,*CTx+X9Y+Xf  H  n * (D* "6, F !"##$f%b&f'B((()x**+,-R--./0l1.124556v78 9T:@:;8?4@@ABCxDtEEGDGGH.HIXJJJ@$i Uiii4 <++{b  "$%&'()*+,-./0123456789:;<=?BDEFGHIJKLMNOPQRSTUVWXYZ[\](7>F F F  V 4b    ArtBrushMediumFontMonger:ArtBrush MediumArtBrush Medium001.001ArtBrushArtBrushMediumFontMonger:ArtBrush MediumArtBrush Medium001.001ArtBrush!ArtBrush Medium7@"@33  +1+0!!'!!B!B!!@   ^ #+1?*04722632.1".5467632#"UP $& .5+w!?@ Y V;wZ )G J.@gLl' H!@ a #+1?*0>7#"'>6%>7#"'>6o5%,.>xL!S<,.=xM !!(N \JYz.BlC'A `HVy,Cld@X  //    D!+1????++073737#7#''#'IHőFC–îǏgb`^`3bwV[fqG@=hg`\H@86/  n k khgd`\YVRMJFC@:64/,)#! 8<s+1???*0263267632.547&#"#.#"507#"'&54>732763.5>7>746>74&'7257 IAT+/QU 1܏!; -HVOp,ņD PGf+69`lc Ck5*:W9?/g:@5bN&Ej7 J1K[o+@#e^UL8-"D cZQ4) n?q++??*0#"&567>724>3#"'&&#"'.'&54>72"327>543267654'"#"3V! R_K2\UDon'#+< hMI7uD LVFly-.= `*G :Y n%` $UFI՗B p'-=|d}-LEwr32##"'&54>7&54>7632#&54673267 32>7&54654P&GI2 IwЌY]ZN{(7#"'>6o5%,.>xL!!(N \JYz.Bl@  | ++?.0#.547721nV-+P9>o/S)٥?CC%?e& '@ |++?.0>54&'&5463"&5>6=1V-9(wH8*Ut٤P>V0'=C_ޯȺ& ÃFOR@DJBA76.*&#"N K I / !   JICBA<:765.-("! _>Q+1???????*0#"&'74&#"&57>54'&5467'>54637327632732%%'.#" T    % z!   P    " s     '  "    7!0,@%0-)  0&"! X2+1*0%.#"#"&'>54'&5467%>7>323267P !*& # L==& +% + & F+ /  &''@  i+1..0.547>3#"'4>54V:A'4? {X6Y2? )&./(4Yz2D55\@ ` +1..065>5%4&'4\& V   o ' {N@ f +1..07&5467632#"&3 :038&? 9219&=J1_!"1]!"@ R +1*06332632"#"'66V?ϱ(  {!By@?O/*`3)3@*( (+   $ |$p+++1++07.5467632 #" 3274.#"h#_Yw97M(2f "E.30栓I*$t'%شs~<`%00iL! @   V#+1??*0.'.5>72>76322632:" 8+U*'6l-=}<~u 7 ON+C l,=M6@.B F+'#KF@=60-+'#!@ 4O+1*+0>7632>32.'&5465.507>$7654&'&#".54'&&5ZtL:0G`67!e/L @@11  6q;I /1El= Am'oA64\y=]M1uߺF  !  &  93@;G2" $WU@KT/,'"K1 OK 1&  TQOCA>;," 5/ s GIo5*'$/Y++1?++0>7632#"'&54>732>74.#&54674&547>54'&#"&5465.&xd`563A^ffg?/o2A=HOK2]Y#pkcW 4 42I [g"6/'   ED>;/'& C1I+1????*0>763226323".'#>&546.547627>7 . gR! ",B A@F ?_wQQ_    4  '  '&K: 0IN@F/(%!;1 H =E0;1)  H=86% t6E(-r%!K+++++02632#"2#"&5>72332>54'.#".54'.56727:uFB8ܒՋvj>sE^5d O"-@X[*YQ[0 u, !  D K_]H4Q=K$5! N:#<9 !0$=3@*5)'7 0.'+ 7   < {3!?++??++06$763232632#"'&5466&#"#"'32>74De  #0 .Ą(cVfOiyT0Zrb?D 2LGA VR[)'#i@ WikvP{Q#('2=@NRQ. 50"@'&  /,)'& N2+1??..0>7632".'.527667&5465.54%]hU@0 )#] ) "IDXr    -cXT U`&5.  ^ 7ENL@@A-* N8 J ,    ?,6= KNJF j%D82|H6=/P+++????*+0672>7&'#"'.547.5432654%.'fQN^J!!N4  !77U" $U' (=6kpqn@1}Oi\d BFmD{M74_A, ( #E#,C7Qj9*.g4Ma)g\c+[k84FcR!8+@"/-'(7  % 3:++??.+0&54>7632.'#"&&3267632>54'&#" kݠ-Zl{mlt( UHeD~<RAF,Q0&<h_ۼ. `[ "${oX #$+k)852 %H%=P'5X$@#! c&+1*07&5467632#"&5467632#"3 ;/09'> 811;Rd 9/47T 900:Ts0b!!1^!1b=1_!X+@*!% h -+1*07.54763#"'4>54&5467632#"bFu5= KyC,h,3 9/47T 900:T+:#)i0,2BsF*T/91b=1_!?`.&@**)$"  Z -0+1*065>5%4&'465>5%4&'4++' n  ' o    PO;@00 E3C C3.+ oI+?=85 e Q++1??*+07&54>7632#"#".'&547>7>7654&'&#"&54654.547>7632\ 1!5:V# :e7654.'>7>7>72+9- OU@li+ @3j 8] ;3rK M'JfX6z 8 0o{>7o " [DBu7%9G_M@D\TPHB>=: FX 2.F( NK)&X# "  VPK>5.)} Bl\a++??++0>7632#"'.'.'.5667.54>&6$65.#">322>5.&𞰰4$B`NVw|);񥗌 7 #_"4oGB Pb/p8I)*c'9#uf(RTL4$:W5L<]{NBY[HMp?4P-" %}{~/*  5(feU.Xrh+7 # Al33!B4@(=7"9 )    3/, =o?D++????..+0%2367.'>732>76323#".'&5466z;!u$ -0L|+)1.. 8\*D,'/B5{u RL.SB&J.k-)R{`z0  6\Y6 \ڨKBQ@L^*  <,!.Z7632!&'&%6$>7654&(BhP0.ґN/~$& r&ZZ1`Z"SzcVT ?Q;id}D1@''"-   B>:74-,)"> /F+1???*0>72%#>32&'>7.'>7>7.'&&Ru*  `%f)CH5 *f;hNR18Tp ##Ju  ** )'%%% >+IAh|}:"eAvȥc 59A>.@%>; '  >;86'&%#  =*@+1??*0>7.'.'6$>32%.5>7>7>54'>3NTS ' HBC Պ )/*>n $-!'   P,,*I:) ! " #! 6`/.Oema$%>Xj>5<>-9G1@)D?"'A 85/,( 5,&DmFI++?*+06$763233.'6732>54'6$32.#"#"&'&54+ZE d. T7'=2"'#_d>^%-[FgW1#sS  /#O>C9X?a2C=B@3:P> =R"aaWs`@R_J  %59+"̈v"7YKW uG9@)$F -      ?<9-($ 74I+1????????..0>32%>7632>32.'.'>7".'.'>7.'>7>7>32+21&(9= L-6_A -S\k)2 OC;N**H!_U%  %Q0 XxDQ' MwNk*V@   [ +1????06332632.'>69@ LH;3:Q)5W -E\x%"@ A$+1?*067632 #"&'&54>7>6o3;/JE-Na%Z!J;%)!87S3Ao@t7'*@     : $)+1???*067632 .'.'6ŇE`*6/;Yaa*3]"9HI .w%-322>3#"'&'67>7>6*x0ʧOy#)  PC< 4 .2# ;1@%2 - * %   72/-*# 5 =+1?????*06;>32"&' .'>67.'>667632263>7>6):CH7-  =#SQ KP> "BE!  Mbk,LB@1UiF  31*KR{-Zx$*](\_] Bcw#@ #   < %+1???*0>72"&'. '&'.'>7>3h!`K0, K T-=->5r$)ra#9J ZT1!H$k)kF, 5*&@)! !  &g,++?+0%.54$7632 #"3267.#"7-/'Wp<ݑI4*4iŀ &60#.ۙQ;% QW($ֲ@f9@oC@*><@3+=5 != 1.5  51.)&# 9@++??++0>7632#"'".'.'7&54654&545>36$65.#"KkEP_)'%)*R-?0">8DqQ')-5$qՏUVb h '  & "Ha#!gH#G1 b(D=@3:70" C :7?- u ?42q-'F++1?.+0>7632.'#"&'&54327&54672>54'&#"uD;Ud3\d.0%i]26jiI'p$@8641(cB%;.,E[;-ߊ/") (J@2  qHZ^4CO 71",/#Y]Y(31@(&#1 *  *&#"~ /5++??*+0>7632&'.'66>7&#"ZiOUwyj :M EYqV ȲM lF550hMC4.'uC * 1 &ND`88MlB9L<,@$2" * 840-*  ? &>+1*+046$%632.547 #"'&54>7327>7.&-YEQb%)/@e 2l9f@{WU=X 9sV]S& S`Ko +$%2Q6&6"^w`Tp!>pDl aAHHwN0N~ * @!  !F ),+1??..0,%2.'.5.54.540b ~U B?jC]8Q"[ AC* ,()6Fۍ@ ('7y'#@ % 'l)++??.+0327632#"'$467>32632T#6^ }-+ߕPbpD 2QE_$5e '!#-Q0j ! @   = !+1??..0>7632.'.'47>7>32P$P *8! =1="V11Bc 2>  9^35/@%(%  5   520('   4 7+1???*0 632"&'.'&'676322>32>766767263 @:P *}zcddtF VC* >% V B }&  {pcrEk  #|a7+ J>/@$$< %  <830$ 6 ,@+1????*06$>722#"&'"#.'".'.'65&'>7>35!y%` ^dhz 5C' ^ "0 H*T A."$9  '+pu  hY^}+| 2s~" -f-8&  7-+@+(%   -(# I/+1?????*0>7632631.'>7.'6323>32B׃+2 $S+JPL;V2JO 29Q L%?OCVB<,[Li ##/*@")(" .,)('" ;%1+1?*0>7632>32 #.547467"54]Ǝ[h<za00  ()gA3'$+bb$ S(A   N%jJ65#@ R +1*0" '&&'>323#"&#"{>!AyA 6  (GǒO_*h@1 G+1+015!hh3#(36@*-' )  '  )z-!5++???+..+0>722#".'#"547#".'&54676$32>76m$:&'  ; ;7'X? F[_#1z:mbJ8 "  $a'a !<"%+Gi;dgV"0<@2.( .( ,& u,y&2++1?++0>7632632#"'&546632$7&#"քQ+ D t6,r`nG6\8S$kI ?D(: uxBTD]y#8Uɾ3a,| 39,@#(.8 +   41- w$;++??*+07&54>$76326322&#'.5>73267#"N &5V "Fx(),#o'1d6 yU%V\,0 : u 42: _1s .VNVh .*@!' ! ! u%0++??.+0>7632".'"'>7#"'&54$32>766 *-! 9  k5 `^0~_&F   #&%!3v;.a'bnE$3-@$%# ,' 2/,)% U 5+1?*+07&546$33267#"&#">7>54##n_r%>Z|7.h= -f8%1h?!.bom7Xr YF?bD4[A2 xn9'US-'xc3%Q" +B6@+41.) A    =:41.) K&D+1????*0>3".'7"2.'.'>7027#&5.'>76632+5@14E6#%P?]9 @v" |)&C)  R7L ,aB1V^M)7P< +%;u;q{3/5/c94G<@0' ;# D2 / ,  @ w9'I++?????.+02632 #".54763267>7#".'46$7226722>54'&#"C Ŷ?f(.>CZ1:Q!VJ!;)EK$A3>"#l! "M՜+͂!-$h.ც"Oy8;%eWnGpSQo!J;EK( Q#ܽ. qF1@#&D@+  B32".'.'>7>7".'.'>76>7>32326$y\.GD'.n +* @% 6/1yu9) . eX@ "R^   $V *m \*9"6(Vf? $PLr_h8n  CLj>Fx  h -"@% ( "  *r/++???*0&546?#"#"&'&567>76322632B3!T3P%!39AMS-pB & , RcN%7=jN*^@KT1.&1Ug!` +$@!( (D &-+1?*0&5467632 632>32 #"'.547B7!)(6JqA =w‡V#Kp&#I+'^04y* :tHF˺;//%#>klYF8@+=8+ D , &   B=:8+&#  M3H+1??????*0>32>7>7#.'".'>6724>7632{E 6e/CO"#$s{u57'n32.'.547>7V 0 8 8']: +k +#%b<X 4b((   FYUw\7@)R0V L I F 8 #   ZRN?0+~^++????????*0>32"&'.'&54665 ".'.5>65".'7676323>32>32VQk=z( RMMsT,VO 7 Q " 3  1ed+?'R*|1F%Q^,մ-  A#/#`B   ;5BQ7'$W@` E B.5(?/@$1& 6 , )  81.)!  S:A+1????*0%"&'.5>67".'.5>7>76323>32>32R 2L= ;tnE3|d0 YJQe3 / 6  JHI":7?=B) '=?4VuVA2% 3f ' %.61''1[oZ/&,@$   " t %{(+1++07&54>7632 #"&#"267>54Ns=@DpGepPB67H%TS9"O^ͬ8Jw9pbNSCAw}/-0H&5.@%+ 3"  )$q17++??*+067632#"'.'&#"#"52763232>7654#"+1!]W/UxCU_J- " i e`%3*yD=u%i\D@O/6 ^ 1Gy@_@F 1!/-@"', .   ,|'1++???..+0>7272&'.5>7#"'&54627654#"j9d:/\FF[7.'.5>763632>32:?  .F'/ 5 L@2# ?!L6" " P[n=tU. 3xH ) B'DK@B@;75$ = ',=**   n$@7k,v;/F++??++0467632#&547>7&#"#"'.547>3232674.&(6:qS . 5Mg<' !V!PJ\)Wd gBT7(^l Kf-Y@39\[ho, (8 A5='D& <*8LzbHM3"$hL$()L3[31`64@haXsD.@%'%>  A>;41/,)'% P F+1??*0"67 #".'&#"'>7""5465.547>7>7>7>72V?  j#Qc ))/UktS bP E D@; JMX  %   %8 lʚ 5) 0x,y &` 60@!05 & #    0-%t8++????????..07&5476322632>63232632".'.5467#"] - 0 [. D 71  8?' e`9fw(8p7p j! =!  1wbRE^%(@#   O *+1??..0747632>76;2632#"&'&&^," 9  շ$A8 u * '-:M]  !);[3  7GI@8D63'  A > ; /       DC63/'$"  98I+1??????????*06323632>676323>32"&'""'"547".'""'63212632> #Td}# :&P ' A.'H0%?&   $A i !u8H - 78cE3O!K92@&4  1 . !  61,'!  J&;+1?????*0>7632327632#"'&'.5.'6323>32s6r51 >#); . Z   Z4 7 O66$ B (X-Gdr $1Qnb6*@ 30-)  32$"!  E8+1???*0#4>7632.'&547&47>3232632>6Y`D1?  2.7 @8# (9 ' eenvT  C4F9 # ͤ®XR&;G-@$C@$ 0 C@520/+(&  L9I+1??*0.547>76322>32&5>5.5>7>7"=4 7@c$ 4-f!# pGN3=)MU!'G'/NJ /   + # c9>  * 1 )8"C##RDO(@"HE?862  H;32 # K)Q++*047>7'>5.'&54>746?632#4&'&&632 DYgcL# l/9O.0>Y}VL p"   %/' &s:  $"LN8o82%0H&E;:"L!]P.4vT77@ ]+1..0#".54>763238WP?sR46AoN_QiVi##[W@LWTJ@=<9+L 20-1 O2LZ1D 5 WTQOJD@=<90+ H 5H&]++1??++0".54>3232>54.#"&54>7632632.#'.5>73267#"hPmP@uPronqTr@(T[ ' "=H  :X 1orB]OgRkQs>nqqo@p),rtZ  B=  |1 W8  @V @  d "+1??..0&54>7632#"&#"267654VNCzI!#6$WJ% 1N;,9-3'b@#$:MɐpSA 2CP?@ Y +1..065>5%4&'4P' V   o )'h@ B +1..065>5%4&'4' n   )hN3-@"(2! &i2i!-5++1??..0#".547>72#".547>72 #0d,AxI ?5u#0d,AxI ?5u(!@2O+Fs@8&1i("=2O+Fs@8&1o73)@!+"2 %h'2- h 5++1*0.547>3#"'4>54%.547>3#"'4>54'V=5? }W6Z0'V=5? }W6Z0="):./*2Zy2F3="):./*2Zy2F3)N@ i+1?.0#".547>72B#0d,AxI ?5u("=2O+Fs@8&157@  i+1..0.547>3#"'4>549B&5? {X6Y2? (&./(4Zz2D55'FR;3'f' +7d'sF P'FPR9^ -%R F 7!7##DhPD{+qPB\T3H\X3^ {7DTqf5br d%bPqqf @ &k#GD-2.50/t/test.out.8.png-20000644000175100017510000000702312164634363014367 0ustar lsteinlsteinPNG  IHDRyv~PLTE___?????__ccGG77oo__??OO//77cc> PIDATx흉8mLpd3;{ nnU*jMBI^RJjOmRA$J~n<ܾ[ӟCa0O{LߑL >7u|]y7oe0A~0gB-)\k7;swΧks=h^N[D>ʥcCss6p?j{qKDA.tb.7XI\LAF{gR"luxI ~ VVAN$}]S 7ݟq:XANta.*sۑ0vWrWDt#։ە=c{? )x#YW7]Sh! ɓ}=g6;F9X4;VQ틋V.\qe:'=͏cIƜQ׳Gw9u'vt 1GMXA/扷tyy*q#4r"Y^٬( $YAP]/d|:]O98;'kV`> g61x5]̿Ƅ9tlV=֍8h%('vdyF:O}3'I?(mN6PE>zℬR,T-`&A zmKbB/%՘4kڦWF8ct©\U|'f@ z,:X'\ڢ$z<$ Jg,e_k%u8: D4uTAFW@oS2i!t&2OTW3ebG-ч8nNl|)L+s 7ݥ0Vr+_9͗\, UűL )MvBdSsyIY&0fHw()iIi<8 #!B7r%J7?>9pWB ]tˏ5*?hp RJbGCt( 1(p/+E{"QB)w!0Վ|\He'笓7\n6_0e0C&O^E)WCY _amsFV0]xD8 YI,bR%; XJ7.aP3٬*n\)W#.Hoȱ@XFQ #!aAnk.v=C^7D ӇÊquFT}{YI'[9JL8&48`*OEROW &;d+ɬbi6+Rq'# ΦB~2v :R0Y)I2n,VElvFvS!S^<Cǒ&X #M5g@Y#/zM{MijO!暴| '!<̋rXjԾ0{I%ULaA;Vz?bU"9#b+|!{R3+.3WKg8a'ıqObYt ZS0oobnHKp23US%PNKSWa'wNw` |NqW&嘜2qrnY>UzDv(GPsvYvvEӋӤ'x:ϳ-w0UF?>d*MXP[\MB5 Y &wzDTR*fIZnY=:e\:8SIEoyQ Xh1p U &'|GDGsUaӏtB,=^վfT`O`)(!$/d#5=,pd2 H0W,J40WQ7˳%#bCk0AAZ.Zo%1IENDB`GD-2.50/t/test.out.6.gif0000644000175100017510000000615412164634363014213 0ustar lsteinlsteinGIF89a,,!,,,0I8ͻ`(dihlp,tmx|pH$q)L:PsڌZX u[z^GzȮ4mK{}we6 3-d5 1 )D7/"ǺȫǫŔڠ4ӻC츚{B6zXJm@/ !'rNTFVD%,&AD\jO#O.;3cGz7*魢F!\h9)Yժo8iOWm_~sI-1gqQv.nNtEk 8>D10ƍ?Ld-{e9`ΝC}ZtMoF}c0 xNص*ctC1D hm\ؒʙܜCuف>pyzڱc~GDw|^xDGB5~g߄> ^X߆iw!w *`{`3uh!"@e&Xr ע0d/r}NhcLGe#GF')ݓ_MF#(%UNCUdGIfmdߠIߏ7P-_/CggrH"um⥞m*lZuʨ]iliz`ʒ6֩ i+hKk2 rmZY`V"be^Fn(E- /P;缪|-[*V+/+Kq gk`D|'r3mJ:ۯS{,׿7]?;T<*X\{S;OO}wV~7?o_>ֻ|?zQj?ˁ|&@ ˠ=yp3D6vh9a|GC-/~b. Qy| X|0=lah+bE`$K2 a!tmэ*9HG1wxԂG5nym 2BT =ҐD" %A#7I3R5hcXJkE\%+K+ `y咓^$( Y0YhL`z}4b&GVF e)Il~2Ԥ oBa7iNtJ3K$9Lw4%ӖJmnl=99Q%f F&td$9iiҙ/hQ1'Qi˖u,&HخiU*cXwBֳ Zhcfs=jD+=e$*V]nh2EgbF}-l]6=:{3|mfyWҺ].^zGCj_h_b|΋W[6#A\pKC8rT`{pt dktK˻']+Iڔ%sa,ּu 6#ɶnw6'?y~޹ pZoypJ-8=k\ϋ +vKnr} Y([~mb)|箎~\nD/:+P+ӟS0TW uO=Fs/':Y=f`.;u#Z{=tkz߻*/ނ`xG<ToCݒ\/5^\|3v}Is|ؓj]~}6;z=}/^yӽJO~YOkW{_+޾1nbzY|W|+P}܇Hr|̶~}|?7w*m/lȀ$3~8z)жg@XsBx,\2xFyc#S=cG(*ȅ_q$ׄN%8헆OgnxpֆuvI,fZxdhqh&FVH`2syqvtLj\'3RSa>~([x'({(,x({؅v*h}h苷sɨ(؂t؊،x즍cm)a(YȍȎ(H&(#Y"눍aw9h:8|8 ,F@^xeɏ6pKI,ْI[H`hy}?u.w=vHJILPR)lN9VyX#\ٕ^`b9dYfyhjlI] ;GD-2.50/t/test.out.5.png-10000644000175100017510000000117512164634363014365 0ustar lsteinlsteinPNG  IHDRV PLTE͠?[;)IDATIn0 ᤹@}'( tCREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!222222222222222222222222222222222222222222222222222d" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?iWoi\\>ȢNdxpz=xMa1o'BְYb.HaSZФ&vrF:߲8}3lVs]mrYd*<88l pxM%4gv+FЀv-RWkB[?4 :x Jjf^|Dܟ!hs$:-x}XB&7R"(w!`/lD%HQ!l]])#qo,y98ÿ)iyRo+.H_*v.c<7JFAdY;85qtcLebSk"yc*ܞ25Ek uU_0?xz;w?ԴKF[}SO:u DrF@`2ϱukW 2(5 0<Ԑrr6B'smw"O"K%m!#0sw zqpχ8|Pz8:( 㺷1y <ҋ9@6up$y XoỴ`T/, M2I$sUI;J2n[`+(((X_iN\ےE<WdJӵk[qBVŖHmU$ ~P+ƾ ѦѴQi~#JLXW,gn ~1!  K|S.-5O$JsXu#V>cu1++rLu|t?>Y4m˶hx+Wfqmvggu4]ފG32(JIDATHmT]H#Y2t=(! D_X4B Ch nA%IZi[3342 tDhFBb0 iK~gž[~wsnUH6e3U\^3?GF0_Z(,ԇbdqdϷTc P>L`=q*83!\0f q/wy>LHBtwwQ%Kx E|ϗHӾ~H^rBe 9<H&Lv230  Hwf4L C0"X?'bt4s sFg@7u 56ٱf #I9}vvgnP Jֱ~6l&bj?En -)W 覑BWLky|3}2T+qE/JvaEQ7[hq w!+cV0 C'+s$<=IX\ΡsBPZwwy?XH0,}yQ?+p쩅X4eNzFpdn\zWb]W-Pd #۝powx85 cv\u@VwG]j*(*9qi?^/X1=8YڒmlɪlMUSq-.g'O uĻ(ksx)&%-%pJq"O`@9.xi$t oO>"s#W&`3p [N4Ag6SpE8Ƙ ͷ 5) a]RRJk>zEŷ VJDTn(Bw"HɪIbg<˱ fbmOt۲n\;*ǜ>{L1Znys[tM]:6{=6X'x]E#jyD;<端ȫoܛy< OO. 1{m^Z*6|ٗ>p6tfU'!ZR]c:Tl6y gdb=R稥M,Vsy=xϚ"ߤ^Kx9Չc_ B p8JKU89-ÊRdӯwkFyD&-{v FOpUEXb ..`Y 3B  m pD^ ?ѓ`=dmJ(=nmQ7?;5|I}eSlwkQi4}t=p ݎRZ 4FƗ=aycRRJ&]}=k`C!AO/"!LF%IF:{ j;9lGHϷvtwL~ٽ'(h I wc`vct-4xA0@ d2<ߖ1zp6V=n)~K`xe~0^ms :AԩSRę {Suw;uCN꜇"ߛEJek87}]lcٌ ]%+naj5K]:&5)0L]M&ǧIf 4йT?3ԭ اbS1f3LvS3f|F9O͉u-@o}Y;5rf\yOऱ*3k3K<52#%|fS#3D@OH3`=0ǣY2\{Qt{5c!2po)Xvm@=tr(zQ#tNBTm]/q9̖ dqfosC< ql Yy Fx)mv 2H3j3{pfsqfM9YIf +7{̔@3ʚIT0{f0O]శmp2=콥܇j; &?ҎgOxYz,"W%l3K<411 Rh80")3Z3'4<6}H!@W3\"-yf\f@d{3zDYEH̼Q*ѶcEQ̤{-T?iS\b[ˬp)b&(MܥZVԨ`}f_zYW k]$t)2㺈Q뷂\4 tL1XJ'a:' VbY,ku f)F,$Z<9asus K9YՆI>:H}%V;Iǎ6,Xm.Y[jr[o@sN29 x^<sL+,e'S>BXb,%,JĢ8Y+bIV%,e$^%'IXh'Xy'K1,$1 VI"/lvB*BCa!abapN"PNgT,Bb ,M|mXdkf¦Y>XoU]kX73n9^ުeL`!܋nگ> ϗ" *uOA|uH"\c%Zyc%UC:v(Cl?8_WֱrwNy9'f S3G/|]Q a9{SH,'KXR;9mW$KFXcQܰ4Ywִc{_SM6, `f>VU잙Xwf󰪂cߎXXu(EEjZ@՝?vZXU]kV͹h,99MŢ&*~X3$L(P9,ߛ`^< >|+!$|;EJW[R^Z,(`pc<ޟۖf5>\<:}K Fϱ'}&K o+ۑNr-~2_8WWIbm1)<,-X=ZRX=&,bQV*V,Ja*E,%,J+j"jQH~N V,Bċ"d+GBZ*īt͊{5+V>XXxᓢoݭX3 >+|ZN$c^H"V.V:`- `B Xp ,LpX۱Rw"B,ہCbskFdo4lDˆIw >p$õ߻oiʴncw6ZAZ olno,CVI SQEhE-Ii%´xh"G+pjBT6Rn&&l2ks9Gʄ;{{,A .s2|c"?LU\x5>U/Gc9Jk U"VVňר~M/ HXYC^3FqY{!}h]@ZPQJGԯ JLk=TQDL f娨y%Vb;+P1^JHxt<OWL+,䄫'~rO+a_}Z`E*.V6X'+ I/_ꨢKaOZ`uTQ띧OŀVUbZأ ^i3ߤ˧Ub%ׇ ΟBkXZi*~3-D'xb7O؅RDK$Vu6?Қ*Nl,W fASW~Q:b+)^NcТm#b@hU<eG32(,00?ɓrz ؔzL P< "arE)Z2,^NرA"B Of E%24藠*)BҦӎyvB d ڲӧj٣GY@Ueȋ{lZsx>A(R(l͑6YѠ<^Q;$E0@"SHx"T('8b.Sw#q6rʂ c! Wcm*!1}~XNNxP+_ꩵK$I#v @"E1+?d' L0r!YGIBICLe/h+לVBqU"cHŒe Xr' \' P!p bq bP U8b8D# /k0A`xc J u+P@F @xl80 ю#q# ,7]AԴ p`ȱ6a;hj` ~M<`vG~0<?A>.354U]lqju(zt`&8LT@&! 4 \Pv\P4!Ih8Xb+ @r,2[?8 ]btP$CqT<A Љ.H o{ۘxc X)6a#(E7𲣉AX l0x Pd Vxӄ)Ta aA6B;8Uh / !L KPlm@X7G#x @*,Xgha21IrdaNahe7|#: x=ంQhB`0 P՝c0P+ D >ta+ )>/ahz./ * 0'`.2PcKhB0Gq@ Ѝ'PaD'av`aX;19` xDu;Z8 J GcfP( "D4Z ,XY ,#TX AT#@pkb Ġu̠,D [84Ђfpcޗ 7 PQݚDCGC403-0hXg aX1,aЀl!{8n=kHs%9hu`c s6 B83 Ѷ̀l 9DhZ=x# @8 f6MDgF p .wʹьauhZ>? oh tЇ> L`B*ka܆4qYGZF s}:'6G5׊kH1I^TF7{'.i}eB@;GD-2.50/t/test.out.8.png0000644000175100017510000000657112164634363014237 0ustar lsteinlsteinPNG  IHDRyvPLTE͟___???777;;;///cccoooSSSGGGwww??__SS77ccoo??__ooccwwOOSS''//;FH= IDATx흋rEjttzo%YR hҞM͊]HQǦO4a+b~Yj=̀ŦVwj󥩶ГuvUmWoj.9ؑnߡ Vj &nofϧ6^]i?URKe缪>NAhɒ٦Btv[f_5ͦZѬޭ3U_7]W~ͧDVV|| }[W;kVV%6WC* ٰ߸S c]jٺ=2x9kV? QkvdU-{{Ru;dn,(ZcO?k`dXAv =BqNRi=VMa_BYSl6%5HBff!p#eill=5iYگsq8>p7TK}חn95Ʃsyo4 >W~X<  2`Ǒ[=uz/K]_ϩqJp//tpq+'|Ɲ/$E\V +dm75d={V o]|~IxxXuM2:ϟ/V.pARpqΟ&`mdHl]c9_4<>n/+ L՝߱r|P}O/p)dqp~OvՒ> M?B1G9 D98/}R9q=CazA/`O|OB*dWeg,a#`>.|@{|yޅƛ—؏vrxv]lj[%x/)qjՊt~حAO /h| \7>TmdVA* #D mzbL"fei"mF프W3뢷A^?K8AOX' ȌWfxUexo!Ktǧ 핔pei{.I VI)?ڋ bT%r *&N 0SM2-,kMU,߇KAFqtp1U0NfH)LNy;% IdCh$;B]5BtC# =lMíF>X%Â7M/oY`fC.t;PV1p9V!M;A {O2'&hq'&4J+彸L:$b'`1l%uZ "q[yܴAEM܉T]T_FAq܊(O B0FAf}b=;N2? &3 wL|a%Zv`VFLb1iN"tVJ\ D"1u]_kYvueZ$PF$<ϫ'[!iZ]3f`,K V7VDLɓR钉0b`0(Lz&7˴̨X-Yv$S*I ] \9Y`Rȡ[ VqZ.n?BU*" G)Hm%x? W>&V"X>.9ܶ)L(]А.FI !sa)15C7`!WD_Xߦn|k8HMGJQ*'8욒mCC$-m=17!x-`|FhO BP/ﻰPr,N! o/J!OK!zyKGIF_C3GK0j Qp&̍M6_I]30 D%n>T0WY-qɇ12q-q<9E' sU^%Lk<\v@v-U!H.%7KTKJ=]{ b\sUdk(ē'-+}d|zS; IENDB`GD-2.50/t/frog.jpg0000644000175100017510000000302312164634363013222 0ustar lsteinlsteinJFIFC    $.' ",#(7),01444'9=82<.342C  2!!2222222222222222222222222222222222222222222222222200"-!1"Q2AqB#3Ra/!1QAaq"#$2 ?Y5Ɗ:h҅2j|Қ{:T mA]{ϟkĩYkjrJaG 1:Ag%GfTI#pVg}w.x0F_r4ƹ,ݭ \b A9cz5m:+k1#|M{ebZdJQ,eRC$ddL$yQÿY|Vآ6T7ZeEpg$#C[D(*o=BڊAd x:m[Pz.<4 "1c*Kvxy(m f"˷p ;S]9Y q<IO`2HeaCsݐzzQ 0[;q20+:GBk IhxxIpӕL{64rCl(wFOrwPTT$"H BRJJn2 >5ZR $-T`ȪKc8>ՅKKeAdaT=yypԴ}0 ;X4lݧ-{UUHeNFꝺJi- m=2J 'v S~N%E0ƱDApzP`;=t݋RFGD-2.50/t/test.out.1.png0000644000175100017510000000236612164634363014226 0ustar lsteinlsteinPNG  IHDR,,SFPLTEܸ L$}IDATxڽn@`R5q EԜիo7{g490$%!Mp8Sv܆)˴m4mQ#Q\U._U+T_+\vq+R1b\c*j S+.ڐJT >qa*R+.|\ ڸr[V(kǕ K/1~\`e̥₶5F5 kU.֠2ӏNN\,R`2,Z\ -JXӈ,ѡ]EXNÜXɰhVkaɸ`ZqXaMq[X,HXS\XѰƸ˕ӡhQƸȲ7>"rua q鰒aqYZ,r!bth`6{:ºX?,R\Vji2:ZڬE=du˳\dZr;u:d:v_Xټ!,?#Y'gyF"tYpKYded},:miec?'uez J 2vx27~sV`%Y;b5v۫U)S2{o&K!vZU X{Ed%KVaCn{)vvz$+٢ZY;/W VEZ`V4.,w1VzVEW>kX.xJ`;ldZ"Xru3 %° %| m-?z8oэK իd\^Xfen?z?'_XErTk˪ѩ \EenS8Vy2k z i< 55ĺbc,Ea]p̸31WeX{NAhɒ٦Btv[f_5ͦZѬޭ3U_7]W~ͧDVV|| }[W;kVV%6WC* ٰ߸S c]jٺ=2x9kV? QkvdU-{{Ru;dn,(ZcO?k`dXAv =BqNRi=VMa_BYSl6%5HBff!p#eill=5iYگsq8>p7TK}חn95Ʃsyo4 >W~X<  2`Ǒ[=uz/K]_ϩqJp//tpq+'|Ɲ/$E\V +dm75d={V o]|~IxxXuM2:ϟ/V.pARpqΟ&`mdHl]c9_4<>n/+ L՝߱r|P}O/p)dqp~OvՒ> M?B1G9 D98/}R9q=CazA/`O|OB*dWeg,a#`>.|@{|yޅƛ—؏vrxv]lj[%x/)qjՊt~حAO /h| \7>TmdVA* #D mzbL"fei"mF프W3뢷A^?K8AOX' ȌWfxUexo!Ktǧ 핔pei{.I VI)?ڋ bT%r *&N 0SM2-,kMU,߇KAFqtp1U0NfH)LNy;% IdCh$;B]5BtC# =lMíF>X%Â7M/oY`fC.t;PV1p9V!M;A {O2'&hq'&4J+彸L:$b'`1l%uZ "q[yܴAEM܉T]T_FAq܊(O B0FAf}b=;N2? &3 wL|a%Zv`VFLb1iN"tVJ\ D"1u]_kYvueZ$PF$<ϫ'[!iZ]3f`,K V7VDLɓR钉0b`0(Lz&7˴̨X-Yv$S*I ] \9Y`Rȡ[ VqZ.n?BU*" G)Hm%x? W>&V"X>.9ܶ)L(]А.FI !sa)15C7`!WD_Xߦn|k8HMGJQ*'8욒mCC$-m=17!x-`|FhO BP/ﻰPr,N! o/J!OK!zyKGIF_C3GK0j Qp&̍M6_I]30 D%n>T0WY-qɇ12q-q<9E' sU^%Lk<\v@v-U!H.%7KTKJ=]{ b\sUdk(ē'-+}d|zS;4IENDB`GD-2.50/t/test.out.8.png-50000644000175100017510000000641412164634363014375 0ustar lsteinlsteinPNG  IHDRyv{PLTEߟ___???wwwSSS777__??oo77OO__??SSoo4z LIDATx흉rItr]$ Ab7?aq<VWG)Z}fUwaxwxӚ?zs!zn>?+vfyny[o?c{)H=+ȺAZV;dZXzh_w/nuP-vu]mv>lҶ뺮X$,ʯfmEK|x};/uK{X9bӴf!=Umj-Z/d-Ξ?udFfx}M۶ j6dt.־.ZO8ThY0[i0EQ5ḯv<KZi+k֎x3٬CeZJV-Z~CN޻%=huy d֕j[W, i)hwk~K_$D<[F{=kMaaPx{nwb͹-58pko9cs W4͵76wB=7`;IK#֐\NP/s6 H+YS\n$NΑ&JGK܍4Me4 ߚ {,3)ǥV'.}xuYpc's,/>~?g /r;c3aBG7BX6߈Ɣ{G:E|zW v *>Mƿ++ V "9lBhb-.!CGd2$a^>MBVR1<R[=і DCd%i|=zGIJi(>(CE|Vb7 G B>JD'.P`Ũ3,+Q!`8@jYPQ=GEK2גsiC (x;!B!A,CV'QpTXYL9r'!EQ["\YGCKg%}Ν(q1>+!:>ίˠ)rG`!txznj0 ɄμcĺIV_iM| }(I&!jJ(DVz +D/ YYa:;M6m4r(uAPTF)B^Tـdg&QTXcW 1Z2| v W&bQHAYxl(9 ׯ*M6UT)7ZIYƊ=T7XϏDൃD Pl:pf{e;|/1o7+;څ$u'\Ӄ`i l=bчr lcRnMV:s4owt5Nn˺>4)J.NX iH.H4œs{8ʅ42鷧G~b8<:b.3"S6ĐLIK y3ёfJB޲%FͺC'h,ʉCW;GR ^B W."""$}5+v1dyrOlaࡗ@ /kt,zr sG!2&a/Kō(!ԶIN Ɋ Bid.0o<3(ΆXdVr2j=LtA[O G> Xg"]xR8aħ!7/LU2<Nv4=i[GI$ miCT8d'ӯuOZCC/vifY%y)gFr=8;tKH$#d<⧊ a=$I Q#[%V*z­cjxOnRqe%z'ǃ eHz ›`2eц[>qwY>߇h9X^$# g!(VVT4s{sN8Mg^7F ʁ&0ŰOT ;Q%`ALVԋ6:LZs\ ՑtQrya !<͋a6>^WU1b!K#}P.| 8VJ\{`{jM|L|B=|3`= IENDB`GD-2.50/t/test.out.2.gif0000644000175100017510000000553312164634363014207 0ustar lsteinlsteinGIF87a,,ܸ ,,,0I8ͻ`(dihlp,tmx|pH,Ȥrl:ШtJZجvzxLannzNixn{Dm-1> Nۢ"dJ ( dKֶˀjV;/S#'/pz2[%k 2!2+Dj&+ 39;DokH/mҾP,sƸ RrV4]K\8[|mk, G&M|3p8s9񠽾S^9@:i;ӓ+y=k7=X~7"ȓ!H F"h0 P!{h£Q+ o.p|Z%=VZAmRN3Mھε+pڏ浬 <ڎ&tu}fZVv{ >{`jT v-n[Mv3 bp[p3n's;ַӝ[[v뱭x+'8yL\eF#~q~C'2'g?;vnn:֬nKo;6[r[f}rK5ҍr.z+K[t\::؝u0G>{]aoq}|/??}I]ٞ[诺3?=n~R}oywg ؀WwN瀵p 8o HhWzyxz!&ȁ%Hq#{+xzg1Wx7x7ԃo@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXf li8k؆ojȆu8xhpz(w}(tȇy8xh~Hhx38Xx؊8Xx ;GD-2.50/t/test.out.2.png0000644000175100017510000000236612164634363014227 0ustar lsteinlsteinPNG  IHDR,,SFPLTEܸ L$}IDATxڽn@`R5q EԜիo7{g490$%!Mp8Sv܆)˴m4mQ#Q\U._U+T_+\vq+R1b\c*j S+.ڐJT >qa*R+.|\ ڸr[V(kǕ K/1~\`e̥₶5F5 kU.֠2ӏNN\,R`2,Z\ -JXӈ,ѡ]EXNÜXɰhVkaɸ`ZqXaMq[X,HXS\XѰƸ˕ӡhQƸȲ7>"rua q鰒aqYZ,r!bth`6{:ºX?,R\Vji2:ZڬE=du˳\dZr;u:d:v_Xټ!,?#Y'gyF"tYpKYded},:miec?'uez J 2vx27~sV`%Y;b5v۫U)S2{o&K!vZU X{Ed%KVaCn{)vvz$+٢ZY;/W VEZ`V4.,w1VzVEW>kX.xJ`;ldZ"Xru3 %° %| m-?z8oэK իd\^Xfen?z?'_XErTk˪ѩ \EenS8Vy2k z i< 55ĺbc,Ea]p̸31WeX{G32(0ߊIDATxmT XS>Ŀ:U~$2 hpg ▌ECb"nOhtZnSeb)86թ-s}}{~}<Zv}WIyV+y=|mV,l LaO N[:v6f;npjn7nhj˳4h_mOlX-]ugrlVr46]/"rsBP}˅!lq1ONˆgMC=77n$:yr[@!E|VVVkVA]yMúp&"ȠLN '5 VU&|{kVʦ[8}:y]ܼJ 궶ի>-b<ص!E6\w`iK9r:qۍZn0VmMujv!l=ޑv#7{7p3Zc-qn㍖~/۞(Ε46G{n7Yw{7n}w-їaa {7w3qjI D&9]uu/y'x/OsXtiX bO f4׮31Ղ׳'ZPa<&)b|T#ˉT=nt΄WɟffS8^!ݝ =j^$ǣ~9իǛ%8pv{{ཁ13PbԦj!0(ynNǯF C {` Ff2 L Ё+0yGH,bEqqTh&xAzRuzσpyU&65Cű9_I`c$l#  #r@e-ǎ5/<֘_HgI6l% ¬^V߯psv疔@% "4V4pK`J%'0QrSX3I#RL& KL$U_xU߈B` ȷW2`N. *6 @xL N:2 $=^Z"u(e b9?\^Nc~Cr/;^82)| N u2!׵x|ba7Ѝw}sW7pN%gIm oX*~,0!S|^4|( >Nu/0_T[/JaːX ݇K47'\c(dKSBWǒP 3p}2s_& /&)dnTsJpϰKv=^ܤ;QQ!$PoG}h<`ĥJ)tśVK\+ܷ&wŹm\wЮ{ S r0c0_)xR)1J R6EmUT5f؝ )йvsoc杊]ko5|pgެKe"Mt‚Ec VT_\P(hZϐд"D*+];?%.nE-rj E94]VUfPt33sپf`8RTԟ37tNΓxdeo\S54T4jhpUU`QE1:*)PH'$ ,*,^UV&eeejDkGi ͗Х,  PC(zE{/ZLW4tict4X*IMezTﺯ^7lY1i²KsB5?XTD2茜aQ.!!9Aij3,H$'FϠG32(JIDATmT]H#Y2t=(! D_X4B Ch nA%IZi[3342 tDhFBb0 iK~gž[~wsnUH6e3U\^3?GF0_Z(,ԇbdqdϷTc P>L`=q*83!\0f q/wy>LHBtwwQ%Kx E|ϗHӾ~H^rBe 9<H&Lv230  Hwf4L C0"X?'bt4s sFg@7u 56ٱf #I9}vvgnP Jֱ~6l&bj?En -)W 覑BWLky|3}2T+qE/JvaEQ7[hq w!+cV0 C'+s$<=IX\ΡsBPZwwy?XH0,}yQ?+p쩅X4eNzFpdn\zWb]W-Pd #۝powx85 cv\u@VwG]j*(*9qi?^/X1=8YڒmlɪlMUSq-.g'O uĻ(ksx)&%-%pJq"O`@9.xi$t oO>"s#W&`3p [N4Ag6SpE8Ƙ ͷ 5) a]RRJk>zEŷ VJDTn(Bw"HɪIbg<˱ fbmOt۲n\;*ǜ>{L1Znys[tM]:6{=6X'x]E#jyD;<端ȫoܛy< OO. 1{m^Z*6|ٗ>p6tfU'!ZR]c:Tl6y gdb=R稥M,Vsy=xϚ"ߤ^Kx9Չc_ B p8JKU89-ÊRdӯwkFyD&-{v FOpUEXb ..`Y 3B  m pD^ ?ѓ`=dmJ(=nmQ7?;5|I}eSlwkQi4}t=p ݎRZ 4FƗ=aycRRJ&]}=k`C!AO/"!LF%IF:{ j;9lGHϷvtwL~ٽ'(h I wc`vct-4xA0@ d2<ߖ1zp6Vqa*R+.|\ ڸr[V(kǕ K/1~\`e̥₶5F5 kU.֠2ӏNN\,R`2,Z\ -JXӈ,ѡ]EXNÜXɰhVkaɸ`ZqXaMq[X,HXS\XѰƸ˕ӡhQƸȲ7>"rua q鰒aqYZ,r!bth`6{:ºX?,R\Vji2:ZڬE=du˳\dZr;u:d:v_Xټ!,?#Y'gyF"tYpKYded},:miec?'uez J 2vx27~sV`%Y;b5v۫U)S2{o&K!vZU X{Ed%KVaCn{)vvz$+٢ZY;/W VEZ`V4.,w1VzVEW>kX.xJ`;ldZ"Xru3 %° %| m-?z8oэK իd\^Xfen?z?'_XErTk˪ѩ \EenS8Vy2k z i< 55ĺbc,Ea]p̸31WeX{՞Sv7Ͼ^*ޣہϮ5S++w;F;~Go)فדh`&osNG&7,ڍA~wS>D| G%lh3=f%x|dD}L}<A ~@W8rܨ7';H[dwabGݍ#L'z&"#1{GKֻA=8~TGOakN>6uM>]c/œV XO$w+C䂢 -x[map{ R?ѩ { , ~8thrkW\j 5Ov罃Oz{Mى-.f݀w'=xh7B=W0t62b-QovW{h;o#qptN?PEdoA/}&{clzkI3Cm@]v;tKSWCnG7RKiZ՛G _zcT uw]WnrwtՎf_\i^f=W9ir~KNݨN5,ˢVk.A]'v.kIKP}$׫k4v*>_"&W,} w7|-B+-kL= dp]KVv{nj_즋I]OYvv?۰KulSV˛j;N/{*b? of%rʮV4Kھ٥% .I yCtʼnr$^/_o=mpy=O\פnV?2&۷kbWx]ˊ3',=/e߯ھU{3Xg?"ras=({m:ꃽlj{j{wK5nti?>|g6/".>n͛cnqX`W+.\`˖ ɦR;!B!B!B!B!B!B!B!vRdT=IENDB`GD-2.50/t/test.out.10.jpeg0000644000175100017510000000354412164634363014446 0ustar lsteinlsteinJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!2222222222222222222222222222222222222222222222222200" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?$.-frr8QOQWE%+i?qߩWnka}U=Pq2rH5_&o^LfZۅ̲IܝIģAEB4v P8SS7?WW7Q8rGgG(EEfGD-2.50/t/test.out.5.jpeg0000644000175100017510000000747312164634363014377 0ustar lsteinlsteinJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?((((((((((((((((٧oDMXw0@}k֡e}oc7R*\EWhQEhk:gEvwvݸIv'g3JϯX,XEeigJ) a"=UGP: z((((((((((*{kfu4[[4胩UUE tBWM;­^]નT`+E(Y#wi2F>nYT7fH}k­~{>믮ݑZa|Uiw "{{ $dCYu|+?(xz]wg]Ҿ =#QNjq ?a^_GҚgVk57nxǓcݱQEQEQEQEQEQEQEQEQEQEioE _ EzαJ1D{8v-hK/S?U(/eſ ?%~Gjnf?aIrzOm6kw4a,-渔19*PŅ3du,RLdy,eA=!Xi6RNrݚ%ch-6kF&%W'%Hhu"q?C}PQk"ē $r$yUc9*(((((((((((((+f_kWWC²訨(Osyۏ/ŷ9VslOM/hڣ4~EőE bx1*ǧp(eg-Z,HP`˹ :w>hknͮy" s$gתKᧀlƺ%ZH9}ۂ WYxmZXk;!E$Am"Q<_ޟgWoKVd}SG+,m4D<"p'N|#CN?9 :' "⫖NrܥdoXGTstOET7N|#CN?9 :' "}۞n巸&T)$r(eu#x 1 >m߇ɽl1ޱ\Ӣ/*N|#CNa;3> )iu 0HRv69 W9_i/[oqMh%BG%,` `;W]gͻM&OkwonǒTeraZIJ*ˢi-Ս2Vk+7\e'pl3T+((((}?6E$5;w*XY1PI=&ۯ> ^пI䯯n$Ӽ;~gG>WpF:#WWO4 (((W,H>zRU4JYrSo*QEŠ(((((((((` F_Oϟ4ljn(ȒXXUIJ Huw҈+7?|H4ˇ X)`=>$(459r~w9Kc|>&I^L4"MNl_϶Xa@QD0o k*([_QEQEQEQEQEQEQEQElXĚevv m-c`4\N OV?; z f⫟:NaC^?; z f⫟$y%I$Y$I'tQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@GD-2.50/t/test.out.3.png-10000644000175100017510000000623512164634363014365 0ustar lsteinlsteinPNG  IHDR,,TPLTE1tRNS@f 9IDAT[& g >7Ч70Y@UyVb!nnO?$ ǯ mǤL/6MJ_mش/ߦ?l6MٞB۟mm*i킏͟c¶uWC`ۮm/ `~Xo;wƦ`AcSz&l B~E~LmL-{c[mJǶ?mKېn6NE9g|uo{<ۚ{ͤۑYζFw yxhS(% PYa3َlʳiMr!uTAL8VjL8n/Ϲ)OϹ69 J97㕺u;u[ֻJܴ 877ҧ7o ݕ )7jo}ss fz?7B; v\ZDn%n[̾ESsktR n»n0`IsmdJL v[Ŝ[pW䶉9)鶉nӏW;B#m1=mg9f_ (;77oj仩%znsob-qt[Dnv^mp.Kƹ%p%vc^pnT%#tZF?v{dns27ILW8[^Qj$`P-ź$Xtw]˕W9׷{ȔylkTmw\ci2ćnSQԻQ5R*:8sJ[TӸ͇KyS[j!rSvVx77ylmdn?CM"s֍TMa7Ÿi.hn r-Uo#/즻uZ듛X-KQ[9: VI%*TsZ;EkU"i*S>B- Y0gj4UL h!c(}stN--,dV~JχUwք2˞v5٭ B m` Ǻ302JlY9Kk jh§HUxkeOH՝?^UZUghUejE*?c5}kS\}kZgVtRKT2-@ :fkR}ޏf-Z@*>dR|ڢS"'W:.jj opߏN&޶XCf2fZgsvZKk @ViO9/UZgr-lnR^i%]j׺ke{DT{xr'#-f?2X+߻Vw%jP!%ɴpT?|OMFHGjnZ!oR(׋D4H !}VNmϞ\JO_EZ|ZܵZ={ܚTXc4hiҳE+L| ZD_VXuժ :~J-觵7FZޫqhc.i-F ==L k%DosZL*eZ}UWk-٣Yg]t V!u`ma0%Ʋ 72D1e -ߍEm_}7V0Mk|X.%QR. &aSt@-~t%dknX_Z/ >j5'L.K9KOiŕNJlGre*Ł\9,EPQܹF<,d{=peh*ŝj,*(I/L cҋJЏ0rX8b2XڣJt E(2XdEQ<]i,v(.,?ݓ>ppX"N(&r1ExV6Ʈ V&CߋXϋ?brTQr+,5 nx'b,"D2߆x 0R?XpC,ocFXmXrlac62GF)uXz^!y  xkQr=/ؗ'q{ VY/H*⥻%Q 0]7C65_%M |\(Wcɦ .]Nrm>{ЃNUDÁO[sXwwQ|LX?V&;qX,9-&o F`1\8Xjl~p1V؄wNt[ϩ T5xZGyVhr呑6_$oR[dv7-? nJ{aխznX XfXK,XUW]ɱ*frfDՀ1V4٫OV;1]ðj^QK#V>QX]~<9X[(ao߃q[(V`ݾKb,+=CڣXuPW[ @2,Gjb`5E XEW `5EK ZXXQE9Gj0(|*VCaEK˱(ł(j+`Dq,VueXUEVL%jH(`a*>*c18]oaaQ?/R116IENDB`GD-2.50/t/test.out.10.gif0000644000175100017510000000514312164634363014263 0ustar lsteinlsteinGIF87a00@Ll ȖF CԦ|dD)H7gWFx.,G=(6&7)qU'8(hHhYRG32(,00ɓG=l S~*8(3j̃=Q("H΢V Acjs'K<̣H Amd"z~ISh4u`Y'Q MyZ׃Fc*h#׭&|ܺ1&2pR2ŋM߉[< j. n=%tp\L2u8gj??,?scG&h:8pU0F"$1UcRsq ?7F$cN'd Dya2O<O9^1ItM%7sCv5  Ɉ_'cO|meRC q'漑IFTRI!"b~EE6zz< htΝxI!d` d`hnцA!T9g!9$O&PkT.S pAjٝmhQüc@Oaӏ n:Ftúcj4b9꿷x7:*4d11d!a8`aaf3PJ6! g gjJ憣aca@G:$hhǽLC5?x0pi"G.\ 4A 0| ?8(Mh[PЄ !D" 4(6LA8|V ) HaO"Ђɰmtmr Q1Rh"pr7P @AF5`G.P  m ; h9l$1@ C "81CaEd#ԣށC06Ihý!:wdC1@6 d#H2:Oݠ21Jl3Z30d@g XÜw2;rEbc04!1#vhCՉL,htdQXCchp ?䕂'%BkptBj1I: ] (#*H1 xj<2!as.@BP1@M S0 )6FAyAZ60  R=  )W_BjT_` _P_>}C  Y8C3ַx/ʘd XZg AT1FbPPZ#1oq3lVȵ.2W'UYdjT.v@qZ#qo 7PY# F`av׵{m}Y CӠG9wPRo0]b셉3`ڥm!ڶg8e=Ǝ/ k>l;]ؾѕAm{d9ZOv_)9B4z]=hũWs<@Sy݂Tф.u*w^.̘ Ʒ:jX+^cz3j躣*-벊^ꘀJkyr RrjJԶ :~94Iw;*:t{Rdžoi }q 睷9Dpn1' 1t~.zgolKlʆhc~4 DC@ylS/;[j 3K B"@#B '&H@FP`A8$? lL  .ȟp<8懁L@> , Bh7O H&!pMDP"BP@j@'4w?`_ 5갃i QhjP}YPO z{6\nj4]:eo6[DT mu|C.N'fObhIf@ytlT%ff}8,tDDW6)cBAKƆQxG$hxIxbh8+0_v]5yQ?VQKfV耠X&5FԋEA}SNEZuaD@XOD[!V[DHY5F[|ѶdxV]IgFWA!xn&MyUX]2Uh}YKtwdAWWOnt?+Zu}mSw[|t]jՍַvF5u|(wցp^_w:7oT?ʅgSunDm*UAaC{֧x9ynus_hsxyW9yPCj(J5xHyySAET eHIVVCZ6PdyW׃ugz\[xb$؋dZh\bE?K]ensNGYHT`̨GCS$Sifd5A_ǚwIvNtVtEBpɛMPQ©XTYșR9YEA;GD-2.50/t/test.out.8.png-30000644000175100017510000000702512164634363014372 0ustar lsteinlsteinPNG  IHDRyvPLTE___?????__ccGG77oo__??;;OO77//ccCD& OIDATx흉(%9T\;>d 4?fr Tc,_TW[+RyAoRC$Og|[o~x7{a \N,~ ;wMd64(3yoI%l?a9PߓPHkCϢ"d{(SiCG=kǁ~{,hv,{ާo {>P Gz鬻zi+Ğn=%I L1gD 2D{ȱSoIJг&û5ddvo D޼PK[Oq 燦=X/>[=tH2*Ⱦƈ!E9wei2_|DrA3xSzvx:weA~0=g[RnݽnSwߗo{=_,׎ m.˹s^sӝt|[]~ҩ==ܭV.oP$q2ݿ8>va[GSu5*!XA.]y89:ȳ/?3 |o]߭U $<~bw1u>+ѕOxu~cAorE#BJ0a֍@=g;:B֒+y}|<-Z<~ xac1ޭAQc5 u>](Ɗԋ¥7V+ۭu# a, 3zv|.̮Z!,;+v<ޝ /{Y%2ndF\NT$Sw8+ەw1Ϸs磦;}EƆd\:9$΃\mcfYmХsQ[1[7p JY.ͱ&I?(m.RE>v?qFV&4IS)j%hSA$&%In°mze7VQ'|z]8@!z&9b!^2йY+8 xyF%#yjH,>L8& d4uʨTANåW@懻0%Qy^}!|~1D!ʥ5Z:6F->ċ@ptjd7mKaC]ie0]I;me*2]0|RYe8f!M<E(=ɸErDIRHKJc>ʃ0*$p#,YV}dÅ >⋢ c:L*ڡy;XĨ cLb HlBVU PBY)Y3l#juJk>1^%D&+0P/#d㮔k!S Oa_-9#+=r8Y uTwI[16%Kyʤ2Ɨ5 K"};>MA>,Ȧ $SP!o&T A>aVܽ N^X`AAD'NhPKn1 iz5""8eM$5q]$+F)pMܛc[5&;^n&rbHc:m9dK]ބջiO.1y.boADʠvD&O|=*!ҚI-=dᯖq10RD RL)jw#nd6UKN`~f-☵K(lN@Y6 D! ]&\zl6)GфKAT2.` EAxy;ĵ%St$HC !].[XJOeljp>;f#~C/(KAK9%y!G|| (‡W&ΆOdXo0sU 3)sUT ::3RPPg87k\ a(OѨ?b,IENDB`GD-2.50/t/frog.xpm0000644000175100017510000002445412164634363013261 0ustar lsteinlstein/* XPM */ static char *magick[] = { /* columns rows colors chars-per-pixel */ "48 48 256 2", " c #060604040606", ". c #080888884040", "X c #9c9c9e9e4c4c", "o c #1f1fc7c73c3c", "O c #47478a8a5151", "+ c #4747c4c43939", "@ c #747448482828", "# c #4747a5a53131", "$ c #2020d8d8b8b8", "% c #a4a4c6c66c6c", "& c #71716a6a4444", "* c #0c0ca6a61414", "= c #4848aeae7474", "- c #c8c896960808", "; c #040446460c0c", ": c #4848d8d8a0a0", "> c #0505e9e9e5e5", ", c #a4a443431111", "< c #d4d4a6a67c7c", "1 c #d0d0a8a82424", "2 c #6464a2a24444", "3 c #2929ededd9d9", "4 c #242484845c5c", "5 c #4848b3b33737", "6 c #040427270606", "7 c #6767c7c75757", "8 c #a2a254541a1a", "9 c #eaeaaaaa1414", "0 c #4747d9d95454", "q c #4646c2c27878", "w c #2e2eaaaa2c2c", "e c #0808f6f6dede", "r c #4a4ab4b44f4f", "t c #282805050505", "y c #4747cfcf3d3d", "u c #e9e9adad4545", "i c #2828d6d63636", "p c #272787872f2f", "a c #4949e9e9c7c7", "s c #2626fafaf6f6", "d c #3737b5b52929", "f c #717155552727", "g c #4c4c60604040", "h c #040418180505", "j c #e4e48e8e0707", "k c #a3a353533333", "l c #3838c6c62828", "z c #5656c6c63c3c", "x c #6767adad7373", "c c #fafab4b41212", "v c #68688c8c4848", "b c #292993935959", "n c #a8a868680808", "m c #5959b5b55252", "M c #3c3cb5b55555", "N c #3333c7c75555", "B c #b5b54a4a2626", "V c #26269a9a1c1c", "C c #e4e49a9a5c5c", "Z c #4646a9a95454", "A c #484894943434", "S c #1818f9f9e9e9", "D c #e4e4caca4c4c", "F c #040434340808", "G c #fafaa9a90606", "H c #e8e89c9c0606", "J c #909054541717", "K c #4747c6c65252", "L c #a7a745452e2e", "P c #2929edededed", "I c #3c3ccece1c1c", "U c #f9f99a9a0707", "Y c #1c1ce9e9e9e9", "T c #36368b8b6666", "R c #6161e6e6d1d1", "E c #4646bbbb7474", "W c #b7b755551111", "Q c #3737b4b43d3d", "! c #414175754040", "~ c #181805050404", "^ c #9494c2c28484", "/ c #3939d2d2cfcf", "( c #10107e7e3030", ") c #6464cecec9c9", "_ c #161615150404", "` c #5656aaaa5a5a", "' c #ccccdededcdc", "] c #929263633737", "[ c #8c8c52522f2f", "{ c #a3a35c5c1717", "} c #4949bcbc5454", "| c #b6b658583939", " . c #2c2c6e6e2c2c", ".. c #565685856666", "X. c #3838fbfbf3f3", "o. c #e7e7fdfdf9f9", "O. c #c4c4bebe1414", "+. c #5757baba3737", "@. c #373788884444", "#. c #04041b1b2424", "$. c #3737c5c53b3b", "%. c #040428282222", "&. c #fbfba9a92020", "*. c #a2a24c4c2b2b", "=. c #09099a9a3737", "-. c #8484b2b26868", ";. c #4646caca3b3b", ":. c #8a8a44441c1c", ">. c #6666b9b96c6c", ",. c #5757bcbc5b5b", "<. c #3535bbbb3c3c", "1. c #45458b8b6c6c", "2. c #6666b6b65b5b", "3. c #26268b8b7e7e", "4. c #0606fcfcfafa", "5. c #a4a45b5b3838", "6. c #c9c967671919", "7. c #fafaa0a00808", "8. c #5757b8b87474", "9. c #59597a7a3737", "0. c #0707f1f1f2f2", "q. c #1515fbfbfbfb", "w. c #34346e6e5c5c", "e. c #8f8f43433737", "r. c #05050c0c0505", "t. c #4848dbdbdcdc", "y. c #3939ebebd4d4", "u. c #4747e6e6e4e4", "i. c #373798985959", "p. c #9191fefefcfc", "a. c #a4a49a9a1c1c", "s. c #6464e2e26c6c", "d. c #b8b8b8b83434", "f. c #2121b9b92525", "g. c #c4c4a2a24444", "h. c #ccccc2c29494", "j. c #acacc2c28484", "k. c #d3d3fefefbfb", "l. c #b4b4fefefcfc", "z. c #a4a4aeae5454", "x. c #717177773f3f", "c. c #6f6f9b9b4949", "v. c #efefbbbb3737", "b. c #8c8c78785050", "n. c #464696967070", "m. c #6060e8e8ecec", "M. c #6868dcdcb8b8", "N. c #c6c6a8a84646", "B. c #a9a964644545", "V. c #3939d8d83d3d", "C. c #7474cccc7272", "Z. c #2020a8a84343", "A. c #7c7cb2b2acac", "S. c #262699994040", "D. c #aeaeb9b95f5f", "F. c #24241a1a0404", "G. c #dcdcb2b2c4c4", "H. c #3939a6a65757", "J. c #2424bebe6464", "K. c #b8b8b7b7bcbc", "L. c #b4b4dede8c8c", "P. c #3737dfdfd4d4", "I. c #1010dddddcdc", "U. c #646465653a3a", "Y. c #69699e9e6c6c", "T. c #bcbca8a83c3c", "R. c #d4d4b9b94141", "E. c #4444f2f2cccc", "W. c #6c6c92927c7c", "Q. c #6161f3f3c4c4", "!. c #dada9d9d1414", "~. c #f4f4a2a24040", "^. c #09097d7d5151", "/. c #6565abab5959", "(. c #2a2a97977a7a", "). c #5959dede6767", "_. c #5757c8c86c6c", "`. c #f8f8aaaa4444", "'. c #5c5c9c9c5c5c", "]. c #5050f3f3ecec", "[. c #7878ceceb8b8", "{. c #2f2f7c7c5050", "}. c #bcbc72722c2c", "|. c #3434e4e44848", " X c #8484aeae4444", ".X c #5c5caeae4444", "XX c #717155554444", "oX c #424279795f5f", "OX c #94946d6d5151", "+X c #dcdc9c9c5454", "@X c #747478786060", "#X c #191999994040", "$X c #5757dbdbdada", "%X c #5c5cf2f2e8e8", "&X c #3c3ccfcf6464", "*X c #91914d4d1c1c", "=X c #2c2c7c7c6969", "-X c #1c1c8d8d4242", ";X c #808066664444", ":X c #7777aeae6f6f", ">X c #3939ecece8e8", ",X c #f8f8fcfcfafa", " q.q.UXs s p.l.k.k.,Xo.,Xo.k.k.o.k.k.k.l.p.t.P q.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.", "4.4.4.q.> q.I.>Xl.k.o.o.,X,Xk.o.o.o.,Xk.k.l.l.p.P 4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.> 4.4.", "0.4.4.4.4.q.S S P ].l.k.k.l.l.k.k.l.l.l.p.X.I.0.4.4.4.4.4.4.4.S 4.4.4.4.4.4.4.4.q.4.4.4.4.4.4.4.", "4.4.4.0.q.e s 0.e q.>Xp.m.m./ u.$Xt.t.>Xs q.4.4.4.4.4.4.4.4.0.q.4.4.4.4.4.4.4.4.UXS s q.e 4.4.0.", "4.0.4.q.X.>X0Xs S 0.> Y P Y P s Y s s 0.0.0.q.q.4.4.4.4.4.4.4.4.UXq.0.4.4.4.4.4.s P.t./ s 4.4.4.", "4.4.Y P %.%.eXy.3 S q.q.0.q.4.4.4.0.4.4.4.q.0.4.4.4.4.4.4.4.4.0.UXq.4.4.4.4.S y.P.eX#.%.u.UXq.4.", "4.UX].6 (.4 4 6 #.$X>XS q.0.4.4.4.4.0.4.4.0.4.4.4.4.4.4.4.0.q.0.4.4.4.4.4.S P.%.6 3.3.3.#.t.S 4.", "e X.h =XT H.sX@.gX6 / X.> q.4.4.4.0.X.0XP X.UXUXs UXX.0X0XX.UXq.0.4.4.4.S X.6 3.T T 3.zX=XeX$ S ", "y.F cXn.( -XbX-XE (.F t.S 4.4.4.4.S P.#.#.#.%.%X/ m.#.#.#.#.>XS 4.0.4.e y.%.T oX=X4 T =X=X3.%.y.", "R 6 4 4 8.#X#X=.=.bX^.eXs > 4.4.S 3 %.o.,X,Xk.#.M.h o.,X,Xk.6 E.0.4.q.X.%.=Xw.O {.Z sXi.cX3.%.SX", "r.n.(.bX4 1X#XN J.uX(.F y.S 4.s >X6 k.,Xt ~ ,X,Xh k.o. ,X,X#.s e S P.6 1.oX@.# -X( -XH.4 =Xh ", "r.w.3.= @.@.* N N &XE . F y.s I.$Xh ,X~ G.,X ,Xr.o. ' o. ,Xr.0Xs >X%.gX{.dXp LXQ s.#X. cXKXr.", "h x VX@.-XM K $.BXf.0 uXcX%.u.].) #.k. K.K.r.,Xr.,Xr.K.K. ,X#.>XP %.(.zX4 sX} HXZXo o &X-Xw. ", "h VXlXO S.N l y I BXIXAX= 6 6X6 6 h k.o.r.r.k.o.h o.,X ,Xo.6 a y.%.=Xi.i.Q ZX5 AX* i =.q lXr.", "6 VXT @.Z.f.l l I I o 0 Z 6 F uXM ,.h o.,Xo.k.h '.h o.,X,Xo.6 M 6 6 1.1.p z V + PXAXi i BXS.{.h ", "h n.9X1XJ.0 l I + IX&XQ F ,.5 $.y K .Xh h h 6 8.,.m h r.h 6 FXK K C.6 dX7 PXPX+ ;.d i 5Xi <.x h ", "F VX4 #XZ.N + PXjX} F 6 ,.5 + l BXIXd hX5 jX<.<.$.$.} m LXr AXIXl f.$.F LXLXz + IXV.|.5Xo &XZ h ", "A.#.bXbXZ.N r F 6 F r ,.} 5 <.;.uX} 5 7 5 LX).uXuX} FX7 7 # jXK l y <.).F 6 F F IX|.f.5X|.J.6 [.", "[.eX^.q = r 6 m z <.BXQ } ,.8.h 6 6 r.r.r.h h h 6 h h r.r.h h h h .X>.Z uXK jXFX6 F $.|.f.N F R ", ") %.4 -XF 6 2.6 LXjXjX} 6 h h r.r. ~ r. ~ r.r.h h h ,.Z m 6 9XE F <.$.&XF / ", "6X6 T 6 M jXdX6 h h h r. ~ ~ h ~ t qXt t ~ ~ t qXt t ~ r.r. ~ r.h #.h r.h 8.H.} ; 5 uXF GX", "GX6 sXh jXQ ,.h r.r. r.~ t r.~ < C u +XiXqX:.~.C u N.h ~ ~ r. r.h ` 7 LXF + uXF GX", "Y eX=XF r Q ,.Z h h h r. r. < +X~.~.!.n J J ~.v.u g.h. ~ ~ h h xX+.z PXF $.J.eXP ", "q.P h h m +._.r x r.h F r.h h h r.r. ~ 4XtXD d.R.R.1 1 T.F. r.r.r.h h 6 h X.%.oX6 6 6 m x :X:XO 2.9Xh h h h h h h h h h h 6 h h 6 h h 6 6 PXK K + IXPX+..X6 h _.E F X.UX", "q.P %.3.x dXm F 6 6 h F 6 m x >.2.7 LX,.jXr ,.,.2.Z Z ,.r m C.LX<.0 Q uXBX;.l ; F Z 8.gXq F 0Xs ", "q.I.y.F b HX5 PX+ ;.Q M ` 6 h h ` Z uXBX$.$.0 d ;.+ IX0 $.Q Z m + } ,.'.kX6 F IXd AXq q F a E.$ ", "a Q.Q.a F #Xw V l BX&XK Z h ! O 6 F K <.N + y PXd ;.;.uXuX} ,.,.5 6 h h h .X+ l BX$.H.6 6X6XCXCX", "N.D.C.: E.; ^._.-XK <._.h .i.r r jXF 6 6 6 6 F F 6 6 6 h 6 6 F F i.oXoX1XuXBXl $.LX6 L.% NXd.O.", "7.v.D.C.Q.: F 4 b p } H.F O -XZ.K 5 5 2.x {.O {.r 2.>.KX1.sXHXd r ,.h h @.} IXBXjXh % z.R.9 9 c ", "G 9 u T.pX% h 6 h F @.'.:Xh i.M o BXz # 6 @.b E r jXm 6 i.-X$.i ;.FXHX/.2.2.6 6 h h D.R.!.&.G 7.", "9 !.u tXt r.9.! /.` h 6 h h @.i.N BXl z 6 sXb -X&XV C.6 @.E BXo $.+ 6 6 h h kXKX2 -.6 r.1 v.j 7.", "9 u ~ h 9.O ` 1Xr LXK ,.m 6 r.lX= } + +.F 1XsX,.jXjXm 6 H.S.IXy uXjXF H.@.1X9X/.>.` A .6 z FX2.h U. dX-XQ z 6 @.9XO '.2.m 6 -XM y <.m 8.h zX{.T 6 nX@.6 >.h 2 c.h d.", "t ;X@Xr...oXh Y.Y.h Y.-.r.U.OX {.#XAXQ F h yXr. h h h S.#X;.PX2 h h r.W.g r.9.v 6 nX! 6 9.X _ ", "XX~ ~ & _ & U.r. & f ;XU.6 E Q + ` ^ XX;X lXT -XK w hXh & & U._ pX~ _ z.h h D.~ ~ N.", ";XmX[ 5.rX:.MXvXMXvX5.[ [ ;Xb.! @.-XZ.F .Xc. OXMX yX{.F M jX# h T.tXv.DX9 v.1 9 2X- 2X!.9 9 9 ", "vX@ B.7XL 7X3XJ J { *.k iX[ x.lXh /.2.h r.OX[ MXf _ h ! x h Xa.qXH G G 7.7.c 9 H c 7.7.G U &.", "8 { 7X*.| *.*.8 k 3XiX*XMXOX@ t t f ~ ~ f MXMXMX5.iX] vX~ ~ @ qXqX!.c G G 7.G G G G 7.7.7.7.U 7.", "7XW 5.*.:.rXk aX*XJ J iX[ 5.rXe.e.B.:.e.B.rX*.k { J *X3X8 8 }.J DXv.7.7.G 7.U U G 7.7.7.7.U 7.7.", "L L *.k B.B.*X:.5.8 iXiX[ rXL | | k rX| 5.e.rX[ J n n DX`.H fXfXc &.H G c 7.G G 7.G G G G G 7.&.", "B k | [ *X*X*.aX5.*.*.k k L L L k e.k , e.aX{ { { 9 fX7.c 7.9 c U 7.&.&.7.7.G 7.7.G G G 9 9 G G ", "e.L L *.7Xk B 7XB B L B B B B 7Xk iX3X, 6.~.fX7.!.c &.7.7.c 9 H G 7.G 7.H G G 7.G 7.G 9 9 G 9 G ", "aX8 7X6.JXJX6., B B B B , W W { 8 { 7XW j &.U G G 7.7.7.7.7.c 7.G wX7.7.7.c G G 7.G G G G G c G ", "H 7.H U 7.7.7.7.7.&.&.7.fX7.9 9 &.fX7.7.G c 7.c G U 7.G 7.7.G c G U G G G 7.H 7.G 7.7.G 7.G G G ", "c c G G G G G G G G 9 9 c c 9 9 H 7.G G G G G G G U 7.7.7.G G 7.G 7.G U G c 7.&.&.7.7.7.7.7.7.G " }; GD-2.50/t/test.out.9.jpeg0000644000175100017510000000353212164634363014373 0ustar lsteinlsteinJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!2222222222222222222222222222222222222222222222222200" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?彵. m,L#Q]ۻ=ϵx\(byT!Ccd$etETaVɔjx'P2]^Z?=_*Vi?^^is.aa&0v=xVWa[_NyqB#h 3DTiP&׏dL$kZcی~oo1žG!rYrTh[\qȢaЀ܂xs\nq3EYv#]XpmW%y=KkY%,fu$.ݽ |HRu=_ART{T[:jZx{T my(C$E]pojjjn0o%-6yg{֦ ZŨk aYz岌䓴^+?\j[uA<}e ֕n1|c,-%  [Ik+6:GG9'䞞h}B9dxaQMH2F t}=@Gi$^Zo>^9@9 45%S2 eudu hU$2 VS~VwoSί-jsZj[%'`O8.=V="He* vvGDԊ3T};~udVG 0H#\ЂQK>ޮS m>E B̒M2FffQ v;~QiZ!ua1K!IQԎFO2BEhQIlpҝ][̪'l05s<-5ȵo?'K^]U,5}RY/SMrC% ,I88ssZ6~!TXm(:L ';)'ci ) QqFQ`()ּIE3ԣQӌk?GD-2.50/t/test.out.7.gif0000644000175100017510000000473512164634363014217 0ustar lsteinlsteinGIF87a,ڋ޼H扦ʶ L ĢL*̦ JԪjܮ N (8HXhx)9IYiy *:JZjz +;K[k{ ,N^n~/?O_o0 <0… :|1ĉ+Z1;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{ 4СD=4ҥL:} 5ԩTZ5֭\z 65Kٵi%=[)53 w[bn_ю;8La! 'ncǏD!re˗'S<0˘9t- N~0_ܺݶW,Aqo,4g^t͝ӆt*c]vݽK};+O~+/[xqEhW}`!\lAp-`>aN%6qg.aZbчH7ژ@-'3G"yC2$Qzi@2Rch%i" &|@&hk&9gZN&R#zV&wX`깡y@ yxZ ?b藁)TiY (f~z jRjP)ZiH먶SjdK'S ƊyJ5-%>[-e}J-v5vnU:. ʮmUKaҦɯo< +o;yS[. o5/ +KZ 8*d u.,q,r-3Ϭv9o1LE\tӸ hAܬVI۴WMWQ͵邍,rP]vGNM*wdMj 8w/4܁ m6V⹊x|E.o>8әw1 s%pN&I8벇r${kk{сs Ὗd5',} <_͠{4t>}~wo7O'@9n(g*p[aWJd56mWRJf 3} A|pC q H!qz 'PR۪8`q.R!3фj$ ۈF"c}gG(0<c?Z&! y!T\$"H$Y$% K:В|d;)FEz%iPN-2t"+[W&rD!kE3rr_14"1%c<])gBS{fޮh$$79oN&dK9])PɤelFFP9% l CiЇI%[^Y;m 6w?}ԗ+7ICnh yOLiOgҒxyNKB>:/aFHդ7m+bT;dA.5QCG2hTJQvԊGU*Ql)\&X8W]md`͟uYE [o|=)՞Sv7Ͼ^*ޣہϮ5S++w;F;~Go)فדh`&osNG&7,ڍA~wS>D| G%lh3=f%x|dD}L}<A ~@W8rܨ7';H[dwabGݍ#L'z&"#1{GKֻA=8~TGOakN>6uM>]c/œV XO$w+C䂢 -x[map{ R?ѩ { , ~8thrkW\j 5Ov罃Oz{Mى-.f݀w'=xh7B=W0t62b-QovW{h;o#qptN?PEdoA/}&{clzkI3Cm@]v;tKSWCnG7RKiZ՛G _zcT uw]WnrwtՎf_\i^f=W9ir~KNݨN5,ˢVk.A]'v.kIKP}$׫k4v*>_"&W,} w7|-B+-kL= dp]KVv{nj_즋I]OYvv?۰KulSV˛j;N/{*b? of%rʮV4Kھ٥% .I yCtʼnr$^/_o=mpy=O\פnV?2&۷kbWx]ˊ3',=/e߯ھU{3Xg?"ras=({m:ꃽlj{j{wK5nti?>|g6/".>n͛cnqX`W+.\`˖ ɦR;!B!B!B!B!B!B!B!vRdT3^IENDB`GD-2.50/t/test.out.6.jpeg0000644000175100017510000002261312164634363014371 0ustar lsteinlsteinJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222,,"  ܦDOU`DG /؟G4J)v?*4>ڡ&ivd^9O$9x&H#I|[䏠1k5~Ģ<+(m?#}&фl[l ,|Ӕ.UZY)Ԩ9H13[@[g`qv۔/Wv>I\1rG! 9_>B#7HfO `AN׳6ÖA{%5{a:@5=i8N^9nBr{ݱ `q3[>M PŽw\x6Mӈ; vq2>>Jt6 9yw ˈ6Kn#ڍK(dz#xZYyI1dz%!krEHZ,*޼ ɹyiHoP%Ӎ%b(6?Tw`5qO??]w5"Ŏ/EG6켃^=7_ÙDR SjC 2 Q3v]b뭫y´=7$]U1w/ *!)Sj$c,\H{ yyƻo= SUr P1:#٧lyʾMӛ1Se1־%%%%%%%%%%%%%%%%%%ByKOMz, 01!AQ"@P$24a? te~QTc-s/ 8 w 頢3(pu,Wvq6K E @V3"Wkf!ƒ mCp/Ί9o4?VO}ZRˮ!lMA̷e>SsE>ٚ R1(88Z=:b )Uzqn+}3s*0! A12Q@"Ba?/dE\?r9 + Vڠji٢K'id,}BjOacrd&hkEME~hqupmbmewiRKȔd;NyOI-ZH2u7ϳG)J{k)oc UeOόi5N7;8\?CM :r=c p2èm>D<_ ٦ipb8c>1,48 j1ZUZUZUZUZS+OA !1 "0@AQ#3aq2BRbrCP`c?(ij@@ZTϖӒ|!Td@4."&J)T`;S+R͉'ԘccI0}qH*Q IPԀ["rq#e!<*ht;3g*q: X2EyN.T.Zh5 Bu@J 72*&0V U,2kAbrP m%2"F*IªU:TLJ)%(Qs pSi- 2"|!oGnmr0:&U3.ZP6$5L(M0w5)hu>rFwf|X IHPRNoNӌI, 6|RPX9e͈R%e&?uI$5jν!oTUؠbI=ZTlgjpL;ǢR4K4gu{33$8joʉXIY6F\/hv ]K*GKTLے0ΘBrAV}l@Ф&bKd/фy8c_I6?YT0Dj"bɧEh8~ߔO?Q޹?K,#ۯ1Hq_m̖& Ѱ⤭ QOHC޹۪͝E׌!'&`p;tjgY#lW}+Ae$sY)}6Cc:Zn|}ى*01'J\?:>z{ 96Jbkw\צ/2{k!}Ei 0Vk~}Bd?\ק!!Ԥ8G~hV"[?֏s_,՚ S\[GG޹˞$mU)I*J@-G޹̖Φt}YRKDԻ-!A/ bүzçxԐ5κݦ Rj.6+l޹)~ʃEYR8Ƣ5LOBҚ zS-_QdUU?fmʚ'@inj2Yʔ`FTIԓ}e!9)j!+At8.y] zvco\GPJ.0n0p֭CE2M?r6@'I[19o\gPS ɭ=S@Xk޹PI# )$l#>g&J66͠KB_!zgY]R6j\ݨ/rKtz9D4Xosh5?E1v$ guJUFSzeͩB%X?/? e`zVm޹|eMK^_l 2AI)#&獽sh%* wWUD lmBDkI5:Eݙ6M΢X޹"2Vj'\1ᝥE*T5nn6͡) 0:9T~C޹17TGK *͡*yjw'\1JrɤMЦ~2Mesb.:us8pq<㫝yW;w\:us8pq<㫝yW;w\:us8\"{-%%>Rs ) k)%! Hӿ+!1AQ @aq0P`?!J uWf?%+q3eiXp&.uhFp|N"_DtX ۈTͩ7kG^$Evz qۈ^$Ev#ݭFLIJ uWo} !?%K [?!)?E֌/y19F@&.[Ub`څevقL:QP],HBY&5FtḎ4FOZ WwB (! iuh[ :NDЉ4U"|z`JiL2"B4JhΌX]]68̋VFxb@A$( b[q<:l=yzڬ׍@!t63[ ؄҅Pwr-%8.re:u:H+7?1A)pwYBEB15. zB&>Kn"t_+ =FG}mZ2L?}g0F28&҆dL\8^?N2y{*_ W:ԇ{x&y ڮ3u.qz2cxMd42/ːX lQ$MCӔ"J$O*Z&u{׉>I»E*L#I_R@)yf9ն 0$|?|9-x#CJo҉·H<%{ŧ|Vhʙ|? 4L8#GHʣDEO#aX 3>Mo ,>V}k<<H豕)gsEp3Es-~56N|Z!'tcU"y/qt5A# ??Y?8K̘r92t5o'QʛxV&/W>y'`K2(1.CqHbXDy9 \A.Mbŋ,Xbŋ,Xb`  _sXa <_<<=~>:/S<ρ@<<TAT<<ϑ<A<<F_<<ρA|<AA<<ρAD<)XF_BC-8cs6IRT%IRT%I?(!01AQa q@?$ /1p΁yA(.!1'mQY@ #Tp@AfE$ba'4G|#ZhLEՉv4 em_TBBw̰tvgoQgL4T_#lB0>,8=f8R& waBTG.7Q#^Y15,*9~ˀb }@v5,*ʻ2 @o,(s.q;c ɵK{9K&›&@" 0`44/SXh4Ӱ`44b4,44 e[kmmG+!1A @Qa0qP`?N$* |{ ~ r)c+&e V> JTAOyխhS& j .J@q@C*S=+/x*-ց 4Z^ @M/_Z4mixʤ~pxLIUW <x}mk HG{cTY2Q3Mg8H h Ė4/q3B0=^n$2 ƪ%D o]2P{5DBTKkrRSep9ea,FY3,5`Ó`20ˠ^IbBQ\ ǑtW[b{^TÅ3jW VR)x㩀"AV0y٫,v9\^>܎J@q@ @~9U`U/%(J2{E3}KSHe3O"scJ$ D 9[KN,^'U|3r'^lgU|> DL"wׇ7Am@P9ȇى=mG8C.\w͕b a>? x V5iDUq~?WueLO!5zԎ%K;9O F'~|IIHV ]q{_V)IUq9} iR|Lg98*eW_1<5  }VF*36 V0JdNV!| t,!*ۚx_*3`:3H&E0yv _y֨ &z(͊uaܯ|O܋ بb$r5 .7ɾbnԱjM}$Nٰċgo`Oп4Q2^%ʹV âm7pDhFEWrc]9*vNC$t<X!$M DB@z%1|6)`gt-Vۣ x[0%gO״D+aRǐ-EdnܘkMڶ IםΎ@ĸ6߮i~6g=阆$NϮM;Z]vڃQ>$(L߯# ,5V 9HD5 i-6R kqS[(LgMຸ ˷К(Xvg I$QZbDAlvY`sY!9LU֏HNt330'7Є fmaӊД ;gpAu[iVj<}nA""8D뙑C*S=gr:yGւCHpݎZ] [V$g[ ;:k`#.dɖ;1,i茣DH) haHFz=$d ܏م\㽾o1G)'hLpqu &ڪxȰA`$RT,=߿~߿~TXr$][>{Wk!9Ty*X0U_;GD-2.50/t/test.out.8.png-40000644000175100017510000000654012164634363014374 0ustar lsteinlsteinPNG  IHDRyvPLTEߟ___???cccSSSwwwË__??oo77OO??__GGSS''wwccoo//77;;< |IDATx mhX)ɲd39gKn3 A?uZ%W|/+z\|ׇ uMY֛K!2~`_U]n+ /ڿ^ի Z5lxB-)j۲"@?5_|1Zk3d#ueMkM_t͖4u 噮&,&kvhKn|D]n 侴u]TVvCgi<cI"` X/Y6| rWK4ff]X/W^eSzֿC[RE +[vk ϖ'3P&!1ءOV,L(]Y9it-lѥ mVvhcB\:uZocmifG]䓷& $^U6&&cPٲ07}l]ڐش, gb^L:F]=T ?- @=M(ɭ浪^Oym]I fN;b5'cg9[I{(ݹ97|Gҡ_T(ǽ>5Lçlv$mԹ!NV:YscLyvx`Znk8Ѭ7#[BϬ~da~e8Fv|=?{Vss<X(NA~Oj}mR=lNtv5fivwtxٯ9Nh̑y}zg\a*0adhbHvt'6ei: W~o`?8~`C!-;'֕& {v8&mKʟcXzn89p4P{`=L{~5c΄XRnp Bu#-+rǹi#|91:ɰ;ߝ(BJ)J0H-WJ/F)=3_\K2xНxdzRwC$R7]!*tNDI=1V COf^4XB(0m*VaXAz&:" ;"5dtI=3bIu˃,BQVRUVzҥIZn," JEOVR1DvDD-$Qu< DlyWp3` baMQ p5]鋪!K@ Y b2 ѫ1pAt:ƚi%IwOmoY.⏟xOR]OmBx}d|(^\+)Bl?c˔ݵ1pp/(c7XiAO̕&.o=X}o+_@g-1W(W$\ܶ\XH1S*1W3]tތp״`41Th| ,RyVD`-׊k;ج|(cd1WaEC>ϧaۖQMr!S?$  V.#םR\ gtʾV §&n9yʸzD;s+$$y>[W!/V>& gω١qzZDP !2v R6M,weW\&,ӓ!BO!j h.J*_U"C k^.! v@C $KiS\A$\i$\%V  ?QX{6l >Y,jԃ{M_oJvn $0'yl9I7{^Ul2CHY>Qb![D*J~:]#' aClȋHf?F>)TJuv"fq]5΅Kb>IbrQ1 L }G*]4ID/4vJJV$lQ90NN)|}pCF*D[%EܛufŊDV4O7BcXaAAR :To:y3GJ.>O#MeX nvrqqȜ_ŵHl9[ZD)iW c.g(F%;N]/(H~&[阳hؗ"-3!&z&\ qڒ98\."l=@mE ˘\8t^Rh-\+h ״qq 0j:<*+M8▎YTlMq9QH'󍣮y<a&>0V㨭y!{mu[w"덣X4ҋ+}p #G箢 \ijXE7]\`qH>0mmK3nKN=#I3WSwSVS;O{'01Vg)q:gdAɣO tbnyN2iV,.BJR:!&JbbHy[E1F7 8G+32*Ƣ29:&$w}e`W9 F,=I6S{)'/g$UuҼ0aVrGbGnp_^ʌ[?1R%C ߔY F:fnb'tX[#?@0'2(#mMDLtZ\@W'=u>ʁv \M^o <ؽQd  1G&o_aǻJZ |1o_`Tʦsngv迒pefI9R&UZqA\l _d'*{x_a4^/%w=q*_Ċ y<_v{m>rB=jNbض;WZCWX dʊ0 H@ذ#36 6@> 2u!` _ rrIENDB`GD-2.50/t/test.out.5.gif0000644000175100017510000000161212164634363014204 0ustar lsteinlsteinGIF87a,0I8ͻ`(dihlp,tmx|pH,Ȥrl:ШtJZجvzxL.ύz}R"7|ޑ;:p{U-zN,Q+)KJ(FmE&A%<#9q>!ƺ74u2/,*y+A  0ȰBB$JbA%Te#-?bhOMFA2 ˖'IŒr&6̹R&O)(S4TP"E:I ӦJBE"u*ѠVT:d+W EK~e Ilضnv.vu͋Y+x  *܅9č Hv, ɘ%3|%g͹8SL)ĉ^mBXn5ٸiӱ$oox+M8G+7^9Йq$u_;;>5lӓb 5>}_~7'Q7Àx2$蠂Hރx'T!>' w(Ha~c`,I6cȣ;B F@I>dĔ2HNi70֓6W\Y-Y$ ciLzS)ÛtB%' tԝ.R|C jf 6'4*iNlTi`L0j¨d* Ҫ"*I "歸r+k,DZZZ*lFKгDkm?n`dke@~:nFrczKޫ,l' 7 ;GD-2.50/t/test.out.4.gif0000644000175100017510000000044712164634363014210 0ustar lsteinlsteinGIF87ad2,d2TF@(ʶh~rL_( E,M*Vg튝Lg*1ۺt%ҮF~ӧhx3xPxxH(Y0gC 8yiJz"ʈ+kHk+I[[j6LlL\ |< yXM(m-\ o"oLc/?~ˮ_'s$PEX#;GD-2.50/t/test.out.3.jpeg0000644000175100017510000002070712164634363014370 0ustar lsteinlsteinJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222,,"  ܦ@'bD??l+@#? Bڡnird  pV8'v4+(k>Gok6#gH m*u@82v=L.~h1\9kK#=vGt\tfm6ziX=]8j {Jk?ckyfqrxr pAb HF\r-.pX !̊WfNBk81\˵|~}&U8{vU;]9D30O  pVyq$}Hm^읛<3Ůb7 m 'c?+H>ffg 9dO=M >(1:teVx܏pSlmɝ׶RMS Z%>@͚[FxH/{dsР=]6?_*՛#مm y`4ĝb @7V@2o'1+C@~2ݘ ث l1JttEg*"ܨr?|-Dg YX-~)hf41,0@F 5"!42%Pi(9W]vn~JY ##M+i( ~DlyQh$50&_+1mJ̇":F FM$-ʪDS}8M-9.dw+V6]'ۮAyTӐREd Ci"S&_:tGu;#ֻ~Asfcqr: u*~"}OpȪfnAs; rRV}nvېSˊniofu0"X1s]"nASbErT0e܂SE4t\HB+5Z@Bڡ=ېSFmW.U~lnAsY EcZ$>d\=M Avɹ򩠱&C5PGm/c۹A^|9RJ02\, d*c/YEE\(_ơޟܱXSr"HI r'hq)WJFBs\~VTaWci޹SRF~C-ssz2%F~9]l\OswhȚWȚWȚWȚWȚWȚWȚWȚR̖F%aBOaiVLظaV F{ / 0!1@AQ"3$2q4a?nmSp]^2zIou pS|:9LrT C_G!Ma6[~}d:N9ߏq~Gs62hTӑV0\Bq1u1B!n50E7rָ{k:.tum8d*j3l}dѱ3Cj2F9SS|JJV=}_A !1"0@AQ #2aq3bsBRr4CPc?(ih@;#%<|!T~Hi4]E^&%dsCg0hҥr*ht;3gV*q: X2Ex.T.Zhj0$\\R)Tbi@Ԑ2b6ԥ_0>rƅtIfѝwWKQd9)Jo1_hCXFL~a9^eDrm<}3%Ig"j9z_;עE}Ps08z_s~VyZ )%KM!MU5jΆ:Znk}~6bmB >U2Kת-fQ)7^\ Ȟzr3~0ZH# z@Pp7^Pȑ~Gk'7^ӐRӒ<ն(תQ`FVhTҚ*`}߽z˞$kX"S)`*UN[^o޽WKgS:zc5.HP|߽zt9| H} L\먭a`ɩ+쫥=mM!^IN˽z JEYUBp&?<41S(ZSWL`i"޸D 4sXːS[Ia){h>SCFrX a2&X&}э7Bt$%b_L\I;8)U?W(T6iJB~W0p֭TCE2t7Nu$Q{׫.YdKCi'e&26zfbIys,⣦@̻׫07Nnq^fU)xUCPS*N zINTY@L`ѥN y° Z`%ѥmdfF8$G$`&PIU6TH6BJhyVZ8@RH FgrfRKutb;$fU LHRP)QN^x}Q2&IOnRV*%:G^)Ppm2grdUqXo!/8G؉&H[2{[3ȩz;b_^́Xҍ+4i97̮^쁡2*m a/fAHPt1̢s+iQj'H/fDM5>cDzcrpĊ-oKّTgN~vcrd)j:xxs|9>w;{Ý=rԉ촔$ʠCn^)X9#[zgw/kw ng?*!1AQ@a 0qP?!J uOWf)[(O*+i7k2G[viNr%OyEp;\iDQ{hC;@S/t"{ UeC%4\mn͏M+lkc#.qG1>kN-B,0<`3G{Yx,$5 .x#RUN J=On?Foϥ$,ilx`ti$tE'@6OG0K0(-*W4ՓaN;mi9@pޯxEb0>a1][1$.5>@CTKeL&,Ow˼8L$HMiH"[deQкeArY#A"mH>9&߸r:\mk~ Dȑ+X|"kk~~BxY9wX7H>N i[R<QP`+إ\n(O #>+"I&qՋo-˞ZrZH%.]O[)D$\/(B kD.f3rL"n>g2sS0(YW"~ &v^>g]֍߀u_?6#:گrOvpy&8!!M7vb67铜 uS-Sl#z&h#[jKnG=,2ux_pl3 ji͹OyȡZ%74DFTQa 96%(ض7qU`5P46x'Bǀ 2s/Xih60W2؟gSSl4OX50>0[ȸM:䠑M􍓓ZrLr92t57I{c#TQʛvVM^{SZ8]ɍx}n&,ifXe8e3s3X!+,Xbŀ6.),@ ,n^Q 🗧h?S;pg <_<<<<<<>:/<<ρ@<<TAT<<ϑ<A<<FK=|<ρA+CO<aDK0!rT!>ORH1\ϻxl=rdC':pH)f*ӡ8`" oQR|7P%ld]@ 1#Ikm&$Ղ,0I" #y=u'?tm 䟟ʷy a@a^ns64L\v,!/0\E9Crf@hK2(ăa\:hab1U@4κ&!10A Qaq?PubJUpۭ+P:<*yO! ^xOS&u0xMnxUdzsP?Ʀ GnHV^'}LN܆3h xu0k e䆡3'LZY9=<:<$PqRw`Jc8)': B` zIeS qUJF 1r4}9t3^Y , = sUT e*Ws,Owo(!?C'͍(.*mm-;X !y߀9Īp:.l`P <9UaDJ=p뽀 2#y̐S̶ؓ1vڔpA>_#W?|/t b[QL7 >:dO~?_ _y:pe@`b2D~$ j~go =|'BےP[mz اsuI蔖=3|c[ '4}%(`%hB\@ crL|8 ڇ\A.ϯD ~yF:i#.=3/حqط>N'K0yk"m1y2gn<9,7_oh<Q'Ʉ3꾂~z3~\`Ep 0:?v 0ʮ'/m*V>_o'Lc<,kOMB!,}_/F)L*d:{?U`6%UsO [Y8fq1 a±B^E؉*^A ɿGP@1Lk&2Qù_r,S+bH8`L,@ޗ&5 : &30۠80C' LS> э)`=UC`MF F3f]TDW*tM4O #"+޹h1VWW' KV:V`a! !cY݂K2W-78 Nכtvat! 1Kydluz=l*UؠN7[nL5U390WS#_0S;Ui̐E)-%8)Vv#~rp3DG$~Ko4 Y F+BHh/H:.A3z(ҷӞhY@`]ؿ$jc}\qP;RV~N4AS⦶ "Q) [O'Gy2&jϟ: r D&oVgX35tb@vSu7yC\Ɣu$U K3l ޜVQ3; iMZ>F&"#N1e3>qMVsߧm2ӰsoGւCHpՎZ] [iQ?pHD piuV#u2E@F]ɓ-w[OJ,/|@Bs2au"ï2\2e-k+\P?/,A@{Q]%;kc 6oV~u3RNИ> (2L9o0t t0P߿~Z IQcʒb ~vl;۲BnR~`l@BGD-2.50/t/test.out.9.png-10000644000175100017510000000536412164634363014375 0ustar lsteinlsteinPNG  IHDR00` PLTE@LG32(0ߊIDATHmT XS>Ŀ:U~$2 hpg ▌ECb"nOhtZnSeb)86թ-s}}{~}<Zv}WIyV+y=|mV,l LaO N[:v6f;npjn7nhj˳4h_mOlX-]ugrlVr46]/"rsBP}˅!lq1ONˆgMC=77n$:yr[@!E|VVVkVA]yMúp&"ȠLN '5 VU&|{kVʦ[8}:y]ܼJ 궶ի>-b<ص!E6\w`iK9r:qۍZn0VmMujv!l=ޑv#7{7p3Zc-qn㍖~/۞(Ε46G{n7Yw{7n}w-їaa {7w3qjI D&9]uu/y'x/OsXtiX bO f4׮31Ղ׳'ZPa<&)b|T#ˉT=nt΄WɟffS8^!ݝ =j^$ǣ~9իǛ%8pv{{ཁ13PbԦj!0(ynNǯF C {` Ff2 L Ё+0yGH,bEqqTh&xAzRuzσpyU&65Cű9_I`c$l#  #r@e-ǎ5/<֘_HgI6l% ¬^V߯psv疔@% "4V4pK`J%'0QrSX3I#RL& KL$U_xU߈B` ȷW2`N. *6 @xL N:2 $=^Z"u(e b9?\^Nc~Cr/;^82)| N u2!׵x|ba7Ѝw}sW7pN%gIm oX*~,0!S|^4|( >Nu/0_T[/JaːX ݇K47'\c(dKSBWǒP 3p}2s_& /&)dnTsJpϰKv=^ܤ;QQ!$PoG}h<`ĥJ)tśVK\+ܷ&wŹm\wЮ{ S r0c0_)xR)1J R6EmUT5f؝ )йvsoc杊]ko5|pgެKe"Mt‚Ec VT_\P(hZϐд"D*+];?%.nE-rj E94]VUfPt33sپf`8RTԟ37tNΓxdeo\S54T4jhpUU`QE1:*)PH'$ ,*,^UV&eeejDkGi ͗Х,  PC(zE{/ZLW4tict4X*IMezTﺯ^7lY1i²KsB5?XTD2茜aQ.!!9Aij3,H$'FϠt`li{$izi,&iRi_ݿ@ڧrB5yig Ǥ}v}`JZia4i#^{H{FFFFFFFFFFFFFF|xtfViy{?iIzi?iǘҾ:1PgnUm{}LoϿ_(oh kkkkkkkkkkkkkkkEӥ [W[j_J?Z{ixϹ&7/G7I*^X+wʗ\```````````````-P:pt\ڟ~oNHS[^kt,/珘(GHvJ/H)񇚥=WX#X#X#X#X#X#X#X#X#X#X#X#X#X#X .,}[:.1ilܜOKIoI&I mIQ~riNUi=!Kڟ9Oگh-Zp8@aҾ}Ya"Qg7[}ɚv' ikai?SҾjF^0Q־Ҟ+Iʏ&"HW'GkGڷ}+lFw!nƭ'C1M>G ``````````````-wҁg%㊴ϳey~}T}j+T (J_eyד/I;=WX#X#X#X#X#X#X#X#X#X#X#X#X#X#X E$H/hG=DڏXiݏ^.7T}/G f79Y/S*/S Ñ}FFFFFFFFFFFFFF,.@:P$+Q>ҾU~h io~iFk?YߍC=}j<Ƴ޿H^\```````````````-$KWռ}ZAimri?Zڿ;VisYWJ@ DJѾ#"v~]ZiB)ҁo}}QҾ.s!Q?tz߫~SL{i঱ҾwwMXO{i!F{>+Z]?"x|Liv?yji)4$-9+-O J;JP}EM>eh\}TXiւ6L:Ei?iU!/5H.]}o'(iY%פJKMfI[k7J>umҞ+2I)>o~ˮRi.;oFIڟHG׽$ "}C~mפŀ%Ҟ+r9+{IENDB`GD-2.50/t/test.out.4.png0000644000175100017510000000041512164634363014222 0ustar lsteinlsteinPNG  IHDRd2[- PLTE3JIDATx 0 E ̓z =0@6ʊD&?cۘKjGUOςx|pvrՑ3 9l`deVM2lh8ceB{"r{ܩ?Oy(k> S϶M(T^IENDB`GD-2.50/t/Polyline.t0000644000175100017510000000075412164634363013553 0ustar lsteinlstein# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.pl' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use Test; BEGIN { plan tests => 1 }; use GD::Polyline; ok(1); # If we made it this far, we're ok. ######################### # Insert your test code below, the Test module is use()ed here so read # its man page ( perldoc Test ) for help writing this test script. GD-2.50/t/test.out.7.jpeg0000644000175100017510000003077512164634363014402 0ustar lsteinlsteinJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((+kúb^4bFoOp=>**qrgV S^4)Vt{v!m#?CV*U#R<;W]ЫQEQWn4[E꾄.QM&5BHPj:-JTQEQQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEe_۴*wyT$Hd)*280Ev B4sJѷc^zƵU{\ 5asMWӧs+><+Ks#3W]äZA7>uJ>)c'>]i7.w$c2 ^mukCn 1Vy}M;x $:sfŠ(AR3k=x~=Aq~t+mrv|uOWVc x;~9_b6t*1Ī{;^qoռJ2>Zi, ppr nx=|e]b)v{Ky z O=Bi\SAW~e|Q&F Ĭ$ +SŐwBLߥr]#sev٧9|+kkF+~Wu[ m"A1z~mNZV| a==MiVg?sЅi'YJ@@=F :X}ϓYuX㨢FycooO3}zt5w)y$'zEo]=v)Rvv6qʞ .+cu=8y}^Y[yż7QdCهOq}跸99G\ooK^&~gXw8mWFNczQh_c !ma]JV +<>֊6 (?^(bX:sL`][_WQTt :9X|?ǃ%8Э VJt_8t6 ɧZ)VXPF8bnp{ N8_V~v*u$R#8==TӺ7#8KgSM[ \z@*Q)964B8ӂJ+Ӭ5y]Q_$nϯӽtQ1tU:1.JՒ)G%><=kq ߿Sk [1x1zՊxp0>D/=ԫ^\Ϯ/躼*=^^qCwXm#5TM%4^G9,j:hRPQ?5q_J^((((((((((((((((( EbKm _ ( s?Ns\dr<2p]G&E\:_<x\L;z6OTEѮXĀOnF1%Ƌ[@hqߎwW-֞!j`}Kb>g]EW}PE$I %PbdQE ( ( ( oç6?Ө)YHPTzUj2NJөVҗ,];Kn/(0da~i|E-'%Z]pe.y3(]r;1 .v/e5!)˖(bidzd8{"S4\LLsƉfg/#5{|? :~_fy**T5y3 FŢ(/g?.# e؏ȚxKk>KY8^c>VK1SN?W=:柅M7{]{Wic>VK2Ssj<+5Ru\kvڎT?'9֝W[ 4`i#U87x+#0qƟ.&JRQPuQ@Q@Q@Q@Q@Q@Q@T7vy1F\m9曲&B[XCh8GX:rNg1.r/_ֺ}>noo\ol7gi?1:ur2ɔ_v;Q]԰4ᬵ>WBV$M!y]VciQ]Ͷۻ (Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@oi~#kHR#$H0^l J5,׃WT%gն܎'62V_Oִݶ{f1ê+^ϫ񄖘_?EqSI4 0,o|Uv=Xqf_%w̽W6vW3 w8_ƭl):pXO Y}e6i#ni}m|҉7X4VHU6}V(EQ@Q@Q@Q@Q@Q@Q@j'!x \3;f,rI9$ץrhE :3},lir%p\]GQ욿_$yˤi(Vs.T 1nTFB)LgEu[³./w >?2v?ÙrszjkiԮ:SOTxdŠ(HQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEKoo5Ԣ(#iQzMʌe6vȨo ]J3q*@>f~m>1)᎟r҆~"Q_-u-i뎃zkY u:8;Pn>=UTPUF Z⩏/C|'g]}_ĩe.  X?Nn+RrwljTт8DQE#@((((((f!f1$d!m \RmQ\&ԡ𣎪֙ U[k5O|SfvW U[hy[-4X?֬Š*V#x)#~MQ'Yww*e 0AW+[K[[bs$k'9϶sӶ= 5NX5Ok:0Yҗ4>cTQEw(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQWt{]J)T=;MhSJʛJ慄ao%RS?:mᵈEk:ST !Q ?_ ¼ZX> ZH'ߙ_﹧Ec]:-Isbc* +2Uϛu!vS0šb8OJI_I$p^WTA՘ lS:TA(i]ƣ0XԬy#_>Ycn@QԞ}Og^)ivv9'0nOizOEW1Q@Q@Q@Q@Q@Q@Q@/t[qҹGwlLÿoƊޖ&-dLrnm.?3S-?xrNJӈ'E9RϯzqPϱgb ɮh2WO̥EWIQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ohkKRr?n \4E7цv$N2zӢ3O>$dŧH};xVP$h0TQ^cw՟s$VV-7uF^q{V%/*푐\cE\1RkFsRPVTiؖ(:((((( nkhc dWh9~sZk_ uFx@롮7]ўVf$OOۆUף>g;x3 6Kv]uvױ﷙d::ŤX) [~$ M5u2-`r`T9_u_2VPEc}>F!؆3ӏ;{{ 'igGj*Jq>*^W0O ,¹$}>9\+#e*pA ץfGۖU)ÿ'Wfjm熩NZ[~(X(((((((((((((((((+д/'m~q>ўѐF,yOW^>qx_O]*+mb2"ƃW=⟽~kA*Bu_f\iY{s@c\;ص^nz{fg/#4C ,0y(R4yⱲt{zY|OzjjKFyT"<é=k,R+t9ϩ:EgVwl- oE(fTRUFI' Ȱ?uy!b"$9sϰ?LNRM_JNoޛ_Cb(:B()$k"#:|Ryluǭm-QE ̸#ՖvD O֝`c[βt}q0i- }XokINQ53 d?+_*9d4C4wиxd0+Tϣ*C48M_K}2.ɓv>uz-7={YI=l`0g [N ^w//ֵ:9$@;#ShSiKhEE'"7R"YV~Ɵ_0+C(((((((((((((((((z(UuU"Tnt\NLƤyTWK\Mu)yG=ڢI%dxܤWQ8,fOXsV{ylgw?zq1$H0Tz\8ܱ[˕j5o_Ek`kQ>tʤb}/K I֬^#I&+^Jg'r*NO+fgbřI'$|1oifR2 ` uׄhWSrM\9UmvVZ~TsʰA$ XԱy)_C)IE9={ #Ÿ9t549Ko,8;^]*]x%?My't܂Ha*:32B6I\ϋx?/vqk,m鷫cÁه_E[?7g6؎ooOʻ M/eQ.?H܊;y ep}RF8ãaEzUq~$>dQC.zN_Rpx_ JZ??[L4"<poU]:Ԭn>=س1fcI&4\LLsƣ_AQHE-aAD'μyH #8HL_ OZ֪e MɊ;pH36O^ߙoW s c_ԚS窟mOkqWJ)?w >f]z O=@f}سp$ @{9*;s_iW3sW3sŃ<~I"fQ:igZ_g1g½LUk 7G9qI\]5gn?x#[u,I E*H1^5)MKV? Xii~=?'HXѱRGL;~7(Y+e9kL/cWnޟsVu(¢ق18)Pnz\Ǵ=8>%E4hƒj&g[0jVI4Š(8(((((((((((((((((((*H%h'el 棢'GI'd1-&`:KirXtVTӧ+Nz%+QZ*7VT"UoWW []y^Gy[KnYK`d^tř3NI5X˃\tirÙ=n)~K`xe~0^ms :AԩSRę {Suw;uCN꜇"ߛEJek87}]lcٌ ]%+naj5K]:&5)0L]M&ǧIf 4йT?3ԭ اbS1f3LvS3f|F9O͉u-@o}Y;5rf\yOऱ*3k3K<52#%|fS#3D@OH3`=0ǣY2\{Qt{5c!2po)Xvm@=tr(zQ#tNBTm]/q9̖ dqfosC< ql Yy Fx)mv 2H3j3{pfsqfM9YIf +7{̔@3ʚIT0{f0O]శmp2=콥܇j; &?ҎgOxYz,"W%l3K<411 Rh80")3Z3'4<6}H!@W3\"-yf\f@d{3zDYEH̼Q*ѶcEQ̤{-T?iS\b[ˬp)b&(MܥZVԨ`}f_zYW k]$t)2㺈Q뷂\4 tL1XJ'a:' VbY,ku f)F,$Z<9asus K9YՆI>:H}%V;Iǎ6,Xm.Y[jr[o@sN29 x^<sL+,e'S>BXb,%,JĢ8Y+bIV%,e$^%'IXh'Xy'K1,$1 VI"/lvB*BCa!abapN"PNgT,Bb ,M|mXdkf¦Y>XoU]kX73n9^ުeL`!܋nگ> ϗ" *uOA|uH"\c%Zyc%UC:v(Cl?8_WֱrwNy9'f S3G/|]Q a9{SH,'KXR;9mW$KFXcQܰ4Ywִc{_SM6, `f>VU잙Xwf󰪂cߎXXu(EEjZ@՝?vZXU]kV͹h,99MŢ&*~X3$L(P9,ߛ`^< >|+!$|;EJW[R^Z,(`pc<ޟۖf5>\<:}K Fϱ'}&K o+ۑNr-~2_8WWIbm1)<,-X=ZRX=&,bQV*V,Ja*E,%,J+j"jQH~N V,Bċ"d+GBZ*īt͊{5+V>XXxᓢoݭX3 >+|ZN$c^H"V.V:`- `B Xp ,LpX۱Rw"B,ہCbskFdo4lDˆIw >p$õ߻oiʴncw6ZAZ olno,CVI SQEhE-Ii%´xh"G+pjBT6Rn&&l2ks9Gʄ;{{,A .s2|c"?LU\x5>U/Gc9Jk U"VVňר~M/ HXYC^3FqY{!}h]@ZPQJGԯ JLk=TQDL f娨y%Vb;+P1^JHxt<OWL+,䄫'~rO+a_}Z`E*.V6X'+ I/_ꨢKaOZ`uTQ띧OŀVUbZأ ^i3ߤ˧Ub%ׇ ΟBkXZi*~3-D'xb7O؅RDK$Vu6?Қ*Nl,W fASW~Q:b+)^NcТm#b@hU<e TIDATx흉8q ٝ=7S7eܡPJ)%U'U)]W ;~8vz7v:돏g޴g-Ok_3_hFk҆S|˩էG[ԡ:>>AAˉ-߷Ǻ5-uTPv{TvLɬ#ivPwQ[:LM!|?b9PۓPHkCˢ"ÑdR([c۶'jkǑ~:};,dvj#X>t{ʡ>V;@Mܒ赧R{:$V=Ȗ%%*v'(;לm)HZuhI N&)u]˚pƐá=읂PG}Kq Ǫ>/ktFoN5$=cPcĐNh|VݽNj) \gqg:/úof$fpGsaWNCZ>M?XAoƉΗќ}Rl*nJDt vr ~#3m̪p/6DH z u𝋵XgbXzyM6_c¬6^=eɬ>;CI>͵7Qƅ[1ޅ>?XZ +|I_ՍzZCW. RjJ r%(]Bf$F)PZRAzih[Y[d:mU .cZmq!jA zL:)r X'2P٤$z<{F!+ybka 5kh6N:S" 22U0xSp02ԫ Z]jD?{34Ď01ZQ[R+#q"K:5VrSZ2x.҅k%ƙ.h.rfIج(i4$7 aK2H515)F?˃a$3EH:ՠgE%of >ܥF "ƌ`T}8pB$K v\c)] ~u CdLrD^ uAzEwëVK7&bHZ<ي@qb]1aGOUy*|$Gw1ݮC:̚-fY$?iVY(w9 1HF\+d T$'ܺ? 2Ye+Byr`Q|74)bAL 4Ԙydf|^=rsWmWABQ jBx(xp9^+C &/mWK3[=A"Z<R \fHhⓂ GzHr6Halr]4jaBI ,SrBh[I W|cvId&.W{B,Vϕ hq;V}à)Wd٣8bxetz#Bl觱-tmGNr^`Mb "1S8վ@gD.@ aw4K/ı|bNf*LaA;Z?&b"9#b+|!{3 .[+ͩ#R򴓍 ՑX'1Wc&~cVEdk-+Y&HJfe¾.L+3f/ă;ǦVXc٠qD#&a9PjPxB1,ʊ7>泇ΆbBnz8w>W-giw2X^{s!VE>,Nt7aC-V k9`=/Hd54dŨ^DL!dƬe}J1)b(@azDC ZƵ 31xQ ɀ5Xڋ&@8c\`ph֖H`2!l.[cҥ=lD\ם^ bLB6R2 OG&NqY)[#5\C4)Oܦ>>*)x >=KMp_;ҫZ Z ~| (C+jY"ƶvIENDB`GD-2.50/t/test.out.2.jpeg0000644000175100017510000003141412164634363014364 0ustar lsteinlsteinJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222,," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( +/Q&-i3X&+2qy5^_y%#Ld!E*z%|Jw:khOt$!ՈJjxEnm;( Hb@_+ d;0م z&";f o_zg|y+iwqg>TpG=kĺ/TKb*RџY^}|3}+#z0 1ےS`Et򖟨%q^Lhsۡ~!tA=U\CѽG8C'/6Fְ~GoEWaAEPEPEPEPEPEPEPEPEPEPEPEP'|Oc  !ϴ.ׂrH냁x8umSƞ(Ԯe& =I<𽸔[Y(`p 2 54Ap;(3W^ ,D91ivAxrH%p$/{(zI&_Ӵ&>^58gnAkT`(j1]OJ2&QUg`I5 Lkdl~9Һ (L #z}=ZYysM}g*OTqڗT2 T|T. KfNhWh-rP+Ȍ(ea#xZWYZ]NraE{XlٴWK9q92Gz)¢ 朇Qȁ$Cz}:ruZ^-)2J? 'Y:][ӟ@F=9?8`mcz(Zily$fK[{Y'Yba x>o _5֜u=?1_5~9Rx:ߪO|!h|Q%bK[P I ?Z?{ cld <ZWC]gzbaU_/(Š((((((((((/i~qŘxi>}[2^=.R%ڧ}=x+ Ww[- *C>ჸWك=wr '󽣩ٛJvMۤ덣#+𝪥L;$s{WE_-὎-~]?31S杻Q^QEQExI椱F}s /=x }L³\yLٰ2@l$A_Vamcw+0k(TG֩KFu4mbc|~ עQ҈~A瑸3Wx:f[ˈ@Z08k4F%*gWoџYOz>+?8 ( ( ( ( ( ( ( ( ( ( T ݿ\ӻЊ6`&mn.%yy$3I{ׯ~G(4t>%w+83>xj4}T)e9]i5R ʊæA#?ξ;kJ>u/nU;oiʃr8csVzpPvZ-݅QV ((+xfw2rFT_x};wP(Yxܠi_۪|+oב»Tdy$ܢNWDŽ?'7p??Z<05UXzy#x&7TQYI3,$g ;bPIkJD~}RpQE2(((((((((b%۷yQ{c5|,rC#*2HU ׷yOs_|+Wo'ªqv`F{kr3oup! $l'}$IRu0PEWQ@Q@Q@x' & +. l$#5uu*^%} HϘv| q20ЊJܵ68 i楹 6jv_fGõy0?<5kgN2KndӏN+VU1kKuR8 +ɂ((((((((((suټP.Udw f.HS={pֹ Z\7 INSw91 Oy٥/ik|7Nʁ"%1 y2$h89XRD9FE|\q0%⍸f5)R}u5F~ Zߤ8&*nӏ-_w++QL3 \{]?GQQ|$ʮ^NN01Jtft+ T5pe_QE0QEQ\'?_ _؅Q`dbA]ps@2@m3.c} IId"kAk_!c5YK}w8,NDk'"ݟKX W{y/v? n 46gev@2N+mkBH'xԈA tkkWEuw~Sxa}_E!EPEPEPEPEPEPEPEPEPEPTu2-gGӦ;Vt`;QN2qjKt)EI8mͼRN%r.A2=uMaO?z;FZMU47P(0P1' \xZ;#-kpq8z:9Ֆ_{7oFvXa=+ٮ18b$I pq2=z eX4?^3 ,gy^24*8XKFzW|Me0]Zr76#Wnbt`p08;+ؼ/L>gx~ǩ>cp7WFjͲ f5=;Z(<;w{YP0Tհ YgGoi~յixU^^W=v8 8|S}jy8 X*MOz]_ȁBG @ '$N=bV>m\=o*ƶ">#$p4`1L:ץW2]RbE>Re~W}?u֫Ij4`01/) ޠ^;XpFb/rO'_j,"[֝wUG#@1ǥq8k?:H"K?!>|xž%]&8/Ӄ== 2Jtcg~}T{[O2̱NKM[Ls/?UoZ]c'/!WWBOS.n]{ɜ8_o/3X%^u- ơ"vF_P\j83^ jˡ搳1ӓUoY]*"/0|,XT+{;k:⣀۔ok}]?|9OjOMO[E%yUXyi'^ .? ?µkW~W9lFR#ؤ(㪶tT|O 4qE_0x: ^q$?VKZ.T-:緰U'Wӥ뽾G-W~|G)fRU$?W]ԼM *,ڼoF_UU'FsbqwW|3*mEe.? ]N L[y!e}+"zKjĭzԚ3^hWNżsTZQirۿdXb*4.ǢQEyEPEPEPEPEPvL7*u&7+GמGC^ i>=Q4-rFAЂ5]s-𕿉l.o\C1_w\_yyĿZ~+1gqry5\^h2= 5iZz88K:zo(a{twdvu7-ڏzOӼ3I^UomFa!_2۠f䞨ܿ8*u5x >{ &#y@u㓞> igzI6zyw~Gv$BOC۞? ޯ>?ƽfqjizeU\c44q$1EDF)/ Vc$B(y<А=?Ʀ2ܯt#{KY?ta _>NZnQYG0Q˱$EE mC]=E t#J: csLutG7F7V6}y-`~?nk/}_i3qW^͟E^[j "UNXCm}^e6y5%yzxB?_ʯϛ*αOkH<7+cO6L~v~ _Kyw>l!4'l&T¯l\]?װN2"G5j]m}Y^űXglDӡ!Fy&f<% B)m:?]f!*φ91^|4H?k/<>wrڷ.lԼ6v0y ڎqM׽ =F.4:IU5\Sbjwϧ#—i$ qj/riNk)R骜9@s-_ T-yXZyZ=4zξ/J5v ($((((((|3x Q$P 6G>הk^ 3\ľsFIf_UNGWxk.sz7!i<8J[|)# t<+ğ"o>kt 'o/G5s¾5ƌ19kM&yL ɷ˧&?kͫ-GynK/fx#L#SyU}җ꿻{|E.\|!e>[8&ƗuO^ ^? ›i7l{V?Q: d(((((((((((,"C#\ZR2L\W^ !^x{Wa'Vn*KY6G5`|g]t:|Mhr[_GtTzV>6¼'MxZߕ 鏍y?/y' y\!l?^[__;/cnKgxcKΖ`LLG8#޹frٹhxK~m` ;NskVrE|쯩.1NK= PҴۯb<K}s·5cK? mfƸIFqz6պ9~c.h:]-elHdĽ|78!qFFFE^Y9]z7:nw~fwg 򰐨*>ý1_'gQW?&OV 2Kce~s~[+>_¾y|⼾ӗ%oÚmY\K+~;U_:iQar~?uo.;'fq uQڸ ?յݗi>l*U)SqቅZRQ}XKi+R7uW3?%s(m6K=`1ҷ-x~ǛoZp,|ǧ[ž'WJ<${W m-5q#L_2y'urD 2e,'s^srח}UQRckmb}J).#ʪNA?JIuiE;N XMq]2:?i–ѿ;vfў-|ϑ&Q}~"N|?=O$դVˮN9+ng ^\4yЌcU5_iŮG{:u ~m,BdR\ʯoxXU_HYOy%z$ V_:$мRkGR7Xo3?%FFJm s}HJ$]bK-V=&%[Z#'5?fu|̀3xj-(45Toƺ Nuŕ\鐶⊘UF0cC JJ: ~ 0d[&>Q]QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU#iecٖȉsq/r=FBM-6^8?(zJϷ#ӛ yhGFBM-6^8?(zJfZ"&m̼p~Q^}?.[̻ER:6Z:mḧ12G#zPtm,,t2?0.cn>eGve*Ѵбl@dD9҃iecٖȉsq/r=oG7˵.TfZ"&m̼p~QK- 6̴DL ۏx=(~?=9~]vtm,,t2?0.cn>eGYhXe2"`\|AEn˴U#iecٖȉsq/r=FBM-6^8?(zJ/>ߏNokw-]K- 6̴DL ۏx=(:6Z:mḧ12G#zQyzs|[o2HYhXe2"`\|AAѴбl@dD9ҋϷ#ӛ yhGFBM-6^8?(zJfZ"&m̼p~Q^}?.[̻ER:6Z:mḧ12G#zPtm,,t2?0.cn>eGve*Ѵбl@dD9҃iecٖȉsq/r=oG7˵.TfZ"&m̼p~QK- 6̴DL ۏx=(~?=9~]vtm,,t2?0.cn>eGYhXe2"`\|AEn˴U#iecٖȉsq/r=FBM-6^8?(zJ/>ߏNokw-]K- 6̴DL ۏx=(:6Z:mḧ12G#zQyzs|[o2HYhXe2"`\|AAѴбl@dD9ҋϷ#ӛ yhGFBM-6^8?(zJfZ"&m̼p~Q^}?.[̻ER:6Z:mḧ12G#zU-BG POӗU}%*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEGD-2.50/t/test.out.4.png-20000644000175100017510000000041512164634363014361 0ustar lsteinlsteinPNG  IHDRd2[- PLTE3JIDAT 0 E ̓z =0@6ʊD&?cۘKjGUOςx|pvrՑ3 9l`deVM2lh8ceB{"r{ܩ?Oy(k> S϶M(*IENDB`GD-2.50/MANIFEST0000644000175100017510000000276212164636126012461 0ustar lsteinlsteinChangeLog GD.pm GD.xs GD/Image.pm.PLS GD/Polygon.pm GD/Polyline.pm GD/Simple.pm GD/Group.pm MANIFEST META.yml Module meta-data (added by MakeMaker) Makefile.PL README README.QUICKDRAW README.unix bdf_scripts/README bdf_scripts/bdf2gdfont.PLS bdf_scripts/bdftogd demos/brushes.pl demos/copies.pl demos/fills.pl demos/font_list.png demos/fonttest demos/gd_example.cgi demos/polyline.pl demos/polys.pl demos/shapes.pl demos/tile.png demos/transform.pl demos/truetype_test demos/ttf.pl qd.pl t/GD.t t/Generic.ttf t/Polyline.t t/frog.jpg t/frog.xpm t/palettemap.png t/test.out.1.png t/test.out.10.gif t/test.out.10.jpeg t/test.out.10.png t/test.out.10.png-1 t/test.out.10.png-2 t/test.out.10.png-3 t/test.out.2.gif t/test.out.2.jpeg t/test.out.2.png t/test.out.2.png-1 t/test.out.3.gif t/test.out.3.jpeg t/test.out.3.png t/test.out.3.png-1 t/test.out.4.gif t/test.out.4.jpeg t/test.out.4.png t/test.out.4.png-1 t/test.out.4.png-2 t/test.out.5.gif t/test.out.5.jpeg t/test.out.5.png t/test.out.5.png-1 t/test.out.6.gif t/test.out.6.jpeg t/test.out.6.png t/test.out.6.png-1 t/test.out.7.gif t/test.out.7.jpeg t/test.out.7.png t/test.out.7.png-1 t/test.out.8.gif t/test.out.8.jpeg t/test.out.8.png t/test.out.8.png-1 t/test.out.8.png-2 t/test.out.8.png-3 t/test.out.8.png-4 t/test.out.8.png-5 t/test.out.8.png-6 t/test.out.9.gif t/test.out.9.jpeg t/test.out.9.png t/test.out.9.png-1 t/test.out.9.png-2 t/tile.gif t/tile.jpeg t/tile.png typemap META.json Module JSON meta-data (added by MakeMaker) GD-2.50/META.json0000664000175100017510000000154012164636125012743 0ustar lsteinlstein{ "abstract" : "Interface to Gd Graphics Library", "author" : [ "Lincoln Stein (lstein@cshl.org)" ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 6.68, CPAN::Meta::Converter version 2.112621", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "GD", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : 0 } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : 0 } }, "runtime" : { "requires" : { "Math::Trig" : 0 } } }, "release_status" : "stable", "version" : "2.50" } GD-2.50/typemap0000644000175100017510000000010212164634363012715 0ustar lsteinlsteinTYPEMAP GD::Image T_PTROBJ GD::Font T_PTROBJ GD::Polygon T_PTROBJ GD-2.50/ChangeLog0000644000175100017510000001635212164635764013111 0ustar lsteinlstein2.50 Fix gdUseFontConfig so that it can be called as a class method. 2.49 Add GitHub information to README. 2.48 Fix compile crash on windows and strawberry (https://rt.cpan.org/Public/Bug/Display.html?id=67990). 2.47 Fix compilation on older perl's without the Newxz macros. 2.46 Added a basic "use" test for GD::Simple 2.45 Clarified the GD license. There is now a formal LICENSE file in the package. 2.44 GD::Group now installed properly. Quenched compiler warning caused by Newxs() calls. 2.43 Added "transparent" color to GD::Simple. Fixed Makefile so that GD/Image.pm depends both on GD/Image.pm.PLS and .config.cache 2.42 Fixed magic number detection to autodetect certain missed jpeg files (thanks to Mike Walker) 2.41 Added backend support for grouping features in GD::SVG module. 2.40 ** Do not use - contains a bug ** 2.39 Makefile.PL will refuse to run if the proper version of libgd is unavailable. 2.38 Fixed bizarre warning about /usr/include/gd.h != /usr/include/gd.h. 2.37 GD/Image.pm did not bring in croak() properly, meaning that incorrect error messages are printed out when any of the newFromXXX() calls are made. 2.36 Instructions on using gdAntiAliased with palette images. 2.35 Some instructions on installation for Windows users. Doesn't push libpng onto @LIBS unless png support is requested. Supports Storable's freeze/thaw via a custom serializer. Remove "scale redefined" message during compilation of Polyline. 2.34 Added a check for stray gd.h include files from older installations. If any are found, Makefile.PL will issue a warning. Fixed incorrect documentation of GD::Simple->string() method. The method call *does* move the pen. 2.33 Added appropriate #ifdefs to allow to compile under version 5.6.0 (due to lack of threading macros before 5.8). 2.32 Added a GD::Simple->HSVtoRGB() method. Documentation fixes from Mark Manning. Added a clear() method to GD::Polygon to remove all vertices. 2.31 Fixed GD::Simple->transparent to support symbolic color names. Made changes that should render the module thread-safe. Changed newSVpv calls to newSVpvn, in hopes of improving performance. Added a GD::Simple->HSVtoRGB() method. Fixed incorrect freeing of user-provided raw data in newFromGdData() and newFromGd2Data() (this caused segfaults; patch provided by Nigel Sandever) 2.30 Migrated polyline() support into GD::Simple. 2.29 Better support for fonts and brushed patterns in GD::Simple 2.28 Having troubles getting all the modules installed correctly. Should work now. 2.27 Reworked the way that GD.pm is created at compile time so that CPAN picks up correct version information. No code changes. 2.26 CPAN isn't propagating GD, so I'll upload another version 2.25 Fixed Makefile.PL so that GD::Polyline and GD::Simple are installed (thanks to Guy Albertelli). 2.24 Fixed gif/anim gif support so that you can't have animated gif support without having gif support. 2.23 Added patch from Slaven Rezic which makes it possible to call GD constants in an OO way (without generating warnings), and removes #! from the top of autogenerated GD.pm Rewrote tests 11 and 12 - if they continue to randomly fail on various platforms, they will be removed. 2.22 Changed the way the gd and gd2 round-trip tests are evaluated. This might fix test failures that have been reported on some platforms. 2.21 Regression tests are now functional for versions of libgd compiled exclusively with PNG, JPEG or GIF support. 2.20 GD::Image->newFromGdData() and newFromGd2Data() got broken somewhere along the line. They are now fixed (and have a regression test). Added copyRotated() method. 2.19 Added a HAVE_FTCIRCLE define to handle versions of libgd that do not have the gdImageStringFTCircle() function. 2.18 This version needs libgd 2.0.28 or higher. Fixed documentation bug in synopsis of GD::Simple. Updated Polyline to version 0.20 2.17 Added animated GIF patches from Jaakko Hyvtti. Added dynamic bitmapped font loading support. Added fontconfig support. Added a simplified API called GD::Simple. Added support for kern control and other libgd-based FT improvements. Fixed a define that caused gif functions to be miscompiled on some platforms. Documentation fixes. 2.16 Fixed bug in GIF #IFDEFs pointed out by BZAJAC Added #IFDEF for WIN32 provided by Randy Kobes 2.15 Brought back GIF support (requires libgd 2.0.28 or higher). Takes advantage of gdlib-config support in libgd 2.0.27 or higher. 2.14 Support for AMD64 libraries. 2.12 Fixed regression test 10 to succeed when used with libgd 2.0.22 2.11 More alpha functions from Cory Watson 2.10 Suppress CAPI warning. Warn about Math::Trig warning 2.09 VMS documentation patch from Martin Zinser Non-standard library finding path options from Peter Kruty 2.08 Applied 5.00503 compatibility patch from Mathieu Arnold New check for JPEG magic tag returned by some digital cameras. 2.07 Now compatible with (and requires!) libgd 2.0.12. Added setThickness() method. Added support for compression level argument to png(). Added support for antialiasing drawing using setAntiAliased() and setAntiAliasedDontBled(). Added extended options to stringFT(). Added filledArc(), ellipse() and filledEllipse() methods. Added command-line options to Makefile.PL provided by David Eisenberg. 2.06 Added saveAlpha() and alphaBlending() methods. 2.05 Alpha methods courtesy Georges Arnould. 2.041 Added a regression test to detect certain versions of freetype. 2.04 Removed the patch file since Tom has begun adding his own configure file. Changed the context member from free to gd_free to allow for compiling. Fixed the regression tests since the gd-generated images have changed slightly. 2.03 Skipped so as to remain version number compatible with libgd. 2.02 Changed Math::Trig version requirement from 0.0 to 1.0 as Perl 5.8 no long recognizes this as a valid version number. 2.01 Added Math::Trig to the prerequisites because GD::Polyline needs it. 2.00 Folded in support for gd version 2.0 from Dan Palermo Folded in support for splines (GD::Polyline) from Dan Harasty. Removed all GIF support. 1.43 Added demo of Type1 fonts to truetype demo from Slaven Rezic. 1.42 Fixed the patch_gd.pl file Version 2.0 is coming. 1.39 Fixed FreeType test, at least on some platforms. Added patches from Stephen Clouse to allow to build on 5.8.0rc1. 1.35 Patches to support Philip Warner's GIF-reinstating library maintained at http://www.rime.com.au/gd/ 1.34 Fixed problems that arise when compiling against older versions of libgd that do not have XPM support. 1.33 Updated patch file for gd 1.8.4 1.32 Added support for Tru64 UNIX v5.0 1.29 Fixed a corrupted .xpm file in the regression suite (caused test 9 to fail) 1.28 Added support for gd 1.8.3 1.27 Fixed strict refs problem on 5.00503 and earlier 1.26 Brought up to date with libgd 1.8.1 1.24-1.25 More tweaks to Makefile.PL. 1.23 Added a bunch more libraries and includes... might or might not port to other platforms now 1.22 Fix to Makefile.PL to accomodate linking static libraries. Added newFromGd2Part() method. Supports libgd 1.7.1. 1.21 Slight fix in regression tests so that test 8 doesn't fail when compiled without TrueType support. 1.20 Rewritten for libgd 1.6.3 1.19 Fixed Makefile.PL for better compilation on Windoze machines GD-2.50/qd.pl0000644000175100017510000010004612164634363012264 0ustar lsteinlstein#!/usr/local/bin/perl # $Id: qd.pl,v 1.1 2001-12-06 23:25:48 lstein Exp $ # This is a package of routines that let you create Macintosh # PICT files from within perl. It implements a subset of Quickdraw # drawing commands, primarily those related to line drawing, rectangles, # ovals, polygons, and text. Flagrantly absent are: regions and the # snazzy color transfer modes. Regions are absent because they were # more trouble than I had time for, and the transfer modes because I # never use them. (The latter shouldn't be too hard to add.) Also # missing are the pixmap commands. If you want to do pixmaps, you # should be using the ppm utilities. # A QUICK TUTORIAL ON QUICKDRAW # # Quickdraw is not Postscript. You cannot write routines in it or get # (any useful) information out of it. Quickdraw pictures are a series of # drawing commands, concatenated together in a binary format. # # A Macintosh picture consists of a header describing the size of the # picture and its bounding rectangle, followed by a series of drawing # commands, followed by a termination code. This perl library is # modeled closely on the way that you would draw a picture on the Mac. # First you open the picture with the &qd'OpenPicture() command. This # initializes some data structures. Then you call a series of drawing # subroutines, such as &qd'TextFont(), &qd'MoveTo(), &qd'DrawString(). # These routines append their data to the growing (but still private) # picture. You then close the picture with &qd'ClosePicture. This # returns a scalar variable containing the binary picture data. # RECTANGLES # # To open a picture you need to define a rectangle that will serve as # its frame and will define its drawing area. The rectangle is (of # course) a binary structure. The following utilities allow you to # create and manipulate rectangles: # # &qd'SetRect(*myRect,left,top,right,bottom); # Set the sides of $myRect # &qd'OffsetRect(*myRect,deltaH,deltaV); # Shift the rectangle as indicated # &qd'InsetRect(*myRect,deltaH,deltaV); # Shrink rectangle by size indicated # OPENING A PICTURE # # Pass a previously-defined rectangle to the routine OpenPicture. Only one picture # may be open at a time. The rectangle defines the drawing area in pixels. # A printer page is 8.5 x 11 inches, at 72 pixels per inch = 612 x 792 pixels. # # &qd'OpenPicture($myRect); # # You will next very likely want to set the clipping rectangle to the same rectangle # you used to open the picture with. Clipping rectangles limit quickdraw's drawing # to the area within the rectangle. Even if you don't use clipping, however, it's a # good idea to define the rectangle because some drawing programs behave eratically # when displaying unclipped pictures. # # You then issue drawing commands. When you're done you can get the picture data with # something like $pictData = &qd'ClosePicture; # # SETTING THE FOREGROUND AND BACKGROUND COLORS # # The foreground color is the color of the ink when a "frame" or "paint" command # is given. The background color is the color of the erased area when an "erase" # command is given. The defaults are black and white. The colors can be changed # in either of two ways: # # 1. The "old" 8-color system: black, white, red, green, blue, cyan, magenta, yellow # Call the routines &qd'FgColor() and &qd'BgColor() with one of the constants # $qd'REDCOLOR,$qd'GREENCOLOR, etc. This gives you a limited number of highly # satured colors. # # 2. The new 24-bit color system. Call the routines &qd'RGBForeColor() and # &qd'RGBBackColor(), passing the routines the red, green and blue components # of the color. These components are two-byte unsigned integers, so you can choose # any value between 0x000 and 0xFFFF. Higher is darker, so: # (0x0000,0x0000,0x0000) = BLACK # (0xFFFFF,0xFFFF,0xFFFF) = WHITE # (0xFFFFF,0x0000,0x0000) = PURE RED # etc. # SETTING THE PATTERN # # Like colors, the drawing commands use the current pattern, a 32 row x 32 column # bit array that defines the pattern of the "ink". # The default pattern is $qd'BLACK, which is solid black. The only # other pattern I've defined is $qd'GRAY, which is a 50% checkerboard. You # might want to define others. # # The current pattern is set using &qd'PenPat($myPattern). # LINE DRAWING # # Quickdraw has the concept of the "current point" of the pen. Generally # you move the pen to a point and then start drawing. The next time you draw, # the pen will be wherever the last drawing command left it. In addition, the # pen has a width, a pattern and a color. In the below descriptions, # h=horizontal, v=vertical # # &qd'MoveTo(h,v) # Move to indicated coordinates (0,0 is upper left of picture) # &qd'LineTo(h,v) # Draw from current position to indicated position # &qd'Line(dh,dv) # Draw a line dh pixels horizontally, dv pixels vertically, # starting at current position # &qd'PenSize(h,v) # Set the size of the pen to h pixels wide, v pixels high # PEN SCALING # # The original quickdraw was incapable of drawing at higher than the screen resolution, # so even if the PenSize is set to (1,1) the lines will appear chunky when printed out # on the laserwriter (which has four times the resolution of the screen). Call # &qd'Scale(1,4) to fix this problem by shrinking the pen down to a quarter of its # (1,1) size. # # &qd'Scale(numerator,denominator) # Scale the pen by the fraction numerator/denominator # TEXT # # &qd'TextFont(fontCode) # Set the current font to indicated code. Currently # defined fonts are $qd'TIMES, $qd'NEWCENTURYSCHOOLBK, # $qd'SYMBOL, $qd'HELVETICA, and $qd'COURIER. # # &qd'TextSize(size) # Set the current font size (in points). 12 point is typical # # &qd'TextFace(attributes) # Set one or more font style attributes. Currently defined # are $qd'PLAIN, $qd'BOLD, $qd'ITALIC, $qd'UNDERLINE, and # can be used in combination: # &qd'TextFace($qd'BOLD + $qd'ITALIC); # # &qd'DrawString(string) # Draw the indicated text. It will be drawn from the # current pen location. Word wrap is NOT supported. # Rotated text is NOT supported. # # &qd'TextWidth(string) # This will return an approximate width for the string # when it is printed in the current size, font and face. # Unfortunately, since perl has no access to the Macintosh # font description tables, the number returned by this # routine will be wildly inaccurate at best. # However, if you have X11R5 bdf fonts installed, we look # in the directory $qd'X11FONTS in order to find a bdf metrics # font to use. This will give you extremely accurate measurements. # Please set this variable to whatever is correct for your local # system. To add more fonts, put them in your bdf font directory # and update the %qd'font_metric_files array at the bottom of this # file. It maps a key consisting of the Quickdraw font number, # font size, and font style (0 for plain, 1 for italic, 2 for bold, # 3 for both) to the appropriate bdf file. # RECTANGLES # # Draw rectangles using the routines: # &qd'FrameRect($myRect); # Draw wire-frame rectangle # &qd'PaintRect($myRect); # Fill rectangle with current foreground # color and pattern # &qd'EraseRect($myRect); # Erase the rectangle (fill with bg color) # &qd'InvertRect($myRect); # Invert black and white in rectangle # OVALS # # Draw ovals using the routines: # &qd'FrameOval($myRect); # Draw wire-frame oval # &qd'PaintOval($myRect); # Fill oval with current foreground # color and pattern # &qd'EraseOval($myRect); # Erase the oval (fill with bg color) # &qd'InvertOval($myRect); # Invert black and white in oval # &qd'FillOval($myRect,$pat); # Fill with specified pattern # # ROUND RECTANGLES # # Draw round-cornered rectangles with these routines. They each take an oval radius # to determine the amount of curvature. Values of 10-20 are typical. # &qd'FrameRoundRect($myRect,$ovalWidth,$ovalHeight); # wire-frame outline # &qd'PaintRoundRect($myRect,$ovalWidth,$ovalHeight); # fill with current foreground # &qd'EraseRoundRect($myRect,$ovalWidth,$ovalHeight); # erase # &qd'InvertRoundRect($myRect,$ovalWidth,$ovalHeight);# invert # &qd'FillRoundRect($myRect,$ovalWidth,$ovalHeight,$pat); # fill with specified pattern # ARCS # Draw an arc subtending the specified rectangle. Angles are in degrees and # start pointing northward and get larger clockwise: # e.g. PaintArc($r,45,90) gives you a pie wedge from 2 o'clock to 5 o'clock # &qd'FrameArc($rect,$startAngle,$arcAngle); # wire-frame the arc # &qd'PaintArc($rect,$startAngle,$arcAngle); # fill with current foreground # &qd'EraseArc($rect,$startAngle,$arcAngle); # erase arc # &qd'InvertArc($rect,$startAngle,$arcAngle); # flip white and black # &qd'FillArc($rect,,$startAngle,$arcAngle,$pat); # fill with specified pattern # POLYGONS # Calling OpenPoly returns the name of a variable in which a growing # polygon structure will be stored. Once a polygon is opened, all drawing # commands cease to have an effect on the picture. Instead, all MoveTo, # LineTo and Line commands accumulate polygon vertices into the data structure. # Call ClosePoly to stop recording drawing commands. The polygon can now # be moved, scaled, drawn, filled and erased as many times as wished. Call # KillPoly to release the memory taken up by the polygon # $polygon = &qd'OpenPoly; # begin recording drawing commands # &qd'ClosePoly($polygon); # stop recording drawing commands # &qd'FramePoly($polygon); # wire-frame the polygon # &qd'PaintPoly($polygon); # fill with current foreground # &qd'ErasePoly($polygon); # erase polygon # &qd'FillPoly($polygon,$pat); # fill polygon with pattern # &qd'OffsetPoly($polygon,$dh,$dv); # translate poly by dh horizontally, dv vertically # &qd'MapPoly($polygon,$srcRect,$destRect); # map polygon from coordinate system defined by # source rectangle to that defined by destination # rectangle (moving or resizing it as needed) # PRINTING OUT THE PICTURE IN A FORM THAT THE MACINTOSH CAN READ # # The Mac expects its picture files to begin with 512 bytes of "application specific" # data. By default the picture data that you get will be proceeded by 512 bytes of # 0's. If you want something else, or if you just want the picture data, set the # package variable $qd'PICTHEADER to whatever you desire before calling ClosePicture. # In order for the picture data to be readable on the Macintosh, the file type must # be set to 'PICT'. A number of UNIX utilities, including mcvert and BinHex allow # you to do this. Or you can use the picttoppm utility (part of the netppm suite of # graphics tools) to translate the file into any format you desire. # A WORKING EXAMPLE # require "qd.pl"; # &qd'SetRect(*myRect,0,0,500,500); # Define a 500 pixel square # &qd'OpenPicture($myRect); # Begin defining the picture # &qd'ClipRect($myRect); # Always a good idea # &qd'MoveTo(5,5); # Move the pen to a starting point # &qd'LineTo(400,400); # A diagonal line # &qd'TextFont($qd'COURIER); # Set the font # &qd'MoveTo(50,20); # Move the pen to a new starting point # &qd'DrawString("Hello there!"); # Friendly greeting # &qd'SetRect(*myRect,80,80,250,250); # New rectangle # &qd'RGBForeColor(0x0000,0x0000,0xFFFF); # Set the color to blue # &qd'PaintRect($myRect); # Fill rectangle with that color # $data = &qd'ClosePicture; # Close picture and retrieve data # # Pipe through binhex, setting the creator type to JVWR for JPEG Viewer # # Note: BinHex is available at # open (BINHEX "| BinHex -t PICT -c JVWR -n 'An Example'"); # print BINHEX $data; # close BINHEX; # # Turn it into a GIF file, using the ppm utilities # open (GIF, "| picttoppm | ppmtogif -transparent white"); # print GIF $data; # close GIF; # MISCELLANEOUS NOTES # NOTE: For some reason the various FILL routines don't work as # advertised. They are simulated by a PnPat followed by a paint # -------------------------------------------------------------------- # Quickdraw-like functions -- now using PICT2 # -------------------------------------------------------------------- { package qd; # Directory to look in to find font metric definitions -- change this # for your installation $X11FONTS = '/usr/local/X11R5/X11/fonts/bdf'; # Apple quickdraw constants $TIMES = 20; $HELVETICA = 21; $COURIER = 22; $SYMBOL = 23; $NEWCENTURYSCHOOLBK = 34; $PLAIN = 0; $BOLD = 1; $ITALIC = 2; $UNDERLINE = 4; # Some minimal patterns -- define your own if you like $GRAY = pack ('n4',0xAA55,0xAA55,0xAA55,0xAA55); $DKGRAY = pack ('n4',0xDD77,0xDD77,0xDD77,0xDD77); $LTGRAY = pack ('n4',0x8822,0x8822,0x8822,0x8822); $WHITE = pack('n4',0x0000,0x0000,0x0000,0x0000); $BLACK = pack ('n4',0xFFFF,0xFFFF,0xFFFF,0xFFFF); # absolute colors to be used with FgColor/BgColor # (for better control, use RGBFgColor/RGBBgColor) $BLACKCOLOR = 33; $WHITECOLOR = 30; $REDCOLOR = 209; $GREENCOLOR = 329; $BLUECOLOR = 389; $CYANCOLOR = 269; $MAGENTACOLOR = 149; $YELLOWCOLOR = 89; # This defines the header used at the beginning of PICT files: $PICTHEADER = "\0" x 512; # These are phoney font metrics which we use when no font metrics files are # around to help us out. $fudgefactor = 0.55; $ITALICEXTRA = 0.05; $BOLDEXTRA = 0.08; # Initial starting values $textFont = $HELVETICA; $textSize = 12; $textFace = $PLAIN; $rgbfgcolor = pack('n*',0xFFFF,0xFFFF,0xFFFF); $rgbbgcolor = pack('n*',0,0,0); $fgcolor = $BLACKCOLOR; $bgcolor = $WHITECOLOR; $polySave = undef; $_PnPattern = $BLACK; $_polyName = "polygon000"; sub OpenPicture { # begin a picture local($rect) = @_; $currH = $currV = 0; # current pen position $pict = $PICTHEADER; # the header $pict .= pack('n',0); # size int (placeholder) $pict .= $rect; # pict frame $pict .= pack('n',0x0011); # Type 2 picture $pict .= pack('n',0x02FF); # version number $pict .= pack('nC24',0x0C00,0); # reserved header opcode + 24 bytes of reserved data # initialize the font and size &TextFont($textFont); &TextSize($textSize); &TextFace($textFace); } sub ClosePicture { # close pict and return it $pict .= pack ('n',0x00FF); # end of pict code substr($pict,512,2) = pack('n',length($pict) - 512); # fill in length return $pict; } sub ClipRect { local($rect) = @_; $pict .= pack('nn',0x0001,0x0A) . $rect; } sub PenPat { local($newpat) = @_; return unless $newpat ne $_PnPattern; $_PnPattern = $newpat; $pict .= pack('n',0x0009) . $_PnPattern; } sub RGBForeColor { local($rgb) = pack('n3',@_); return unless $rgb ne $rgbfgcolor; $rgbfgcolor = $rgb; $pict .= pack('n',0x001A) . $rgbfgcolor; } sub RGBBackColor { local($rgb) = pack('n3',@_); return unless $rgb ne $rgbbgcolor; $rgbbgcolor = $rgb; $pict .= pack('n',0x001B) . $rgbbgcolor; } sub FgColor { local($color) = @_; return unless $color != $fgcolor; $fgcolor = $color; $pict .= pack('nL',0x000E,$color); } sub BgColor { local($color) = @_; return unless $color != $bgcolor; $bgcolor = $color; $pict .= pack('nL',0x000F,$color); } sub TextFont { local($font) = @_; $textFont = $font; $pict .= pack('nn',0x0003,$font); } sub TextSize { local($size) = @_; $textSize = $size; $pict .= pack('nn',0x000D,$size); } sub PenSize { local($h,$v) = @_; $pict .= pack('nnn',0x0007,$v,$h); } sub TextFace { return if $textFace == @_[0]; $textFace = @_[0]; $pict .= pack ('nCC',0x0004,$textFace,0); # (zero added to pad to word) } sub DrawString { local($text) = @_; $text .= "\0" x ((length($text) + 1) % 2); # pad text to an odd length $pict .= pack('nnnC',0x0028,$currV,$currH,length($text)) . $text; } # RECTANGLE MANIPULATION ROUTINES. Note that # the rectangles are passed by NAME rather than by value, # in accordance with the MacOS way of doing things. sub SetRect { local(*r,$h1,$v1,$h2,$v2) = @_; $r = pack ('n4',$v1,$h1,$v2,$h2); } sub OffsetRect { local(*r,$x,$y) = @_; local($v1,$h1,$v2,$h2) = unpack('n4',$r); $h1 += $x; $h2 += $x; $v1 += $y; $v2 += $y; $r = pack ('n4',$v1,$h1,$v2,$h2); } sub InsetRect { local(*r,$x,$y) = @_; local($v1,$h1,$v2,$h2) = unpack('n4',$r); $h1 -= int($x/2); $h2 -= int($x/2); $v1 -= int($y/2); $v2 -= int($y/2); $r = pack ('n4',$v1,$h1,$v2,$h2); } # A few utility routine to translate between perl # arrays and rectangles. # four-element perl array to quickdraw rect structure sub a2r { local($top,$left,$bottom,$right) = @_; return pack('n4',$top,$left,$bottom,$right); } # rectangle to four-element perl array sub r2a { local($rect) = @_; return unpack('n4',$rect); } # associative array in which the keys are 'top','left','bottom','right' # to quickdraw rect structure sub aa2r { local(%r) = @_; return pack('n4',$r{'top'},$r{'left'},$r{'bottom'},$r{'right'}); } # quickdraw rect structure to associative array sub r2aa { local($r) = @_; local(%r); ($r{'top'},$r{'left'},$r{'bottom'},$r{'right'}) = unpack('n4',$r); return %r; } # LINE DRAWING ROUTINES sub MoveTo { ($currH,$currV) = @_; } sub Move { local($dh,$dv) = @_; $currH += $dh; $currV += $dv; } sub LineTo { local($h,$v) = @_; # Special handling for polygons if (defined(@polySave)) { &_addVertex(*polySave,$h,$v) } else { $pict .= pack('nn4',0x0020,$currV,$currH,$v,$h); } ($currH,$currV) = ($h,$v); } sub Line { local($dh,$dv) = @_; # Special handling for polygons if (defined(@polySave)) { &_addVertex(*polySave,$h,$v); } else { $pict .= pack('nn4',0x0020,$currV,$currH,$currV+$dv,$currH+$dh); } ($currH,$currV) = ($currH+$dh,$currV+$dv); } sub Scale { #use picComment to set laserwriter line scaling local($numerator,$denominator)= @_; $pict .= pack('nnnn2',0x00A1,182,4,$numerator,$denominator); } # Rectangles sub FrameRect { local($rect) = @_; $pict .= pack('n',0x0030) . $rect; } sub PaintRect { local($rect) = @_; $pict .= pack('n',0x0031) . $rect; } sub EraseRect { local($rect) = @_; $pict .= pack('n',0x0032) . $rect; } sub InvertRect { local($rect) = @_; $pict .= pack('n',0x0033) . $rect; } sub FillRect { local($rect,$pattern) = @_; local($oldpat) = $_PnPattern; &PenPat($pattern); &PaintRect($rect); &PenPat($oldpat); } # Ovals sub FrameOval { local($rect) = @_; $pict .= pack('n',0x0050) . $rect; } sub PaintOval { local($rect) = @_; $pict .= pack('n',0x0051) . $rect; } sub EraseOval { local($rect) = @_; $pict .= pack('n',0x0052) . $rect; } sub InvertOval { local($rect) = @_; $pict .= pack('n',0x0053) . $rect; } sub FillOval { local($rect,$pattern) = @_; local($oldpat) = $_PnPattern; &PenPat($pattern); &PaintOval($rect); &PenPat($oldpat); } # Arcs sub FrameArc { local($rect,$startAngle,$arcAngle) = @_; $pict .= pack('n',0x0060) . $rect; $pict .= pack('nn',$startAngle,$arcAngle); } sub PaintArc { local($rect,$startAngle,$arcAngle) = @_; $pict .= pack('n',0x0061) . $rect; $pict .= pack('nn',$startAngle,$arcAngle); } sub EraseArc { local($rect,$startAngle,$arcAngle) = @_; $pict .= pack('n',0x0062) . $rect; $pict .= pack('nn',$startAngle,$arcAngle); } sub InvertArc { local($rect,$startAngle,$arcAngle) = @_; $pict .= pack('n',0x0063) . $rect; $pict .= pack('nn',$startAngle,$arcAngle); } sub FillArc { local($rect,$startAngle,$arcAngle,$pattern) = @_; local($oldpat) = $_PnPattern; &PenPat($pattern); &PaintArc($rect,$startAngle,$arcAngle); &PenPat($oldpat); } # Round rects sub FrameRoundRect { local($rect,$ovalWidth,$ovalHeight) = @_; unless ($_roundRectCurvature eq "$ovalWidth $ovalHeight") { $pict .= pack('nn2',0x000B,$ovalHeight,$ovalWidth); $_roundRectCurvature = "$ovalWidth $ovalHeight"; } $pict .= pack('n',0x0040) . $rect; } sub PaintRoundRect { local($rect,$ovalWidth,$ovalHeight) = @_; unless ($_roundRectCurvature eq "$ovalWidth $ovalHeight") { $pict .= pack('nn2',0x000B,$ovalHeight,$ovalWidth); $_roundRectCurvature = "$ovalWidth $ovalHeight"; } $pict .= pack('n',0x0041) . $rect; } sub EraseRoundRect { local($rect,$ovalWidth,$ovalHeight) = @_; unless ($_roundRectCurvature eq "$ovalWidth $ovalHeight") { $pict .= pack('nn2',0x000B,$ovalHeight,$ovalWidth); $_roundRectCurvature = "$ovalWidth $ovalHeight"; } $pict .= pack('n',0x0042) . $rect; } sub InvertRoundRect { local($rect,$ovalWidth,$ovalHeight) = @_; unless ($_roundRectCurvature eq "$ovalWidth $ovalHeight") { $pict .= pack('nn2',0x000B,$ovalHeight,$ovalWidth); $_roundRectCurvature = "$ovalWidth $ovalHeight"; } $pict .= pack('n',0x0043) . $rect; } sub FillRoundRect { local($rect,$ovalWidth,$ovalHeight,$pattern) = @_; local($oldpat) = $_PnPattern; &PenPat($pattern); &PaintRoundRect($rect,$ovalWidth,$ovalHeight); &PenPat($oldpat); } # Polygons -- you are only allowed to create one polygon at a time. # You will be returned a "handle" which contains the growing polygon # structure. The "handle" is actually the NAME of the scalar sub OpenPoly { $_polyName++; undef $polySave; # close one if it was already defined *polySave = $_polyName; @polySave = (10,0,0,0,0); # initialize it to empty size and rectangle return $_polyName; } sub ClosePoly { *polySave = 'scratch'; undef @polySave; } # Kill the poly -- really a no-op in perl sub KillPoly { local(*poly) = @_; undef @poly; } # Polygon drawing sub FramePoly { local(*poly) = @_; return unless @poly; $pict .= pack('n*',0x0070,@poly); } sub PaintPoly { local(*poly) = @_; return unless @poly; $pict .= pack('n*',0x0071,@poly); } sub ErasePoly { local(*poly) = @_; return unless @poly; $pict .= pack('n*',0x0072,@poly); } sub InvertPoly { local(*poly) = @_; return unless @poly; $pict .= pack('n*',0x0073,@poly); } sub FillPoly { local(*poly,$pattern) = @_; return unless @poly; local($oldpat) = $_PnPattern; &PenPat($pattern); &PaintPoly(*poly); &PenPat($oldpat); } sub OffsetPoly { local(*poly,$dh,$dv) = @_; return unless @poly; local($size,@vertices) = @poly; local($i); for ($i=0;$i<@vertices;$i+=2) { $vertices[$i] += $dv; $vertices[$i+1] += $dh; } @poly = ($size,@vertices); } sub MapPoly { local(*poly,$srcRect,$destRect) = @_; return unless @poly; local($size,@vertices) = @poly; local(@src) = unpack('n4',$srcRect); local(@dest) = unpack('n4',$destRect); local($factorV) = ($dest[2]-$dest[0])/($src[2]-$src[0]); local($factorH) = ($dest[3]-$dest[1])/($src[3]-$src[1]); for ($i=0;$i<@vertices;$i+=2) { $vertices[$i] = int($dest[0] + ($vertices[$i] - $src[0]) * $factorV); $vertices[$i+1] = int($dest[1] + ($vertices[$i+1] - $src[1]) * $factorH); } @poly = ($size,@vertices); } # A utility routine to add a vertex to the growing polygon structure # We need to grow both the size of the polygon and increase the bounding # rectangle. A special case occurs when we add the first vertex: # we store both the current position sub _addVertex { local(*polygon,$h,$v) = @_; local($size,$top,$left,$bottom,$right,@vertices) = @polygon; # Special case for empty vertices -- add the current point unless (@vertices) { push(@vertices,$currV,$currH); $size += 4; $top = $bottom = $currV; $left = $right = $currH; } # IM V1 implies that all vertices are stored relative to # the first point -- I don't know if this is really the case push (@vertices,$v,$h); $size += 4; $top = $v if $v < $top; $bottom = $v if $v > $bottom; $left = $h if $h < $left; $right = $h if $h > $right; @polygon=($size,$top,$left,$bottom,$right,@vertices); } # We try to get the metrics from an X11 bdf font file, if possible. sub TextWidth { local($text) = @_; # See if we can derive the character widths from a metrics file local($face) = 0xFB & $textFace; # underlining don't count local($metric_name) = &_getFontMetrics($textFont,$textSize,$face); if ($metric_name && (*metrics = $metric_name) && defined(%metrics)) { local($length); foreach (split('',$text)) { $length += $metrics{ord($_)}; } return $length; } else { # we get here if we don't have any metrics - make it up local($extra); $extra += $ITALICEXTRA if vec($textFace,$ITALIC,1); $extra += $BOLDEXTRA if vec($textFace,$BOLD,1); return length($text) * $textSize * ($fudgefactor+$extra); } } # Utility routine to read text widths out of bdf files. We create a metrics # array on the fly. The names of the metrics files are stored in an array # called _metricsArrays. We return the name of the array, or undef if inapplicable. sub _getFontMetrics { local($font,$size,$face) = @_; local($key) = "$font $size $face"; return $_metricsArrays{$key} if $_metricsArrays{$key}; # If we get here, we don't have a metrics array to return. See if we can # construct one from a bdf file. # Don't bother unless this font is defined. return undef unless $font_metric_files{$key}; # Don't bother if we tried before and failed return undef if $_failed_metric{$key}; # Try to open up the bdf file. Remember if we fail unless (open(BDF,"$font_metric_files{$key}")) { $_failed_metric_files{$key}++; return undef; } # Wow! We're golden. Create a new metrics array $next_metric++; # bump up the name local(*metrics) = $next_metric; local($char); while () { next unless /^STARTCHAR/../^ENDCHAR/; if (/^ENCODING\s+(\d+)/) { $char = $1; } elsif (/^DWIDTH\s+(\d+)/) { $metrics{$char}=$1; } } close(BDF); # Remember the name of the metrics array and return it return $_metricsArrays{$key} = $next_metric; } # Ugly stuff that I want to hide at the bottom # For the purposes of mapping from quickdraw fonts to X11fonts, we define # the following dictionary: %font_metric_files = ( "22 8 1","$X11FONTS/courB08.bdf", "22 10 1","$X11FONTS/courB10.bdf", "22 12 1","$X11FONTS/courB12.bdf", "22 14 1","$X11FONTS/courB14.bdf", "22 18 1","$X11FONTS/courB18.bdf", "22 24 1","$X11FONTS/courB24.bdf", "22 8 2","$X11FONTS/courO08.bdf", "22 10 2","$X11FONTS/courO10.bdf", "22 12 2","$X11FONTS/courO12.bdf", "22 14 2","$X11FONTS/courO14.bdf", "22 18 2","$X11FONTS/courO18.bdf", "22 24 2","$X11FONTS/courO24.bdf", "22 8 0","$X11FONTS/courR08.bdf", "22 10 0","$X11FONTS/courR10.bdf", "22 12 0","$X11FONTS/courR12.bdf", "22 14 0","$X11FONTS/courR14.bdf", "22 18 0","$X11FONTS/courR18.bdf", "22 24 0","$X11FONTS/courR24.bdf", "21 8 1","$X11FONTS/helvB08.bdf", "21 10 1","$X11FONTS/helvB10.bdf", "21 12 1","$X11FONTS/helvB12.bdf", "21 14 1","$X11FONTS/helvB14.bdf", "21 18 1","$X11FONTS/helvB18.bdf", "21 24 1","$X11FONTS/helvB24.bdf", "21 8 2","$X11FONTS/helvO08.bdf", "21 10 2","$X11FONTS/helvO10.bdf", "21 12 2","$X11FONTS/helvO12.bdf", "21 14 2","$X11FONTS/helvO14.bdf", "21 18 2","$X11FONTS/helvO18.bdf", "21 24 2","$X11FONTS/helvO24.bdf", "21 8 0","$X11FONTS/helvR08.bdf", "21 10 0","$X11FONTS/helvR10.bdf", "21 12 0","$X11FONTS/helvR12.bdf", "21 14 0","$X11FONTS/helvR14.bdf", "21 18 0","$X11FONTS/helvR18.bdf", "21 24 0","$X11FONTS/helvR24.bdf", "20 8 1","$X11FONTS/timB08.bdf", "20 10 1","$X11FONTS/timB10.bdf", "20 12 1","$X11FONTS/timB12.bdf", "20 14 1","$X11FONTS/timB14.bdf", "20 18 1","$X11FONTS/timB18.bdf", "20 24 1","$X11FONTS/timB24.bdf", "20 8 3","$X11FONTS/timBI08.bdf", "20 10 3","$X11FONTS/timBI10.bdf", "20 12 3","$X11FONTS/timBI12.bdf", "20 14 3","$X11FONTS/timBI14.bdf", "20 18 3","$X11FONTS/timBI18.bdf", "20 24 3","$X11FONTS/timBI24.bdf", "20 8 2","$X11FONTS/timI08.bdf", "20 10 2","$X11FONTS/timI10.bdf", "20 12 2","$X11FONTS/timI12.bdf", "20 14 2","$X11FONTS/timI14.bdf", "20 18 2","$X11FONTS/timI18.bdf", "20 24 2","$X11FONTS/timI24.bdf", "20 8 0","$X11FONTS/timR08.bdf", "20 10 0","$X11FONTS/timR10.bdf", "20 12 0","$X11FONTS/timR12.bdf", "20 14 0","$X11FONTS/timR14.bdf", "20 18 0","$X11FONTS/timR18.bdf", "20 24 0","$X11FONTS/timR24.bdf", "34 8 1","$X11FONTS/ncenB08.bdf", "34 10 1","$X11FONTS/ncenB10.bdf", "34 12 1","$X11FONTS/ncenB12.bdf", "34 14 1","$X11FONTS/ncenB14.bdf", "34 18 1","$X11FONTS/ncenB18.bdf", "34 24 1","$X11FONTS/ncenB24.bdf", "34 8 3","$X11FONTS/ncenBI08.bdf", "34 10 3","$X11FONTS/ncenBI10.bdf", "34 12 3","$X11FONTS/ncenBI12.bdf", "34 14 3","$X11FONTS/ncenBI14.bdf", "34 18 3","$X11FONTS/ncenBI18.bdf", "34 24 3","$X11FONTS/ncenBI24.bdf", "34 8 2","$X11FONTS/ncenI08.bdf", "34 10 2","$X11FONTS/ncenI10.bdf", "34 12 2","$X11FONTS/ncenI12.bdf", "34 14 2","$X11FONTS/ncenI14.bdf", "34 18 2","$X11FONTS/ncenI18.bdf", "34 24 2","$X11FONTS/ncenI24.bdf", "34 8 0","$X11FONTS/ncenR08.bdf", "34 10 0","$X11FONTS/ncenR10.bdf", "34 12 0","$X11FONTS/ncenR12.bdf", "34 14 0","$X11FONTS/ncenR14.bdf", "34 18 0","$X11FONTS/ncenR18.bdf", "34 24 0","$X11FONTS/ncenR24.bdf" ); $next_metric = "metrics0000"; # name of our metrics arrays - dynamically allocated 1; } #end of package qd GD-2.50/GD.xs0000644000175100017510000013722212164635400012170 0ustar lsteinlstein#ifdef PERL_CAPI #define WIN32IO_IS_STDIO #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include #include #include #include #include #ifdef FCGI #include #else #ifdef USE_SFIO #include #else #include #endif #include #endif /* Copyright 1995 - 1998, Lincoln D. Stein. See accompanying README file for usage restrictions */ #ifndef PERL_REVISION # ifndef __PATCHLEVEL_H_INCLUDED__ # include "patchlevel.h" # endif # ifndef PERL_REVISION # define PERL_REVISION (5) /* Replace: 1 */ # define PERL_VERSION PATCHLEVEL # define PERL_SUBVERSION SUBVERSION /* Replace PERL_PATCHLEVEL with PERL_VERSION */ /* Replace: 0 */ # endif #endif #if (PERL_VERSION == 5) && (PERL_SUBVERSION==3) #ifndef PL_na # define PL_na na #endif #ifndef SvPV_nolen # define SvPV_nolen(sv) SvPV(sv, PL_na) #endif #endif /* 5.00503 */ #ifdef WIN32 #define snprintf _snprintf #endif #ifndef START_MY_CXT static truecolor_default = 0; #endif static int not_here(char *s) { croak("%s not implemented on this architecture", s); return -1; } static double constant(char *name) { errno = 0; switch (*name) { case 'A': break; case 'B': break; case 'C': break; case 'D': break; case 'E': break; case 'F': break; case 'G': if (strEQ(name, "GD_CMP_IMAGE")) #ifdef GD_CMP_IMAGE return GD_CMP_IMAGE; #else goto not_there; #endif if (strEQ(name, "GD_CMP_NUM_COLORS")) #ifdef GD_CMP_NUM_COLORS return GD_CMP_NUM_COLORS; #else goto not_there; #endif if (strEQ(name, "GD_CMP_COLOR")) #ifdef GD_CMP_COLOR return GD_CMP_COLOR; #else goto not_there; #endif if (strEQ(name, "GD_CMP_SIZE_X")) #ifdef GD_CMP_SIZE_X return GD_CMP_SIZE_X; #else goto not_there; #endif if (strEQ(name, "GD_CMP_SIZE_Y")) #ifdef GD_CMP_SIZE_Y return GD_CMP_SIZE_Y; #else goto not_there; #endif if (strEQ(name, "GD_CMP_TRANSPARENT")) #ifdef GD_CMP_TRANSPARENT return GD_CMP_TRANSPARENT; #else goto not_there; #endif if (strEQ(name, "GD_CMP_BACKGROUND")) #ifdef GD_CMP_BACKGROUND return GD_CMP_BACKGROUND; #else goto not_there; #endif if (strEQ(name, "GD_CMP_INTERLACE")) #ifdef GD_CMP_INTERLACE return GD_CMP_INTERLACE; #else goto not_there; #endif if (strEQ(name, "GD_CMP_TRUECOLOR")) #ifdef GD_CMP_TRUECOLOR return GD_CMP_TRUECOLOR; #else goto not_there; #endif break; case 'H': break; case 'I': break; case 'J': break; case 'K': break; case 'L': break; case 'M': break; case 'N': break; case 'O': break; case 'P': break; case 'Q': break; case 'R': break; case 'S': break; case 'T': break; case 'U': break; case 'V': break; case 'W': break; case 'X': break; case 'Y': break; case 'Z': break; case 'a': break; case 'b': break; case 'c': break; case 'd': break; case 'e': break; case 'f': break; case 'g': if (strEQ(name, "gdBrushed")) #ifdef gdBrushed return gdBrushed; #else goto not_there; #endif if (strEQ(name, "gdDashSize")) #ifdef gdDashSize return gdDashSize; #else goto not_there; #endif if (strEQ(name, "gdMaxColors")) #ifdef gdMaxColors return gdMaxColors; #else goto not_there; #endif if (strEQ(name, "gdStyled")) #ifdef gdStyled return gdStyled; #else goto not_there; #endif if (strEQ(name, "gdStyledBrushed")) #ifdef gdStyledBrushed return gdStyledBrushed; #else goto not_there; #endif if (strEQ(name, "gdTiled")) #ifdef gdTiled return gdTiled; #else goto not_there; #endif if (strEQ(name, "gdTransparent")) #ifdef gdTransparent return gdTransparent; #else goto not_there; #endif if (strEQ(name,"gdAntiAliased")) #ifdef gdAntiAliased return gdAntiAliased; #else goto not_there; #endif if (strEQ(name,"gdAntiAliased")) #ifdef gdAntiAliased return gdAntiAliased; #else goto not_there; #endif if (strEQ(name,"gdArc")) #ifdef gdArc return gdArc; #else goto not_there; #endif if (strEQ(name,"gdPie")) #ifdef gdPie return gdPie; #else goto not_there; #endif if (strEQ(name,"gdChord")) #ifdef gdChord return gdChord; #else goto not_there; #endif if (strEQ(name,"gdNoFill")) #ifdef gdNoFill return gdNoFill; #else goto not_there; #endif if (strEQ(name,"gdEdged")) #ifdef gdEdged return gdEdged; #else goto not_there; #endif if (strEQ(name,"gdAlphaMax")) #ifdef gdAlphaMax return gdAlphaMax; #else goto not_there; #endif if (strEQ(name,"gdAlphaOpaque")) #ifdef gdAlphaOpaque return gdAlphaOpaque; #else goto not_there; #endif if (strEQ(name,"gdAlphaTransparent")) #ifdef gdAlphaTransparent return gdAlphaTransparent; #else goto not_there; #endif break; case 'h': break; case 'i': break; case 'j': break; case 'k': break; case 'l': break; case 'm': break; case 'n': break; case 'o': break; case 'p': break; case 'q': break; case 'r': break; case 's': break; case 't': break; case 'u': break; case 'v': break; case 'w': break; case 'x': break; case 'y': break; case 'z': break; } errno = EINVAL; return 0; not_there: errno = ENOENT; return 0; } typedef gdImagePtr GD__Image; typedef gdFontPtr GD__Font; typedef PerlIO * InputStream; #ifdef PERL_OBJECT # ifdef WIN32 #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng((FILE*)x) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm((FILE*)x) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg((FILE*)x) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif((FILE*)x) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP((FILE*)x) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd((FILE*)x) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2((FILE*)x) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part((FILE*)x,a,b,c,d) # endif #else # ifdef USE_PERLIO #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part(PerlIO_findFILE(x),a,b,c,d) # else #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng(x) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm(x) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg(x) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif(x) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP(x) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd(x) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2(x) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part(x,a,b,c,d) # endif #endif #define littleendian(a) \ (a[3]<<24)+(a[2]<<16)+(a[1]<<8)+a[0] /* definitions required to create images from in-memory buffers */ typedef struct bufIOCtx { gdIOCtx ctx; char* data; int length; int pos; } bufIOCtx; typedef struct bufIOCtx *bufIOCtxPtr; static int bufGetC (gdIOCtxPtr ctx) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; if (bctx->pos >= bctx->length) return EOF; return bctx->data[bctx->pos]; } static int bufGetBuf (gdIOCtxPtr ctx, void* buf, int len) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; int remain,rlen; remain = bctx->length - bctx->pos; if (remain >= len) { rlen = len; } else { if (remain <= 0) return EOF; rlen = remain; } memcpy(buf,(void*)(bctx->data + bctx->pos),rlen); bctx->pos += rlen; return rlen; } static int bufSeek (gdIOCtxPtr ctx, const int pos) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; bctx->pos = pos; if (bctx->pos > bctx->length) bctx->pos = bctx->length; return TRUE; } static long bufTell (gdIOCtxPtr ctx) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; return bctx->pos; } static void bufFree(gdIOCtxPtr ctx) { Safefree(ctx); } static gdIOCtx* newDynamicCtx (char* data, int length) { bufIOCtxPtr ctx; #ifdef Newz Newz(0,ctx,1,bufIOCtx); #else Newxz(ctx,1,bufIOCtx); #endif if (ctx == NULL) return NULL; ctx->data = data; ctx->pos = 0; ctx->length = length; ctx->ctx.getC = bufGetC; ctx->ctx.getBuf = bufGetBuf; ctx->ctx.seek = bufSeek; ctx->ctx.tell = bufTell; ctx->ctx.gd_free = bufFree; ctx->ctx.putC = NULL; ctx->ctx.putBuf = NULL; return (gdIOCtx*)ctx; } /* helper routines for image transformation */ static GD__Image gd_cloneDim(GD__Image src, int x, int y) { GD__Image dst; if (gdImageTrueColor(src)) { dst = (GD__Image) gdImageCreateTrueColor(x,y); } else { int i; dst = (GD__Image) gdImageCreatePalette(x,y); /* copy across the palette information */ for (i = 0; i < gdMaxColors; i++) { dst->red[i] = src->red[i]; dst->green[i] = src->green[i]; dst->blue[i] = src->blue[i]; dst->alpha[i] = src->alpha[i]; dst->open[i] = src->open[i]; } dst->colorsTotal = src->colorsTotal; dst->transparent = src->transparent; dst->interlace = src->interlace; dst->thick = src->thick; } return(dst); } void get_xformbounds(GD__Image src, int *x, int *y, int *x1, int *y1, int *x2, int *y2) { *x = gdImageSX(src); *y = gdImageSY(src); *x1 = *x - 1; *y1 = *y - 1; *x2 = *x / 2; *y2 = *y / 2; } /* helper macros for image transformations */ #define GDGetImagePixel(im,x,y) \ gdImageTrueColor(im) ? \ gdImageTrueColorPixel(im,x,y) : \ gdImagePalettePixel(im,x,y) #define GDSetImagePixel(im,x,y,p) \ gdImageTrueColor(im) ? \ (gdImageTrueColorPixel(im,x,y) = p) : \ (gdImagePalettePixel(im,x,y) = p) #define GDCopyImagePixel(dst,dx,dy,src,sx,sy) \ gdImageTrueColor(src) ? \ (gdImageTrueColorPixel(dst,dx,dy)=gdImageTrueColorPixel(src,sx,sy)) : \ (gdImagePalettePixel(dst,dx,dy)=gdImagePalettePixel(src,sx,sy)) /* Check the image format being returned */ void gd_chkimagefmt(GD__Image image, int truecolor) { if ((image != NULL) && !truecolor) { /* return a palette image */ if (gdImageTrueColor(image)) { gdImageTrueColorToPalette(image,1,gdMaxColors); } } } /* GLOBAL THREAD-SAFE DATA */ #ifdef START_MY_CXT #define MY_CXT_KEY "GD::_guts" XS_VERSION typedef struct { /* Current image true color default * 0 - create palette based images by default * 1 - create true color images by default */ int truecolor_default; } my_cxt_t; START_MY_CXT #endif MODULE = GD PACKAGE = GD double constant(name) char * name BOOT: { #ifdef START_MY_CXT MY_CXT_INIT; MY_CXT.truecolor_default = 0; #endif } MODULE = GD PACKAGE = GD::Image PREFIX=gd # Set the new image true color default # 0 - create palette based images by default # 1 - create true color images by default int gdtrueColor(packname="GD::Image", ...) char * packname PROTOTYPE: $$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int previous_value = MY_CXT.truecolor_default; #else int previous_value = truecolor_default; #endif CODE: { if (items > 1) #ifdef START_MY_CXT MY_CXT.truecolor_default = (int)SvIV(ST(1)); #else truecolor_default = (int)SvIV(ST(1)); #endif RETVAL = previous_value; } OUTPUT: RETVAL GD::Image gd_new(packname="GD::Image", x=64, y=64, ...) char * packname int x int y PROTOTYPE: $;$$$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: { gdImagePtr theImage; if (items > 3) truecolor = (int)SvIV(ST(3)); if (truecolor) { theImage = (GD__Image) gdImageCreateTrueColor(x,y); } else { theImage = (GD__Image) gdImageCreate(x,y); } RETVAL = theImage; } OUTPUT: RETVAL #ifdef HAVE_PNG GD::Image gd_newFromPng(packname="GD::Image", filehandle, ...) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: RETVAL = (GD__Image) GDIMAGECREATEFROMPNG(filehandle); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL GD::Image gdnewFromPngData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromPngCtx(ctx); (ctx->gd_free)(ctx); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif GD::Image gdnewFromGdData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: char* data; STRLEN len; CODE: data = SvPV(imageData,len); RETVAL = (GD__Image) gdImageCreateFromGdPtr(len,(void*) data); OUTPUT: RETVAL GD::Image gdnewFromGd2Data(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: char* data; STRLEN len; CODE: data = SvPV(imageData,len); RETVAL = (GD__Image) gdImageCreateFromGd2Ptr(len,(void*) data); OUTPUT: RETVAL #ifdef HAVE_JPEG GD::Image gdnewFromJpegData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromJpegCtx(ctx); (ctx->gd_free)(ctx); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif GD::Image gdnewFromWBMPData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromWBMPCtx(ctx); (ctx->gd_free)(ctx); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL GD::Image gd_newFromXbm(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: RETVAL = GDIMAGECREATEFROMXBM(filehandle); OUTPUT: RETVAL GD::Image gd_newFromGd(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: RETVAL = GDIMAGECREATEFROMGD(filehandle); OUTPUT: RETVAL GD::Image gd_newFromGd2(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: RETVAL = GDIMAGECREATEFROMGD2(filehandle); OUTPUT: RETVAL #ifdef HAVE_JPEG GD::Image gd_newFromJpeg(packname="GD::Image", filehandle, ...) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: RETVAL = GDIMAGECREATEFROMJPEG(filehandle); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif GD::Image gd_newFromWBMP(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ PREINIT: gdImagePtr img; SV* errormsg; CODE: img = GDIMAGECREATEFROMWBMP(filehandle); if (img == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with WBMP support\n"); XSRETURN_EMPTY; } RETVAL = img; OUTPUT: RETVAL GD::Image gdnewFromXpm(packname="GD::Image", filename) char * packname char * filename PROTOTYPE: $$ PREINIT: gdImagePtr img; SV* errormsg; CODE: #ifdef HAVE_XPM img = (GD__Image) gdImageCreateFromXpm(filename); if (img == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with xpm support\n"); XSRETURN_EMPTY; } RETVAL = img; #else errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with xpm support\n"); XSRETURN_EMPTY; #endif OUTPUT: RETVAL GD::Image gd_newFromGd2Part(packname="GD::Image", filehandle,srcX,srcY,width,height) char * packname InputStream filehandle int srcX int srcY int width int height PROTOTYPE: $$$$$$ CODE: RETVAL = GDIMAGECREATEFROMGD2PART(filehandle,srcX,srcY,width,height); OUTPUT: RETVAL #ifdef HAVE_GIF GD::Image gd_newFromGif(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: RETVAL = GDIMAGECREATEFROMGIF(filehandle); OUTPUT: RETVAL GD::Image gdnewFromGifData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromGifCtx(ctx); (ctx->gd_free)(ctx); OUTPUT: RETVAL #endif void gdDESTROY(image) GD::Image image PROTOTYPE: $ CODE: { gdImageDestroy(image); } SV* gdSTORABLE_freeze(image,cloning) GD::Image image int cloning PROTOTYPE: $$ CODE: { void* data; int size; if (cloning) XSRETURN_UNDEF; data = gdImageGd2Ptr(image,0,GD2_FMT_COMPRESSED,&size); RETVAL=newSVpvn((char*)data,size); gdFree(data); } OUTPUT: RETVAL void gdSTORABLE_thaw(object,cloning,serialized) SV* object int cloning SV* serialized PREINIT: STRLEN length; void* data; GD__Image image; CODE: { if (cloning) XSRETURN_UNDEF; data = (void*) SvPV(serialized,length); image = gdImageCreateFromGd2Ptr(length,data); /* sv_setiv(SvRV(object),(int)image); */ sv_setiv(SvRV(object),(long int)image); } #ifdef HAVE_PNG SV* gdpng(image, ...) GD::Image image PROTOTYPE: $;$ PREINIT: CODE: { void* data; int size; int level; if (items > 1) { level = (int)SvIV(ST(1)); data = (void *) gdImagePngPtrEx(image,&size,level); } else { data = (void *) gdImagePngPtr(image,&size); } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #endif #ifdef HAVE_JPEG SV* gdjpeg(image,quality=-1) GD::Image image int quality PROTOTYPE: $ PREINIT: SV* errormsg; CODE: { void* data; int size; data = (void *) gdImageJpegPtr(image,&size,quality); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with jpeg support\n"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #endif SV* gdgifanimbegin(image,globalcm=-1,loops=-1) GD::Image image int globalcm int loops PROTOTYPE: $$$ PREINIT: CODE: { void* data; int size; #ifdef HAVE_ANIMGIF data = (void *) gdImageGifAnimBeginPtr(image,&size,globalcm,loops); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else die("libgd 2.0.33 or higher required for animated GIF support"); #endif } OUTPUT: RETVAL SV* gdgifanimadd(image,localcm=-1,leftofs=-1,topofs=-1,delay=-1,disposal=-1,previm=0) GD::Image image int localcm int leftofs int topofs int delay int disposal GD::Image previm PROTOTYPE: $$$$$$$ CODE: { void* data; int size; #ifdef HAVE_ANIMGIF data = (void *) gdImageGifAnimAddPtr(image,&size,localcm,leftofs,topofs,delay,disposal,previm); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else die("libgd 2.0.33 or higher required for animated GIF support"); #endif } OUTPUT: RETVAL SV* gdgifanimend(image) GD::Image image PROTOTYPE: $ CODE: { void* data; int size; #ifdef HAVE_ANIMGIF data = (void *) gdImageGifAnimEndPtr(&size); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else die("libgd 2.0.33 or higher required for animated GIF support"); #endif } OUTPUT: RETVAL SV* gdwbmp(image,fg) GD::Image image int fg PROTOTYPE: $ PREINIT: SV* errormsg; CODE: { void* data; int size; data = (void *) gdImageWBMPPtr(image,&size,fg); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with WBMP support\n"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #ifdef HAVE_GIF SV* gdgif(image) GD::Image image PROTOTYPE: $ PREINIT: SV* errormsg; CODE: { void* data; int size; data = (void *) gdImageGifPtr(image,&size); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with gif support\n"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #endif SV* gdgd(image) GD::Image image PROTOTYPE: $ CODE: { void* data; int size; data = gdImageGdPtr(image,&size); RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL SV* gdgd2(image) GD::Image image PROTOTYPE: $ CODE: { void* data; int size; data = gdImageGd2Ptr(image,0,GD2_FMT_COMPRESSED,&size); RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL int gdtransparent(image, ...) GD::Image image PROTOTYPE: $;$ CODE: { int color; if (items > 1) { color=(int)SvIV(ST(1)); gdImageColorTransparent(image,color); } RETVAL = gdImageGetTransparent(image); } OUTPUT: RETVAL void gdgetBounds(image) GD::Image image PROTOTYPE: $ PPCODE: { int sx,sy; sx = gdImageSX(image); sy = gdImageSY(image); EXTEND(sp,2); PUSHs(sv_2mortal(newSViv(sx))); PUSHs(sv_2mortal(newSViv(sy))); } int gdisTrueColor(image) GD::Image image PROTOTYPE: $ CODE: { RETVAL=gdImageTrueColor(image); } OUTPUT: RETVAL void gdtrueColorToPalette(image, dither=0, colors=gdMaxColors) GD::Image image int dither int colors PROTOTYPE: $;$$ CODE: { gdImageTrueColorToPalette(image,dither,colors); } void gdrgb(image,color) GD::Image image int color PROTOTYPE: $$ PPCODE: { int r,g,b; r = gdImageRed(image,color); g = gdImageGreen(image,color); b = gdImageBlue(image,color); EXTEND(sp,3); PUSHs(sv_2mortal(newSViv(r))); PUSHs(sv_2mortal(newSViv(g))); PUSHs(sv_2mortal(newSViv(b))); } int gdboundsSafe(image,x,y) GD::Image image int x int y PROTOTYPE: $$$ CODE: { RETVAL=gdImageBoundsSafe(image,x,y); if (RETVAL == 0) XSRETURN_UNDEF; } OUTPUT: RETVAL int gdgetPixel(image,x,y) GD::Image image int x int y PROTOTYPE: $$$ CODE: { RETVAL=gdImageGetPixel(image,x,y); } OUTPUT: RETVAL void gdsetPixel(image,x,y,color) GD::Image image int x int y int color PROTOTYPE: $$$$ CODE: { gdImageSetPixel(image,x,y,color); } GD::Image gdcopyRotate90(src) GD::Image src PROTOTYPE: $ CODE: { int x, y, x1, y1, x2, y2, i, j; GD__Image dst; get_xformbounds(src, &x, &y, &x1, &y1, &x2, &y2); dst = (GD__Image) gd_cloneDim(src, y, x); for (j=0;j 1) { if (SvOK(ST(1))) gdImageInterlace(image,1); else gdImageInterlace(image,0); } RETVAL = gdImageGetInterlaced(image); } OUTPUT: RETVAL int compare(image1,image2) GD::Image image1 GD::Image image2 PROTOTYPE: $$ CODE: { RETVAL = gdImageCompare(image1,image2); } OUTPUT: RETVAL void colorDeallocate(image,color) GD::Image image int color PROTOTYPE: $$ CODE: { gdImageColorDeallocate(image,color); } void copy(destination,source,dstX,dstY,srcX,srcY,w,h) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h PROTOTYPE: $$$$$$$$ CODE: { gdImageCopy(destination,source,dstX,dstY,srcX,srcY,w,h); } void copyResized(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int destW int destH int srcW int srcH PROTOTYPE: $$$$$$$$$$ CODE: { gdImageCopyResized(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH); } void copyResampled(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int destW int destH int srcW int srcH PROTOTYPE: $$$$$$$$$$ CODE: { gdImageCopyResampled(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH); } void copyMerge(destination,source,dstX,dstY,srcX,srcY,w,h,pct) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h int pct PROTOTYPE: $$$$$$$$$ CODE: { gdImageCopyMerge(destination,source,dstX,dstY,srcX,srcY,w,h,pct); } void copyMergeGray(destination,source,dstX,dstY,srcX,srcY,w,h,pct) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h int pct PROTOTYPE: $$$$$$$$$ CODE: { gdImageCopyMergeGray(destination,source,dstX,dstY,srcX,srcY,w,h,pct); } void paletteCopy(destination,source) GD::Image destination GD::Image source PROTOTYPE: $$ CODE: { gdImagePaletteCopy(destination,source); } void gdchar(image,font,x,y,c,color) GD::Image image GD::Font font int x int y char * c int color PROTOTYPE: $$$$$$ CODE: { gdImageChar(image,font,x,y,*c,color); } void gdcharUp(image,font,x,y,c,color) GD::Image image GD::Font font int x int y char * c int color PROTOTYPE: $$$$$$ CODE: { gdImageCharUp(image,font,x,y,*c,color); } void gdstring(image,font,x,y,s,color) GD::Image image GD::Font font int x int y char * s int color PROTOTYPE: $$$$$$ CODE: { gdImageString(image,font,x,y,(unsigned char*)s,color); } void gdstringUp(image,font,x,y,s,color) GD::Image image GD::Font font int x int y char * s int color PROTOTYPE: $$$$$$ CODE: { gdImageStringUp(image,font,x,y,(unsigned char*)s,color); } void gdstringFT(image,fgcolor,fontname,ptsize,angle,x,y,string,...) SV * image int fgcolor char * fontname double ptsize double angle int x int y char * string PROTOTYPE: $$$$$$$$;$ PREINIT: gdImagePtr img; int brect[8]; char *err; char *a; SV* errormsg; HV* hash; SV** value; int i; int hdpi; int vdpi; gdFTStringExtra strex; PPCODE: { #ifndef HAVE_FT errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with FreeType font support\n"); XSRETURN_EMPTY; #endif if (sv_isobject(image) && sv_derived_from(image, "GD::Image")) { IV tmp = SvIV((SV*)SvRV(image)); img = (gdImagePtr) tmp; } else { img = NULL; } if (items == 9) { /* hashref options at end */ if (SvTYPE(SvRV(ST(8))) != SVt_PVHV) croak ("Usage: $gd->stringFT(image,fgcolor,fontname,ptsize,angle,x,y,string,[{options}])"); hash = (HV*)SvRV(ST(8)); strex.flags = 0; strex.linespacing = 0; strex.charmap = 0; if (value = hv_fetch(hash,"linespacing",strlen("linespacing"),0)) { strex.flags |= gdFTEX_LINESPACE; strex.linespacing = SvNV(*value); } if (value = hv_fetch(hash,"charmap",strlen("charmap"),0)) { strex.flags |= gdFTEX_CHARMAP; if (strEQ(SvPV_nolen(*value),"Unicode")) strex.charmap = gdFTEX_Unicode; else if (strEQ(SvPV_nolen(*value),"Shift_JIS")) strex.charmap = gdFTEX_Shift_JIS; else if (strEQ(SvPV_nolen(*value),"Big5")) strex.charmap = gdFTEX_Big5; else croak("Unknown charmap %s",SvPV_nolen(*value)); } #ifdef VERSION_33 if (value = hv_fetch(hash,"resolution",strlen("resolution"),0)) { strex.flags |= gdFTEX_RESOLUTION; a = SvPV_nolen(*value); if (sscanf(a,"%d,%d",&hdpi,&vdpi) == 2) { strex.hdpi = hdpi; strex.vdpi = vdpi; } } if (value = hv_fetch(hash,"kerning",strlen("kerning"),0)) { if (!SvTRUE(*value)) { strex.flags |= gdFTEX_DISABLE_KERNING; } else strex.flags &= gdFTEX_DISABLE_KERNING; } #endif err = gdImageStringFTEx(img,brect,fgcolor,fontname,ptsize,angle,x,y,string,&strex); } else { err = gdImageStringFT(img,brect,fgcolor,fontname,ptsize,angle,x,y,string); } if (err) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,err); XSRETURN_EMPTY; } else { EXTEND(sp,8); for (i=0;i<8;i++) { PUSHs(sv_2mortal(newSViv(brect[i]))); } } } int gdstringFTCircle(image,cx,cy,radius,textRadius,fillPortion,fontname,points,top,bottom,fgcolor) GD::Image image int cx int cy double radius double textRadius double fillPortion char * fontname double points char * top char * bottom int fgcolor PROTOTYPE: $$$$$$$$$$$ PREINIT: char* err; SV* errormsg; CODE: { #ifdef HAVE_FT #ifdef HAVE_FTCIRCLE fprintf(stderr,"cx=%d,cy=%d,radius=%f,textRadius=%f,fillPortion=%f,fontname=%s,points=%f,top=%s,bottom=%s,fgcolor=%d", cx,cy,radius,textRadius, fillPortion,fontname,points,top,bottom,fgcolor); err = gdImageStringFTCircle(image,cx,cy,radius,textRadius, fillPortion,fontname,points,top,bottom,fgcolor); if (err) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,err); XSRETURN_EMPTY; } else { RETVAL = 1; } #else errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd must be version 2.0.33 or higher to use this function\n"); XSRETURN_EMPTY; #endif #else errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with FreeType support\n"); XSRETURN_EMPTY; #endif } OUTPUT: RETVAL int gduseFontConfig(image,flag) SV* image int flag PROTOTYPE: $$ PREINIT: SV* errormsg; CODE: { #ifdef HAVE_FONTCONFIG RETVAL = gdFTUseFontConfig(flag); #else errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with fontconfig support\n"); XSRETURN_EMPTY; #endif } OUTPUT: RETVAL void gdalphaBlending(image,blending) GD::Image image int blending PROTOTYPE: $$ CODE: { gdImageAlphaBlending(image,blending); } void gdsaveAlpha(image,saveAlphaArg) GD::Image image int saveAlphaArg PROTOTYPE: $$ CODE: { gdImageSaveAlpha(image,saveAlphaArg) ; } void gdclip(image,...) GD::Image image PROTOTYPE: $;$$$$ PREINIT: int coords[4]; int i; PPCODE: { if (items == 5) { for (i=0;i<4;i++) coords[i] = (int)SvIV(ST(i+1)); gdImageSetClip(image,coords[0],coords[1],coords[2],coords[3]); } else if (items > 1) /* something weird */ croak("Usage: $gd->clip() or $gd->clip(x1,x2,y1,y2)"); gdImageGetClip(image,&coords[0],&coords[1],&coords[2],&coords[3]); EXTEND(sp,4); for (i=0;i<4;i++) PUSHs(sv_2mortal(newSViv(coords[i]))); } void gdsetAntiAliased(image,color) GD::Image image int color PROTOTYPE: $$ CODE: { gdImageSetAntiAliased(image,color); } void gdsetAntiAliasedDontBlend(image,color,flag=1) GD::Image image int color int flag PROTOTYPE: $$$ CODE: { gdImageSetAntiAliasedDontBlend(image,color,flag); } MODULE = GD PACKAGE = GD::Font PREFIX=gd GD::Font gdload(packname="GD::Font",fontpath) char * packname char * fontpath PROTOTYPE: $$ PREINIT: int fontfile; int datasize; SV* errormsg; char errstr[256]; gdFontPtr font; unsigned char word[4]; char* fontdata; CODE: { fontfile = open(fontpath,O_RDONLY); if (fontfile < 0) { errormsg = perl_get_sv("@",0); snprintf(errstr,256,"could not open font file %s: %s",fontpath,strerror(errno)); sv_setpv(errormsg,errstr); XSRETURN_EMPTY; } font = (gdFontPtr)safemalloc(sizeof(gdFont)); if (font == NULL) croak("safemalloc() returned NULL while trying to allocate font struct.\n"); /* read header from font - note that the file is assumed to be littleendian*/ if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->nchars = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->offset = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->w = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->h = littleendian(word); datasize = font->nchars * font->w * font->h; fontdata = (char*)safemalloc(datasize); if (fontdata == NULL) croak("safemalloc() returned NULL while trying to allocate font bitmap.\n"); if (read(fontfile,fontdata,datasize) < datasize) croak("error while reading font file: %s",strerror(errno)); font->data = fontdata; close(fontfile); /* please don't leak file descriptors! */ RETVAL = font; } OUTPUT: RETVAL void gdDESTROY(self) GD::Font self PROTOTYPE: $ CODE: { if (self == gdFontGetSmall() || self == gdFontGetLarge() || self == gdFontGetGiant() || self == gdFontGetMediumBold() || self == gdFontGetTiny() ) XSRETURN_EMPTY; safefree(self->data); safefree(self); } GD::Font gdSmall(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetSmall(); } OUTPUT: RETVAL GD::Font gdLarge(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetLarge(); } OUTPUT: RETVAL GD::Font gdGiant(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetGiant(); } OUTPUT: RETVAL GD::Font gdMediumBold(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetMediumBold(); } OUTPUT: RETVAL GD::Font gdTiny(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetTiny(); } OUTPUT: RETVAL int gdnchars(font) GD::Font font PROTOTYPE: $ CODE: { RETVAL = font->nchars; } OUTPUT: RETVAL int gdoffset(font) GD::Font font PROTOTYPE: $ CODE: { RETVAL = font->offset; } OUTPUT: RETVAL int gdwidth(font) GD::Font font PROTOTYPE: $ CODE: { RETVAL = font->w; } OUTPUT: RETVAL int gdheight(font) GD::Font font PROTOTYPE: $ CODE: { RETVAL = font->h; } OUTPUT: RETVAL GD-2.50/GD.pm0000644000175100017510000016637212164636047012172 0ustar lsteinlsteinpackage GD; # Copyright 1995 Lincoln D. Stein. See accompanying README file for # usage information use strict; require 5.004; require FileHandle; require Exporter; require DynaLoader; require AutoLoader; use Carp 'croak','carp'; use GD::Image; use GD::Polygon; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $AUTOLOAD); $VERSION = '2.50'; @ISA = qw(Exporter DynaLoader); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. @EXPORT = qw( gdBrushed gdDashSize gdMaxColors gdStyled gdStyledBrushed gdTiled gdTransparent gdAntiAliased gdArc gdChord gdPie gdNoFill gdEdged gdTinyFont gdSmallFont gdMediumBoldFont gdLargeFont gdGiantFont gdAlphaMax gdAlphaOpaque gdAlphaTransparent ); @EXPORT_OK = qw ( GD_CMP_IMAGE GD_CMP_NUM_COLORS GD_CMP_COLOR GD_CMP_SIZE_X GD_CMP_SIZE_Y GD_CMP_TRANSPARENT GD_CMP_BACKGROUND GD_CMP_INTERLACE GD_CMP_TRUECOLOR ); %EXPORT_TAGS = ('cmp' => [qw(GD_CMP_IMAGE GD_CMP_NUM_COLORS GD_CMP_COLOR GD_CMP_SIZE_X GD_CMP_SIZE_Y GD_CMP_TRANSPARENT GD_CMP_BACKGROUND GD_CMP_INTERLACE GD_CMP_TRUECOLOR ) ] ); # documentation error *GD::Polygon::delete = \&GD::Polygon::deletePt; sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my($constname); ($constname = $AUTOLOAD) =~ s/.*:://; my $val = constant($constname); if ($! != 0) { if ($! =~ /Invalid/) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { my($pack,$file,$line) = caller; die "Your vendor has not defined GD macro $pack\:\:$constname, used at $file line $line.\n"; } } eval "sub $AUTOLOAD { $val }"; goto &$AUTOLOAD; } bootstrap GD; # Preloaded methods go here. sub GD::gdSmallFont { return GD::Font->Small; } sub GD::gdLargeFont { return GD::Font->Large; } sub GD::gdMediumBoldFont { return GD::Font->MediumBold; } sub GD::gdTinyFont { return GD::Font->Tiny; } sub GD::gdGiantFont { return GD::Font->Giant; } sub GD::Image::startGroup { } # does nothing - used by GD::SVG sub GD::Image::endGroup { } # does nothing - used by GD::SVG sub GD::Image::newGroup { my $self = shift; GD::Group->new($self,$self->startGroup); } =head1 NAME GD.pm - Interface to Gd Graphics Library =head1 SYNOPSIS use GD; # create a new image $im = new GD::Image(100,100); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); # make sure we are writing to a binary stream binmode STDOUT; # Convert the image to PNG and print it on standard output print $im->png; =head1 DESCRIPTION B is a Perl interface to Thomas Boutell's gd graphics library (version 2.01 or higher; see below). GD allows you to create color drawings using a large number of graphics primitives, and emit the drawings as PNG files. GD defines the following four classes: =over 5 =item C An image class, which holds the image data and accepts graphic primitive method calls. =item C A font class, which holds static font information and used for text rendering. =item C A simple polygon object, used for storing lists of vertices prior to rendering a polygon into an image. =item C A "simple" class that simplifies the GD::Image API and then adds a set of object-oriented drawing methods using turtle graphics, simplified font handling, ability to work in polar coordinates, HSV color spaces, and human-readable color names like "lightblue". Please see L for a description of these methods. =back A Simple Example: #!/usr/local/bin/perl use GD; # create a new image $im = new GD::Image(100,100); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); # make sure we are writing to a binary stream binmode STDOUT; # Convert the image to PNG and print it on standard output print $im->png; Notes: =over 5 =item 1. To create a new, empty image, send a new() message to GD::Image, passing it the width and height of the image you want to create. An image object will be returned. Other class methods allow you to initialize an image from a preexisting JPG, PNG, GD, GD2 or XBM file. =item 2. Next you will ordinarily add colors to the image's color table. colors are added using a colorAllocate() method call. The three parameters in each call are the red, green and blue (rgb) triples for the desired color. The method returns the index of that color in the image's color table. You should store these indexes for later use. =item 3. Now you can do some drawing! The various graphics primitives are described below. In this example, we do some text drawing, create an oval, and create and draw a polygon. =item 4. Polygons are created with a new() message to GD::Polygon. You can add points to the returned polygon one at a time using the addPt() method. The polygon can then be passed to an image for rendering. =item 5. When you're done drawing, you can convert the image into PNG format by sending it a png() message. It will return a (potentially large) scalar value containing the binary data for the image. Ordinarily you will print it out at this point or write it to a file. To ensure portability to platforms that differentiate between text and binary files, be sure to call C on the file you are writing the image to. =back =head1 Object Constructors: Creating Images The following class methods allow you to create new GD::Image objects. =over 4 =item B<$image = GD::Image-Enew([$width,$height],[$truecolor])> =item B<$image = GD::Image-Enew(*FILEHANDLE)> =item B<$image = GD::Image-Enew($filename)> =item B<$image = GD::Image-Enew($data)> The new() method is the main constructor for the GD::Image class. Called with two integer arguments, it creates a new blank image of the specified width and height. For example: $myImage = new GD::Image(100,100) || die; This will create an image that is 100 x 100 pixels wide. If you don't specify the dimensions, a default of 64 x 64 will be chosen. The optional third argument, $truecolor, tells new() to create a truecolor GD::Image object. Truecolor images have 24 bits of color data (eight bits each in the red, green and blue channels respectively), allowing for precise photograph-quality color usage. If not specified, the image will use an 8-bit palette for compatibility with older versions of libgd. Alternatively, you may create a GD::Image object based on an existing image by providing an open filehandle, a filename, or the image data itself. The image formats automatically recognized and accepted are: PNG, JPEG, XPM and GD2. Other formats, including WBMP, and GD version 1, cannot be recognized automatically at this time. If something goes wrong (e.g. insufficient memory), this call will return undef. =item B<$image = GD::Image-EtrueColor([0,1])> For backwards compatibility with scripts previous versions of GD, new images created from scratch (width, height) are palette based by default. To change this default to create true color images use: GD::Image->trueColor(1); somewhere before creating new images. To switch back to palette based by default, use: GD::Image->trueColor(0); =item B<$image = GD::Image-EnewPalette([$width,$height])> =item B<$image = GD::Image-EnewTrueColor([$width,$height])> The newPalette() and newTrueColor() methods can be used to explicitly create an palette based or true color image regardless of the current setting of trueColor(). =item B<$image = GD::Image-EnewFromPng($file, [$truecolor])> =item B<$image = GD::Image-EnewFromPngData($data, [$truecolor])> The newFromPng() method will create an image from a PNG file read in through the provided filehandle or file path. The filehandle must previously have been opened on a valid PNG file or pipe. If successful, this call will return an initialized image which you can then manipulate as you please. If it fails, which usually happens if the thing at the other end of the filehandle is not a valid PNG file, the call returns undef. Notice that the call doesn't automatically close the filehandle for you. But it does call C for you, on platforms where this matters. You may use any of the following as the argument: 1) a simple filehandle, such as STDIN 2) a filehandle glob, such as *PNG 3) a reference to a glob, such as \*PNG 4) an IO::Handle object 5) the pathname of a file In the latter case, newFromPng() will attempt to open the file for you and read the PNG information from it. Example1: open (PNG,"barnswallow.png") || die; $myImage = newFromPng GD::Image(\*PNG) || die; close PNG; Example2: $myImage = newFromPng GD::Image('barnswallow.png'); To get information about the size and color usage of the information, you can call the image query methods described below. Images created by reading PNG images will be truecolor if the image file itself is truecolor. To force the image to be palette-based, pass a value of 0 in the optional $truecolor argument. The newFromPngData() method will create a new GD::Image initialized with the PNG format B contained in C<$data>. =item B<$image = GD::Image-EnewFromJpeg($file, [$truecolor])> =item B<$image = GD::Image-EnewFromJpegData($data, [$truecolor])> These methods will create an image from a JPEG file. They work just like newFromPng() and newFromPngData(), and will accept the same filehandle and pathname arguments. Images created by reading JPEG images will always be truecolor. To force the image to be palette-based, pass a value of 0 in the optional $truecolor argument. =item B<$image = GD::Image-EnewFromGif($file)> =item B<$image = GD::Image-EnewFromGifData($data)> These methods will create an image from a GIF file. They work just like newFromPng() and newFromPngData(), and will accept the same filehandle and pathname arguments. Images created from GIFs are always 8-bit palette images. To convert to truecolor, you must create a truecolor image and then perform a copy. =item B<$image = GD::Image-EnewFromXbm($file)> This works in exactly the same way as C, but reads the contents of an X Bitmap (black & white) file: open (XBM,"coredump.xbm") || die; $myImage = newFromXbm GD::Image(\*XBM) || die; close XBM; There is no newFromXbmData() function, because there is no corresponding function in the gd library. =item B<$image = GD::Image-EnewFromGd($file)> =item B<$image = GD::Image-EnewFromGdData($data)> These methods initialize a GD::Image from a Gd file, filehandle, or data. Gd is Tom Boutell's disk-based storage format, intended for the rare case when you need to read and write the image to disk quickly. It's not intended for regular use, because, unlike PNG or JPEG, no image compression is performed and these files can become B. $myImage = newFromGd GD::Image("godzilla.gd") || die; close GDF; =item B<$image = GD::Image-EnewFromGd2($file)> =item B<$image = GD::Image-EnewFromGd2Data($data)> This works in exactly the same way as C and newFromGdData, but use the new compressed GD2 image format. =item B<$image = GD::Image-EnewFromGd2Part($file,srcX,srcY,width,height)> This class method allows you to read in just a portion of a GD2 image file. In addition to a filehandle, it accepts the top-left corner and dimensions (width,height) of the region of the image to read. For example: open (GDF,"godzilla.gd2") || die; $myImage = GD::Image->newFromGd2Part(\*GDF,10,20,100,100) || die; close GDF; This reads a 100x100 square portion of the image starting from position (10,20). =item B<$image = GD::Image-EnewFromXpm($filename)> This creates a new GD::Image object starting from a B. This is unlike the other newFrom() functions because it does not take a filehandle. This difference comes from an inconsistency in the underlying gd library. $myImage = newFromXpm GD::Image('earth.xpm') || die; This function is only available if libgd was compiled with XPM support. NOTE: The libgd library is unable to read certain XPM files, returning an all-black image instead. =head1 GD::Image Methods Once a GD::Image object is created, you can draw with it, copy it, and merge two images. When you are finished manipulating the object, you can convert it into a standard image file format to output or save to a file. =head2 Image Data Output Methods The following methods convert the internal drawing format into standard output file formats. =item B<$pngdata = $image-Epng([$compression_level])> This returns the image data in PNG format. You can then print it, pipe it to a display program, or write it to a file. Example: $png_data = $myImage->png; open (DISPLAY,"| display -") || die; binmode DISPLAY; print DISPLAY $png_data; close DISPLAY; Note the use of C. This is crucial for portability to DOSish platforms. The optional $compression_level argument controls the amount of compression to apply to the output PNG image. Values range from 0-9, where 0 means no compression (largest files, highest quality) and 9 means maximum compression (smallest files, worst quality). A compression level of -1 uses the default compression level selected when zlib was compiled on your system, and is the same as calling png() with no argument. Be careful not to confuse this argument with the jpeg() quality argument, which ranges from 0-100 and has the opposite meaning from compression (higher numbers give higher quality). =item B<$gifdata = $image-Egifanimbegin([$GlobalCM [, $Loops]])> For libgd version 2.0.33 and higher, this call begins an animated GIF by returning the data that comprises animated gif image file header. After you call this method, call gifanimadd() one or more times to add the frames of the image. Then call gifanimend(). Each frame must be the same width and height. A typical sequence will look like this: my $gifdata = $image->gifanimbegin; $gifdata .= $image->gifanimadd; # first frame for (1..100) { # make a frame of right size my $frame = GD::Image->new($image->getBounds); add_frame_data($frame); # add the data for this frame $gifdata .= $frame->gifanimadd; # add frame } $gifdata .= $image->gifanimend; # finish the animated GIF print $gifdata; # write animated gif to STDOUT If you do not wish to store the data in memory, you can print it to stdout or a file. The image that you call gifanimbegin on is used to set the image size, color resolution and color map. If argument $GlobalCM is 1, the image color map becomes the GIF89a global color map. If $Loops is given and >= 0, the NETSCAPE2.0 application extension is created, with looping count. Looping count 0 means forever. =item B<$gifdata = $image-Egifanimadd([$LocalCM [, $LeftOfs [, $TopOfs [, $Delay [, $Disposal [, $previm]]]]]])> Returns the data that comprises one animated gif image frame. You can then print it, pipe it to a display program, or write it to a file. With $LeftOfs and $TopOfs you can place this frame in different offset than (0,0) inside the image screen. Delay between the previous frame and this frame is in 1/100s units. Disposal is usually and by default 1. Compression is activated by giving the previous image as a parameter. This function then compares the images and only writes the changed pixels to the new frame in animation. The Disposal parameter for optimized animations must be set to 1, also for the first frame. $LeftOfs and $TopOfs parameters are ignored for optimized frames. =item B<$gifdata = $image-Egifanimend()> Returns the data for end segment of animated gif file. It always returns string ';'. This string must be printed to an animated gif file after all image frames to properly terminate it according to GIF file syntax. Image object is not used at all in this method. =item B<$jpegdata = $image-Ejpeg([$quality])> This returns the image data in JPEG format. You can then print it, pipe it to a display program, or write it to a file. You may pass an optional quality score to jpeg() in order to control the JPEG quality. This should be an integer between 0 and 100. Higher quality scores give larger files and better image quality. If you don't specify the quality, jpeg() will choose a good default. =item B<$gifdata = $image-Egif()>. This returns the image data in GIF format. You can then print it, pipe it to a display program, or write it to a file. =item B<$gddata = $image-Egd> This returns the image data in GD format. You can then print it, pipe it to a display program, or write it to a file. Example: binmode MYOUTFILE; print MYOUTFILE $myImage->gd; =item B<$gd2data = $image-Egd2> Same as gd(), except that it returns the data in compressed GD2 format. =item B<$wbmpdata = $image-Ewbmp([$foreground])> This returns the image data in WBMP format, which is a black-and-white image format. Provide the index of the color to become the foreground color. All other pixels will be considered background. =back =head2 Color Control These methods allow you to control and manipulate the GD::Image color table. =over 4 =item B<$index = $image-EcolorAllocate(red,green,blue)> This allocates a color with the specified red, green and blue components and returns its index in the color table, if specified. The first color allocated in this way becomes the image's background color. (255,255,255) is white (all pixels on). (0,0,0) is black (all pixels off). (255,0,0) is fully saturated red. (127,127,127) is 50% gray. You can find plenty of examples in /usr/X11/lib/X11/rgb.txt. If no colors are allocated, then this function returns -1. Example: $white = $myImage->colorAllocate(0,0,0); #background color $black = $myImage->colorAllocate(255,255,255); $peachpuff = $myImage->colorAllocate(255,218,185); =item B<$index = $image-EcolorAllocateAlpha(reg,green,blue,alpha)> This allocates a color with the specified red, green, and blue components, plus the specified alpha channel. The alpha value may range from 0 (opaque) to 127 (transparent). The C function changes the way this alpha channel affects the resulting image. =item B<$image-EcolorDeallocate(colorIndex)> This marks the color at the specified index as being ripe for reallocation. The next time colorAllocate is used, this entry will be replaced. You can call this method several times to deallocate multiple colors. There's no function result from this call. Example: $myImage->colorDeallocate($peachpuff); $peachy = $myImage->colorAllocate(255,210,185); =item B<$index = $image-EcolorClosest(red,green,blue)> This returns the index of the color closest in the color table to the red green and blue components specified. If no colors have yet been allocated, then this call returns -1. Example: $apricot = $myImage->colorClosest(255,200,180); =item B<$index = $image-EcolorClosestHWB(red,green,blue)> This also attempts to return the color closest in the color table to the red green and blue components specified. It uses a Hue/White/Black color representation to make the selected color more likely to match human perceptions of similar colors. If no colors have yet been allocated, then this call returns -1. Example: $mostred = $myImage->colorClosestHWB(255,0,0); =item B<$index = $image-EcolorExact(red,green,blue)> This returns the index of a color that exactly matches the specified red green and blue components. If such a color is not in the color table, this call returns -1. $rosey = $myImage->colorExact(255,100,80); warn "Everything's coming up roses.\n" if $rosey >= 0; =item B<$index = $image-EcolorResolve(red,green,blue)> This returns the index of a color that exactly matches the specified red green and blue components. If such a color is not in the color table and there is room, then this method allocates the color in the color table and returns its index. $rosey = $myImage->colorResolve(255,100,80); warn "Everything's coming up roses.\n" if $rosey >= 0; =item B<$colorsTotal = $image-EcolorsTotal> I This returns the total number of colors allocated in the object. $maxColors = $myImage->colorsTotal; In the case of a TrueColor image, this call will return undef. =item B<$index = $image-EgetPixel(x,y)> I This returns the color table index underneath the specified point. It can be combined with rgb() to obtain the rgb color underneath the pixel. Example: $index = $myImage->getPixel(20,100); ($r,$g,$b) = $myImage->rgb($index); =item B<($red,$green,$blue) = $image-Ergb($index)> This returns a list containing the red, green and blue components of the specified color index. Example: @RGB = $myImage->rgb($peachy); =item B<$image-Etransparent($colorIndex)> This marks the color at the specified index as being transparent. Portions of the image drawn in this color will be invisible. This is useful for creating paintbrushes of odd shapes, as well as for making PNG backgrounds transparent for displaying on the Web. Only one color can be transparent at any time. To disable transparency, specify -1 for the index. If you call this method without any parameters, it will return the current index of the transparent color, or -1 if none. Example: open(PNG,"test.png"); $im = newFromPng GD::Image(PNG); $white = $im->colorClosest(255,255,255); # find white $im->transparent($white); binmode STDOUT; print $im->png; =back =head2 Special Colors GD implements a number of special colors that can be used to achieve special effects. They are constants defined in the GD:: namespace, but automatically exported into your namespace when the GD module is loaded. =over 4 =item B<$image-EsetBrush($image)> You can draw lines and shapes using a brush pattern. Brushes are just images that you can create and manipulate in the usual way. When you draw with them, their contents are used for the color and shape of the lines. To make a brushed line, you must create or load the brush first, then assign it to the image using setBrush(). You can then draw in that with that brush using the B special color. It's often useful to set the background of the brush to transparent so that the non-colored parts don't overwrite other parts of your image. Example: # Create a brush at an angle $diagonal_brush = new GD::Image(5,5); $white = $diagonal_brush->colorAllocate(255,255,255); $black = $diagonal_brush->colorAllocate(0,0,0); $diagonal_brush->transparent($white); $diagonal_brush->line(0,4,4,0,$black); # NE diagonal # Set the brush $myImage->setBrush($diagonal_brush); # Draw a circle using the brush $myImage->arc(50,50,25,25,0,360,gdBrushed); =item B<$image-EsetThickness($thickness)> Lines drawn with line(), rectangle(), arc(), and so forth are 1 pixel thick by default. Call setThickness() to change the line drawing width. =item B<$image-EsetStyle(@colors)> Styled lines consist of an arbitrary series of repeated colors and are useful for generating dotted and dashed lines. To create a styled line, use setStyle() to specify a repeating series of colors. It accepts an array consisting of one or more color indexes. Then draw using the B special color. Another special color, B can be used to introduce holes in the line, as the example shows. Example: # Set a style consisting of 4 pixels of yellow, # 4 pixels of blue, and a 2 pixel gap $myImage->setStyle($yellow,$yellow,$yellow,$yellow, $blue,$blue,$blue,$blue, gdTransparent,gdTransparent); $myImage->arc(50,50,25,25,0,360,gdStyled); To combine the C and C behaviors, you can specify C. In this case, a pixel from the current brush pattern is rendered wherever the color specified in setStyle() is neither gdTransparent nor 0. =item B Draw filled shapes and flood fills using a pattern. The pattern is just another image. The image will be tiled multiple times in order to fill the required space, creating wallpaper effects. You must call C in order to define the particular tile pattern you'll use for drawing when you specify the gdTiled color. details. =item B The gdStyled color is used for creating dashed and dotted lines. A styled line can contain any series of colors and is created using the setStyled() command. =item B The C color is used for drawing lines with antialiasing turned on. Antialiasing will blend the jagged edges of lines with the background, creating a smoother look. The actual color drawn is set with setAntiAliased(). =item B<$image-EsetAntiAliased($color)> "Antialiasing" is a process by which jagged edges associated with line drawing can be reduced by blending the foreground color with an appropriate percentage of the background, depending on how much of the pixel in question is actually within the boundaries of the line being drawn. All line-drawing methods, such as line() and polygon, will draw antialiased lines if the special "color" B is used when calling them. setAntiAliased() is used to specify the actual foreground color to be used when drawing antialiased lines. You may set any color to be the foreground, however as of libgd version 2.0.12 an alpha channel component is not supported. Antialiased lines can be drawn on both truecolor and palette-based images. However, attempts to draw antialiased lines on highly complex palette-based backgrounds may not give satisfactory results, due to the limited number of colors available in the palette. Antialiased line-drawing on simple backgrounds should work well with palette-based images; otherwise create or fetch a truecolor image instead. When using palette-based images, be sure to allocate a broad spectrum of colors in order to have sufficient colors for the antialiasing to use. =item B<$image-EsetAntiAliasedDontBlend($color,[$flag])> Normally, when drawing lines with the special B "color," blending with the background to reduce jagged edges is the desired behavior. However, when it is desired that lines not be blended with one particular color when it is encountered in the background, the setAntiAliasedDontBlend() method can be used to indicate the special color that the foreground should stand out more clearly against. Once turned on, you can turn this feature off by calling setAntiAliasedDontBlend() with a second argument of 0: $image->setAntiAliasedDontBlend($color,0); =back =head2 Drawing Commands These methods allow you to draw lines, rectangles, and ellipses, as well as to perform various special operations like flood-fill. =over 4 =item B<$image-EsetPixel($x,$y,$color)> This sets the pixel at (x,y) to the specified color index. No value is returned from this method. The coordinate system starts at the upper left at (0,0) and gets larger as you go down and to the right. You can use a real color, or one of the special colors gdBrushed, gdStyled and gdStyledBrushed can be specified. Example: # This assumes $peach already allocated $myImage->setPixel(50,50,$peach); =item B<$image-Eline($x1,$y1,$x2,$y2,$color)> This draws a line from (x1,y1) to (x2,y2) of the specified color. You can use a real color, or one of the special colors gdBrushed, gdStyled and gdStyledBrushed. Example: # Draw a diagonal line using the currently defined # paintbrush pattern. $myImage->line(0,0,150,150,gdBrushed); =item B<$image-EdashedLine($x1,$y1,$x2,$y2,$color)> DEPRECATED: The libgd library provides this method solely for backward compatibility with libgd version 1.0, and there have been reports that it no longer works as expected. Please use the setStyle() and gdStyled methods as described below. This draws a dashed line from (x1,y1) to (x2,y2) in the specified color. A more powerful way to generate arbitrary dashed and dotted lines is to use the setStyle() method described below and to draw with the special color gdStyled. Example: $myImage->dashedLine(0,0,150,150,$blue); =item B<$image-Erectangle($x1,$y1,$x2,$y2,$color)> This draws a rectangle with the specified color. (x1,y1) and (x2,y2) are the upper left and lower right corners respectively. Both real color indexes and the special colors gdBrushed, gdStyled and gdStyledBrushed are accepted. Example: $myImage->rectangle(10,10,100,100,$rose); =item B<$image-EfilledRectangle($x1,$y1,$x2,$y2,$color)> This draws a rectangle filed with the specified color. You can use a real color, or the special fill color gdTiled to fill the polygon with a pattern. Example: # read in a fill pattern and set it $tile = newFromPng GD::Image('happyface.png'); $myImage->setTile($tile); # draw the rectangle, filling it with the pattern $myImage->filledRectangle(10,10,150,200,gdTiled); =item B<$image-EopenPolygon($polygon,$color)> This draws a polygon with the specified color. The polygon must be created first (see below). The polygon must have at least three vertices. If the last vertex doesn't close the polygon, the method will close it for you. Both real color indexes and the special colors gdBrushed, gdStyled and gdStyledBrushed can be specified. Example: $poly = new GD::Polygon; $poly->addPt(50,0); $poly->addPt(99,99); $poly->addPt(0,99); $myImage->openPolygon($poly,$blue); =item B<$image-EunclosedPolygon($polygon,$color)> This draws a sequence of connected lines with the specified color, without connecting the first and last point to a closed polygon. The polygon must be created first (see below). The polygon must have at least three vertices. Both real color indexes and the special colors gdBrushed, gdStyled and gdStyledBrushed can be specified. You need libgd 2.0.33 or higher to use this feature. Example: $poly = new GD::Polygon; $poly->addPt(50,0); $poly->addPt(99,99); $poly->addPt(0,99); $myImage->unclosedPolygon($poly,$blue); =item B<$image-EfilledPolygon($poly,$color)> This draws a polygon filled with the specified color. You can use a real color, or the special fill color gdTiled to fill the polygon with a pattern. Example: # make a polygon $poly = new GD::Polygon; $poly->addPt(50,0); $poly->addPt(99,99); $poly->addPt(0,99); # draw the polygon, filling it with a color $myImage->filledPolygon($poly,$peachpuff); =item B<$image-Eellipse($cx,$cy,$width,$height,$color)> =item B<$image-EfilledEllipse($cx,$cy,$width,$height,$color)> These methods() draw ellipses. ($cx,$cy) is the center of the arc, and ($width,$height) specify the ellipse width and height, respectively. filledEllipse() is like Ellipse() except that the former produces filled versions of the ellipse. =item B<$image-Earc($cx,$cy,$width,$height,$start,$end,$color)> This draws arcs and ellipses. (cx,cy) are the center of the arc, and (width,height) specify the width and height, respectively. The portion of the ellipse covered by the arc are controlled by start and end, both of which are given in degrees from 0 to 360. Zero is at the top of the ellipse, and angles increase clockwise. To specify a complete ellipse, use 0 and 360 as the starting and ending angles. To draw a circle, use the same value for width and height. You can specify a normal color or one of the special colors B, B, or B. Example: # draw a semicircle centered at 100,100 $myImage->arc(100,100,50,50,0,180,$blue); =item B<$image-EfilledArc($cx,$cy,$width,$height,$start,$end,$color [,$arc_style])> This method is like arc() except that it colors in the pie wedge with the selected color. $arc_style is optional. If present it is a bitwise OR of the following constants: gdArc connect start & end points of arc with a rounded edge gdChord connect start & end points of arc with a straight line gdPie synonym for gdChord gdNoFill outline the arc or chord gdEdged connect beginning and ending of the arc to the center gdArc and gdChord are mutually exclusive. gdChord just connects the starting and ending angles with a straight line, while gdArc produces a rounded edge. gdPie is a synonym for gdArc. gdNoFill indicates that the arc or chord should be outlined, not filled. gdEdged, used together with gdNoFill, indicates that the beginning and ending angles should be connected to the center; this is a good way to outline (rather than fill) a "pie slice." Example: $image->filledArc(100,100,50,50,0,90,$blue,gdEdged|gdNoFill); =item B<$image-Efill($x,$y,$color)> This method flood-fills regions with the specified color. The color will spread through the image, starting at point (x,y), until it is stopped by a pixel of a different color from the starting pixel (this is similar to the "paintbucket" in many popular drawing toys). You can specify a normal color, or the special color gdTiled, to flood-fill with patterns. Example: # Draw a rectangle, and then make its interior blue $myImage->rectangle(10,10,100,100,$black); $myImage->fill(50,50,$blue); =item B<$image-EfillToBorder($x,$y,$bordercolor,$color)> Like C, this method flood-fills regions with the specified color, starting at position (x,y). However, instead of stopping when it hits a pixel of a different color than the starting pixel, flooding will only stop when it hits the color specified by bordercolor. You must specify a normal indexed color for the bordercolor. However, you are free to use the gdTiled color for the fill. Example: # This has the same effect as the previous example $myImage->rectangle(10,10,100,100,$black); $myImage->fillToBorder(50,50,$black,$blue); =back =head2 Image Copying Commands Two methods are provided for copying a rectangular region from one image to another. One method copies a region without resizing it. The other allows you to stretch the region during the copy operation. With either of these methods it is important to know that the routines will attempt to flesh out the destination image's color table to match the colors that are being copied from the source. If the destination's color table is already full, then the routines will attempt to find the best match, with varying results. =over 4 =item B<$image-Ecopy($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$width,$height)> This is the simplest of the several copy operations, copying the specified region from the source image to the destination image (the one performing the method call). (srcX,srcY) specify the upper left corner of a rectangle in the source image, and (width,height) give the width and height of the region to copy. (dstX,dstY) control where in the destination image to stamp the copy. You can use the same image for both the source and the destination, but the source and destination regions must not overlap or strange things will happen. Example: $myImage = new GD::Image(100,100); ... various drawing stuff ... $srcImage = new GD::Image(50,50); ... more drawing stuff ... # copy a 25x25 pixel region from $srcImage to # the rectangle starting at (10,10) in $myImage $myImage->copy($srcImage,10,10,0,0,25,25); =item B<$image-Eclone()> Make a copy of the image and return it as a new object. The new image will look identical. However, it may differ in the size of the color palette and other nonessential details. Example: $myImage = new GD::Image(100,100); ... various drawing stuff ... $copy = $myImage->clone; =item B<$image-EcopyMerge($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$width,$height,$percent)> This copies the indicated rectangle from the source image to the destination image, merging the colors to the extent specified by percent (an integer between 0 and 100). Specifying 100% has the same effect as copy() -- replacing the destination pixels with the source image. This is most useful for highlighting an area by merging in a solid rectangle. Example: $myImage = new GD::Image(100,100); ... various drawing stuff ... $redImage = new GD::Image(50,50); ... more drawing stuff ... # copy a 25x25 pixel region from $srcImage to # the rectangle starting at (10,10) in $myImage, merging 50% $myImage->copyMerge($srcImage,10,10,0,0,25,25,50); =item B<$image-EcopyMergeGray($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$width,$height,$percent)> This is identical to copyMerge() except that it preserves the hue of the source by converting all the pixels of the destination rectangle to grayscale before merging. =item B<$image-EcopyResized($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$destW,$destH,$srcW,$srcH)> This method is similar to copy() but allows you to choose different sizes for the source and destination rectangles. The source and destination rectangle's are specified independently by (srcW,srcH) and (destW,destH) respectively. copyResized() will stretch or shrink the image to accommodate the size requirements. Example: $myImage = new GD::Image(100,100); ... various drawing stuff ... $srcImage = new GD::Image(50,50); ... more drawing stuff ... # copy a 25x25 pixel region from $srcImage to # a larger rectangle starting at (10,10) in $myImage $myImage->copyResized($srcImage,10,10,0,0,50,50,25,25); =item B<$image-EcopyResampled($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$destW,$destH,$srcW,$srcH)> This method is similar to copyResized() but provides "smooth" copying from a large image to a smaller one, using a weighted average of the pixels of the source area rather than selecting one representative pixel. This method is identical to copyResized() when the destination image is a palette image. =item B<$image-EcopyRotated($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$width,$height,$angle)> Like copyResized() but the $angle argument specifies an arbitrary amount to rotate the image clockwise (in degrees). In addition, $dstX and $dstY species the B
of the destination image, and not the top left corner. =item B<$image-EtrueColorToPalette([$dither], [$colors])> This method converts a truecolor image to a palette image. The code for this function was originally drawn from the Independent JPEG Group library code, which is excellent. The code has been modified to preserve as much alpha channel information as possible in the resulting palette, in addition to preserving colors as well as possible. This does not work as well as might be hoped. It is usually best to simply produce a truecolor output image instead, which guarantees the highest output quality. Both the dithering (0/1, default=0) and maximum number of colors used (<=256, default = gdMaxColors) can be specified. =back =head2 Image Transformation Commands Gd also provides some common image transformations: =over 4 =item B<$image = $sourceImage-EcopyRotate90()> =item B<$image = $sourceImage-EcopyRotate180()> =item B<$image = $sourceImage-EcopyRotate270()> =item B<$image = $sourceImage-EcopyFlipHorizontal()> =item B<$image = $sourceImage-EcopyFlipVertical()> =item B<$image = $sourceImage-EcopyTranspose()> =item B<$image = $sourceImage-EcopyReverseTranspose()> These methods can be used to rotate, flip, or transpose an image. The result of the method is a copy of the image. =item B<$image-Erotate180()> =item B<$image-EflipHorizontal()> =item B<$image-EflipVertical()> These methods are similar to the copy* versions, but instead modify the image in place. =back =head2 Character and String Drawing GD allows you to draw characters and strings, either in normal horizontal orientation or rotated 90 degrees. These routines use a GD::Font object, described in more detail below. There are four built-in monospaced fonts, available in the global variables B, B, B, B and B. In addition, you can use the load() method to load GD-formatted bitmap font files at runtime. You can create these bitmap files from X11 BDF-format files using the bdf2gd.pl script, which should have been installed with GD (see the bdf_scripts directory if it wasn't). The format happens to be identical to the old-style MSDOS bitmap ".fnt" files, so you can use one of those directly if you happen to have one. For writing proportional scaleable fonts, GD offers the stringFT() method, which allows you to load and render any TrueType font on your system. =over 4 =item B<$image-Estring($font,$x,$y,$string,$color)> This method draws a string starting at position (x,y) in the specified font and color. Your choices of fonts are gdSmallFont, gdMediumBoldFont, gdTinyFont, gdLargeFont and gdGiantFont. Example: $myImage->string(gdSmallFont,2,10,"Peachy Keen",$peach); =item B<$image-EstringUp($font,$x,$y,$string,$color)> Just like the previous call, but draws the text rotated counterclockwise 90 degrees. =item B<$image-Echar($font,$x,$y,$char,$color)> =item B<$image-EcharUp($font,$x,$y,$char,$color)> These methods draw single characters at position (x,y) in the specified font and color. They're carry-overs from the C interface, where there is a distinction between characters and strings. Perl is insensible to such subtle distinctions. =item $font = Bload($fontfilepath)> This method dynamically loads a font file, returning a font that you can use in subsequent calls to drawing methods. For example: my $courier = GD::Font->load('./courierR12.fnt') or die "Can't load font"; $image->string($courier,2,10,"Peachy Keen",$peach); Font files must be in GD binary format, as described above. =item B<@bounds = $image-EstringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)> =item B<@bounds = GD::Image-EstringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)> =item B<@bounds = $image-EstringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string,\%options)> This method uses TrueType to draw a scaled, antialiased string using the TrueType vector font of your choice. It requires that libgd to have been compiled with TrueType support, and for the appropriate TrueType font to be installed on your system. The arguments are as follows: fgcolor Color index to draw the string in fontname A path to the TrueType (.ttf) font file or a font pattern. ptsize The desired point size (may be fractional) angle The rotation angle, in radians (positive values rotate counter clockwise) x,y X and Y coordinates to start drawing the string string The string itself If successful, the method returns an eight-element list giving the boundaries of the rendered string: @bounds[0,1] Lower left corner (x,y) @bounds[2,3] Lower right corner (x,y) @bounds[4,5] Upper right corner (x,y) @bounds[6,7] Upper left corner (x,y) In case of an error (such as the font not being available, or FT support not being available), the method returns an empty list and sets $@ to the error message. The string may contain UTF-8 sequences like: "À" You may also call this method from the GD::Image class name, in which case it doesn't do any actual drawing, but returns the bounding box using an inexpensive operation. You can use this to perform layout operations prior to drawing. Using a negative color index will disable antialiasing, as described in the libgd manual page at L. An optional 8th argument allows you to pass a hashref of options to stringFT(). Several hashkeys are recognized: B, B, B, and B. The value of B is supposed to be a multiple of the character height, so setting linespacing to 2.0 will result in double-spaced lines of text. However the current version of libgd (2.0.12) does not do this. Instead the linespacing seems to be double what is provided in this argument. So use a spacing of 0.5 to get separation of exactly one line of text. In practice, a spacing of 0.6 seems to give nice results. Another thing to watch out for is that successive lines of text should be separated by the "\r\n" characters, not just "\n". The value of B is one of "Unicode", "Shift_JIS" and "Big5". The interaction between Perl, Unicode and libgd is not clear to me, and you should experiment a bit if you want to use this feature. The value of B is the vertical and horizontal resolution, in DPI, in the format "hdpi,vdpi". If present, the resolution will be passed to the Freetype rendering engine as a hint to improve the appearance of the rendered font. The value of B is a flag. Set it to false to turn off the default kerning of text. Example: $gd->stringFT($black,'/dosc/windows/Fonts/pala.ttf',40,0,20,90, "hi there\r\nbye now", {linespacing=>0.6, charmap => 'Unicode', }); If GD was compiled with fontconfig support, and the fontconfig library is available on your system, then you can use a font name pattern instead of a path. Patterns are described in L and will look something like this "Times:italic". For backward compatibility, this feature is disabled by default. You must enable it by calling useFontConfig(1) prior to the stringFT() call. $image->useFontConfig(1); For backward compatibility with older versions of the FreeType library, the alias stringTTF() is also recognized. =item B<$hasfontconfig = $image-EuseFontConfig($flag)> Call useFontConfig() with a value of 1 in order to enable support for fontconfig font patterns (see stringFT). Regardless of the value of $flag, this method will return a true value if the fontconfig library is present, or false otherwise. This method can also be called as a class method of GD::Image; =item B<$result = $image->stringFTCircle($cx,$cy,$radius,$textRadius,$fillPortion,$font,$points,$top,$bottom,$fgcolor)> This draws text in a circle. Currently (libgd 2.0.33) this function does not work for me, but the interface is provided for completeness. The call signature is somewhat complex. Here is an excerpt from the libgd manual page: Draws the text strings specified by top and bottom on the image, curved along the edge of a circle of radius radius, with its center at cx and cy. top is written clockwise along the top; bottom is written counterclockwise along the bottom. textRadius determines the "height" of each character; if textRadius is 1/2 of radius, characters extend halfway from the edge to the center. fillPortion varies from 0 to 1.0, with useful values from about 0.4 to 0.9, and determines how much of the 180 degrees of arc assigned to each section of text is actually occupied by text; 0.9 looks better than 1.0 which is rather crowded. font is a freetype font; see gdImageStringFT. points is passed to the freetype engine and has an effect on hinting; although the size of the text is determined by radius, textRadius, and fillPortion, you should pass a point size that "hints" appropriately -- if you know the text will be large, pass a large point size such as 24.0 to get the best results. fgcolor can be any color, and may have an alpha component, do blending, etc. Returns a true value on success. =back =head2 Alpha channels The alpha channel methods allow you to control the way drawings are processed according to the alpha channel. When true color is turned on, colors are encoded as four bytes, in which the last three bytes are the RGB color values, and the first byte is the alpha channel. Therefore the hexadecimal representation of a non transparent RGB color will be: C=0x00(rr)(bb)(bb) When alpha blending is turned on, you can use the first byte of the color to control the transparency, meaning that a rectangle painted with color 0x00(rr)(bb)(bb) will be opaque, and another one painted with 0x7f(rr)(gg)(bb) will be transparent. The Alpha value must be >= 0 and <= 0x7f. =over 4 =item B<$image-EalphaBlending($integer)> The alphaBlending() method allows for two different modes of drawing on truecolor images. In blending mode, which is on by default (libgd 2.0.2 and above), the alpha channel component of the color supplied to all drawing functions, such as C, determines how much of the underlying color should be allowed to shine through. As a result, GD automatically blends the existing color at that point with the drawing color, and stores the result in the image. The resulting pixel is opaque. In non-blending mode, the drawing color is copied literally with its alpha channel information, replacing the destination pixel. Blending mode is not available when drawing on palette images. Pass a value of 1 for blending mode, and 0 for non-blending mode. =item B<$image-EsaveAlpha($saveAlpha)> By default, GD (libgd 2.0.2 and above) does not attempt to save full alpha channel information (as opposed to single-color transparency) when saving PNG images. (PNG is currently the only output format supported by gd which can accommodate alpha channel information.) This saves space in the output file. If you wish to create an image with alpha channel information for use with tools that support it, call C to turn on saving of such information, and call C to turn off alpha blending within the library so that alpha channel information is actually stored in the image rather than being composited immediately at the time that drawing functions are invoked. =back =head2 Miscellaneous Image Methods These are various utility methods that are useful in some circumstances. =over 4 =item B<$image-Einterlaced([$flag])> This method sets or queries the image's interlaced setting. Interlace produces a cool venetian blinds effect on certain viewers. Provide a true parameter to set the interlace attribute. Provide undef to disable it. Call the method without parameters to find out the current setting. =item B<($width,$height) = $image-EgetBounds()> This method will return a two-member list containing the width and height of the image. You query but not change the size of the image once it's created. =item B<$width = $image-Ewidth> =item B<$height = $image-Eheight> Return the width and height of the image, respectively. =item B<$is_truecolor = $image-EisTrueColor()> This method will return a Boolean representing whether the image is true color or not. =item B<$flag = $image1-Ecompare($image2)> Compare two images and return a bitmap describing the differences found, if any. The return value must be logically ANDed with one or more constants in order to determine the differences. The following constants are available: GD_CMP_IMAGE The two images look different GD_CMP_NUM_COLORS The two images have different numbers of colors GD_CMP_COLOR The two images' palettes differ GD_CMP_SIZE_X The two images differ in the horizontal dimension GD_CMP_SIZE_Y The two images differ in the vertical dimension GD_CMP_TRANSPARENT The two images have different transparency GD_CMP_BACKGROUND The two images have different background colors GD_CMP_INTERLACE The two images differ in their interlace GD_CMP_TRUECOLOR The two images are not both true color The most important of these is GD_CMP_IMAGE, which will tell you whether the two images will look different, ignoring differences in the order of colors in the color palette and other invisible changes. The constants are not imported by default, but must be imported individually or by importing the :cmp tag. Example: use GD qw(:DEFAULT :cmp); # get $image1 from somewhere # get $image2 from somewhere if ($image1->compare($image2) & GD_CMP_IMAGE) { warn "images differ!"; } =item B<$image-Eclip($x1,$y1,$x2,$y2)> =item B<($x1,$y1,$x2,$y2) = $image-Eclip> Set or get the clipping rectangle. When the clipping rectangle is set, all drawing will be clipped to occur within this rectangle. The clipping rectangle is initially set to be equal to the boundaries of the whole image. Change it by calling clip() with the coordinates of the new clipping rectangle. Calling clip() without any arguments will return the current clipping rectangle. =item B<$flag = $image-EboundsSafe($x,$y)> The boundsSafe() method will return true if the point indicated by ($x,$y) is within the clipping rectangle, or false if it is not. If the clipping rectangle has not been set, then it will return true if the point lies within the image boundaries. =back =head2 Grouping Methods GD does not support grouping of objects, but GD::SVG does. In that subclass, the following methods declare new groups of graphical objects: =over 4 =item $image->startGroup([$id,\%style]) =item $image->endGroup() =item $group = $image->newGroup See L for information. =back =head1 Polygons A few primitive polygon creation and manipulation methods are provided. They aren't part of the Gd library, but I thought they might be handy to have around (they're borrowed from my qd.pl Quickdraw library). Also see L. =over 3 =item B<$poly = GD::Polygon-Enew> Create an empty polygon with no vertices. $poly = new GD::Polygon; =item B<$poly-EaddPt($x,$y)> Add point (x,y) to the polygon. $poly->addPt(0,0); $poly->addPt(0,50); $poly->addPt(25,25); $myImage->fillPoly($poly,$blue); =item B<($x,$y) = $poly-EgetPt($index)> Retrieve the point at the specified vertex. ($x,$y) = $poly->getPt(2); =item B<$poly-EsetPt($index,$x,$y)> Change the value of an already existing vertex. It is an error to set a vertex that isn't already defined. $poly->setPt(2,100,100); =item B<($x,$y) = $poly-EdeletePt($index)> Delete the specified vertex, returning its value. ($x,$y) = $poly->deletePt(1); =item B<$poly-Eclear()> Delete all vertices, restoring the polygon to its initial empty state. =item B<$poly-EtoPt($dx,$dy)> Draw from current vertex to a new vertex, using relative (dx,dy) coordinates. If this is the first point, act like addPt(). $poly->addPt(0,0); $poly->toPt(0,50); $poly->toPt(25,-25); $myImage->fillPoly($poly,$blue); =item B<$vertex_count = $poly-Elength> Return the number of vertices in the polygon. $points = $poly->length; =item B<@vertices = $poly-Evertices> Return a list of all the vertices in the polygon object. Each member of the list is a reference to an (x,y) array. @vertices = $poly->vertices; foreach $v (@vertices) print join(",",@$v),"\n"; } =item B<@rect = $poly-Ebounds> Return the smallest rectangle that completely encloses the polygon. The return value is an array containing the (left,top,right,bottom) of the rectangle. ($left,$top,$right,$bottom) = $poly->bounds; =item B<$poly-Eoffset($dx,$dy)> Offset all the vertices of the polygon by the specified horizontal (dh) and vertical (dy) amounts. Positive numbers move the polygon down and to the right. $poly->offset(10,30); =item B<$poly-Emap($srcL,$srcT,$srcR,$srcB,$destL,$dstT,$dstR,$dstB)> Map the polygon from a source rectangle to an equivalent position in a destination rectangle, moving it and resizing it as necessary. See polys.pl for an example of how this works. Both the source and destination rectangles are given in (left,top,right,bottom) coordinates. For convenience, you can use the polygon's own bounding box as the source rectangle. # Make the polygon really tall $poly->map($poly->bounds,0,0,50,200); =item B<$poly-Escale($sx,$sy)> Scale each vertex of the polygon by the X and Y factors indicated by sx and sy. For example scale(2,2) will make the polygon twice as large. For best results, move the center of the polygon to position (0,0) before you scale, then move it back to its previous position. =item B<$poly-Etransform($sx,$rx,$sy,$ry,$tx,$ty)> Run each vertex of the polygon through a transformation matrix, where sx and sy are the X and Y scaling factors, rx and ry are the X and Y rotation factors, and tx and ty are X and Y offsets. See the Adobe PostScript Reference, page 154 for a full explanation, or experiment. =back =head2 GD::Polyline Please see L for information on creating open polygons and splines. =head1 Font Utilities The libgd library (used by the Perl GD library) has built-in support for about half a dozen fonts, which were converted from public-domain X Windows fonts. For more fonts, compile libgd with TrueType support and use the stringFT() call. If you wish to add more built-in fonts, the directory bdf_scripts contains two contributed utilities that may help you convert X-Windows BDF-format fonts into the format that libgd uses internally. However these scripts were written for earlier versions of GD which included its own mini-gd library. These scripts will have to be adapted for use with libgd, and the libgd library itself will have to be recompiled and linked! Please do not contact me for help with these scripts: they are unsupported. Each of these fonts is available both as an imported global (e.g. B) and as a package method (e.g. BSmall>). =over 5 =item B =item BSmall> This is the basic small font, "borrowed" from a well known public domain 6x12 font. =item B =item BLarge> This is the basic large font, "borrowed" from a well known public domain 8x16 font. =item B =item BMediumBold> This is a bold font intermediate in size between the small and large fonts, borrowed from a public domain 7x13 font; =item B =item BTiny> This is a tiny, almost unreadable font, 5x8 pixels wide. =item B =item BGiant> This is a 9x15 bold font converted by Jan Pazdziora from a sans serif X11 font. =item B<$font-Enchars> This returns the number of characters in the font. print "The large font contains ",gdLargeFont->nchars," characters\n"; =item B<$font-Eoffset> This returns the ASCII value of the first character in the font =item B<$width = $font-Ewidth> =item B<$height = $font-Eheight> =item C These return the width and height of the font. ($w,$h) = (gdLargeFont->width,gdLargeFont->height); =back =head1 Obtaining the C-language version of gd libgd, the C-language version of gd, can be obtained at URL http://www.boutell.com/gd/. Directions for installing and using it can be found at that site. Please do not contact me for help with libgd. =head1 AUTHOR The GD.pm interface is copyright 1995-2010, Lincoln D. Stein. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. package for details. The latest versions of GD.pm are available at http://stein.cshl.org/WWW/software/GD =head1 SEE ALSO L, L, L, L =cut 1; __END__ GD-2.50/README.QUICKDRAW0000644000175100017510000000072312164634363013535 0ustar lsteinlsteinqd.pl -- a Perl interface to Macintosh Quickdraw routines qd.pl allows you to create Macintosh PICT files from within Perl. You can download them to Macintosh systems, open the pictures up, and manipulate them with standard Macintosh drawing tools. To install, just copy qd.pl into /usr/local/lib/perl, or wherever your perl libraries are kept. The documentation, somewhat crude, is contained within the qd.pl file itself. Lincoln Stein lstein@genome.wi.mit.edu GD-2.50/README0000644000175100017510000004146312164634363012212 0ustar lsteinlsteinGD.pm -- A perl5 interface to Thomas Boutell's gd library. ABSTRACT: This is a autoloadable interface module for libgd, a popular library for creating and manipulating PNG files. With this library you can create PNG images on the fly or modify existing files. Features include: a. lines, polygons, rectangles and arcs, both filled and unfilled b. flood fills c. the use of arbitrary images as brushes and as tiled fill patterns d. line styling (dashed lines and the like) e. horizontal and vertical text rendering f. support for transparency and interlacing g. support for TrueType font rendering, via libfreetype. h. support for spline curves, via GD::Polyline i. support for symbolic font names, such as "helvetica:italic" j. support for symbolic color names, such as "green", via GD::Simple k. produces output in png, gif, jpeg and xbm format l. produces output in svg format via GD::SVG. For full information on usage, see the accompanying man and html documentation. Also check the FAQ at the bottom of this document. => IMPORTANT: This version of GD REQUIRES libgd 2.0.28 or higher. If you <= => have an older version of libgd installed you must remove libgd.a, <= => libgd.so (if present) and gd.h. Then install the new version of <= => libgd from www.boutell.com (see below). This particularly <= => applies to users of Linux systems. Older versions of GD are <= => available at http://www.cpan.org. <= COPYRIGHT INFO The GD.pm interface is copyright 1995-2010, Lincoln D. Stein. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. package for details. INSTALLATION: 1. Windows users can find a binary PPM package in the repositories at either: http://theoryx5.uwinnipeg.ca/ppms or http://stein.cshl.org/ppm These packages are not always updated to the most recent version, but GD is pretty stable and you usually won't miss the bleeding edge version. For MacOSX/Unix users and those who have a developer's kit installed on Windows (e.g. cygwin): 2. Make sure you have downloaded and installed the following packages: a. Perl 5.6.0 or higher: http://www.perl.com/ b. The gd graphics library: http://www.boutell.com/gd/ c. The PNG graphics library: http://www.libpng.org/pub/png/libpng.html d. The zlib compression library: http://www.gzip.org/zlib/ (OPTIONAL) e. The FreeType font rendering library for TrueType fonts: http://www.freetype.org/ f. The JPEG library, version 6b or later: ftp://ftp.uu.net/graphics/jpeg/ g. The XPM library, a standard part of modern X Windows distributions. If you don't have a modern version of X, don't try to get XPM working. If this module fails to compile and link, you are probably using an older version of libgd. Symptoms of this problem include errors about functions not being recognized in the gd.h header file, and undefined symbols from the linker. If you are having this type of error, please REMOVE all versions of libgd, gd.h from your system and reinstall libgd 2.0.28 or higher. Do not contact Lincoln for help until you have done this. Use GD 1.41 for libgd versions 1.8.4 and lower. 3. Unpack the tar file: zcat GD-2.XX.tar.gz | tar xvf - (Where "XX" is the most recent revision number.) This will create the directory GD-2.XX. 4. To compile GD.pm on a system that supports dynamic linking: a. cd GD-2.XX b. perl Makefile.PL c. make d. make test (optional) e. make html (optional) f. make install This will create GD.pm, its HTML manual page, and install GD into the system-wide Perl library directory. You'll need root privileges to do the install step. If you don't have them, see below. During step (b), Makefile.PL will look for the program gdlib-config that newer versions of libgd install for you. If this program is not present, the Makefile.PL script will ask you whether to build support for JPEG, FreeType and/or XPM image formats. Please answer "y" (the default) if libgd was built with the feature, and "n" if it was not. Failure to answer correctly will lead to link errors. If, during step (b) you see notes about missing libraries, then this module will probably not link correctly, even though the warning may say "probably harmless". 5. To compile GD.pm statically on systems that do not support dynamic linking: a. cd GD-2.XX b. perl Makefile.PL LINKTYPE=static c. make perl d. make -f Makefile.aperl inst_perl MAP_TARGET=gdperl This will create a new version of Perl and install it in your system binaries directory, under the name "gdperl". 6. Before you install GD, you will want to run the regression tests. You can do this after the "make" step by typing: make test If any tests fail, you might want to run them verbosely with: make test TEST_VERBOSE=1 7. There are some demos you can run in ext/GD/demos. They print PNG files to standard output. To view the files, pipe their output to "display" or "xv" in this way: a. cd GD-2.XX/demos b perl shapes.pl | display - You will need a graphics program that can read and display PNG format. I recommend Image::Magick's display program, available from ftp://ftp.wizards.dupont.com/pub/ImageMagick/ If you don't have any display programs handy, you can save to a temporary file and display with recent versions of Netscape or Internet Explorer. 8. A program named fonttest is included in this package under demos. This generates an image showing all the built-in fonts available. If you have built libgd with TrueType support, and you have a directory containing some TrueType fonts, you can create a simple font listing by running the program truetype_test, also located in demos. 9. See demos/gd_example.cgi for an example of how to use GD to create a picture dynamically with a CGI script. It's intended to be run under a Web server. To see it work, install it in your server's cgi-bin/ directory and invoke it from a browser by fetching a URL like: http://your.site/cgi-bin/gd_example.cgi INSTALLING GD IN YOUR HOME DIRECTORY IF YOU DON'T HAVE PRIVILEGES TO INSTALL GD.pm in your system's main Perl library directory, don't despair. You can install it into your home directory using the following feature of Makefile.PL: a. cd GD-2.XX b. perl Makefile.PL LIB=/home/fred/lib c. make d. make install (change /home/fred/lib as appropriate for your home directory). This will install GD.pm in /home/fred/lib. You may get some errors about not being able to install the manual pages. Either don't worry about it, or run the "perl Makefile.PL" step with the INST_MAN3DIR variable set to some directory you have write permission for. You'll now need to modify your GD-using scripts to tell Perl where to find GD. This example assumes that your home directory is at path "/home/fred"; change it as appropriate. #!/usr/local/bin/perl use lib '/home/fred/lib'; use GD; ... etc ... USING GD WITH FAST CGI FastCGI is a protocol from OpenMarket Corporation that markedly speeds up the execution of CGI scripts. To use FastCGI with Perl scripts, you need a specially-modified version of the Perl interpreter which you can obtain in binary and/or source form from: http://www.fastcgi.com/ To use GD with a FastCGI version of Perl you'll need to recompile it using the modified Perl. In this example, I assume that this version of Perl is found at '/usr/local/fcgi/bin/perl': modify as appropriate for your system. a. cd GD-2.XX b. edit Makefile.PL and uncomment the line 'DEFINE' => '-DFCGI' c. /usr/local/fcgi/bin/perl Makefile.PL d. make e. make install Note that these instructions have not been verified for a long time, and may no longer work. If you successfully use this module with FastCGI and find that the instructions are no longer valid, please send me the updated information. IF YOU RUN INTO PROBLEMS Some versions of Unix and Unix-like systems such as Linux ship with an incomplete version of the Perl distribution. If you get warnings such as "Module ExtUtils::MakeMaker not found", you may have such a system. Your only option is to obtain the full Perl distribution and reinstall it. If the make and install all seem to go well but you get errors like "Fatal error: can't load module GD.so", or "Fatal error: unknown symbol gdFontSmall" when you try to run a script that uses GD, you may have problems with dynamic linking. Check whether other dynamically-linked Perl modules such as POSIX and DB_File run correctly. If not, then you'll have to link Perl statically, as described above. Other problems may be fixed by compiling libgd as a shared library, as described in step (2) of the installation instructions. If you are trying to compile and link GD on a Windows or Macintosh machine and fail, please verify that you are able to build the Perl distribution from source code. If you can't do that, then you don't have the compiler/linker/make tools required for building Perl modules. You may not even need to do this, as ActiveState and MacPerl both include precompiled versions of GD. If you have problems and can't solve it on your own, post a message to the newsgroup "comp.lang.perl.modules". There are some systems that require obscure compiler and linker options in order to compile correctly, and unfortunately I have a limited number of systems at my disposal. You're much more likely to get correct answers from the gurus on the newsgroup than from myself. THE GD::SIMPLE LIBRARY GD::Simple is a simplified API for GD. It supports turtle graphics, a unified interface for drawing text, and symbolic color names (like "green"). Run "perldoc GD::Simple" for information on using it. The GD::SVG LIBRARY GD::SVG, which is available separately on CPAN, provides a subset of GD method calls. For this subset, you can create images in SVG (scaleable vector graphics) format. THE QUICKDRAW LIBRARY Also included in this package is qd.pl, a package of Quickdraw routines. If you are familiar with the Quickdraw Macintosh library, you can create Macintosh pictures (complete with scaleable fonts, draggable objects, etc. etc.) directly in Perl. See README.QUICKDRAW and qd.pl for more information. FREQUENTLY ASKED QUESTIONS 1. I get a warning about prerequisite Math::Trig not being found The version of Math::Trig that comes with Perl version 5.6.0 and lower has a bug in it that causes it not to be found even when it is installed. Try running perl -MMath::Trig -e0 from the command line. If you get no errors, go ahead and install GD. If you get an error, install Math::Trig from CPAN. 2. Why do I get errors about functions not being found when building this module? You need libgd (the C library that does all the work) version 2.0.28 or higher. Older versions will give you errors during GD installation. Get the latest version from www.boutell.com and install it. Sometimes just installing the new version of libgd is not enough: you must remove the old library first. Find the gd.h include file and all libgd files and remove them from your system. 3. Why do I get errors about symbols being undefined when building this module? See (1). 4. The %&#&#! thing doesn't compile at all! I'm getting lots of compile errors! Does "make" fail with messages like these? GD.xs: In function 'newDynamicCtx': GD.xs:440: error: 'gdIOCtx' has no member named 'gd_free' GD.xs: In function 'gd_cloneDim': GD.xs:460: error: 'struct gdImageStruct' has no member named 'alpha' GD.xs:460: error: 'struct gdImageStruct' has no member named 'alpha' GD.xs:466: error: 'struct gdImageStruct' has no member named 'thick' GD.xs:466: error: 'struct gdImageStruct' has no member named 'thick' If so, then you may have an old gd.h include file located somewhere in your system include path. Please find it and remove it. A typical location is /usr/include/gd.h. The way to make sure you are removing the correct gd.h is to run "gdlib-config --cflags" to find out where the current gd.h lives: % gdlib-config --cflags -I/usr/local/include This tells you that /usr/local/include/gd.h is the correct gd.h. Please find and remove any other gd.h. 5. My scripts fail with "Can't locate object method 'png' via package "GD::Image". libgd can now be built with support for one or more of the PNG, GIF, XPM or JPEG formats. If one or more of these formats are not supported by libgd, then the corresponding GD::Image methods will be unavailable. Unfortunately, many older scripts assume that the png() method will always be present. You can work around this issue with code like the following: my $image = $gd->can('png') ? $gd->png : $gd->gif; or if you prefer eval {} my $image = eval {$gd->png} || $gd->gif; As of libgd 2.0.33, GIF support is always compiled in, so (for the time being!) this is a safe fallback. 6. Is there a utility to convert X Windows BDF fonts into GD fonts. Yes. See the utility bdf2gdfont.pl. Run "bdf2gdfont.pl -h" to get help on using this. 7. Does GD run with Macintosh OS X? Yes. GD compiles just fine under OSX. However, you may need to remove old versions of libgd, libpng, and libz and reinstall the current versions before you try to install GD. 8. Does GD run with Win32 Perl? The latest ActiveState binaries for Win32 systems come with GD already compiled in and ready to go. I don't own any Win32 systems, and cannot provide you with help in compiling GD from scratch on such systems. 9. GD won't compile on system XX. Because libgd relies on multiple external libraries, GD does as well. Unfortunately, different systems place their libraries in different places and sometimes are picky about the order in which libraries are linked. The best thing to do is to install the latest version of libgd. Recent versions of libgd contain a gdlib-config utility, which GD will use to determine which libraries are necessary and in which order to link them. Another thing to be aware of is that some Unix distributions provide a faulty precompiled version of Perl which is unable to build and load new C-based modules (like this one). If you are getting errors like this: /arch/auto/GD/GD.so: undefined symbol: SetCPerlObj at .... then you may have such a faulty version of Perl. The most reliable thing to do is to recompile Perl from source code, thereby ensuring that it is complete. 10. When I try to load an XPM file, all I get is blackness! The libgd createFromXpm() function works with some XPM files, and not with others. The problem is buried deep in the libXpm library somewhere. 11. The stringFTCircle() method doesn't work! I know. I think this might be a problem in libgd because I have never gotten it to work as a C program. If you have any insight into this problem let me know. 12. Test XX fails The regression tests for GD involve generating images, saving them as PNG, JPEG or GIF files, and then comparing the files bit-for-bit to known "correct" files. Sometimes one of the underlying C libraries such as libz, libpng or libgd is updated, causing GD to generate an image that is subtly different. These differences are usually insignificant, such as a reordering of colors in the color table, but they will call isolated tests to fail. If you are seeing the great majority of GD tests pass, but one or two fail, then you are probably seeing the effect of a new library. Just go ahead and install GD and drop me a note about the problem. BUG REPORTS Feel free to contact me via e-mail, subject to the caveats below. Provide the version numbers of GD, Perl, make and model of your operating system, and make and model of your Web server, if appropriate. Provide a small script that demonstrates the bug. Do NOT contact me for issues involving compilation failures on Windows, VMS, or Macintosh systems. I do not have any such systems on hand, and cannot help you out. Also do NOT contact me for issues involving the images looking distorted, having the wrong color tables, or other such low-level issues. These problems should be referred to Tom Boutell because they pertain to the underlying libgd library. ACKNOWLEDGEMENTS: I'd like to thank Jan Pazdziora, Geoff Baysinger, and David Kilzer for their contributions to the library, as well as Thomas Boutell who wrote libgd. UPDATES: The current version of GD can be found in CPAN. The development version can be found on GitHub at https://github.com/lstein/Perl-GD. AUTHOR: Lincoln Stein lincoln.stein@gmail.com GD-2.50/bdf_scripts/0000755000175100017510000000000012164636125013622 5ustar lsteinlsteinGD-2.50/bdf_scripts/bdftogd0000755000175100017510000000776212164634363015177 0ustar lsteinlstein#!/usr/bin/perl -w # # Simple convertor from bdf to gd font format. # # Author: Jan Pazdziora, adelton@fi.muni.cz, http://www.fi.muni.cz/~adelton/ # at Faculty of Informatics, Masaryk University in Brno, Czech Republic. # # Example of use: # fstobdf -s fontserverhost:7100 -fn 8x16 | ./bdftogd FontLarge gdfontl # use strict; my $VERSION = '0.60'; my $now = localtime; if (@ARGV < 2) { die "usage: bdftogd fontname filename, eg. bdftogd FontLarge gdfontl\n"; } my $gdname = shift; $gdname = 'gd' . $gdname unless $gdname =~ /^gd/i; my $filename = shift; $filename = 'gd' . $filename unless $filename =~ /^gd/i; if (-f "$filename.c") { die "File $filename.c already exists, won't overwrite\n"; } if (-f "$filename.h") { die "File $filename.h already exists, won't overwrite\n"; } my ($width, $height); my (@data, @left, @bottom); my ($globalleft, $globaltop); my ($minchar, $maxchar); my ($copyright, $fontdef); my $currentchar; my $gobitmap = 0; while (<>) { chomp; s/\r$//; my ($tag, $value) = split / /, $_, 2; die "Font is not fixed width\n" if $tag eq 'SPACING' and not $value =~ /[CM]/i; $currentchar = $value if $tag eq 'ENCODING'; $minchar = $currentchar if not defined $minchar or ($currentchar < $minchar && $currentchar >= 0); $maxchar = $currentchar if not defined $maxchar or ($currentchar > $maxchar && $currentchar >= 0); if ($tag eq 'ENDCHAR') { next if $currentchar < 0; $gobitmap = 0; my $bottom = $globaltop - $bottom[$currentchar]; if ($bottom > 0) { $data[$currentchar] = substr $data[$currentchar], 0, length($data[$currentchar]) - $bottom * $width; } else { $data[$currentchar] .= '0' x (-$bottom * $width); } } if ($tag eq 'FONTBOUNDINGBOX') { my ($tag, $wid, $hei, $left, $top) = split / /; if (defined $top) { $globalleft = $left; $globaltop = $top; $height = $hei; $width = $wid; } } if ($tag eq 'FONT' and not defined $fontdef) { $fontdef = $value; } if ($tag eq 'COPYRIGHT' and not defined $copyright) { $copyright = $value; } if ($tag eq 'BBX') { my ($tag, $wid, $hei, $left, $bottom) = split / /; if (defined $bottom) { $left[$currentchar] = $left; $bottom[$currentchar] = $bottom; } } if ($gobitmap) { my $value = pack 'H*', $_; my $bits = unpack 'B*', $value; $bits = ('0' x $left[$currentchar]) . $bits; $bits .= '0' x ($width - length $bits); $bits = substr $bits, 0, $width; $data[$currentchar] .= $bits; } if ($tag eq 'BITMAP') { $gobitmap = 1; $data[$currentchar] = ''; } } my $info = <<"EOF"; /* This is a header file for gd font, generated using bdftogd version $VERSION by Jan Pazdziora, adelton\@fi.muni.cz from bdf font $fontdef at $now. EOF if (defined $copyright) { $info .= <<"EOF"; The original bdf was holding following copyright: $copyright */ EOF } else { $info .= <<"EOF"; No copyright info was found in the original bdf. */ EOF } open FILEC, "> $filename.c" or die "Error writing $filename.c: $!\n"; open FILEH, "> $filename.h" or die "Error writing $filename.h: $!\n"; print FILEC <<"EOF"; $info #include "$filename.h" char ${gdname}Data[] = { EOF $minchar = 0 unless defined $minchar; $maxchar = 255 unless defined $maxchar; for (my $i = $minchar; $i <= $maxchar; $i++) { $data[$i] = '' unless defined $data[$i]; $data[$i] = '0' x ($width * $height - length $data[$i]) . $data[$i]; print FILEC "/* Char $i */\n"; for my $line (0 .. $height - 1) { print FILEC join ',', split(//, substr($data[$i], $line * $width, $width)), "\n"; } print FILEC "\n"; next; for my $line (0 .. $height - 1) { print substr($data[$i], $line * $width, $width), "\n"; } } my $capdef = "\U_${filename}_H_"; print FILEC <<"EOF"; }; gdFont ${gdname}Rep = { @{[ $maxchar - $minchar + 1]}, $minchar, $width, $height, ${gdname}Data }; gdFontPtr ${gdname} = &${gdname}Rep; /* This file has not been truncated. */ EOF close FILEC; print FILEH <<"EOF"; #ifndef $capdef #define $capdef 1 $info #include "gd.h" extern gdFontPtr $gdname; #endif EOF 1; GD-2.50/bdf_scripts/bdf2gdfont.PLS0000644000175100017510000001231712164634363016227 0ustar lsteinlstein#!perl use Config; use File::Basename qw(&basename &dirname); use Cwd; $origdir = cwd; chdir dirname($0); $file = basename($0, '.PL','.PLS'); $file .= $^O eq 'VMS' ? '.com' : '.pl'; open OUT,">$file" or die "Can't create $file: $!"; print "Extracting $file (with variable substitutions)\n"; print OUT <<"!GROK!THIS!"; $Config{startperl} !GROK!THIS! # In the following, perl variables are not expanded during extraction. print OUT <<'!NO!SUBS!'; # # Simple convertor from bdf to loadable GD font format. # # Author: Lincoln Stein , heavily adopted from bdftogd from # Jan Pazdziora # # Example of use: # fstobdf -s fontserverhost:7100 -fn 8x16 | bdftofnt > myfont.fnt # use strict; our $VERSION = '1.00'; if ($ARGV[0] =~ /^--?h/) { exec "perldoc $0"; } my ($width, $height); my (@data, @left, @bottom); my ($globalleft, $globaltop); my ($minchar, $maxchar); my ($copyright, $fontdef); my $currentchar; my $gobitmap = 0; foreach (@ARGV) { $_ = "gunzip -c $_ |" if /\.gz$/; } while (<>) { chomp; s/\r$//; next unless $_; my ($tag, $value) = split / /, $_, 2; die "Font is not fixed width\n" if $tag eq 'SPACING' and not $value =~ /[CM]/i; $currentchar = $value if $tag eq 'ENCODING'; $minchar = $currentchar if not defined $minchar or ($currentchar < $minchar && $currentchar >= 0); $maxchar = $currentchar if not defined $maxchar or ($currentchar > $maxchar && $currentchar >= 0); if ($tag eq 'ENDCHAR') { next if $currentchar < 0; $gobitmap = 0; my $bottom = $globaltop - $bottom[$currentchar]; if ($bottom > 0) { $data[$currentchar] = substr $data[$currentchar], 0, length($data[$currentchar]) - $bottom * $width; } else { $data[$currentchar] .= '0' x (-$bottom * $width); } } if ($tag eq 'FONTBOUNDINGBOX') { my ($tag, $wid, $hei, $left, $top) = split / /; if (defined $top) { $globalleft = $left; $globaltop = $top; $height = $hei; $width = $wid; } } if ($tag eq 'FONT' and not defined $fontdef) { $fontdef = $value; } if ($tag eq 'COPYRIGHT' and not defined $copyright) { $copyright = $value; } if ($tag eq 'BBX') { my ($tag, $wid, $hei, $left, $bottom) = split / /; if (defined $bottom) { $left[$currentchar] = $left; $bottom[$currentchar] = $bottom; } } if ($gobitmap) { my $value = pack 'H*', $_; my $bits = unpack 'B*', $value; $bits = ('0' x $left[$currentchar]) . $bits; $bits .= '0' x ($width - length $bits); $bits = substr $bits, 0, $width; $data[$currentchar] .= $bits; } if ($tag eq 'BITMAP') { $gobitmap = 1; $data[$currentchar] = ''; } } $minchar = 0 unless defined $minchar; $maxchar = 255 unless defined $maxchar; binmode STDOUT; # for DOS/Windows systems my $length = $maxchar-$minchar+1; print pack ('VVVV',$length,$minchar,$width,$height); # header for (my $i = $minchar; $i <= $maxchar; $i++) { $data[$i] = '' unless defined $data[$i]; $data[$i] = '0' x ($width * $height - length $data[$i]) . $data[$i]; print pack('C*',split '',$data[$i]); } print STDERR "Successfully converted $length ${width}x$}height} characters\n"; __END__ =head1 NAME bdf2gdfont.pl - Convert X11 "BDF" fonts into a loadable font format for GD. =head1 SYNOPSIS % bdf2gdfont.pl courR12.bdf > courR12.fnt =head1 DESCRIPTION This script converts BDF-style X11 font files into a format that can be loaded by the GD module using the GD::Font->load() method. There are a number of ways to obtain BDF fonts. =over 4 =item 1. The font is already present on your system. Some BDF fonts can be found in the standard X11R6 distribution. This script will automatically uncompress gzipped font files if their extension ends with .gz (the gunzip program must be on your path). =item 2. From a font server. The "fstobdf" utility, a standard X11 utility, will read a named font from the font server of your choice and return it in BDF format. You can pipe it to bdf2gdfont.pl: fstobdf -s fontserverhost:7100 -fn 8x16 | bdf2gdfont.pl > newfont.fnt Use xlsfonts to find out what fonts are available. Most fonts will have long names like -B&H-LucidaTypewriter-Bold-R-Normal-Sans-18-180-75-75-M-110-ISO8859-10. =item 3. Using the pcf2bdf utility. Some fonts are only available in PCF (compiled) format. To obtain these, you can either turn on a font server and follow recipe (2), or use TAGA Nayuta's pcf2bdf utility. This utility is available from http://www.tsg.ne.jp/GANA/S/pcf2bdf/ (page is in Japanese, but you can find the download link). =back =head2 Limitations This font converter only works with fixed-width fonts. If used with a TrueType or proportional font it will die with an error message. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein , heavily adapted from bdftogd from Jan Pazdziora . Copyright (c) 2004 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut !NO!SUBS! close OUT or die "Can't close $file: $!"; chmod 0755, $file or die "Can't reset permissions for $file: $!\n"; exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':'; chdir $origdir; GD-2.50/bdf_scripts/README0000644000175100017510000000055312164634363014507 0ustar lsteinlsteinThe bdf2gdfont.pl script will convert an X11 BDF font into a bitmapped font that can be loaded into GD using the GD::Font->load() method. Some restrictions apply. Run "perldoc bdf2gdfont.pl" for details. Other scripts in this directory were designed for older versions of libgd in which the fonts are compiled in. Please use with care. Lincoln Stein Fall 2004 GD-2.50/demos/0000755000175100017510000000000012164636125012427 5ustar lsteinlsteinGD-2.50/demos/copies.pl0000755000175100017510000000211112164634363014246 0ustar lsteinlstein#!/usr/local/bin/perl use GD; $im = new GD::Image(300,300); $white = $im->colorAllocate(255, 255, 255); $black = $im->colorAllocate(0, 0, 0); $red = $im->colorAllocate(255, 0, 0); $blue = $im->colorAllocate(0,0,255); $yellow = $im->colorAllocate(255,250,205); # Create a flat wide rectangle paintbrush $brush = new GD::Image(10,10); $brush->colorAllocate(255,255,255); # white $brush->colorAllocate(0,0,0); # black $brush->transparent($white); # white is transparent $brush->filledRectangle(0,0,5,2,$black); # a black rectangle $im->setBrush($brush); $im->arc(100,100,100,150,0,360,gdBrushed); $poly = new GD::Polygon; $poly->addPt(30,30); $poly->addPt(100,10); $poly->addPt(190,290); $poly->addPt(30,290); $im->polygon($poly,gdBrushed); $im->fill(132,62,$blue); $im->fill(100,70,$red); $im->fill(40,40,$yellow); $im->interlaced(1); # Copy the 20,20,70,70 region # to a location at 150,150 $im->copy($im,150,150,20,20,50,50); # Same thing, but doubling the size $im->copyResized($im,10,200,20,20,100,100,50,50); binmode STDOUT; # print the image to stdout print $im->png; GD-2.50/demos/transform.pl0000755000175100017510000000130012164634363014776 0ustar lsteinlstein#!/usr/local/bin/perl use GD; # test scaling, translation, transformation $im = new GD::Image(380,225); $black = $im->colorAllocate(0, 0, 0); $white = $im->colorAllocate(255, 255, 255); $red = $im->colorAllocate(255, 0, 0); $blue = $im->colorAllocate(0,0,255); $yellow = $im->colorAllocate(255,250,205); # Create a triangle $poly = new GD::Polygon; $poly->toPt(50,50); $poly->toPt(100,0); $poly->toPt(-50,50); $poly->toPt(-50,-50); $im->filledPolygon($poly,$yellow); # Stretch it a bit $poly->scale(1.8,1.0); $poly->offset(100,0); $im->filledPolygon($poly,$red); # Rotate it $poly->transform(0.55,0.20,0.0,1,-25,50); $im->filledPolygon($poly,$blue); binmode STDOUT; print $im->png; GD-2.50/demos/gd_example.cgi0000755000175100017510000000126112164634363015225 0ustar lsteinlstein#!/usr/local/bin/perl use GD; print "Content-type: image/png\n\n"; # create a new image $im = new GD::Image(100,100); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); binmode STDOUT; # Convert the image to PNG and print it on standard output print $im->png; GD-2.50/demos/tile.png0000644000175100017510000000043012164634363014071 0ustar lsteinlsteinPNG  IHDRR? PLTEܸ [ѧ:bKGDHIDATxc``Z:CCC?bBFCtEXtSoftware@(#)ImageMagick 4.1.0 98/09/08 cristy@mystic.es.dupont.comeB*tEXtSignature7a52b1cac1657d1b4f8ef32b4198eabc{;\tEXtPage21x22+0+0IENDB`GD-2.50/demos/polyline.pl0000644000175100017510000002122012164634363014616 0ustar lsteinlstein############################################################################ # # Sample code for use of Polyline.pm # # Author: Dan Harasty # Email: harasty@cpan.org # Version: 0.1 # Date: 7/20/2002 # # use GD; use GD::Polyline; $PI = 3.14159; $TWO_PI = 2 * $PI; sub r2d {$_[0] * 180 / $PI}; $splinekey = "
  • Green: original polygon or polyline
  • Blue: control points added with addControlPoints()
  • Black: spline generated by toSpline()
"; if (1) { use GD; use GD::Polyline; # create an image $image = new GD::Image (500,300); $white = $image->colorAllocate(255,255,255); $black = $image->colorAllocate( 0, 0, 0); $red = $image->colorAllocate(255, 0, 0); # create a new polyline $polyline = new GD::Polyline; # add some points $polyline->addPt( 0, 0); $polyline->addPt( 0,100); $polyline->addPt( 50,125); $polyline->addPt(100, 0); # polylines can use polygon methods (and vice versa) $polyline->offset(200,100); # rotate 60 degrees, about the centroid $polyline->rotate(3.14159/3, $polyline->centroid()); # scale about the centroid $polyline->scale(1.5, 2, $polyline->centroid()); # draw the polyline $image->polydraw($polyline,$black); # create a spline, which is also a polyine $spline = $polyline->addControlPoints->toSpline; $image->polydraw($spline,$red); # output the png #binmode STDOUT; #print $image->png; SampleImage($image, "polyline-synopsis.png", "Synopsis", "Polyline created by 'SYNOPSIS' section of documentation."); } if (1) { $image = NewImage(); $offset = 50; for $poly (new GD::Polygon, new GD::Polyline) { $table_info = []; $poly->addPt( 0, 0); $poly->addPt( 0,100); $poly->addPt( 50,125); $poly->addPt(100, 0); #print "this " . ref($poly) . " has " . $poly->length() . " points\n"; push @$table_info, ["".ref($poly).""]; push @$table_info, ['vertex number: ', 0..($poly->length()-1)]; @coords = $poly->vertices(); @coords = map {"[".int($_->[0]).",".int($_->[1])."]"} @coords; push @$table_info, ['coordinates (pre-offset): ', @coords]; @lengths = $poly->segLength(); @lengths = map {int($_+0.5)} @lengths; #print "segLengths are : @lengths\n"; #print "perimeter is : " . int($poly->segLength()) . "\n"; push @$table_info, ['segment lengths: ', @lengths]; @angles = $poly->segAngle(); @angles = map {int(r2d($_)+0.5)} @angles; #print "seg angles are : @angles\n"; push @$table_info, ['segment angles: ', @angles]; @angles = $poly->vertexAngle(); @angles = map {defined ($_) ? int(r2d($_)+0.5) : "undef"} @angles; #print "vertex angles are: @angles\n"; push @$table_info, ['vertex angles: ', @angles]; $poly->offset(50 + $offset,80); $offset += 200; # draw the original poly $image->polydraw($poly,$black); #print "\n\n"; push @$summary_table, genHTMLTable($table_info, 0); } SampleImage($image, "polyline-simple.png", "Simple", "GD::Polygon and GD::Polyline with same vertexes.

" . genHTMLTable([$summary_table], 1)); } if (1) { $image = NewImage(); $offset = 50; for $poly (new GD::Polygon, new GD::Polyline) { $poly->addPt( 0, 0); $poly->addPt( 0,100); $poly->addPt( 50,125); $poly->addPt(100, 0); $poly->offset(50 + $offset,80); $offset += 200; # draw the original poly $image->polydraw($poly,$green); # create and draw the control line for the spline $ctrlline = $poly->addControlPoints(); $image->polydraw($ctrlline,$cyan); # create and draw the spline itself $spline = $ctrlline->toSpline(); $image->polydraw($spline,$black); } SampleImage($image, "polyline-spline.png", "Spline", "Splines fit to vertices of polygon and polyline. $splinekey"); } if (1) { $image = NewImage(); $triangle = new GD::Polygon; $triangle->addPt( 0, 0); $triangle->addPt(-19, 95); $triangle->addPt( 19, 95); $triangle->offset(250,50); foreach (1..9) { $image->polydraw($triangle,gdBrushed); $triangle->rotate($TWO_PI / 9, 250, 150); } SampleImage($image, "polyline-star9.png", "Nine Pointed Star", "A triangle, rotated about a point other than the origin.
Demonstration of \$poly->rotate() and \$poly->offset()"); } if (1) { $image = NewImage(); $cloverControl = new GD::Polyline; $cloverControl->addPt(45,45); $cloverControl->addPt(10,10); $cloverControl->addPt(90,10); $cloverControl->addPt(55,45); $cloverControl->addPt(90,10); $cloverControl->addPt(90,90); $cloverControl->addPt(55,55); $cloverControl->addPt(90,90); $cloverControl->addPt(10,90); $cloverControl->addPt(45,55); $cloverControl->addPt(10,90); $cloverControl->addPt(10,10); $cloverControl->addPt(45,45); $clover = $cloverControl->toSpline(); # note that the three following transformations # could have been called on $cloverControl, instead, # followed by the above call $clover->offset($clover->centroid(-1)); $clover->scale(3, 3); $clover->offset(250, 150); $image->filledPolygon($clover,$green); SampleImage($image, "polyline-clover.png", "Clover", "Sample image generated by GD::Polygon"); } if (1) { $image = NewImage(); $polyline = new GD::Polyline; for (0..15) { $polyline->addPt(30 * $_ + 10, rand(90) + 5); } $image->polyline($polyline,$green); $ctrlline = $polyline->addControlPoints(); $ctrlline->offset(0,100); $image->polyline($ctrlline,$cyan); $spline = $ctrlline->toSpline(); $spline->offset(0,100); $image->polyline($spline,$black); SampleImage($image, "polyline-zigzag.png", "Zigzag", "Spline fit to random function. $splinekey"); } if (1) { $image = NewImage(); $ring_network = new GD::Polygon; $num_nodes = 10; $randfactor = 80; for (1..$num_nodes) { $x = 250 + 150 * cos($TWO_PI * $_/$num_nodes); $y = 150 + 100 * sin($TWO_PI * $_/$num_nodes); $x += rand($randfactor)-$randfactor/2; $y += rand($randfactor)-$randfactor/2; $ring_network->addPt($x, $y); } $image->setBrush($brush2); $image->polyline($ring_network->addControlPoints->toSpline,gdBrushed); $ring_node = new GD::Polygon; $ring_node->addPt( 0, 0); $ring_node->addPt(10, 0); $ring_node->addPt(10,10); $ring_node->addPt( 0,10); for $ring_vertex ($ring_network->vertices()) { $ring_node->offset($ring_node->centroid(-1)); $ring_node->offset(@$ring_vertex); $image->filledPolygon($ring_node,$grey); } SampleImage($image, "polyline-ring-network.png", "Ring Network", "Closed spline fit to nodes at somewhat random positions."); } WriteToFile("polyline-example.html", theHTML()); print "\n"; print "open 'polyline-example.html' in your favorite browser that supports PNG.\n"; print "\n"; print "done! " . localtime() . "\n"; ########################## # # helper functions # sub NewImage { $image = new GD::Image (500,300); $white = $image->colorAllocate(255,255,255); $black = $image->colorAllocate( 0, 0, 0); $grey = $image->colorAllocate(128,128,128); $red = $image->colorAllocate(255, 0, 0); $orange = $image->colorAllocate(255,196, 0); $green = $image->colorAllocate( 0,255, 0); $blue = $image->colorAllocate( 0, 0,255); $cyan = $image->colorAllocate( 0,255,255); $purple = $image->colorAllocate(206, 0,165); $brush_width = 2; $brush_color = [255,128,0]; $brush = new GD::Image($brush_width,$brush_width); $brush->transparent($brush->colorAllocate(255,255,255)); $brush->filledRectangle(0,0,$brush_width,$brush_width,$brush->colorAllocate(@$brush_color)); $brush1 = $brush; $brush_width = 3; $brush_color = [206,0,165]; $brush = new GD::Image($brush_width,$brush_width); $brush->transparent($brush->colorAllocate(255,255,255)); $brush->filledRectangle(0,0,$brush_width,$brush_width,$brush->colorAllocate(@$brush_color)); $brush2 = $brush; $image->setBrush($brush1); $image; } my $html; sub SampleImage { my $image = shift; my $file = shift; my $title = shift; my $text = shift; WriteToBinaryFile($file, $image->png()); $html .= "
\n"; $html .= "$title - $file
\n"; $html .= "

$text


\n"; } sub theHTML { $html; } sub WriteToFile { my $file = shift || return 0; my $contents = shift || ""; open (NEWFILE, ">" . $file) or die "couldn't write to file $file"; print NEWFILE $contents; close(NEWFILE); print "created file $file\n"; } sub WriteToBinaryFile { my $file = shift || return 0; my $contents = shift || ""; open (NEWFILE, ">" . $file) or die "couldn't write to file $file"; binmode NEWFILE; print NEWFILE $contents; close(NEWFILE); print "created file $file\n"; } sub genHTMLTable { my $array_of_arrays = shift; my $border = shift; my $html_table; $html_table .= ""; for my $array_of_items (@$array_of_arrays) { $html_table .= ""; } $html_table .= "
"; $html_table .= join("", @$array_of_items); $html_table .= "
"; $html_table; } GD-2.50/demos/polys.pl0000755000175100017510000000142712164634363014143 0ustar lsteinlstein#!/usr/local/bin/perl use GD; $im = new GD::Image(225,180); $black = $im->colorAllocate(0, 0, 0); $white = $im->colorAllocate(255, 255, 255); $red = $im->colorAllocate(255, 0, 0); $blue = $im->colorAllocate(0,0,255); $yellow = $im->colorAllocate(255,250,205); # Create a triangle $poly = new GD::Polygon; $poly->addPt(0,50); $poly->addPt(25,25); $poly->addPt(50,50); $im->filledPolygon($poly,$blue); # offset it down and to the right $poly->offset(100,100); $im->filledPolygon($poly,$red); # make it twice as wide and move it upward a bit $poly->map(50,50,100,100,10,10,110,60); $im->filledPolygon($poly,$yellow); # make it real tall $poly->map($poly->bounds,50,20,80,160); $im->filledPolygon($poly,$white); binmode STDOUT; # print the image to stdout print $im->png; GD-2.50/demos/shapes.pl0000755000175100017510000000242312164634363014255 0ustar lsteinlstein#!/usr/local/bin/perl use GD; $im = new GD::Image(300,300); ($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); $im->transparent($white); # white color is transparent $im->interlaced(1); # cool venetian blinds effect # Create a flat wide rectangle paintbrush $brush = new GD::Image(10,10); $brush->colorAllocate(255,255,255); # white $brush->colorAllocate(0,0,0); # black $brush->transparent($white); # white is transparent $brush->filledRectangle(0,0,5,2,$black); # a black rectangle # Draw a friendly title (ha!) $im->string(gdLargeFont,150,10,"Hello world!",$red); $im->string(gdSmallFont,150,28,"Goodbye cruel world!",$blue); $im->stringUp(gdTinyFont,280,250,"I'm climbing the wall!",$black); $im->charUp(gdMediumBoldFont,280,280,"Q",$black); # Draw an oval $im->setBrush($brush); $im->arc(100,100,100,150,0,360,gdBrushed); $poly = new GD::Polygon; $poly->addPt(30,30); $poly->addPt(100,10); $poly->addPt(190,290); $poly->addPt(30,290); $im->polygon($poly,gdBrushed); $im->fill(132,62,$blue); $im->fill(100,70,$red); $im->fill(40,40,$yellow); binmode STDOUT; # print the image to stdout print $im->png; GD-2.50/demos/brushes.pl0000755000175100017510000000164112164634363014446 0ustar lsteinlstein#!/usr/local/bin/perl use GD; $im = new GD::Image(300,300); # allocate white $white = $im->colorAllocate(255, 255, 255); # allocate black $black = $im->colorAllocate(0, 0, 0); # allocate red $red = $im->colorAllocate(255, 0, 0); # allocate green $green = $im->colorAllocate(0,255,0); # allocate yellow $yellow = $im->colorAllocate(255,250,205); # Get an image from a png file open (TILE,"./tile.png") || die; $tile = newFromPng GD::Image(TILE); close TILE; # use it as a paintbrush $im->setBrush($tile); $im->arc(100,100,100,150,0,360,gdBrushed); # use it as a tiling pattern to fill a rectangle $im->setTile($tile); $im->filledRectangle(150,150,250,250,gdTiled); $im->rectangle(150,150,250,250,$black); # Draw a dotted line $im->setStyle($green,$green,$green,gdTransparent,$red,$red,$red,gdTransparent); $im->line(0,280,300,280,gdStyled); binmode STDOUT; # print the image to stdout print $im->png; GD-2.50/demos/fonttest0000755000175100017510000000165012164634363014227 0ustar lsteinlstein#!/usr/bin/perl -w use lib './blib/arch','./blib/lib'; use strict; use GD; use subs qw( charmap ); my $teststring = pack 'C*', 32, 1 .. 255; my $im = new GD::Image(640, 500); my ($white, $black) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), ); # $im->transparent($white); $im->interlaced(1); charmap($im, gdGiantFont, "GiantFont 9x15", 20, 16); charmap($im, gdLargeFont, "LargeFont 8x16", 120, 16); charmap($im, gdMediumBoldFont, "gdMediumBoldFont 7x13b", 220, 13); charmap($im, gdSmallFont, "gdSmallFont 6x13", 320, 13); charmap($im, gdTinyFont, "gdTinyFont 5x8", 420, 8); binmode(STDOUT); print $im->png; sub charmap { my $im = shift; my ($font, $title, $topoffset, $lineskip) = @_; $im->string($font, 16, $topoffset, $title.':', $black); my $line; for $line (0 .. 4) { $im->string($font, 16, $topoffset + (1 + $line) * $lineskip, substr($teststring, $line * 64, 64), $black); } } GD-2.50/demos/ttf.pl0000755000175100017510000000134612164634363013572 0ustar lsteinlstein#!/usr/local/bin/perl use lib '../blib/lib','../blib/arch'; use GD 1.20; use constant font => '../t/Generic.ttf'; $im = new GD::Image(400,250); warn $GD::VERSION; ($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); $im->interlaced(1); # cool venetian blinds effect # Some TTFs $im->stringTTF($black,font,12.0,0.0,20,20,"Hello world!") || die $@; $im->stringTTF($red,font,14.0,0.0,20,80,"Hello world!")|| die $@;; $im->stringTTF($blue,font,30.0,-0.5,60,100,"Goodbye cruel world!")|| die $@;; binmode STDOUT; # print the image to stdout print $im->png; GD-2.50/demos/truetype_test0000755000175100017510000000154612164634363015305 0ustar lsteinlstein#!/usr/local/bin/perl use lib '../blib/lib','../blib/arch'; use GD 1.20; use constant FONT_DIRECTORY => '/dosc/windows/fonts'; my $directory = shift || FONT_DIRECTORY; my @fonts = <$directory/*.pfa $directory/*.pfb $directory/*.ttf>; die "Usage: $0 \nDisplays a directory of TrueType and Type1 fonts\n" unless @fonts; my $im = new GD::Image(800,600); my ($white,$black) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0)); my ($x,$y) = (20,20); my $max_x = 0; for my $font (@fonts) { my ($font_name) = $font =~ /([^\\\/]+)$/; warn "rendering $font_name\n"; (my @h = $im->stringTTF($black,$font,12.0,0.0,$x,$y,$font_name)) || next; $y = $h[1] + 12 + 5; $max_x = $max_x > $h[4] ? $max_x : $h[4]; if ($y > 600) { $y = 20; $x = $max_x + 5; } } binmode STDOUT; # print the image to stdout print $im->png; GD-2.50/demos/font_list.png0000644000175100017510000005307612164634363015153 0ustar lsteinlsteinPNG  IHDR XhXCPLTE???___///"c IDATxے0&& Ur'/%par/+L$aC$ē'=IOzғ'=Qo]*QmeVixkV"&M7-QVב m8Cd͏Q C_Ut6jo<*/onZw=o;qڀ*y_^*">H}˛#Om/8 zm hio}"ڰ_v].R/̪থ;^Z<`S羬Kțx5'2 ZCiy! QTY\}VQ^bF+ <ľ&v& H_|.+zw9%xnĔ+*'2 ĕWhmG㲬FvhU݌phDnpUd^cs|/?] @"R^l9AB`ӎz`TXy } `ƵpR=  {;d@ly;s ϶)> h-rH]"bYӽp :Y%7$QwWg{T1&Y?ߧ=1LCl`ȀoyS-u!(J$@tu;gޑtjQ6D?=Ɖ juTEb38n3Ul* YZx~~mzS_<񐫿(#KVޅ*ϒL:z)x I'&BI >: _UAHވ ؎HzwzwE! c} nE)ªh'c"i&mA{"aqUsi!0(c O3a2r6h?DwuTWu PQXySj^yU i1mpwgԇml0v,=64ĐyP2;+'bG_ꭼ{aG9 u|.ͯ*&$6J×:~_J{bO͓H'fOzғ;L;# DMrV^No)b:E#[*`h0 ‘o}.fY|Чh`HS@Zh`T\MG[ fkjGi~U|)]o̮|*sձEQs{*Ϲ^5Kix-fMEHbES1-JkL65݁z:Vv_΀$~J$F!;iQ%G :fgD`xm'f`(F.*pUOܣ'@~4iX 5?֯?(`DM1, ۋ>j"}*cse MS6M`H`q uwiX'laMuQ_JHC"f~Ofwi~$oVmH_&5A7)}j/wHct%RR ,4|hFd?M:4ñ6Ĥa:Pr(tt0lpCþ~h{.BoZRG4AMnq7Xoq^&t˪/B@o*r6G&~Eҗ4i}))XtRk Kѷmۗ0T޷jt#'tEdŸ @،~G=iT9vwGHj(xb,q)+1.6TS4=zrhM8VwBd! xEAh'9v gl+KҀ?p4fW^pR.C[aۄI[j{]32*^P}; ğ‰e @jwӾݵ_,=(`wR:jX#ԫu]H¬l+ sh+R=,6Ni-,xlLo: ^|ۊg,Ċz!P3/>`xBAdc8ƓN˃1u>ݥ^.#ƴv:/Y6Btŷt\w?ٕp tLxJvi.Eyr6(b&&!*;vV7LNBwt7^wB~wB\?WGh3"fz/aUE҅Nۃ]W =7P'Am(;+G|#&)ۥ]1/~&0ɾFRc)$Uɺ5!% tk9hƔV٩yHTECN"!䢟l*.零mjW0)JLa؅94g/ Y$fL:T~T{]CUmv_5 dw^t&x.cRk!\*h۴ ]i0J5 QK#_;'kZz\(1.^#$TXŢ+Fd"xVjpکDhߖ(A1;k7;G?.S(O k*U>K vW R26 ^"e-Jck%`tOPy Jw>TQcT Fn:hJQTMyD-zB :C9U[&6mP^~_=?^ߟ*f>y)9t?£.(rpb:?|"-ݡԇ7)qik:yûW~G;:&(JȅH#XCj,㜍 z-'/ OCm O}H׻$){AoH9Swk˦uΗ>wl;nj)dQ2@viȪln _MuF¬o&fɡlS#ocmPBIM}rm3 csSfBۨgō55)_!4ea3\%N,%]Ssj(ssdu!.3j\p/oz-5n)m08.ηCc奸k)“HN NJmM{]am)(u9n 6u`vz\ho&3r4NfgAuL01s@FÛc?[y`._wSםOqna#Avd-jx[st)S& XnͰȜo=uG%)9>ZQľIW;l#fC+\4V"[ d18`Pį'^&gIXtR;q8lxMG iu kS*WwjuRTQFsMXnI0Rm;,v7í씓NNѠעB9rv .&e¥r"7ewW@8_J~ӌko9.iwe;ECށ`7ۯwWͦo~39 Ci=.E #=pQ1wqzMNrU}kӒ !i%YiWVL^U%''RFD4 eyWTi74~:~dĊ#I(yD㎪1 cC3ɸ'qn@"aK1$b6tQ(n,{ "IlǶ]ctq? 2q˥+OGZ]H'/H_"_Bsjy YR/"dx21;Q 0+^ꣃ>潘Qw(E2YY$ }!Tf:NBm.Jس6{CK@S>S}L6!gnEo5cp(u-?`9wO@Mʥxr$`K\EPṚUW|qȒ {F@E4yYe2 za\BNu<-<lnz"9z 5Nnm/5OoTAc#DU'd=DH7I! ~* ϤZ/z=@ @R;{ǹ,R5#C! 2DȄm"5my /xȸ6+i~!mmGrI~1CΪ8s^m@@sEYsy *i/v>$@:1W;V{ #5`28ooEU6es:eÉ,]Ӱ9F)2jc(ƥȉ%YT˪G/i驫)GsoĿHiUW}# ! qa=JJ,1|oR9D&=Vze:q̑gnD2:5rhry_ɱcڮJy>DGMpmbo=)vL¯d)bOv.rc)E!w$']\*M2 Y6BN X*w)55)a2Duo[<YΘA``ΎB4ۭ $3<1밸m>*f9 dwz qN5o .vi#a.#l|Y_L&E,b\R'j(dT6"GEC;qDiXʀ\1 E5%Pm\+6ChxdbMZffq֢քZ]< $UѿZl ȫL @aAp7\Kʀ8pXlŢ \C[ [F*ÚJ5zV)Gsw* +6F cTWErYQ Q|n5A3U %F2eyYUJ;Ak$y\BIlk>7' L:>k 'K@.COo9NgQSN9畤SKi7ڷwy;tg. T4<ˬm[ f!ho@&: ˓-Fxҫ J1i{mQ o)}y|cKVVkh8S03 cRrEyWeary5(@/ 2e ޵yȯ 0uM8Δba|n$5_B uD9 FR-i|Hsě3@tҐ5+Wev:<.nO72r 5)Mbg@BaȪ X\w |t|?a4q V {Cu;Pr+x@E3AvoK@8 JgHaP&k<_>lm9WYm>~ q@DD9HΌ0wci T2Bzc^ `Ŀh 5zH*lhIy WM, aהE0C?#ijŌVlur}\C RZKa#jnGCSݙc-ua*GxF~u# ڍ{M/z܂{YLVفI`hu0[D> f!a=KIKViz):ORV *' "!# :8Dm{Cߴ y<lPeLK, '-ɢ4yhpP;b&Mtf =䄅?!3DE+=rd9 MK ++dy3B| $e"&KRM8rn߾ >&@t`5u QH,,gVdlNcD$wokHjU,o_3$tzvDG+0+HO< ^Cjso\-y}r; 區)5#ʀ$\ͦW$ue `DsX/9-O藀z-@vFUtPE[K#-@T)ڊW7:Iy!? o/{~(EHy:(C"uڒ_u^ZV>)[Ħ!*P,I5#iyl՛BjCl,Zz-OFЅoG)*1XtRsXވ<^mL<{p 4@ mH:"!fa*Nv1(tj~ Vs1(6_f2 u_Q X`['QPDdHdڀ;nVڸy.Y}GHNezfk5.Ƞ E X\rFr:BgҰʙuɗoh,`ua ȉʑ>o֓27 Hwt J#pCI=KY&R 6k Cfo _dd`T(GX= grxk_ד'Fi<ò[?Wp}^ @VPE*诐w7XiyrkZw#Nͼv!)罚7_N(8 $S(.t;xJ 릩k*K5\m1=޾ԗ\8wLv³^*-̙^cM |^F7$&)L +474$_@ K@]F?HPW=@I\;e:Q7{*yQC,pM@R01:]ڂkڢEWTQ鬼i;ZD!+]ҍ؊ZP{eURFN'ț*LʂWl+#)K"noQ֤,Cbrg@]'}FTl@^aIb ChM2|j'bzᇛ\.QypZ^6נ^9Fep"##ދBiG,^xH2D:Lq f?H,ͧu%P"V\, I U<;>R˵U7 0f{d=ZfXBDϛ&?%DAȼ&eYHKH>Lug PGJ.  ֓i7RC7Fƣ%y(e@-FUY?F +,4 Z9 jʩn63@v7]w';(G9Y &dzP;p **\m21.V"_d4֖PHΫ.Z 45{xq R,t܍+HU4˻ Ȋ29xǮN;đ&ZIrݑ@c˪lEgj9[8OWwY)Γ^W9NZ<{*ih8٦ymm[Iv Y^"/ җJc qDt!^l_^Vx#0k#fC. L13$ߜ0rQ}  Hgd|:+M# &tz䊯I]K׷]@9wc4 V43z+w*vDmT9 CT2ʩP4\Qt^^EEb!ᅹmN=R'r6hCF7Y,Hp_s)K0 ,eW$JTJ8Jr#BV2Cۆ}l49){?[ ?u861 @_\д Va] ,gWG:)7-ͳшK[rgU@h#fpK,mAUz}~A 7iZOKaty )K 0`[ʼn݉''mÝ/3)DQf#S{3Ey. *d/6n#T؁ڞC;\" &7Xp\a%ϱD 3Ȃw ysjE͟aMe]QbvЈY␕D $/gK>k-؍~z#`ъ)1Oښm^΀,(l=É+M{|!bC=Dp_= WnowQ6r&Up@<$MN\]KNY!`uDf) 1Du/z״@E홓_0A$ <ĭ .6qqUSt ۙ%MMd@&>yғ~\e\?/ ~=͖i T \ַl P(t'C ׹YBM@],R#}Ǎh 89[@Tb u N̆`h6;9 DRzMf@ts޳> y8,յbWDwh)!HR%Kx5#XBԂV=8z.p]]UX]rrͱϷ Hƨ.Kwf 9&$.4 W{:]+wS`"*ٌ9p.Y8oü@A }?e3s@`Iw] @M<`7wJ-ĒsщNV%)[x.8 G-@¼agvcXP SCkY"~#dtrrj)&UjWKע>!b>yC0Wf% <^n&j!mrx/kk\SgGB-6tTe|G"U xoFfH1L0)ڀ]QZ;X:i^&AgMX ?j}͉mz<;x'Kٳ2\0{ 3 gE@\Ig%jcHn% @L3]" rZI.i~:3̳! \$V8j+@w'T:!g w`tGB$KXcP qE@UjX/9 H<Q_UGN(gHdNY9I:/ShJho\Si7 TYF%iWtɆ<7FfB$gV&Q3 -;gsɜ>{aj_B]W¨<zdMF|@C0NI!~B 76Mcu҇}ܔLdC!GoUSJ& *ɌaTC2f L6$cV'@~g>##Tr`_28ɡ[!3WNO[N&5`"mIOb'UBK(7;OF.~`ťw߹l}Ҍ?e I6H#Zd&T}{PuI%0́{?VoVb!irRZ1Ȕ\Xa*8V>I^ڼ|k<dR9v  .%@RuVqD7&i#]Th? @$<*6H&J!'@tMżlFճP~# T)z~[,BY!%V[_3k)df=PDQ!ʰIَ'mBKg+J.هjXח*B@P\9|i6K@0oyNF}D7E_o9pvSJ)5 i#B1$,6,,p .i Ȋl'NWē[cgs#5B aϐAKex_HM#-)hRl|qWTT%GBhH"یP]i~e@=Dc\- W8Ц55a=1 "׻G_o{, ѷ҆Hy#R̴D{T)>Y||\Ѳ xt 艎3ɕr(X!tMŹm\C|/C}g q#1`ϥzS'ߥw9}D̻8w~,pw҆ 0Q_4%l+j|Ճ׊6'@-;,'*jۢ;.n䬪ݢYe]xYl l虧^%{omx}ۿAIњm2D(K Jo{D44iҢJ*>hYf4H0V;[@-/蕖ǿp2|hAFbN!@dmzm ]͆J!-s' ib 4dvZ|*)ٿI=$6 uVbt~b/L7r 1F99jG?d^2Ma  fsLqqأf#' ENwR; 8`K3_g,?GJ` 柣D}DT{ӊ#[' W|о^RkQ!VO!}г :Sg/Gnfw|btbKU 5gRֲ=窴 w< 0fVf ;@b\ʃ?wpO<0 rI һUv3gM["Osd˜o'} d8Á f w%@soR>>Y+Nc,2K@C {p<&@spQ֋IFtF.S>%f\s@g/E(i^3"D\x YrB"^21%bqa%ݳOL]pD<#1]]ܢ4# -ʍ,uc$<3oeOp^wB#ۡag1oǘ<}}U} <"d s u h3@ЙT mĉ0͞Jxޤ G.L;9\zCx(rꀜ/UϢ/jh#n F [2-~uRvRlQܬ,b-hJ)%cJd$=:q ͏ Ga$>g$B[=$.d{$aa\@i[2 h3tXyƉdIQ-t!b<ĉ:Z/yƉ+IIYI뛥'=ZRɳrΛf*Η|OIv${$HwtYhX_ݓKeU} 4o]Fe5<G)EB|M/X"jEv.wߤqKGrGH3Z0NZ"^Tπ`'mk;-I7e9W-8_?q!^{!y~e.HNGm_V'@$ m;p U4#ͻ<*˟l9ӇV >J|o#Ī*v会L5 ?׀p> a|'_%BINCV1uB]p,C:v3/:Avdwȳ% ɸF@t-Ѓ!]!$sIȃdLYe b<"E\H2Eaǔ'BcY JVfNNHC~ Ph봝v՗TsF} IGNYi挘𙵑M+e|[μ=W佥Hl|9cy5zC<.Nڔo>t1/F^| Ãb萘 !"j1M@ .' ɰnf_5yD QUl :L7mw!\"@I+sQ;H c&^IO׾']a']O@4^[j$xh R}*uvnm}rrҞPɧfW&#NJjg؄h]?m.\,OD 3vlH֩iqI$iڤwg7Ӧ%ώ/\k\J #6/i}F!|Q)8\zVIPhUy:k H[j]Aq_(:t SsWĦ&XM^>¢ b?bÐ 8,hN2!Tc~'7ѦRjJ\B㸃;1L;N&)X l]N \]YS'/Q1 㔰4AD5ЫfG=TGh(ܳkeRC.ro"D!*=¯-KiJmOeA,6! 3wH6HnY@A!0@+E48kTQhB-g\oܓGTz҇^?H'=IOA &q9] xƀXuҝHw:p9.s @HGs d9^gcC ^٤!R^/dp3Utm@n6T䰑t^="]F-\ьHz7e[,q0oոbywT)*|> R{h;vDk:ݩ]KW1_ͭ&mX-EyȿJ.݉{:Υs@8QOŻFݮorLH"|{RS) R&*X@N}M?-!SViG{}7B2> bj [ -iC~Ysуe#h`ͮN]DqP]# _»0Mi|l om+F*B!8:v2 Y Eoqg?x$KU|z:8j`;Ht`^Co ZFS?4cTvaރ(\2Q+1Nl?834rS NY'0 XكQ4Է`׌}3{*A"7AH{u\>7b*FO%_#8Y'OlX!ȹ7wyfP!NRlT]$ᏓyOWT6іYqiSĝfmKq8+;8 1jOMls_[2zڈ!"huxV]CyH*m}$ngb٪X6ĜH{i#k3zJOh@1FR(Jv2Ytti3| !k5Ij -i676gj[rPro[O:7g%JMO$᎛T`DjP5<+(n=0?Mbo=JĈ\B`1AZ]z Nv/퟈KyZrYdg@!S Y! Yrg' Pʎ)!hۍO@eMIENDB`GD-2.50/demos/fills.pl0000755000175100017510000000112412164634363014100 0ustar lsteinlstein#!/usr/local/bin/perl use GD; $im = new GD::Image(100,50); # allocate black -- this will be our background $black = $im->colorAllocate(0, 0, 0); # allocate white $white = $im->colorAllocate(255, 255, 255); # allocate red $red = $im->colorAllocate(255, 0, 0); # allocate blue $blue = $im->colorAllocate(0,0,255); #Inscribe an ellipse in the image $im->arc(50, 25, 98, 48, 0, 360, $white); # Flood-fill the ellipse. Fill color is red, and will replace the # black interior of the ellipse $im->fill(50, 21, $red); binmode STDOUT; # print the image to stdout print $im->png;