]> git.imager.perl.org - imager.git/blobdiff - lib/Imager/Font.pm
note on relative speeds of the scaling mechanisms
[imager.git] / lib / Imager / Font.pm
index c806a25cfc983b2e9e3a75edccb6de2c40539023..66a4b7e44d6cc040cb0780713625ff34e06b05cb 100644 (file)
@@ -2,6 +2,9 @@ package Imager::Font;
 
 use Imager::Color;
 use strict;
+use vars qw($VERSION);
+
+$VERSION = "1.033";
 
 # the aim here is that we can:
 #  - add file based types in one place: here
@@ -120,9 +123,10 @@ sub draw {
     $Imager::ERRSTR = 'No image supplied to $font->draw()';
     return;
   }
+  my $image = $input{image};
   $input{string} = _first($input{string}, $input{text});
   unless (defined $input{string}) {
-    $Imager::ERRSTR = "Missing required parameter 'string'";
+    $image->_set_error("Missing required parameter 'string'");
     return;
   }
   $input{aa} = _first($input{aa}, $input{antialias}, $self->{aa}, 1);
@@ -133,14 +137,19 @@ sub draw {
 
   $input{size} = _first($input{size}, $self->{size});
   unless (defined $input{size}) {
-    $input{image}{ERRSTR} = "No font size provided";
+    $image->_set_error("No font size provided");
     return undef;
   }
   $input{align} = _first($input{align}, 1);
   $input{utf8} = _first($input{utf8}, $self->{utf8}, 0);
   $input{vlayout} = _first($input{vlayout}, $self->{vlayout}, 0);
 
-  $self->_draw(%input);
+  my $result = $self->_draw(%input);
+  unless ($result) {
+    $image->_set_error($image->_error_as_msg());
+  }
+
+  return $result;
 }
 
 sub align {
@@ -148,17 +157,20 @@ sub align {
   my %input = ( halign => 'left', valign => 'baseline', 
                 'x' => 0, 'y' => 0, @_ );
 
-  my $text = _first($input{string}, $input{text});
-  unless (defined $text) {
-    Imager->_set_error("Missing required parameter 'string'");
-    return;
-  }
-
   # image needs to be supplied, but can be supplied as undef
   unless (exists $input{image}) {
     Imager->_set_error("Missing required parameter 'image'");
     return;
   }
+
+  my $errors_to = $input{image} || 'Imager';
+
+  my $text = _first($input{string}, $input{text});
+  unless (defined $text) {
+    $errors_to->_set_error("Missing required parameter 'string'");
+    return;
+  }
+
   my $size = _first($input{size}, $self->{size});
   my $utf8 = _first($input{utf8}, 0);
 
@@ -194,8 +206,11 @@ sub align {
   elsif ($halign eq 'center') {
     $x -= $bbox->start_offset + $bbox->total_width / 2;
   }
-  elsif ($halign eq 'end' || $halign eq 'right') {
-    $x -= $bbox->start_offset + $bbox->total_width - 1;
+  elsif ($halign eq 'end') {
+    $x -= $bbox->advance_width;
+  }
+  elsif ($halign eq 'right') {
+    $x -= $bbox->advance_width - $bbox->right_bearing;
   }
   $x = int($x);
   $y = int($y);
@@ -204,14 +219,6 @@ sub align {
     delete @input{qw/x y/};
     $self->draw(%input, 'x' => $x, 'y' => $y, align=>1)
       or return;
-#      for my $i (1 .. length $text) {
-#        my $work = substr($text, 0, $i);
-#        my $bbox = $self->bounding_box(string=>$work, size=>$size, utf8=>$utf8);
-#        my $nx = $x + $bbox->end_offset;
-#        $input{image}->setpixel(x=>[ ($nx) x 5 ],
-#                                'y'=>[ $y-2, $y-1, $y, $y+1, $y+2 ],
-#                                color=>'FF0000');
-#      }
   }
 
   return ($x+$bbox->start_offset, $y-$bbox->ascent, 
@@ -329,13 +336,9 @@ Imager::Font - Font handling for Imager.
    $advance_width,
    $right_bearing) = $font->bounding_box(string=>"Foo");
 
-  $logo = $font->logo(text   => "Slartibartfast Enterprises",
-                     size   => 40,
-                     border => 5,
-                     color  => $green);
-  # logo is proposed - doesn't exist yet
-
+  my $bbox_object = $font->bounding_box(string=>"Foo");
 
+  # documented in Imager::Draw
   $img->string(font  => $font,
             text  => "Model-XYZ",
             x     => 15,
@@ -344,8 +347,6 @@ Imager::Font - Font handling for Imager.
             color => $red,
             aa    => 1);
 
-  # Documentation in Imager.pm
-
 =head1 DESCRIPTION
 
 This module handles creating Font objects used by imager.  The module
@@ -406,6 +407,85 @@ contruct the full name of the font as above.
 
 Other logical font attributes may be added if there is sufficient demand.
 
+Parameters:
+
+=over
+
+=item *
+
+file - name of the file to load the font from.
+
+=item *
+
+face - face name.  This is used only under Win32 to create a GDI based
+font.  This is ignored if the C<file> parameter is supplied.
+
+=item *
+
+type - font driver to use.  Currently the permitted values for this are:
+
+=over
+
+=item *
+
+tt - Freetype 1.x driver.  Supports TTF fonts.
+
+=item *
+
+t1 - T1 Lib driver.  Supports Postscript Type 1 fonts.  Allows for
+synthesis of underline, strikethrough and overline.
+
+=item *
+
+ft2 - Freetype 2.x driver.  Supports many different font formats.
+Also supports the transform() method.
+
+=back
+
+=item *
+
+color - the default color used with this font.  Default: red.
+
+=item *
+
+size - the default size used with this font.  Default: 15.
+
+=item *
+
+utf8 - if non-zero then text supplied to $img->string(...) and
+$font->bounding_box(...) is assumed to be UTF 8 encoded by default.
+
+=item *
+
+align - the default value for the $img->string(...) C<align>
+parameter.  Default: 1.
+
+=item *
+
+vlayout - the default value for the $img->string(...) C<vlayout>
+parameter.  Default: 0.
+
+=item *
+
+aa - the default value for the $im->string(...) C<aa> parameter.
+Default: 0.
+
+=item *
+
+index - for font file containing multiple fonts this selects which
+font to use.  This is useful for Macintosh DFON (.dfont) and suitcase
+font files.
+
+If you want to use a suitcase font you will need to tell Imager to use
+the FreeType 2.x driver by setting C<type> to C<'ft2'>:
+
+  my $font = Imager::Font->new(file=>$file, index => 1, type=>'ft2')
+    or die Imager->errstr;
+
+=back
+
+
+
 =item bounding_box
 
 Returns the bounding box for the specified string.  Example:
@@ -489,99 +569,49 @@ Returns an L<Imager::Font::BBox> object in scalar context, so you can
 avoid all those confusing indices.  This has methods as named above,
 with some extra convenience methods.
 
-=item string
-
-This is a method of the Imager class but because it's described in
-here since it belongs to the font routines.  Example:
-
-  $img=Imager->new();
-  $img->read(file=>"test.jpg");
-  $img->string(font=>$t1font,
-               text=>"Model-XYZ",
-               x=>0,
-               y=>40,
-               size=>40,
-               color=>$red);
-  $img->write(file=>"testout.jpg");
-
-This would put a 40 pixel high text in the top left corner of an
-image.  If you measure the actuall pixels it varies since the fonts
-usually do not use their full height.  It seems that the color and
-size can be specified twice.  When a font is created only the actual
-font specified matters.  It his however convenient to store default
-values in a font, such as color and size.  If parameters are passed to
-the string function they are used instead of the defaults stored in
-the font.
-
-The following parameters can be supplied to the string() method:
+Parameters are:
 
 =over
 
-=item string
-
-The text to be rendered.  If this isn't present the 'text' parameter
-is used.  If neither is present the call will fail.
-
-=item aa
-
-If non-zero the output will be anti-aliased.
-
-=item x
-
-=item y
-
-The start point for rendering the text.  See the align parameter.
-
-=item align
-
-If non-zero the point supplied in (x,y) will be on the base-line, if
-zero then (x,y) will be at the top-left of the string.
-
-ie. if drawing the string "yA" and align is 0 the point (x,y) will
-aligned with the top of the A.  If align is 1 (the default) it will be
-aligned with the baseline of the font, typically bottom of the A,
-depending on the font used.
-
-=item channel
+=item *
 
-If present, the text will be written to the specified channel of the
-image and the color parameter will be ignore.
+string - the string to calculate the bounding box for.  Required.
 
-=item color
+=item *
 
-The color to draw the text in.
+size - the font size to use.  Default: value set in
+Imager::Font->new(), or 15.
 
-=item size
+=item *
 
-The point-size to draw the text at.
+sizew - the font width to use.  Default to the value of the C<size>
+parameter.
 
-=item sizew
+=item *
 
-For drivers that support it, the width to draw the text at.  Defaults
-to be value of the 'size' parameter.
+utf8 - For drivers that support it, treat the string as UTF8 encoded.
+For versions of perl that support Unicode (5.6 and later), this will
+be enabled automatically if the 'string' parameter is already a UTF8
+string. See L<UTF8> for more information.  Default: the C<utf8> value
+passed to Imager::Font->new(...) or 0.
 
-=item utf8
+=item *
 
-For drivers that support it, treat the string as UTF8 encoded.  For
-versions of perl that support Unicode (5.6 and later), this will be
-enabled automatically if the 'string' parameter is already a UTF8
-string. See L<UTF8> for more information.
+x, y - offsets applied to @box[0..3] to give you a adjusted bounding
+box.  Ignored in scalar context.
 
-=item vlayout
+=item *
 
-For drivers that support it, draw the text vertically.  Note: I
-haven't found a font that has the appropriate metrics yet.
+canon - if non-zero and the C<x>, C<y> parameters are not supplied,
+then $pos_width and $global_ascent values will returned as the width
+and height of the text instead.
 
 =back
 
-If string() is called with the C<channel> parameter then the color
-isn't used and the font is drawn in only one channel of the image.
-This can be quite handy to create overlays.  See the examples for tips
-about this.
+=item string
 
-Sometimes it is necessary to know how much space a string takes before
-rendering it.  The bounding_box() method described earlier can be used
-for that.
+The $img->string(...) method is now documented in
+L<Imager::Draw/string>
 
 =item align(string=>$text, size=>$size, x=>..., y=>..., valign => ..., halign=>...)
 
@@ -589,7 +619,7 @@ Higher level text output - outputs the text aligned as specified
 around the given point (x,y).
 
   # "Hello" centered at 100, 100 in the image.
-  my ($left, $top, $bottom, $right) = 
+  my ($left, $top, $right, $bottom) = 
     $font->align(string=>"Hello",
                  x=>100, y=>100, 
                  halign=>'center', valign=>'center', 
@@ -646,9 +676,7 @@ The point is at the right end of the text.
 
 =item end
 
-The point is at the right end of the text.  This will change to the
-end point of the text (once the proper bounding box interfaces are
-available).
+The point is at the end point of the text.
 
 =back
 
@@ -667,11 +695,28 @@ Returns a list specifying the bounds of the drawn text.
 
 =item dpi(dpi=>$dpi)
 
-Set retrieve the spatial resolution of the image in dots per inch.
+Set or retrieve the spatial resolution of the image in dots per inch.
 The default is 72 dpi.
 
 This isn't implemented for all font types yet.
 
+Possible parameters are:
+
+=over
+
+=item *
+
+xdpi, ydpi - set the horizontal and vertical resolution in dots per
+inch.
+
+=item *
+
+dpi - set both horizontal and vertical resolution to this value.
+
+=back
+
+Returns a list containing the previous xdpi, ydpi values.
+
 =item transform(matrix=>$matrix)
 
 Applies a transformation to the font, where matrix is an array ref of
@@ -689,6 +734,12 @@ See the end of the test script t/t38ft2font.t for an example.
 Currently only the ft2 (Freetype 2.x) driver supports the transform()
 method.
 
+See samples/slant_text.pl for a sample using this function.
+
+Note that the transformation is done in font co-ordinates where y
+increases as you move up, not image co-ordinates where y decreases as
+you move up.
+
 =item has_chars(string=>$text)
 
 Checks if the characters in $text are defined by the font.
@@ -701,18 +752,22 @@ characters.  Supports UTF8 where the font driver supports UTF8.
 Not all fonts support this method (use $font->can("has_chars") to
 check.)
 
-=item logo
+=over
+
+=item *
 
-This method doesn't exist yet but is under consideration.  It would mostly
-be helpful for generating small tests and such.  Its proposed interface is:
+string - string of characters to check for.  Required.  Must contain
+at least one character.
 
-  $img = $font->logo(string=>"Plan XYZ", color=>$blue, border=>7);
+=item *
 
-This would be nice for writing (admittedly multiline) one liners like:
+utf8 - For drivers that support it, treat the string as UTF8 encoded.
+For versions of perl that support Unicode (5.6 and later), this will
+be enabled automatically if the 'string' parameter is already a UTF8
+string. See L<UTF8> for more information.  Default: the C<utf8> value
+passed to Imager::Font->new(...) or 0.
 
-Imager::Font->new(file=>"arial.ttf", color=>$blue, aa=>1)
-            ->string(text=>"Plan XYZ", border=>5)
-            ->write(file=>"xyz.png");
+=back
 
 =item face_name()
 
@@ -739,6 +794,11 @@ say how those name tables are unreliable, or how FT2 handles them.
 Both Freetype 1.x and 2.x allow support for glyph names to not be
 included.
 
+=item draw
+
+This is used by Imager's string() method to implement drawing text.
+See L<Imager::Draw/string>.
+
 =back
 
 =head1 MULTIPLE MASTER FONTS
@@ -812,6 +872,16 @@ unicode character 00C3 "LATIN CAPITAL LETTER A WITH DIAERESIS", and
 your font doesn't support it, Imager will I<not> build it from 0041
 "LATIN CAPITAL LETTER A" and 0308 "COMBINING DIAERESIS".
 
+To check if a driver supports UTF8 call the utf8 method:
+
+=over
+
+=item utf8
+
+Return true if the font supports UTF8.
+
+=back
+
 =head2 Native UTF8 Support
 
 If your version of perl supports UTF8 and the driver supports UTF8,
@@ -850,7 +920,11 @@ Since some formats can be handled by more than one driver, a priority
 list is used to choose which one should be used, if a given format can
 be handled by more than one driver.
 
-The current priority can be retrieved with:
+=over
+
+=item priorities
+
+The current priorities can be retrieved with:
 
   @drivers = Imager::Font->priorities();
 
@@ -858,6 +932,8 @@ You can set new priorities and save the old priorities with:
 
   @old = Imager::Font->priorities(@drivers);
 
+=back
+
 If you supply driver names that are not currently supported, they will
 be ignored.
 
@@ -887,6 +963,10 @@ driver always returns the right edge of the right-most glyph.
 The newer advance_width and right_bearing values allow access to any
 of the above.
 
+=head1 REVISION
+
+$Revision$
+
 =head1 SEE ALSO
 
 Imager(3), Imager::Font::FreeType2(3), Imager::Font::Type1(3),