]> git.imager.perl.org - imager.git/blobdiff - lib/Imager/Fill.pm
typos in Imager::Font
[imager.git] / lib / Imager / Fill.pm
index c727052c7918403a5c79348a9a08a74577c5c2e2..f964c09706c7aa0938f2d5043aa8f5e004789cb6 100644 (file)
@@ -1,4 +1,8 @@
 package Imager::Fill;
+use strict;
+use vars qw($VERSION);
+
+$VERSION = "1.012";
 
 # this needs to be kept in sync with the array of hatches in fills.c
 my @hatch_types =
@@ -10,17 +14,22 @@ my @hatch_types =
 my %hatch_types;
 @hatch_types{@hatch_types} = 0..$#hatch_types;
 
+*_color = \&Imager::_color;
+
 sub new {
   my ($class, %hsh) = @_;
 
   my $self = bless { }, $class;
-  $hsh{combine} ||= 0;
+  $hsh{combine} = Imager->_combine($hsh{combine}, 0);
   if ($hsh{solid}) {
-    if (UNIVERSAL::isa($hsh{solid}, 'Imager::Color')) {
-      $self->{fill} = Imager::i_new_fill_solid($hsh{solid}, $hsh{combine});
+    my $solid = _color($hsh{solid});
+    if (UNIVERSAL::isa($solid, 'Imager::Color')) {
+      $self->{fill} = 
+        Imager::i_new_fill_solid($solid, $hsh{combine});
     }
-    elsif (UNIVERSAL::isa($hsh{colid}, 'Imager::Color::Float')) {
-      $self->{fill} = Imager::i_new_fill_solidf($hsh{solid}, $hsh{combine});
+    elsif (UNIVERSAL::isa($solid, 'Imager::Color::Float')) {
+      $self->{fill} = 
+        Imager::i_new_fill_solidf($solid, $hsh{combine});
     }
     else {
       $Imager::ERRSTR = "solid isn't a color";
@@ -42,17 +51,18 @@ sub new {
       }
       $hsh{hatch} = $hatch_types{$hsh{hatch}};
     }
-    if (UNIVERSAL::isa($hsh{fg}, 'Imager::Color')) {
-      $hsh{bg} ||= Imager::Color->new(255, 255, 255);
+    my $fg = _color($hsh{fg});
+    if (UNIVERSAL::isa($fg, 'Imager::Color')) {
+      my $bg = _color($hsh{bg} || Imager::Color->new(255, 255, 255));
       $self->{fill} = 
-        Imager::i_new_fill_hatch($hsh{fg}, $hsh{bg}, $hsh{combine}, 
+        Imager::i_new_fill_hatch($fg, $bg, $hsh{combine}, 
                                  $hsh{hatch}, $hsh{cust_hatch}, 
                                  $hsh{dx}, $hsh{dy});
     }
-    elsif (UNIVERSAL::isa($hsh{bg}, 'Imager::Color::Float')) {
-      $hsh{bg} ||= Imager::Color::Float->new(1, 1, 1);
+    elsif (UNIVERSAL::isa($fg, 'Imager::Color::Float')) {
+      my $bg  = _color($hsh{bg} || Imager::Color::Float->new(1, 1, 1));
       $self->{fill} = 
-        Imager::i_new_fill_hatchf($hsh{fg}, $hsh{bg}, $hsh{combine},
+        Imager::i_new_fill_hatchf($fg, $bg, $hsh{combine},
                                   $hsh{hatch}, $hsh{cust_hatch}, 
                                   $hsh{dx}, $hsh{dy});
     }
@@ -86,10 +96,63 @@ sub new {
       }
     }
 
+    # check that the segments supplied is an array ref
+    unless (ref $hsh{segments} && $hsh{segments} =~ /ARRAY/) {
+      $Imager::ERRSTR =
+        "segments must be an array reference or Imager::Fountain object";
+      return;
+    }
+
+    # make sure the segments are specified with colors
+    my @segments;
+    for my $segment (@{$hsh{segments}}) {
+      my @new_segment = @$segment;
+
+      $_ = _color($_) or return for @new_segment[3,4];
+      push @segments, \@new_segment;
+    }
+
     $self->{fill} =
       Imager::i_new_fill_fount($hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
                   $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
-                  $hsh{ssample_param}, $hsh{segments});
+                  $hsh{ssample_param}, \@segments);
+  }
+  elsif (defined $hsh{image}) {
+    $hsh{xoff} ||= 0;
+    $hsh{yoff} ||= 0;
+    $self->{fill} =
+      Imager::i_new_fill_image($hsh{image}{IMG}, $hsh{matrix}, $hsh{xoff}, 
+                               $hsh{yoff}, $hsh{combine});
+    $self->{DEPS} = [ $hsh{image}{IMG} ];
+  }
+  elsif (defined $hsh{type} && $hsh{type} eq "opacity") {
+    my $other_fill = delete $hsh{other};
+    unless (defined $other_fill) {
+      Imager->_set_error("'other' parameter required to create opacity fill");
+      return;
+    }
+    unless (ref $other_fill &&
+           eval { $other_fill->isa("Imager::Fill") }) {
+      # try to auto convert to a fill object
+      if (ref $other_fill && $other_fill =~ /HASH/) {
+       $other_fill = Imager::Fill->new(%$other_fill)
+         or return;
+      }
+      else {
+       undef $other_fill;
+      }
+      unless ($other_fill) {
+       Imager->_set_error("'other' parameter must be an Imager::Fill object to create an opacity fill");
+       return;
+      }
+    }
+
+    my $raw_fill = $other_fill->{fill};
+    my $opacity = delete $hsh{opacity};
+    defined $opacity or $opacity = 0.5; # some sort of default
+    $self->{fill} = 
+      Imager::i_new_fill_opacity($raw_fill, $opacity);
+    $self->{DEPS} = [ $other_fill ]; # keep reference to old fill and its deps
   }
   else {
     $Imager::ERRSTR = "No fill type specified";
@@ -104,6 +167,10 @@ sub hatches {
   return @hatch_types;
 }
 
+sub combines {
+  return Imager->combines;
+}
+
 1;
 
 =head1 NAME
@@ -112,14 +179,33 @@ sub hatches {
 
 =head1 SYNOPSIS
 
+  use Imager;
+  use Imager::Fill;
+
   my $fill1 = Imager::Fill->new(solid=>$color, combine=>$combine);
   my $fill2 = Imager::Fill->new(hatch=>'vline2', fg=>$color1, bg=>$color2,
                                 dx=>$dx, dy=>$dy);
+  my $fill3 = Imager::Fill->new(fountain=>$type, ...);
+  my $fill4 = Imager::Fill->new(image=>$img, ...);
+  my $fill5 = Imager::Fill->new(type => "opacity", other => $fill,
+                                opacity => ...);
 
 =head1 DESCRIPTION 
 
-Creates fill objects for use by some drawing functions, currently just
-the Imager box() method.
+Creates fill objects for use by most filled area drawing functions.
+
+All fills are created with the new method.
+
+=over
+
+=item new
+
+  my $fill = Imager::Fill->new(...);
+
+The parameters depend on the type of fill being created.  See below
+for details.
+
+=back
 
 The currently available fills are:
 
@@ -133,10 +219,18 @@ solid
 
 hatch
 
-=item
+=item *
 
 fountain (similar to gradients in paint software)
 
+=item *
+
+image - fill with an image, possibly transformed
+
+=item *
+
+opacity - a lower opacity version of some other fill
+
 =back
 
 =head1 Common options
@@ -145,26 +239,27 @@ fountain (similar to gradients in paint software)
 
 =item combine
 
-If this is non-zero the fill combines the given colors or samples (if
-the fill is an image) with the underlying image.
-
-This this is missing or zero then the target image pixels are simply
-overwritten.
+The way in which the fill data is combined with the underlying image.
+See L<Imager::Draw/"Combine Types">.
 
 =back
 
-In general colors can be specified as Imager::Color or
-Imager::Color::Float objects.  The fill object will typically store
+In general colors can be specified as L<Imager::Color> or
+L<Imager::Color::Float> objects.  The fill object will typically store
 both types and convert from one to the other.  If a fill takes 2 color
 objects they should have the same type.
 
 =head2 Solid fills
 
-  my $fill = Imager::Fill->new(solid=>$color, $combine =>$combine)
+  my $fill = Imager::Fill->new(solid=>$color, combine =>$combine)
 
 Creates a solid fill, the only required parameter is C<solid> which
 should be the color to fill with.
 
+A translucent red fill:
+
+  my $red = Imager::Fill->new(solid => "FF000080", combine => "normal");
+
 =head2 Hatched fills
 
   my $fill = Imager::Fill->new(hatch=>$type, fg=>$fgcolor, bg=>$bgcolor,
@@ -174,11 +269,12 @@ Creates a hatched fill.  You can specify the following keywords:
 
 =over
 
-=item hatch
+=item *
 
-The type of hatch to perform, this can either be the numeric index of
-the hatch (not recommended), the symbolic name of the hatch, or an
-array of 8 integers which specify the pattern of the hatch.
+C<hatch> - The type of hatch to perform, this can either be the
+numeric index of the hatch (not recommended), the symbolic name of the
+hatch, or an array of 8 integers which specify the pattern of the
+hatch.
 
 Hatches are represented as cells 8x8 arrays of bits, which limits their
 complexity.
@@ -187,77 +283,80 @@ Current hatch names are:
 
 =over
 
-=item check1x1, check2x2, check4x4
+=item *
 
-checkerboards at varios sizes
+C<check1x1>, C<check2x2>, C<check4x4> - checkerboards at various sizes
 
-=item vline1, vline2, vline4
+=item *
 
-1, 2, or 4 vertical lines per cell
+C<vline1>, C<vline2>, C<vline4> - 1, 2, or 4 vertical lines per cell
 
-=item hline1, hline2, hline4
+=item *
 
-1, 2, or 4 horizontal lines per cell
+C<hline1>, C<hline2>, C<hline4> - 1, 2, or 4 horizontal lines per cell
 
-=item slash1,  slash2
+=item *
 
-1 or 2 / lines per cell.
+C<slash1>, C<slash2> - 1 or 2 / lines per cell.
 
-=item slosh1,  slosh2
+=item *
 
-1 or 2 \ lines per cell
+C<slosh1>, C<slosh2> - 1 or 2 \ lines per cell
 
-=item grid1,  grid2,  grid4
+=item *
 
-1, 2, or 4 vertical and horizontal lines per cell
+C<grid1>, C<grid2>, C<grid4> - 1, 2, or 4 vertical and horizontal
+lines per cell
 
-=item dots1, dots4, dots16
+=item *
 
-1, 4 or 16 dots per cell
+C<dots1>, C<dots4>, C<dots16> - 1, 4 or 16 dots per cell
 
-=item stipple, stipple2
+=item *
 
-see the samples
+C<stipple>, C<stipple2> - see the samples
 
-=item weave
+=item *
 
-I hope this one is obvious.
+C<weave> - I hope this one is obvious.
 
-=item cross1,  cross2
+=item *
 
-2 densities of crosshatch
+C<cross1>, C<cross2> - 2 densities of crosshatch
 
-=item vlozenge,  hlozenge
+=item *
 
-something like lozenge tiles
+C<vlozenge>, C<hlozenge> - something like lozenge tiles
 
-=item scalesdown,  scalesup,  scalesleft,  scalesright
+=item *
 
-Vaguely like fish scales in each direction.
+C<scalesdown>, C<scalesup>, C<scalesleft>, C<scalesright> - Vaguely
+like fish scales in each direction.
 
-=item tile_L
+=item *
 
-L-shaped tiles
+C<tile_L> - L-shaped tiles
 
 =back
 
-=item fg
+=item *
 
-=item bg
+C<fg>, C<bg> - The C<fg> color is rendered where bits are set in the
+hatch, and the C<bg> where they are clear.  If you use a transparent
+C<fg> or C<bg>, and set combine, you can overlay the hatch onto an
+existing image.
 
-The fg color is rendered where bits are set in the hatch, and the bg
-where they are clear.  If you use a transparent fg or bg, and set
-combine, you can overlay the hatch onto an existing image.
+C<fg> defaults to black, C<bg> to white.
 
-fg defaults to black, bg to white.
+=item *
 
-=item dx
+C<dx>, C<dy> - An offset into the hatch cell.  Both default to zero.
 
-=item dy
+=back
 
-An offset into the hatch cell.  Both default to zero.
+A blue and white 4-pixel check pattern:
 
-=back
+  my $fill = Imager::Fill->new(hatch => "check2x2", fg => "blue");
 
 You can call Imager::Fill->hatches for a list of hatch names.
 
@@ -265,7 +364,7 @@ You can call Imager::Fill->hatches for a list of hatch names.
 
   my $fill = Imager::Fill->new(fountain=>$ftype, 
        xa=>$xa, ya=>$ya, xb=>$xb, yb=>$yb, 
-       segment=>$segments, repeat=>$repeat, combine=>$combine, 
+       segments=>$segments, repeat=>$repeat, combine=>$combine, 
        super_sample=>$super_sample, ssample_param=>$ssample_param);
 
 This fills the given region with a fountain fill.  This is exactly the
@@ -273,27 +372,114 @@ same fill as the C<fountain> filter, but is restricted to the shape
 you are drawing, and the fountain parameter supplies the fill type,
 and is required.
 
-=head1 FUTURE PLANS
+A radial fill from white to transparent centered on (50, 50) with a 50
+pixel radius:
 
-I'm planning on adding the following types of fills:
+  use Imager::Fountain;
+  my $segs = Imager::Fountain->simple(colors => [ "FFFFFF", "FFFFFF00" ],
+                                      positions => [ 0, 1 ]);
+  my $fill = Imager::Fill->new(fountain => "radial", segments => $segs,
+                               xa => 50, ya => 50, xb => 0, yb => 50,
+                               combine => "normal");
+
+
+=head2 Image Fills
+
+  my $fill = Imager::Fill->new(image=>$src, xoff=>$xoff, yoff=>$yoff,
+                               matrix=>$matrix, combine => $combine);
+
+Fills the given image with a tiled version of the given image.  The
+first non-zero value of C<xoff> or C<yoff> will provide an offset
+along the given axis between rows or columns of tiles respectively.
+
+The matrix parameter performs a co-ordinate transformation from the
+co-ordinates in the target image to the fill image co-ordinates.
+Linear interpolation is used to determine the fill pixel.  You can use
+the L<Imager::Matrix2d> class to create transformation matrices.
+
+The matrix parameter will significantly slow down the fill.
+
+  # some image to act as a texture
+  my $txim = Imager->new(...);
+
+  # simple tiling
+  my $fill = Imager::Fill->new(image => $txim);
+
+  # tile with a vertical offset
+  my $fill = Imager::Fill->new(image => $txim, yoff => 10);
+
+  # tile with a horizontal offset
+  my $fill = Imager::Fill->new(image => $txim, xoff => 10);
+
+  # rotated
+  use Imager::Matrix2d;
+  my $fill = Imager::Fill->new(image => $txim,
+                matrix => Imager::Matrix2d->rotate(degrees => 20));
+
+=head2 Opacity modification fill
+
+  my $fill = Imager::Fill->new(type => "opacity",
+      other => $fill, opacity => 0.25);
+
+This can be used to make a fill that is a more translucent or opaque
+version of an existing fill.  This is intended for use where you
+receive a fill object as a parameter and need to change the opacity.
+
+Parameters:
 
 =over
 
-=item image
+=item *
 
-tiled image fill
+type => "opacity" - Required
 
-=item checkerboard
+=item *
 
-combines 2 other fills in a checkerboard
+other - the fill to produce a modified version of.  This must be an
+Imager::Fill object.  Required.
 
-=item combine
+=item *
 
-combines 2 other fills using the levels of an image
+opacity - multiplier for the source fill opacity.  Default: 0.5.
 
-=item regmach
+=back
+
+The source fills combine mode is used.
+
+  my $hatch = Imager::Fill->new(hatch => "check4x4", combine => "normal");
+  my $fill = Imager::Fill->new(type => "opacity", other => $hatch);
+
+=head1 OTHER METHODS
+
+=over
+
+=item Imager::Fill->hatches
+
+A list of all defined hatch names.
+
+=item Imager::Fill->combines
+
+A list of all combine types.
+
+=back
+
+=head1 FUTURE PLANS
+
+I'm planning on adding the following types of fills:
+
+=over
+
+=item *
+
+C<checkerboard> - combines 2 other fills in a checkerboard
+
+=item *
+
+C<combine> - combines 2 other fills using the levels of an image
+
+=item *
 
-uses the transform2() register machine to create fills
+C<regmach> - uses the transform2() register machine to create fills
 
 =back