| 0 | 1 package GD::Simple; | 
|  | 2 | 
|  | 3 =head1 NAME | 
|  | 4 | 
|  | 5 GD::Simple - Simplified interface to GD library | 
|  | 6 | 
|  | 7 =head1 SYNOPSIS | 
|  | 8 | 
|  | 9     use GD::Simple; | 
|  | 10 | 
|  | 11     # create a new image | 
|  | 12     $img = GD::Simple->new(400,250); | 
|  | 13 | 
|  | 14     # draw a red rectangle with blue borders | 
|  | 15     $img->bgcolor('red'); | 
|  | 16     $img->fgcolor('blue'); | 
|  | 17     $img->rectangle(10,10,50,50); | 
|  | 18 | 
|  | 19     # draw an empty rectangle with green borders | 
|  | 20     $img->bgcolor(undef); | 
|  | 21     $img->fgcolor('green'); | 
|  | 22     $img->rectangle(30,30,100,100); | 
|  | 23 | 
|  | 24     # move to (80,80) and draw a green line to (100,190) | 
|  | 25     $img->moveTo(80,80); | 
|  | 26     $img->lineTo(100,190); | 
|  | 27 | 
|  | 28     # draw a solid orange ellipse | 
|  | 29     $img->moveTo(110,100); | 
|  | 30     $img->bgcolor('orange'); | 
|  | 31     $img->fgcolor('orange'); | 
|  | 32     $img->ellipse(40,40); | 
|  | 33 | 
|  | 34     # draw a black filled arc | 
|  | 35     $img->moveTo(150,150); | 
|  | 36     $img->fgcolor('black'); | 
|  | 37     $img->arc(50,50,0,100,gdNoFill|gdEdged); | 
|  | 38 | 
|  | 39     # draw a string at (10,180) using the default | 
|  | 40     # built-in font | 
|  | 41     $img->moveTo(10,180); | 
|  | 42     $img->string('This is very simple'); | 
|  | 43 | 
|  | 44     # draw a string at (280,210) using 20 point | 
|  | 45     # times italic, angled upward 90 degrees | 
|  | 46     $img->moveTo(280,210); | 
|  | 47     $img->font('Times:italic'); | 
|  | 48     $img->fontsize(20); | 
|  | 49     $img->angle(-90); | 
|  | 50     $img->string('This is very fancy'); | 
|  | 51 | 
|  | 52     # some turtle graphics | 
|  | 53     $img->moveTo(300,100); | 
|  | 54     $img->penSize(3,3); | 
|  | 55     $img->angle(0); | 
|  | 56     $img->line(20);   # 20 pixels going to the right | 
|  | 57     $img->turn(30);   # set turning angle to 30 degrees | 
|  | 58     $img->line(20);   # 20 pixel line | 
|  | 59     $img->line(20); | 
|  | 60     $img->line(20); | 
|  | 61     $img->turn(-90); # set turning angle to -90 degrees | 
|  | 62     $img->line(50);  # 50 pixel line | 
|  | 63 | 
|  | 64     # draw a cyan polygon edged in blue | 
|  | 65     my $poly = new GD::Polygon; | 
|  | 66     $poly->addPt(150,100); | 
|  | 67     $poly->addPt(199,199); | 
|  | 68     $poly->addPt(100,199); | 
|  | 69     $img->bgcolor('cyan'); | 
|  | 70     $img->fgcolor('blue'); | 
|  | 71     $img->penSize(1,1); | 
|  | 72     $img->polygon($poly); | 
|  | 73 | 
|  | 74    # convert into png data | 
|  | 75    print $img->png; | 
|  | 76 | 
|  | 77 =head1 DESCRIPTION | 
|  | 78 | 
|  | 79 GD::Simple is a subclass of the GD library that shortens many of the | 
|  | 80 long GD method calls by storing information about the pen color, size | 
|  | 81 and position in the GD object itself.  It also adds a small number of | 
|  | 82 "turtle graphics" style calls for those who prefer to work in polar | 
|  | 83 coordinates.  In addition, the library allows you to use symbolic | 
|  | 84 names for colors, such as "chartreuse", and will manage the colors for | 
|  | 85 you. | 
|  | 86 | 
|  | 87 =head2 The Pen | 
|  | 88 | 
|  | 89 GD::Simple maintains a "pen" whose settings are used for line- and | 
|  | 90 shape-drawing operations.  The pen has the following properties: | 
|  | 91 | 
|  | 92 =over 4 | 
|  | 93 | 
|  | 94 =item fgcolor | 
|  | 95 | 
|  | 96 The pen foreground color is the color of lines and the borders of | 
|  | 97 filled and unfilled shapes. | 
|  | 98 | 
|  | 99 =item bgcolor | 
|  | 100 | 
|  | 101 The pen background color is the color of the contents of filled | 
|  | 102 shapes. | 
|  | 103 | 
|  | 104 =item pensize | 
|  | 105 | 
|  | 106 The pen size is the width of the pen.  Larger sizes draw thicker | 
|  | 107 lines. | 
|  | 108 | 
|  | 109 =item position | 
|  | 110 | 
|  | 111 The pen position is its current position on the canvas in (X,Y) | 
|  | 112 coordinates. | 
|  | 113 | 
|  | 114 =item angle | 
|  | 115 | 
|  | 116 When drawing in turtle mode, the pen angle determines the current | 
|  | 117 direction of lines of relative length. | 
|  | 118 | 
|  | 119 =item turn | 
|  | 120 | 
|  | 121 When drawing in turtle mode, the turn determines the clockwise or | 
|  | 122 counterclockwise angle that the pen will turn before drawing the next | 
|  | 123 line. | 
|  | 124 | 
|  | 125 =item font | 
|  | 126 | 
|  | 127 The font to use when drawing text.  Both built-in bitmapped fonts and | 
|  | 128 TrueType fonts are supported. | 
|  | 129 | 
|  | 130 =item fontsize | 
|  | 131 | 
|  | 132 The size of the font to use when drawing with TrueType fonts. | 
|  | 133 | 
|  | 134 =back | 
|  | 135 | 
|  | 136 One sets the position and properties of the pen and then draws.  As | 
|  | 137 the drawing progresses, the position of the pen is updated. | 
|  | 138 | 
|  | 139 =head2 Methods | 
|  | 140 | 
|  | 141 GD::Simple introduces a number of new methods, a few of which have the | 
|  | 142 same name as GD::Image methods, and hence change their behavior. In | 
|  | 143 addition to these new methods, GD::Simple objects support all of the | 
|  | 144 GD::Image methods. If you make a method call that isn't directly | 
|  | 145 supported by GD::Simple, it refers the request to the underlying | 
|  | 146 GD::Image object.  Hence one can load a JPEG image into GD::Simple and | 
|  | 147 declare it to be TrueColor by using this call, which is effectively | 
|  | 148 inherited from GD::Image: | 
|  | 149 | 
|  | 150   my $img = GD::Simple->newFromJpeg('./myimage.jpg',1); | 
|  | 151 | 
|  | 152 The rest of this section describes GD::Simple-specific methods. | 
|  | 153 | 
|  | 154 =cut | 
|  | 155 | 
|  | 156 use strict; | 
|  | 157 use GD; | 
|  | 158 use GD::Group; | 
|  | 159 use Math::Trig; | 
|  | 160 use Carp 'croak'; | 
|  | 161 | 
|  | 162 our @ISA = 'Exporter'; | 
|  | 163 our @EXPORT    = @GD::EXPORT; | 
|  | 164 our @EXPORT_OK = @GD::EXPORT_OK; | 
|  | 165 our $AUTOLOAD; | 
|  | 166 | 
|  | 167 my %COLORS; | 
|  | 168 my $IMAGECLASS = 'GD::Image'; | 
|  | 169 my $TRANSPARENT; | 
|  | 170 | 
|  | 171 sub AUTOLOAD { | 
|  | 172   my $self = shift; | 
|  | 173   my($pack,$func_name) = $AUTOLOAD=~/(.+)::([^:]+)$/; | 
|  | 174   return if $func_name eq 'DESTROY'; | 
|  | 175 | 
|  | 176   if (ref $self && exists $self->{gd}) { | 
|  | 177     $self->{gd}->$func_name(@_); | 
|  | 178   } else { | 
|  | 179     my @result = $IMAGECLASS->$func_name(@_); | 
|  | 180     if (UNIVERSAL::isa($result[0],'GD::Image')) { | 
|  | 181       return $self->new($result[0]); | 
|  | 182     } else { | 
|  | 183       return @result; | 
|  | 184     } | 
|  | 185   } | 
|  | 186 } | 
|  | 187 | 
|  | 188 =over 4 | 
|  | 189 | 
|  | 190 =item $img = GD::Simple->new($x,$y [,$truecolor]) | 
|  | 191 | 
|  | 192 =item $img = GD::Simple->new($gd) | 
|  | 193 | 
|  | 194 Create a new GD::Simple object. There are two forms of new(). In the | 
|  | 195 first form, pass the width and height of the desired canvas, and | 
|  | 196 optionally a boolean flag to request a truecolor image. In the second | 
|  | 197 form, pass a previously-created GD::Image object. | 
|  | 198 | 
|  | 199 =cut | 
|  | 200 | 
|  | 201 # dual-purpose code - beware | 
|  | 202 sub new { | 
|  | 203   my $pack = shift; | 
|  | 204 | 
|  | 205   unshift @_,(100,100) if @_ == 0; | 
|  | 206 | 
|  | 207   if (@_ >= 2) { # traditional GD::Image->new() call | 
|  | 208     my $gd   = $IMAGECLASS->new(@_); | 
|  | 209     my $self = $pack->new($gd); | 
|  | 210     $self->clear; | 
|  | 211     return $self; | 
|  | 212   } | 
|  | 213 | 
|  | 214   if (@_ == 1) { # initialize from existing image | 
|  | 215     my $gd   = shift; | 
|  | 216     my $self = bless { | 
|  | 217 		      gd             => $gd, | 
|  | 218 		      xy             => [0,0], | 
|  | 219 		      font           => gdSmallFont, | 
|  | 220 		      fontsize       => 9, | 
|  | 221 		      turningangle   => 0, | 
|  | 222 		      angle          => 0, | 
|  | 223 		      pensize        => 1, | 
|  | 224 		     },$pack; | 
|  | 225     $self->{bgcolor} = $self->translate_color(255,255,255); | 
|  | 226     $self->{fgcolor} = $self->translate_color(0,0,0); | 
|  | 227     return $self; | 
|  | 228   } | 
|  | 229 } | 
|  | 230 | 
|  | 231 =item GD::Simple->class('GD'); | 
|  | 232 | 
|  | 233 =item GD::Simple->class('GD::SVG'); | 
|  | 234 | 
|  | 235 Select whether new() should use GD or GD::SVG internally. Call | 
|  | 236 GD::Simple->class('GD::SVG') before calling new() if you wish to | 
|  | 237 generate SVG images. | 
|  | 238 | 
|  | 239 If future GD subclasses are created, this method will subport them. | 
|  | 240 | 
|  | 241 =cut | 
|  | 242 | 
|  | 243 sub class { | 
|  | 244   my $pack    = shift; | 
|  | 245   if (@_) { | 
|  | 246     $IMAGECLASS = shift; | 
|  | 247     eval "require $IMAGECLASS; 1" or die $@; | 
|  | 248     $IMAGECLASS = "$IMAGECLASS\:\:Image" | 
|  | 249       if $IMAGECLASS eq 'GD::SVG'; | 
|  | 250   } | 
|  | 251   $IMAGECLASS; | 
|  | 252 } | 
|  | 253 | 
|  | 254 =item $img->moveTo($x,$y) | 
|  | 255 | 
|  | 256 This call changes the position of the pen without drawing. It moves | 
|  | 257 the pen to position ($x,$y) on the drawing canvas. | 
|  | 258 | 
|  | 259 =cut | 
|  | 260 | 
|  | 261 sub moveTo { | 
|  | 262   my $self = shift; | 
|  | 263   croak 'Usage GD::Simple->moveTo($x,$y)' unless @_ == 2; | 
|  | 264   my ($x,$y) = @_; | 
|  | 265   $self->{xy} = [$x,$y]; | 
|  | 266 } | 
|  | 267 | 
|  | 268 =item $img->move($dx,$dy) | 
|  | 269 | 
|  | 270 =item $img->move($dr) | 
|  | 271 | 
|  | 272 This call changes the position of the pen without drawing. When called | 
|  | 273 with two arguments it moves the pen $dx pixels to the right and $dy | 
|  | 274 pixels downward.  When called with one argument it moves the pen $dr | 
|  | 275 pixels along the vector described by the current pen angle. | 
|  | 276 | 
|  | 277 =cut | 
|  | 278 | 
|  | 279 sub move { | 
|  | 280   my $self = shift; | 
|  | 281   if (@_ == 1) { # polar coordinates -- this is r | 
|  | 282     $self->{angle} += $self->{turningangle}; | 
|  | 283     my $angle = deg2rad($self->{angle}); | 
|  | 284     $self->{xy}[0] += $_[0] * cos($angle); | 
|  | 285     $self->{xy}[1] += $_[0] * sin($angle); | 
|  | 286   } | 
|  | 287   elsif (@_ == 2) { # cartesian coordinates | 
|  | 288     $self->{xy}[0] += $_[0]; | 
|  | 289     $self->{xy}[1] += $_[1]; | 
|  | 290   } else { | 
|  | 291     croak 'Usage GD::Simple->move($dx,$dy) or move($r)'; | 
|  | 292   } | 
|  | 293 } | 
|  | 294 | 
|  | 295 =item $img->lineTo($x,$y) | 
|  | 296 | 
|  | 297 The lineTo() call simultaneously draws and moves the pen.  It draws a | 
|  | 298 line from the current pen position to the position defined by ($x,$y) | 
|  | 299 using the current pen size and color.  After drawing, the position of | 
|  | 300 the pen is updated to the new position. | 
|  | 301 | 
|  | 302 =cut | 
|  | 303 | 
|  | 304 sub lineTo { | 
|  | 305   my $self = shift; | 
|  | 306   croak 'Usage GD::Simple->lineTo($x,$y)' unless @_ == 2; | 
|  | 307   $self->gd->line($self->curPos,@_,$self->fgcolor); | 
|  | 308   $self->moveTo(@_); | 
|  | 309 } | 
|  | 310 | 
|  | 311 =item $img->line($dx,$dy) | 
|  | 312 | 
|  | 313 =item $img->line($dr) | 
|  | 314 | 
|  | 315 The line() call simultaneously draws and moves the pen. When called | 
|  | 316 with two arguments it draws a line from the current position of the | 
|  | 317 pen to the position $dx pixels to the right and $dy pixels down.  When | 
|  | 318 called with one argument, it draws a line $dr pixels long along the | 
|  | 319 angle defined by the current pen angle. | 
|  | 320 | 
|  | 321 =cut | 
|  | 322 | 
|  | 323 sub line { | 
|  | 324   my $self = shift; | 
|  | 325   croak 'Usage GD::Simple->line($dx,$dy) or line($r)' unless @_ >= 1; | 
|  | 326   my @curPos = $self->curPos; | 
|  | 327   $self->move(@_); | 
|  | 328   my @newPos = $self->curPos; | 
|  | 329   $self->gd->line(@curPos,@newPos,$self->fgcolor); | 
|  | 330 } | 
|  | 331 | 
|  | 332 =item $img->clear | 
|  | 333 | 
|  | 334 This method clears the canvas by painting over it with the current | 
|  | 335 background color. | 
|  | 336 | 
|  | 337 =cut | 
|  | 338 | 
|  | 339 sub clear { | 
|  | 340   my $self = shift; | 
|  | 341   $self->gd->filledRectangle(0,0,$self->getBounds,$self->bgcolor); | 
|  | 342 } | 
|  | 343 | 
|  | 344 =item $img->rectangle($x1,$y1,$x2,$y2) | 
|  | 345 | 
|  | 346 This method draws the rectangle defined by corners ($x1,$y1), | 
|  | 347 ($x2,$y2). The rectangle's edges are drawn in the foreground color and | 
|  | 348 its contents are filled with the background color. To draw a solid | 
|  | 349 rectangle set bgcolor equal to fgcolor. To draw an unfilled rectangle | 
|  | 350 (transparent inside), set bgcolor to undef. | 
|  | 351 | 
|  | 352 =cut | 
|  | 353 | 
|  | 354 sub rectangle { | 
|  | 355   my $self = shift; | 
|  | 356   croak 'Usage GD::Simple->rectangle($x1,$y1,$x2,$y2)' unless @_ == 4; | 
|  | 357   my $gd = $self->gd; | 
|  | 358   my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); | 
|  | 359   $gd->filledRectangle(@_,$bg) if defined $bg; | 
|  | 360   $gd->rectangle(@_,$fg)       if defined $fg && (!defined $bg || $bg != $fg); | 
|  | 361 } | 
|  | 362 | 
|  | 363 =item $img->ellipse($width,$height) | 
|  | 364 | 
|  | 365 This method draws the ellipse centered at the current location with | 
|  | 366 width $width and height $height.  The ellipse's border is drawn in the | 
|  | 367 foreground color and its contents are filled with the background | 
|  | 368 color. To draw a solid ellipse set bgcolor equal to fgcolor. To draw | 
|  | 369 an unfilled ellipse (transparent inside), set bgcolor to undef. | 
|  | 370 | 
|  | 371 =cut | 
|  | 372 | 
|  | 373 sub ellipse { | 
|  | 374   my $self = shift; | 
|  | 375   croak 'Usage GD::Simple->ellipse($width,$height)' unless @_ == 2; | 
|  | 376   my $gd = $self->gd; | 
|  | 377   my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); | 
|  | 378   $gd->filledEllipse($self->curPos,@_,$bg) if defined $bg; | 
|  | 379   $gd->ellipse($self->curPos,@_,$fg)       if defined $fg && (!defined $bg || $bg != $fg); | 
|  | 380 } | 
|  | 381 | 
|  | 382 =item $img->arc($cx,$cy,$width,$height,$start,$end [,$style]) | 
|  | 383 | 
|  | 384 This method draws filled and unfilled arcs.  See L<GD> for a | 
|  | 385 description of the arguments. To draw a solid arc (such as a pie | 
|  | 386 wedge) set bgcolor equal to fgcolor. To draw an unfilled arc, set | 
|  | 387 bgcolor to undef. | 
|  | 388 | 
|  | 389 =cut | 
|  | 390 | 
|  | 391 sub arc { | 
|  | 392   my $self = shift; | 
|  | 393   croak 'Usage GD::Simple->arc($width,$height,$start,$end,$style)' unless @_ >= 4; | 
|  | 394   my ($width,$height,$start,$end,$style) = @_; | 
|  | 395   my $gd = $self->gd; | 
|  | 396   my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); | 
|  | 397   my ($cx,$cy) = $self->curPos; | 
|  | 398 | 
|  | 399   if ($bg) { | 
|  | 400     my @args = ($cx,$cy,$width,$height,$start,$end,$bg); | 
|  | 401     push @args,$style if defined $style; | 
|  | 402     $gd->filledArc(@args); | 
|  | 403   } else { | 
|  | 404     my @args = ($cx,$cy,$width,$height,$start,$end,$fg); | 
|  | 405     $gd->arc(@args); | 
|  | 406   } | 
|  | 407 } | 
|  | 408 | 
|  | 409 =item $img->polygon($poly) | 
|  | 410 | 
|  | 411 This method draws filled and unfilled polygon using the current | 
|  | 412 settings of fgcolor for the polygon border and bgcolor for the polygon | 
|  | 413 fill color.  See L<GD> for a description of creating polygons. To draw | 
|  | 414 a solid polygon set bgcolor equal to fgcolor. To draw an unfilled | 
|  | 415 polygon, set bgcolor to undef. | 
|  | 416 | 
|  | 417 =cut | 
|  | 418 | 
|  | 419 sub polygon { | 
|  | 420   my $self = shift; | 
|  | 421   croak 'Usage GD::Simple->polygon($poly)' unless @_ == 1; | 
|  | 422   my $gd = $self->gd; | 
|  | 423   my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); | 
|  | 424   $gd->filledPolygon(@_,$bg) if defined $bg; | 
|  | 425   $gd->openPolygon(@_,$fg)   if defined $fg && (!defined $bg || $bg != $fg); | 
|  | 426 } | 
|  | 427 | 
|  | 428 =item $img->polyline($poly) | 
|  | 429 | 
|  | 430 This method draws polygons without closing the first and last vertices | 
|  | 431 (similar to GD::Image->unclosedPolygon()). It uses the fgcolor to draw | 
|  | 432 the line. | 
|  | 433 | 
|  | 434 =cut | 
|  | 435 | 
|  | 436 sub polyline { | 
|  | 437   my $self = shift; | 
|  | 438   croak 'Usage GD::Simple->polyline($poly)' unless @_ == 1; | 
|  | 439   my $gd = $self->gd; | 
|  | 440   my $fg = $self->fgcolor; | 
|  | 441   $gd->unclosedPolygon(@_,$fg); | 
|  | 442 } | 
|  | 443 | 
|  | 444 =item $img->string($string) | 
|  | 445 | 
|  | 446 This method draws the indicated string starting at the current | 
|  | 447 position of the pen. The pen is moved to the end of the drawn string. | 
|  | 448 Depending on the font selected with the font() method, this will use | 
|  | 449 either a bitmapped GD font or a TrueType font.  The angle of the pen | 
|  | 450 will be consulted when drawing the text. For TrueType fonts, any angle | 
|  | 451 is accepted.  For GD bitmapped fonts, the angle can be either 0 (draw | 
|  | 452 horizontal) or -90 (draw upwards). | 
|  | 453 | 
|  | 454 For consistency between the TrueType and GD font behavior, the string | 
|  | 455 is always drawn so that the current position of the pen corresponds to | 
|  | 456 the bottom left of the first character of the text.  This is different | 
|  | 457 from the GD behavior, in which the first character of bitmapped fonts | 
|  | 458 hangs down from the pen point. | 
|  | 459 | 
|  | 460 This method returns a polygon indicating the bounding box of the | 
|  | 461 rendered text.  If an error occurred (such as invalid font | 
|  | 462 specification) it returns undef and an error message in $@. | 
|  | 463 | 
|  | 464 =cut | 
|  | 465 | 
|  | 466 sub string { | 
|  | 467   my $self   = shift; | 
|  | 468   my $string = shift; | 
|  | 469   my $font   = $self->font; | 
|  | 470   my @bounds; | 
|  | 471   if (ref $font && $font->isa('GD::Font')) { | 
|  | 472     my ($x,$y) = $self->curPos; | 
|  | 473     if ($self->angle == -90) { | 
|  | 474       $x -= $font->height; | 
|  | 475       $y -= $font->width; | 
|  | 476       $self->gd->stringUp($font,$x,$y,$string,$self->fgcolor); | 
|  | 477       $self->{xy}[1] -= length($string) * $font->width; | 
|  | 478       @bounds = ( ($self->{xy}[0],$y), ($x,$y), ($x,$self->{xy}[1]-$font->width), ($self->{xy}[0],$self->{xy}[1]-$font->width) ); | 
|  | 479     } else { | 
|  | 480       $y -= $font->height; | 
|  | 481       $self->gd->string($font,$x,$y,$string,$self->fgcolor); | 
|  | 482       $self->{xy}[0] += length($string) * $font->width; | 
|  | 483       @bounds = ( ($x,$self->{xy}[1]), ($self->{xy}[0],$self->{xy}[1]), ($self->{xy}[0],$y), ($x,$y) ); | 
|  | 484     } | 
|  | 485   } | 
|  | 486   else { | 
|  | 487     $self->useFontConfig(1); | 
|  | 488     @bounds   = $self->stringFT($self->fgcolor,$font, | 
|  | 489 				$self->fontsize,-deg2rad($self->angle), # -pi * $self->angle/180, | 
|  | 490 				$self->curPos,$string); | 
|  | 491     return unless @bounds; | 
|  | 492     my ($delta_x,$delta_y) = $self->_string_width(@bounds); | 
|  | 493     $self->{xy}[0] += $delta_x; | 
|  | 494     $self->{xy}[1] += $delta_y; | 
|  | 495   } | 
|  | 496   my $poly = GD::Polygon->new; | 
|  | 497   while (@bounds) { | 
|  | 498     $poly->addPt(splice(@bounds,0,2)); | 
|  | 499   } | 
|  | 500   return $poly; | 
|  | 501 } | 
|  | 502 | 
|  | 503 =item $metrics = $img->fontMetrics | 
|  | 504 | 
|  | 505 =item ($metrics,$width,$height) = GD::Simple->fontMetrics($font,$fontsize,$string) | 
|  | 506 | 
|  | 507 This method returns information about the current font, most commonly | 
|  | 508 a TrueType font. It can be invoked as an instance method (on a | 
|  | 509 previously-created GD::Simple object) or as a class method (on the | 
|  | 510 'GD::Simple' class). | 
|  | 511 | 
|  | 512 When called as an instance method, fontMetrics() takes no arguments | 
|  | 513 and returns a single hash reference containing the metrics that | 
|  | 514 describe the currently selected font and size. The hash reference | 
|  | 515 contains the following information: | 
|  | 516 | 
|  | 517   xheight      the base height of the font from the bottom to the top of | 
|  | 518                a lowercase 'm' | 
|  | 519 | 
|  | 520   ascent       the length of the upper stem of the lowercase 'd' | 
|  | 521 | 
|  | 522   descent      the length of the lower step of the lowercase 'j' | 
|  | 523 | 
|  | 524   lineheight   the distance from the bottom of the 'j' to the top of | 
|  | 525                the 'd' | 
|  | 526 | 
|  | 527   leading      the distance between two adjacent lines | 
|  | 528 | 
|  | 529 =cut | 
|  | 530 | 
|  | 531 # return %$fontmetrics | 
|  | 532 # keys: 'ascent', 'descent', 'lineheight', 'xheight', 'leading' | 
|  | 533 sub fontMetrics { | 
|  | 534   my $self   = shift; | 
|  | 535 | 
|  | 536   unless (ref $self) {  #class invocation -- create a scratch | 
|  | 537     $self = $self->new; | 
|  | 538     $self->font(shift)     if defined $_[0]; | 
|  | 539     $self->fontsize(shift) if defined $_[0]; | 
|  | 540   } | 
|  | 541 | 
|  | 542   my $font   = $self->font; | 
|  | 543   my $metrics; | 
|  | 544 | 
|  | 545   if (ref $font && $font->isa('GD::Font')) { | 
|  | 546     my $height = $font->height; | 
|  | 547     $metrics = {ascent     => 0, | 
|  | 548 		descent    => 0, | 
|  | 549 		lineheight => $height, | 
|  | 550 		xheight    => $height, | 
|  | 551 		leading    => 0}; | 
|  | 552   } | 
|  | 553   else { | 
|  | 554     $self->useFontConfig(1); | 
|  | 555     my @mbounds   = GD::Image->stringFT($self->fgcolor,$font, | 
|  | 556 					$self->fontsize,0, | 
|  | 557 					0,0,'m'); | 
|  | 558     my $xheight   = $mbounds[3]-$mbounds[5]; | 
|  | 559     my @jbounds   = GD::Image->stringFT($self->fgcolor,$font, | 
|  | 560 					$self->fontsize,0, | 
|  | 561 					0,0,'j'); | 
|  | 562     my $ascent    = $mbounds[7]-$jbounds[7]; | 
|  | 563     my $descent   = $jbounds[3]-$mbounds[3]; | 
|  | 564 | 
|  | 565     my @mmbounds  = GD::Image->stringFT($self->fgcolor,$font, | 
|  | 566 					$self->fontsize,0, | 
|  | 567 					0,0,"m\nm"); | 
|  | 568     my $twolines  = $mmbounds[3]-$mmbounds[5]; | 
|  | 569     my $lineheight  = $twolines - 2*$xheight; | 
|  | 570     my $leading     = $lineheight - $ascent - $descent; | 
|  | 571     $metrics     = {ascent     => $ascent, | 
|  | 572 		    descent    => $descent, | 
|  | 573 		    lineheight => $lineheight, | 
|  | 574 		    xheight    => $xheight, | 
|  | 575 		    leading    => $leading}; | 
|  | 576   } | 
|  | 577 | 
|  | 578   if ((my $string = shift) && wantarray) { | 
|  | 579     my ($width,$height) = $self->stringBounds($string); | 
|  | 580     return ($metrics,abs($width),abs($height)); | 
|  | 581   } | 
|  | 582   return $metrics; | 
|  | 583 } | 
|  | 584 | 
|  | 585 =item ($delta_x,$delta_y)= $img->stringBounds($string) | 
|  | 586 | 
|  | 587 This method indicates the X and Y offsets (which may be negative) that | 
|  | 588 will occur when the given string is drawn using the current font, | 
|  | 589 fontsize and angle. When the string is drawn horizontally, it gives | 
|  | 590 the width and height of the string's bounding box. | 
|  | 591 | 
|  | 592 =cut | 
|  | 593 | 
|  | 594 sub stringBounds { | 
|  | 595   my $self = shift; | 
|  | 596   my $string = shift; | 
|  | 597   my $font   = $self->font; | 
|  | 598   if (ref $font && $font->isa('GD::Font')) { | 
|  | 599     if ($self->angle == -90) { | 
|  | 600       return ($font->height,-length($string) * $font->width); | 
|  | 601     } else { | 
|  | 602       return (length($string) * $font->width,$font->height); | 
|  | 603     } | 
|  | 604   } | 
|  | 605   else { | 
|  | 606     $self->useFontConfig(1); | 
|  | 607     my @bounds   = GD::Image->stringFT($self->fgcolor,$font, | 
|  | 608 				       $self->fontsize,-deg2rad($self->angle), | 
|  | 609 				       $self->curPos,$string); | 
|  | 610     return $self->_string_width(@bounds); | 
|  | 611   } | 
|  | 612 } | 
|  | 613 | 
|  | 614 =item $delta_x = $img->stringWidth($string) | 
|  | 615 | 
|  | 616 This method indicates the width of the string given the current font, | 
|  | 617 fontsize and angle. It is the same as ($img->stringBounds($string))[0] | 
|  | 618 | 
|  | 619 =cut | 
|  | 620 | 
|  | 621 sub stringWidth { | 
|  | 622   return ((shift->stringBounds(@_))[0]); | 
|  | 623 } | 
|  | 624 | 
|  | 625 | 
|  | 626 sub _string_width { | 
|  | 627   my $self   = shift; | 
|  | 628   my @bounds = @_; | 
|  | 629   my $delta_x = abs($bounds[2]-$bounds[0]); | 
|  | 630   my $delta_y = abs($bounds[5]-$bounds[3]); | 
|  | 631   my $angle   = $self->angle % 360; | 
|  | 632   if ($angle >= 0 && $angle < 90) { | 
|  | 633     return ($delta_x,$delta_y); | 
|  | 634 | 
|  | 635   } elsif ($angle >= 90 && $angle < 180) { | 
|  | 636     return (-$delta_x,$delta_y); | 
|  | 637 | 
|  | 638   } elsif ($angle >= 180 && $angle < 270) { | 
|  | 639     return (-$delta_x,-$delta_y); | 
|  | 640 | 
|  | 641   } elsif ($angle >= 270 && $angle < 360) { | 
|  | 642     return ($delta_x,-$delta_y); | 
|  | 643   } | 
|  | 644 } | 
|  | 645 | 
|  | 646 =item ($x,$y) = $img->curPos | 
|  | 647 | 
|  | 648 Return the current position of the pen.  Set the current position | 
|  | 649 using moveTo(). | 
|  | 650 | 
|  | 651 =cut | 
|  | 652 | 
|  | 653 sub curPos {  @{shift->{xy}}; } | 
|  | 654 | 
|  | 655 =item $font = $img->font([$newfont] [,$newsize]) | 
|  | 656 | 
|  | 657 Get or set the current font.  Fonts can be GD::Font objects, TrueType | 
|  | 658 font file paths, or fontconfig font patterns like "Times:italic" (see | 
|  | 659 L<fontconfig>). The latter feature requires that you have the | 
|  | 660 fontconfig library installed and are using libgd version 2.0.33 or | 
|  | 661 higher. | 
|  | 662 | 
|  | 663 As a shortcut, you may pass two arguments to set the font and the | 
|  | 664 fontsize simultaneously. The fontsize is only valid when drawing with | 
|  | 665 TrueType fonts. | 
|  | 666 | 
|  | 667 =cut | 
|  | 668 | 
|  | 669 sub font { | 
|  | 670   my $self = shift; | 
|  | 671   $self->{font}     = shift if @_; | 
|  | 672   $self->{fontsize} = shift if @_; | 
|  | 673   $self->{font}; | 
|  | 674 } | 
|  | 675 | 
|  | 676 =item $size = $img->fontsize([$newfontsize]) | 
|  | 677 | 
|  | 678 Get or set the current font size.  This is only valid for TrueType | 
|  | 679 fonts. | 
|  | 680 | 
|  | 681 =cut | 
|  | 682 | 
|  | 683 sub fontsize { | 
|  | 684   my $self = shift; | 
|  | 685   $self->{fontsize} = shift if @_; | 
|  | 686   $self->{fontsize}; | 
|  | 687 } | 
|  | 688 | 
|  | 689 =item $size = $img->penSize([$newpensize]) | 
|  | 690 | 
|  | 691 Get or set the current pen width for use during line drawing | 
|  | 692 operations. | 
|  | 693 | 
|  | 694 =cut | 
|  | 695 | 
|  | 696 sub penSize { | 
|  | 697   my $self = shift; | 
|  | 698   if (@_) { | 
|  | 699     $self->{pensize} = shift; | 
|  | 700     $self->gd->setThickness($self->{pensize}); | 
|  | 701   } | 
|  | 702   $self->{pensize}; | 
|  | 703 } | 
|  | 704 | 
|  | 705 =item $angle = $img->angle([$newangle]) | 
|  | 706 | 
|  | 707 Set the current angle for use when calling line() or move() with a | 
|  | 708 single argument. | 
|  | 709 | 
|  | 710 Here is an example of using turn() and angle() together to draw an | 
|  | 711 octagon.  The first line drawn is the downward-slanting top right | 
|  | 712 edge.  The last line drawn is the horizontal top of the octagon. | 
|  | 713 | 
|  | 714   $img->moveTo(200,50); | 
|  | 715   $img->angle(0); | 
|  | 716   $img->turn(360/8); | 
|  | 717   for (1..8) { $img->line(50) } | 
|  | 718 | 
|  | 719 =cut | 
|  | 720 | 
|  | 721 sub angle { | 
|  | 722   my $self = shift; | 
|  | 723   $self->{angle} = shift if @_; | 
|  | 724   $self->{angle}; | 
|  | 725 } | 
|  | 726 | 
|  | 727 =item $angle = $img->turn([$newangle]) | 
|  | 728 | 
|  | 729 Get or set the current angle to turn prior to drawing lines.  This | 
|  | 730 value is only used when calling line() or move() with a single | 
|  | 731 argument.  The turning angle will be applied to each call to line() or | 
|  | 732 move() just before the actual drawing occurs. | 
|  | 733 | 
|  | 734 Angles are in degrees.  Positive values turn the angle clockwise. | 
|  | 735 | 
|  | 736 =cut | 
|  | 737 | 
|  | 738 # degrees, not radians | 
|  | 739 sub turn { | 
|  | 740   my $self = shift; | 
|  | 741   $self->{turningangle} = shift if @_; | 
|  | 742   $self->{turningangle}; | 
|  | 743 } | 
|  | 744 | 
|  | 745 =item $color = $img->fgcolor([$newcolor]) | 
|  | 746 | 
|  | 747 Get or set the pen's foreground color.  The current pen color can be | 
|  | 748 set by (1) using an (r,g,b) triple; (2) using a previously-allocated | 
|  | 749 color from the GD palette; or (3) by using a symbolic color name such | 
|  | 750 as "chartreuse."  The list of color names can be obtained using | 
|  | 751 color_names(). The special color name 'transparent' will create a | 
|  | 752 completely transparent color. | 
|  | 753 | 
|  | 754 =cut | 
|  | 755 | 
|  | 756 sub fgcolor { | 
|  | 757   my $self = shift; | 
|  | 758   $self->{fgcolor} = $self->translate_color(@_) if @_; | 
|  | 759   $self->{fgcolor}; | 
|  | 760 } | 
|  | 761 | 
|  | 762 =item $color = $img->bgcolor([$newcolor]) | 
|  | 763 | 
|  | 764 Get or set the pen's background color.  The current pen color can be | 
|  | 765 set by (1) using an (r,g,b) triple; (2) using a previously-allocated | 
|  | 766 color from the GD palette; or (3) by using a symbolic color name such | 
|  | 767 as "chartreuse."  The list of color names can be obtained using | 
|  | 768 color_names(). The special color name 'transparent' will create a | 
|  | 769 completely transparent color. | 
|  | 770 | 
|  | 771 =cut | 
|  | 772 | 
|  | 773 sub bgcolor { | 
|  | 774   my $self = shift; | 
|  | 775   $self->{bgcolor} = $self->translate_color(@_) if @_; | 
|  | 776   $self->{bgcolor}; | 
|  | 777 } | 
|  | 778 | 
|  | 779 =item $index = $img->translate_color(@args) | 
|  | 780 | 
|  | 781 Translates a color into a GD palette or TrueColor index.  You may pass | 
|  | 782 either an (r,g,b) triple or a symbolic color name. If you pass a | 
|  | 783 previously-allocated index, the method will return it unchanged. | 
|  | 784 | 
|  | 785 =cut | 
|  | 786 | 
|  | 787 sub translate_color { | 
|  | 788   my $self = shift; | 
|  | 789   return unless defined $_[0]; | 
|  | 790   my ($r,$g,$b); | 
|  | 791   if (@_ == 1 && $_[0] =~ /^-?\d+/) {  # previously allocated index | 
|  | 792     return $_[0]; | 
|  | 793   } | 
|  | 794   elsif (@_ == 3) {  # (rgb triplet) | 
|  | 795     ($r,$g,$b) = @_; | 
|  | 796   } | 
|  | 797   elsif (lc $_[0] eq 'transparent') { | 
|  | 798       return $TRANSPARENT ||= $self->alphaColor('white',127); | 
|  | 799   } | 
|  | 800   else { | 
|  | 801     $self->read_color_table unless %COLORS; | 
|  | 802     die "unknown color" unless exists $COLORS{lc $_[0]}; | 
|  | 803     ($r,$g,$b) = @{$COLORS{lc $_[0]}}; | 
|  | 804   } | 
|  | 805   return $self->colorResolve($r,$g,$b); | 
|  | 806 } | 
|  | 807 | 
|  | 808 sub transparent { | 
|  | 809   my $self = shift; | 
|  | 810   my $index = $self->translate_color(@_); | 
|  | 811   $self->gd->transparent($index); | 
|  | 812 } | 
|  | 813 | 
|  | 814 =item $index = $img->alphaColor(@args,$alpha) | 
|  | 815 | 
|  | 816 Creates an alpha color.  You may pass either an (r,g,b) triple or a | 
|  | 817 symbolic color name, followed by an integer indicating its | 
|  | 818 opacity. The opacity value ranges from 0 (fully opaque) to 127 (fully | 
|  | 819 transparent). | 
|  | 820 | 
|  | 821 =cut | 
|  | 822 | 
|  | 823 sub alphaColor { | 
|  | 824   my $self = shift; | 
|  | 825   return unless defined $_[0]; | 
|  | 826   my ($r,$g,$b,$a); | 
|  | 827   if (@_ == 4) {  # (rgb triplet) | 
|  | 828     ($r,$g,$b,$a) = @_; | 
|  | 829   } else { | 
|  | 830     $self->read_color_table unless %COLORS; | 
|  | 831     die "unknown color" unless exists $COLORS{lc $_[0]}; | 
|  | 832     ($r,$g,$b) = @{$COLORS{lc $_[0]}}; | 
|  | 833     $a = $_[1]; | 
|  | 834   } | 
|  | 835   return $self->colorAllocateAlpha($r,$g,$b,$a); | 
|  | 836 } | 
|  | 837 | 
|  | 838 =item @names = GD::Simple->color_names | 
|  | 839 | 
|  | 840 =item $translate_table = GD::Simple->color_names | 
|  | 841 | 
|  | 842 Called in a list context, color_names() returns the list of symbolic | 
|  | 843 color names recognized by this module.  Called in a scalar context, | 
|  | 844 the method returns a hash reference in which the keys are the color | 
|  | 845 names and the values are array references containing [r,g,b] triples. | 
|  | 846 | 
|  | 847 =cut | 
|  | 848 | 
|  | 849 sub color_names { | 
|  | 850   my $self = shift; | 
|  | 851   $self->read_color_table unless %COLORS; | 
|  | 852   return wantarray ? sort keys %COLORS : \%COLORS; | 
|  | 853 } | 
|  | 854 | 
|  | 855 =item $gd = $img->gd | 
|  | 856 | 
|  | 857 Return the internal GD::Image object.  Usually you will not need to | 
|  | 858 call this since all GD methods are automatically referred to this object. | 
|  | 859 | 
|  | 860 =cut | 
|  | 861 | 
|  | 862 sub gd { shift->{gd} } | 
|  | 863 | 
|  | 864 sub read_color_table { | 
|  | 865   my $class = shift; | 
|  | 866   while (<DATA>) { | 
|  | 867     chomp; | 
|  | 868     last if /^__END__/; | 
|  | 869     my ($name,$r,$g,$b) = split /\s+/; | 
|  | 870     $COLORS{$name} = [hex $r,hex $g,hex $b]; | 
|  | 871   } | 
|  | 872 } | 
|  | 873 | 
|  | 874 sub setBrush { | 
|  | 875   my $self  = shift; | 
|  | 876   my $brush = shift; | 
|  | 877   if ($brush->isa('GD::Simple')) { | 
|  | 878     $self->gd->setBrush($brush->gd); | 
|  | 879   } else { | 
|  | 880     $self->gd->setBrush($brush); | 
|  | 881   } | 
|  | 882 } | 
|  | 883 | 
|  | 884 =item ($red,$green,$blue) = GD::Simple->HSVtoRGB($hue,$saturation,$value) | 
|  | 885 | 
|  | 886 Convert a Hue/Saturation/Value (HSV) color into an RGB triple. The | 
|  | 887 hue, saturation and value are integers from 0 to 255. | 
|  | 888 | 
|  | 889 =cut | 
|  | 890 | 
|  | 891 sub HSVtoRGB { | 
|  | 892   my $self = shift; | 
|  | 893   @_ == 3 or croak "Usage: GD::Simple->HSVtoRGB(\$hue,\$saturation,\$value)"; | 
|  | 894 | 
|  | 895   my ($h,$s,$v)=@_; | 
|  | 896   my ($r,$g,$b,$i,$f,$p,$q,$t); | 
|  | 897 | 
|  | 898   if( $s == 0 ) { | 
|  | 899     ## achromatic (grey) | 
|  | 900     return ($v,$v,$v); | 
|  | 901   } | 
|  | 902   $h %= 255; | 
|  | 903   $s /= 255;                      ## scale saturation from 0.0-1.0 | 
|  | 904   $h /= 255;                      ## scale hue from 0 to 1.0 | 
|  | 905   $h *= 360;                      ## and now scale it to 0 to 360 | 
|  | 906 | 
|  | 907   $h /= 60;                       ## sector 0 to 5 | 
|  | 908   $i = $h % 6; | 
|  | 909   $f = $h - $i;                   ## factorial part of h | 
|  | 910   $p = $v * ( 1 - $s ); | 
|  | 911   $q = $v * ( 1 - $s * $f ); | 
|  | 912   $t = $v * ( 1 - $s * ( 1 - $f ) ); | 
|  | 913 | 
|  | 914   if($i<1) { | 
|  | 915     $r = $v; | 
|  | 916     $g = $t; | 
|  | 917     $b = $p; | 
|  | 918   } elsif($i<2){ | 
|  | 919     $r = $q; | 
|  | 920     $g = $v; | 
|  | 921     $b = $p; | 
|  | 922   } elsif($i<3){ | 
|  | 923     $r = $p; | 
|  | 924     $g = $v; | 
|  | 925     $b = $t; | 
|  | 926   } elsif($i<4){ | 
|  | 927     $r = $p; | 
|  | 928     $g = $q; | 
|  | 929     $b = $v; | 
|  | 930   } elsif($i<5){ | 
|  | 931     $r = $t; | 
|  | 932     $g = $p; | 
|  | 933     $b = $v; | 
|  | 934   } else { | 
|  | 935     $r = $v; | 
|  | 936     $g = $p; | 
|  | 937     $b = $q; | 
|  | 938   } | 
|  | 939   return (int($r+0.5),int($g+0.5),int($b+0.5)); | 
|  | 940 } | 
|  | 941 | 
|  | 942 =item ($hue,$saturation,$value) = GD::Simple->RGBtoHSV($hue,$saturation,$value) | 
|  | 943 | 
|  | 944 Convert a Red/Green/Blue (RGB) value into a Hue/Saturation/Value (HSV) | 
|  | 945 triple. The hue, saturation and value are integers from 0 to 255. | 
|  | 946 | 
|  | 947 =back | 
|  | 948 | 
|  | 949 =cut | 
|  | 950 | 
|  | 951 sub RGBtoHSV { | 
|  | 952   my $self = shift; | 
|  | 953   my ($r, $g ,$bl) = @_; | 
|  | 954   my ($min,undef,$max) = sort {$a<=>$b} ($r,$g,$bl); | 
|  | 955   return (0,0,0) unless $max > 0; | 
|  | 956 | 
|  | 957   my $v = $max; | 
|  | 958   my $s = 255 * ($max - $min)/$max; | 
|  | 959   my $h; | 
|  | 960   my $range = $max - $min; | 
|  | 961 | 
|  | 962   if ($range == 0) { # all colors are equal, so monochrome | 
|  | 963     return (0,0,$max); | 
|  | 964   } | 
|  | 965 | 
|  | 966   if ($max == $r) { | 
|  | 967     $h = 60 * ($g-$bl)/$range; | 
|  | 968   } | 
|  | 969   elsif ($max == $g) { | 
|  | 970     $h = 60 * ($bl-$r)/$range + 120; | 
|  | 971   } | 
|  | 972   else { | 
|  | 973     $h = 60 * ($r-$g)/$range + 240; | 
|  | 974   } | 
|  | 975 | 
|  | 976   $h = int($h*255/360 + 0.5); | 
|  | 977 | 
|  | 978   return ($h, $s, $v); | 
|  | 979 } | 
|  | 980 | 
|  | 981 sub newGroup { | 
|  | 982     my $self  = shift; | 
|  | 983     return $self->GD::newGroup(@_); | 
|  | 984 } | 
|  | 985 | 
|  | 986 1; | 
|  | 987 | 
|  | 988 __DATA__ | 
|  | 989 white                FF           FF            FF | 
|  | 990 black                00           00            00 | 
|  | 991 aliceblue            F0           F8            FF | 
|  | 992 antiquewhite         FA           EB            D7 | 
|  | 993 aqua                 00           FF            FF | 
|  | 994 aquamarine           7F           FF            D4 | 
|  | 995 azure                F0           FF            FF | 
|  | 996 beige                F5           F5            DC | 
|  | 997 bisque               FF           E4            C4 | 
|  | 998 blanchedalmond       FF           EB            CD | 
|  | 999 blue                 00           00            FF | 
|  | 1000 blueviolet           8A           2B            E2 | 
|  | 1001 brown                A5           2A            2A | 
|  | 1002 burlywood            DE           B8            87 | 
|  | 1003 cadetblue            5F           9E            A0 | 
|  | 1004 chartreuse           7F           FF            00 | 
|  | 1005 chocolate            D2           69            1E | 
|  | 1006 coral                FF           7F            50 | 
|  | 1007 cornflowerblue       64           95            ED | 
|  | 1008 cornsilk             FF           F8            DC | 
|  | 1009 crimson              DC           14            3C | 
|  | 1010 cyan                 00           FF            FF | 
|  | 1011 darkblue             00           00            8B | 
|  | 1012 darkcyan             00           8B            8B | 
|  | 1013 darkgoldenrod        B8           86            0B | 
|  | 1014 darkgray             A9           A9            A9 | 
|  | 1015 darkgreen            00           64            00 | 
|  | 1016 darkkhaki            BD           B7            6B | 
|  | 1017 darkmagenta          8B           00            8B | 
|  | 1018 darkolivegreen       55           6B            2F | 
|  | 1019 darkorange           FF           8C            00 | 
|  | 1020 darkorchid           99           32            CC | 
|  | 1021 darkred              8B           00            00 | 
|  | 1022 darksalmon           E9           96            7A | 
|  | 1023 darkseagreen         8F           BC            8F | 
|  | 1024 darkslateblue        48           3D            8B | 
|  | 1025 darkslategray        2F           4F            4F | 
|  | 1026 darkturquoise        00           CE            D1 | 
|  | 1027 darkviolet           94           00            D3 | 
|  | 1028 deeppink             FF           14            100 | 
|  | 1029 deepskyblue          00           BF            FF | 
|  | 1030 dimgray              69           69            69 | 
|  | 1031 dodgerblue           1E           90            FF | 
|  | 1032 firebrick            B2           22            22 | 
|  | 1033 floralwhite          FF           FA            F0 | 
|  | 1034 forestgreen          22           8B            22 | 
|  | 1035 fuchsia              FF           00            FF | 
|  | 1036 gainsboro            DC           DC            DC | 
|  | 1037 ghostwhite           F8           F8            FF | 
|  | 1038 gold                 FF           D7            00 | 
|  | 1039 goldenrod            DA           A5            20 | 
|  | 1040 gray                 80           80            80 | 
|  | 1041 green                00           80            00 | 
|  | 1042 greenyellow          AD           FF            2F | 
|  | 1043 honeydew             F0           FF            F0 | 
|  | 1044 hotpink              FF           69            B4 | 
|  | 1045 indianred            CD           5C            5C | 
|  | 1046 indigo               4B           00            82 | 
|  | 1047 ivory                FF           FF            F0 | 
|  | 1048 khaki                F0           E6            8C | 
|  | 1049 lavender             E6           E6            FA | 
|  | 1050 lavenderblush        FF           F0            F5 | 
|  | 1051 lawngreen            7C           FC            00 | 
|  | 1052 lemonchiffon         FF           FA            CD | 
|  | 1053 lightblue            AD           D8            E6 | 
|  | 1054 lightcoral           F0           80            80 | 
|  | 1055 lightcyan            E0           FF            FF | 
|  | 1056 lightgoldenrodyellow FA           FA            D2 | 
|  | 1057 lightgreen           90           EE            90 | 
|  | 1058 lightgrey            D3           D3            D3 | 
|  | 1059 lightpink            FF           B6            C1 | 
|  | 1060 lightsalmon          FF           A0            7A | 
|  | 1061 lightseagreen        20           B2            AA | 
|  | 1062 lightskyblue         87           CE            FA | 
|  | 1063 lightslategray       77           88            99 | 
|  | 1064 lightsteelblue       B0           C4            DE | 
|  | 1065 lightyellow          FF           FF            E0 | 
|  | 1066 lime                 00           FF            00 | 
|  | 1067 limegreen            32           CD            32 | 
|  | 1068 linen                FA           F0            E6 | 
|  | 1069 magenta              FF           00            FF | 
|  | 1070 maroon               80           00            00 | 
|  | 1071 mediumaquamarine     66           CD            AA | 
|  | 1072 mediumblue           00           00            CD | 
|  | 1073 mediumorchid         BA           55            D3 | 
|  | 1074 mediumpurple         100          70            DB | 
|  | 1075 mediumseagreen       3C           B3            71 | 
|  | 1076 mediumslateblue      7B           68            EE | 
|  | 1077 mediumspringgreen    00           FA            9A | 
|  | 1078 mediumturquoise      48           D1            CC | 
|  | 1079 mediumvioletred      C7           15            85 | 
|  | 1080 midnightblue         19           19            70 | 
|  | 1081 mintcream            F5           FF            FA | 
|  | 1082 mistyrose            FF           E4            E1 | 
|  | 1083 moccasin             FF           E4            B5 | 
|  | 1084 navajowhite          FF           DE            AD | 
|  | 1085 navy                 00           00            80 | 
|  | 1086 oldlace              FD           F5            E6 | 
|  | 1087 olive                80           80            00 | 
|  | 1088 olivedrab            6B           8E            23 | 
|  | 1089 orange               FF           A5            00 | 
|  | 1090 orangered            FF           45            00 | 
|  | 1091 orchid               DA           70            D6 | 
|  | 1092 palegoldenrod        EE           E8            AA | 
|  | 1093 palegreen            98           FB            98 | 
|  | 1094 paleturquoise        AF           EE            EE | 
|  | 1095 palevioletred        DB           70            100 | 
|  | 1096 papayawhip           FF           EF            D5 | 
|  | 1097 peachpuff            FF           DA            B9 | 
|  | 1098 peru                 CD           85            3F | 
|  | 1099 pink                 FF           C0            CB | 
|  | 1100 plum                 DD           A0            DD | 
|  | 1101 powderblue           B0           E0            E6 | 
|  | 1102 purple               80           00            80 | 
|  | 1103 red                  FF           00            00 | 
|  | 1104 rosybrown            BC           8F            8F | 
|  | 1105 royalblue            41           69            E1 | 
|  | 1106 saddlebrown          8B           45            13 | 
|  | 1107 salmon               FA           80            72 | 
|  | 1108 sandybrown           F4           A4            60 | 
|  | 1109 seagreen             2E           8B            57 | 
|  | 1110 seashell             FF           F5            EE | 
|  | 1111 sienna               A0           52            2D | 
|  | 1112 silver               C0           C0            C0 | 
|  | 1113 skyblue              87           CE            EB | 
|  | 1114 slateblue            6A           5A            CD | 
|  | 1115 slategray            70           80            90 | 
|  | 1116 snow                 FF           FA            FA | 
|  | 1117 springgreen          00           FF            7F | 
|  | 1118 steelblue            46           82            B4 | 
|  | 1119 tan                  D2           B4            8C | 
|  | 1120 teal                 00           80            80 | 
|  | 1121 thistle              D8           BF            D8 | 
|  | 1122 tomato               FF           63            47 | 
|  | 1123 turquoise            40           E0            D0 | 
|  | 1124 violet               EE           82            EE | 
|  | 1125 wheat                F5           DE            B3 | 
|  | 1126 whitesmoke           F5           F5            F5 | 
|  | 1127 yellow               FF           FF            00 | 
|  | 1128 yellowgreen          9A           CD            32 | 
|  | 1129 gradient1	00 ff 00 | 
|  | 1130 gradient2	0a ff 00 | 
|  | 1131 gradient3	14 ff 00 | 
|  | 1132 gradient4	1e ff 00 | 
|  | 1133 gradient5	28 ff 00 | 
|  | 1134 gradient6	32 ff 00 | 
|  | 1135 gradient7	3d ff 00 | 
|  | 1136 gradient8	47 ff 00 | 
|  | 1137 gradient9	51 ff 00 | 
|  | 1138 gradient10	5b ff 00 | 
|  | 1139 gradient11	65 ff 00 | 
|  | 1140 gradient12	70 ff 00 | 
|  | 1141 gradient13	7a ff 00 | 
|  | 1142 gradient14	84 ff 00 | 
|  | 1143 gradient15	8e ff 00 | 
|  | 1144 gradient16	99 ff 00 | 
|  | 1145 gradient17	a3 ff 00 | 
|  | 1146 gradient18	ad ff 00 | 
|  | 1147 gradient19	b7 ff 00 | 
|  | 1148 gradient20	c1 ff 00 | 
|  | 1149 gradient21	cc ff 00 | 
|  | 1150 gradient22	d6 ff 00 | 
|  | 1151 gradient23	e0 ff 00 | 
|  | 1152 gradient24	ea ff 00 | 
|  | 1153 gradient25	f4 ff 00 | 
|  | 1154 gradient26	ff ff 00 | 
|  | 1155 gradient27	ff f4 00 | 
|  | 1156 gradient28	ff ea 00 | 
|  | 1157 gradient29	ff e0 00 | 
|  | 1158 gradient30	ff d6 00 | 
|  | 1159 gradient31	ff cc 00 | 
|  | 1160 gradient32	ff c1 00 | 
|  | 1161 gradient33	ff b7 00 | 
|  | 1162 gradient34	ff ad 00 | 
|  | 1163 gradient35	ff a3 00 | 
|  | 1164 gradient36	ff 99 00 | 
|  | 1165 gradient37	ff 8e 00 | 
|  | 1166 gradient38	ff 84 00 | 
|  | 1167 gradient39	ff 7a 00 | 
|  | 1168 gradient40	ff 70 00 | 
|  | 1169 gradient41	ff 65 00 | 
|  | 1170 gradient42	ff 5b 00 | 
|  | 1171 gradient43	ff 51 00 | 
|  | 1172 gradient44	ff 47 00 | 
|  | 1173 gradient45	ff 3d 00 | 
|  | 1174 gradient46	ff 32 00 | 
|  | 1175 gradient47	ff 28 00 | 
|  | 1176 gradient48	ff 1e 00 | 
|  | 1177 gradient49	ff 14 00 | 
|  | 1178 gradient50	ff 0a 00 | 
|  | 1179 __END__ | 
|  | 1180 | 
|  | 1181 =head1 COLORS | 
|  | 1182 | 
|  | 1183 This script will create an image showing all the symbolic colors. | 
|  | 1184 | 
|  | 1185  #!/usr/bin/perl | 
|  | 1186 | 
|  | 1187  use strict; | 
|  | 1188  use GD::Simple; | 
|  | 1189 | 
|  | 1190  my @color_names = GD::Simple->color_names; | 
|  | 1191  my $cols = int(sqrt(@color_names)); | 
|  | 1192  my $rows = int(@color_names/$cols)+1; | 
|  | 1193 | 
|  | 1194  my $cell_width    = 100; | 
|  | 1195  my $cell_height   = 50; | 
|  | 1196  my $legend_height = 16; | 
|  | 1197  my $width       = $cols * $cell_width; | 
|  | 1198  my $height      = $rows * $cell_height; | 
|  | 1199 | 
|  | 1200  my $img = GD::Simple->new($width,$height); | 
|  | 1201  $img->font(gdSmallFont); | 
|  | 1202 | 
|  | 1203  for (my $c=0; $c<$cols; $c++) { | 
|  | 1204    for (my $r=0; $r<$rows; $r++) { | 
|  | 1205      my $color = $color_names[$c*$rows + $r] or next; | 
|  | 1206      my @topleft  = ($c*$cell_width,$r*$cell_height); | 
|  | 1207      my @botright = ($topleft[0]+$cell_width,$topleft[1]+$cell_height-$legend_height); | 
|  | 1208      $img->bgcolor($color); | 
|  | 1209      $img->fgcolor($color); | 
|  | 1210      $img->rectangle(@topleft,@botright); | 
|  | 1211      $img->moveTo($topleft[0]+2,$botright[1]+$legend_height-2); | 
|  | 1212      $img->fgcolor('black'); | 
|  | 1213      $img->string($color); | 
|  | 1214    } | 
|  | 1215  } | 
|  | 1216 | 
|  | 1217  print $img->png; | 
|  | 1218 | 
|  | 1219 =head1 AUTHOR | 
|  | 1220 | 
|  | 1221 The GD::Simple module is copyright 2004, Lincoln D. Stein.  It is | 
|  | 1222 distributed under the same terms as Perl itself.  See the "Artistic | 
|  | 1223 License" in the Perl source code distribution for licensing terms. | 
|  | 1224 | 
|  | 1225 The latest versions of GD.pm are available at | 
|  | 1226 | 
|  | 1227   http://stein.cshl.org/WWW/software/GD | 
|  | 1228 | 
|  | 1229 =head1 SEE ALSO | 
|  | 1230 | 
|  | 1231 L<GD>, | 
|  | 1232 L<GD::Polyline>, | 
|  | 1233 L<GD::SVG>, | 
|  | 1234 L<Image::Magick> | 
|  | 1235 | 
|  | 1236 =cut |