]> git.imager.perl.org - imager.git/blobdiff - lib/Imager/Font.pm
deprecate Imager::Font::T1
[imager.git] / lib / Imager / Font.pm
index 6fb624df1aa668d54f02a3ec1a903af164e01b4e..e0ccc8f76e52b0f45f33c834d8ec3bfc32ab96fe 100644 (file)
@@ -2,6 +2,9 @@ package Imager::Font;
 
 use Imager::Color;
 use strict;
+use vars qw($VERSION);
+
+$VERSION = "1.039";
 
 # the aim here is that we can:
 #  - add file based types in one place: here
@@ -14,16 +17,20 @@ my %drivers =
         class=>'Imager::Font::Truetype',
         module=>'Imager/Font/Truetype.pm',
         files=>'.*\.ttf$',
+       description => 'FreeType 1.x',
+       checktype => 1,
        },
    t1=>{
-        class=>'Imager::Font::Type1',
-        module=>'Imager/Font/Type1.pm',
+        class=>'Imager::Font::T1',
+        module=>'Imager/Font/T1.pm',
         files=>'.*\.pfb$',
+       description => 'T1Lib',
        },
    ft2=>{
-         class=>'Imager::Font::FreeType2',
-         module=>'Imager/Font/FreeType2.pm',
+         class=>'Imager::Font::FT2',
+         module=>'Imager/Font/FT2.pm',
          files=>'.*\.(pfa|pfb|otf|ttf|fon|fnt|dfont|pcf(\.gz)?)$',
+        description => 'FreeType 2.x',
         },
    ifs=>{
          class=>'Imager::Font::Image',
@@ -31,32 +38,20 @@ my %drivers =
          files=>'.*\.ifs$',
         },
    w32=>{
-         class=>'Imager::Font::Win32',
-         module=>'Imager/Font/Win32.pm',
+         class=>'Imager::Font::W32',
+         module=>'Imager/Font/W32.pm',
+        description => 'Win32 GDI Fonts',
         },
   );
 
 # this currently should only contain file based types, don't add w32
-my @priority = qw(t1 tt ft2 ifs);
-
-# when Imager::Font is loaded, Imager.xs has not been bootstrapped yet
-# this function is called from Imager.pm to finish initialization
-sub __init {
-  @priority = grep Imager::i_has_format($_), @priority;
-  delete @drivers{grep !Imager::i_has_format($_), keys %drivers};
-}
-
-# search method
-# 1. start by checking if file is the parameter
-# 1a. if so qualify path and compare to the cache.
-# 2a. if in cache - take it's id from there and increment count.
-#
+my @priority = qw(tt ft2 ifs);
 
 sub new {
   my $class = shift;
   my $self = {};
   my ($file, $type, $id);
-  my %hsh=(color => Imager::Color->new(255,0,0,0),
+  my %hsh=(color => Imager::Color->new(255,0,0,255),
           size => 15,
           @_);
 
@@ -64,27 +59,47 @@ sub new {
 
   if ($hsh{'file'}) {
     $file = $hsh{'file'};
-    if ( $file !~ m/^\// ) {
-      $file = './'.$file;
-      if (! -e $file) {
-       $Imager::ERRSTR = "Font $file not found";
-       return();
-      }
-    }
 
     $type = $hsh{'type'};
-    if (!defined($type) or !$drivers{$type}) {
+    if (defined $type) {
+      unless ($drivers{$type}) {
+       Imager->_set_error("Unknown font type $type");
+       return;
+      }
+
+      unless ($Imager::formats{$type}) {
+       Imager->_set_error("The $type {$drivers{$type}) font driver is not installed");
+       return;
+      }
+    }
+    else {
       for my $drv (@priority) {
         undef $type;
         my $re = $drivers{$drv}{files} or next;
         if ($file =~ /$re/i) {
-          $type = $drv;
-          last;
+         if (eval { require $drivers{$drv}{module}; 1 } and !( $drivers{$drv}{checktype} && !$Imager::formats{$drv} )) {
+           $type = $drv;
+           last;
+         }
         }
       }
     }
     if (!defined($type)) {
-      $Imager::ERRSTR = "Font type not found";
+      # some types we can support, but the driver isn't available
+      # work out which drivers support it, so we can provide the user
+      # some useful information on how to get it working
+      my @not_here;
+      for my $driver_name (keys %drivers) {
+       my $driver = $drivers{$driver_name};
+       push @not_here, "$driver_name ($driver->{description})"
+         if $driver->{files} && $file =~ /$driver->{files}/i;
+      }
+      if (@not_here) {
+       $Imager::ERRSTR = "No font drivers enabled that can support this file, rebuild Imager with any of ".join(", ", @not_here)." to use this font file";
+      }
+      else {
+       $Imager::ERRSTR = "No font type found for $hsh{'file'}";
+      }
       return;
     }
   } elsif ($hsh{face}) {
@@ -94,7 +109,7 @@ sub new {
     return;
   }
 
-  if (!$Imager::formats{$type}) {
+  if ($drivers{$type}{checktype} && !$Imager::formats{$type}) {
     $Imager::ERRSTR = "`$type' not enabled";
     return;
   }
@@ -120,9 +135,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 +149,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 +169,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 +218,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 +231,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, 
@@ -230,7 +249,8 @@ sub bounding_box {
   $input{sizew} = _first($input{sizew}, $self->{sizew}, 0);
   $input{utf8} = _first($input{utf8}, $self->{utf8}, 0);
 
-  my @box = $self->_bounding_box(%input);
+  my @box = $self->_bounding_box(%input)
+    or return;
 
   if (wantarray) {
     if(@box && exists $input{'x'} and exists $input{'y'}) {
@@ -240,7 +260,7 @@ sub bounding_box {
       $box[0]+=$input{'x'};
       $box[2]+=$input{'x'};
     } elsif (@box && $input{'canon'}) {
-      $box[3]-=$box[1];    # make it cannoical (ie (0,0) - (width, height))
+      $box[3]-=$box[1];    # make it canonical (ie (0,0) - (width, height))
       $box[2]-=$box[0];
     }
     return @box;
@@ -296,11 +316,50 @@ sub priorities {
   my @old = @priority;
 
   if (@_) {
-    @priority = grep Imager::i_has_format($_), @_;
+    @priority = @_;
   }
   return @old;
 }
 
+sub register {
+  my ($self, %opts) = @_;
+
+  my $type = delete $opts{type};
+  my $class = delete $opts{class};
+  my $files = delete $opts{files};
+  my $description = delete $opts{description} || $class;
+
+  defined $type
+    or return Imager->_set_error("No type parameter supplied to Imager::Font->regster");
+
+  defined $class
+    or return Imager->_set_error("No class parameter supplied to Imager::Font->register");
+
+  if ($files) {
+    eval { qr/$files/ }
+      or return Imager->_set_error("files isn't a valid regexp");
+  }
+
+  if ($drivers{$type} && $drivers{$type}{class} ne $class) {
+    Imager->_set_error("Font type $type already registered as $drivers{$type}{class}");
+    return;
+  }
+
+  (my $module = $class . ".pm") =~ s(::)(/)g;
+
+  my $driver =
+    {
+     class => $class,
+     module => $module,
+     description => $description,
+    };
+  $files and $driver->{files} = $files;
+
+  $drivers{$type} = $driver;
+
+  1;
+}
+
 1;
 
 __END__
@@ -311,6 +370,8 @@ Imager::Font - Font handling for Imager.
 
 =head1 SYNOPSIS
 
+  use Imager;
+
   $t1font = Imager::Font->new(file => 'pathtofont.pfb');
   $ttfont = Imager::Font->new(file => 'pathtofont.ttf');
   $w32font = Imager::Font->new(face => 'Times New Roman');
@@ -329,13 +390,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,15 +401,15 @@ 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
+=for stopwords TrueType FreeType
+
+This module handles creating Font objects used by Imager.  The module
 also handles querying fonts for sizes and such.  If both T1lib and
-freetype were avaliable at the time of compilation then Imager should
-be able to work with both truetype fonts and t1 postscript fonts.  To
-check if Imager is t1 or truetype capable you can use something like
+FreeType were available at the time of compilation then Imager should
+be able to work with both TrueType fonts and t1 Postscript fonts.  To
+check if Imager is t1 or TrueType capable you can use something like
 this:
 
   use Imager;
@@ -373,40 +430,125 @@ This creates a font object to pass to functions that take a font argument.
                            size  => 30,
                            aa    => 1);
 
-This creates a font which is the truetype font denmark.ttf.  It's
+This creates a font which is the TrueType font F<denmark.ttf>.  It's
 default color is $blue, default size is 30 pixels and it's rendered
-antialised by default.  Imager can see which type of font a file is by
-looking at the suffix of the filename for the font.  A suffix of 'ttf'
-is taken to mean a truetype font while a suffix of 'pfb' is taken to
-mean a t1 postscript font.  If Imager cannot tell which type a font is
-you can tell it explicitly by using the C<type> parameter:
+anti-aliased by default.  Imager can see which type of font a file is
+by looking at the suffix of the file name for the font.  A suffix of
+C<ttf> is taken to mean a TrueType font while a suffix of C<pfb> is
+taken to mean a Type 1 Postscript font.  If Imager cannot tell which
+type a font is you can tell it explicitly by using the C<type>
+parameter:
 
   $t1font = Imager::Font->new(file => 'fruitcase', type => 't1');
   $ttfont = Imager::Font->new(file => 'arglebarf', type => 'tt');
 
 The C<index> parameter is used to select a single face from a font
 file containing more than one face, for example, from a Macintosh font
-suitcase or a .dfont file.
+suitcase or a C<.dfont> file.
 
 If any of the C<color>, C<size> or C<aa> parameters are omitted when
-calling C<Imager::Font->new()> the they take the following values:
+calling C<< Imager::Font->new() >> the they take the following values:
 
   color => Imager::Color->new(255, 0, 0, 0);  # this default should be changed
   size  => 15
   aa    => 0
   index => 0
 
-To use Win32 fonts supply the facename of the font:
+To use Win32 fonts supply the face name of the font:
 
   $font = Imager::Font->new(face=>'Arial Bold Italic');
 
 There isn't any access to other logical font attributes, but this
 typically isn't necessary for Win32 TrueType fonts, since you can
-contruct the full name of the font as above.
+construct the full name of the font as above.
 
 Other logical font attributes may be added if there is sufficient demand.
 
-=item bounding_box
+Parameters:
+
+=over
+
+=item *
+
+C<file> - name of the file to load the font from.
+
+=item *
+
+=for stopwords GDI
+
+C<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 *
+
+C<type> - font driver to use.  Currently the permitted values for this are:
+
+=over
+
+=item *
+
+C<tt> - FreeType 1.x driver.  Supports TrueType (C<.ttf>) fonts.
+
+=item *
+
+=for stopwords strikethrough overline
+
+C<t1> - T1 Lib driver.  Supports Postscript Type 1 fonts.  Allows for
+synthesis of underline, strikethrough and overline.
+
+=item *
+
+C<ft2> - FreeType 2.x driver.  Supports many different font formats.
+Also supports the transform() method.
+
+=back
+
+=item *
+
+C<color> - the default color used with this font.  Default: red.
+
+=item *
+
+C<size> - the default size used with this font.  Default: 15.
+
+=item *
+
+C<utf8> - if non-zero then text supplied to $img->string(...) and
+$font->bounding_box(...) is assumed to be UTF-8 encoded by default.
+
+=item *
+
+C<align> - the default value for the $img->string(...) C<align>
+parameter.  Default: 1.
+
+=item *
+
+C<vlayout> - the default value for the $img->string(...) C<vlayout>
+parameter.  Default: 0.
+
+=item *
+
+C<aa> - the default value for the $im->string(...) C<aa> parameter.
+Default: 0.
+
+=item *
+
+C<index> - for font file containing multiple fonts this selects which
+font to use.  This is useful for Macintosh C<DFON> (F<.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
+
+Returns the new font object on success. Returns C<undef> on failure
+and sets an error message readable with C<< Imager->errstr >>.
+
+=item bounding_box()
 
 Returns the bounding box for the specified string.  Example:
 
@@ -479,112 +621,75 @@ the space needed for the string:
 
   @metrics = $font->bounding_box(string=>"testing",size=>15,canon=>1);
 
-This returns tha same values in $metrics[0] and $metrics[1],
+This returns the same values in $metrics[0] and $metrics[1],
 but:
 
  $bbox[2] - horizontal space taken by glyphs
  $bbox[3] - vertical space taken by glyphs
 
 Returns an L<Imager::Font::BBox> object in scalar context, so you can
-avoid all those confusing indices.  This has methods as named above,
+avoid all those confusing indexes.  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
+=item *
 
-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 first character.
+C<string> - the string to calculate the bounding box for.  Required.
 
-=item channel
+=item *
 
-If present, the text will be written to the specified channel of the
-image and the color parameter will be ignore.
+C<size> - the font size to use.  Default: value set in
+Imager::Font->new(), or 15.
 
-=item color
+=item *
 
-The color to draw the text in.
+C<sizew> - the font width to use.  Default to the value of the C<size>
+parameter.
 
-=item size
+=item *
 
-The point-size to draw the text at.
+C<utf8> - For drivers that support it, treat the string as UTF-8 encoded.
+For versions of perl that support Unicode (5.6 and later), this will
+be enabled automatically if the 'string' parameter is already a UTF-8
+string. See L</UTF-8> for more information.  Default: the C<utf8> value
+passed to Imager::Font->new(...) or 0.
 
-=item sizew
+=item *
 
-For drivers that support it, the width to draw the text at.  Defaults
-to be value of the 'size' parameter.
+C<x>, C<y> - offsets applied to @box[0..3] to give you a adjusted bounding
+box.  Ignored in scalar context.
 
-=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.
+C<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.
 
-=item vlayout
+=back
 
-For drivers that support it, draw the text vertically.  Note: I
-haven't found a font that has the appropriate metrics yet.
+On success returns either the list of bounds, or a bounding box object
+in scalar context.  Returns an empty list or C<undef> on failure and
+sets an error message readable with C<< Imager->errstr >>.
 
-=back
+The transformation matrix set by L</transform()> has no effect on the
+result of this method - the bounds of the untransformed text is
+returned.
 
-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=>...)
+=item align(string=>$text,size=>$size,x=>...,y=>...,valign => ...,halign=>...)
 
 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', 
@@ -595,66 +700,69 @@ parameters:
 
 =over
 
-=item valign
+=item *
 
-Possible values are:
+C<valign> - Possible values are:
 
 =over
 
-=item top
+=item C<top>
 
 Point is at the top of the text.
 
-=item bottom
+=item C<bottom>
 
 Point is at the bottom of the text.
 
-=item baseline
+=item C<baseline>
 
 Point is on the baseline of the text (default.)
 
-=item center
+=item C<center>
 
 Point is vertically centered within the text.
 
 =back
 
-=item halign
+=item *
+
+C<halign>
 
 =over
 
-=item left
+=item *
 
-The point is at the left of the text.
+C<left> - the point is at the left of the text.
 
-=item start
+=item *
 
-The point is at the start point of the text.
+C<start> - the point is at the start point of the text.
 
-=item center
+=item *
 
-The point is horizontally centered within the text.
+C<center> - the point is horizontally centered within the text.
 
-=item right
+=item *
 
-The point is at the right end of the text.
+C<right> - the point is at the right end of the text.
 
-=item end
+=item *
 
-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).
+C<end> - the point is at the end point of the text.
 
 =back
 
-=item image
+=item *
 
-The image to draw to.  Set to C<undef> to avoid drawing but still
-calculate the bounding box.
+C<image> - The image to draw to.  Set to C<undef> to avoid drawing but
+still calculate the bounding box.
 
 =back
 
-Returns a list specifying the bounds of the drawn text.
+Returns a list specifying the bounds of the drawn text on success.
+Returns an empty list on failure, if an C<image> parameter was
+supplied the error message can be read with C<< $image->errstr >>,
+otherwise it's available as C<< Imager->errstr >>.
 
 =item dpi()
 
@@ -662,12 +770,33 @@ 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.
 
-=item transform(matrix=>$matrix)
+Possible parameters are:
+
+=over
+
+=item *
+
+C<xdpi>, C<ydpi> - set the horizontal and vertical resolution in dots
+per inch.
+
+=item *
+
+C<dpi> - set both horizontal and vertical resolution to this value.
+
+=back
+
+Returns a list containing the previous C<xdpi>, C<ydpi> values on
+success.  Returns an empty list on failure, with an error message
+returned in C<< Imager->errstr >>.
+
+=item transform()
+
+  $font->transform(matrix=>$matrix);
 
 Applies a transformation to the font, where matrix is an array ref of
 numbers representing a 2 x 3 matrix:
@@ -681,38 +810,57 @@ It's possible that a driver will disable hinting if you use a
 transformation, to prevent discontinuities in the transformations.
 See the end of the test script t/t38ft2font.t for an example.
 
-Currently only the ft2 (Freetype 2.x) driver supports the transform()
+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.
+
+C<transform()> has no effect on the results of L</bounding_box()>.
+
+Returns true on success.  Returns false on failure with the cause
+readable from C<< Imager->errstr >>.
+
 =item has_chars(string=>$text)
 
 Checks if the characters in $text are defined by the font.
 
 In a list context returns a list of true or false value corresponding
 to the characters in $text, true if the character is defined, false if
-not.  In scalar context returns a string of NUL or non-NUL
-characters.  Supports UTF8 where the font driver supports UTF8.
+not.  In scalar context returns a string of C<NUL> or non-C<NUL>
+characters.  Supports UTF-8 where the font driver supports UTF-8.
 
 Not all fonts support this method (use $font->can("has_chars") to
 check.)
 
-=item logo
+On error, returns an empty list or undef in scalar context, and sets
+an error message readable with C<< Imager->errstr >>.
+
+=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:
+C<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:
+C<utf8> - For drivers that support it, treat the string as UTF-8
+encoded.  For versions of perl that support Unicode (5.6 and later),
+this will be enabled automatically if the 'string' parameter is
+already a UTF-8 string. See L</UTF-8> 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()
 
 Returns the internal name of the face.  Not all font types support
-this method yet.
+this method yet, so you should check with C<< $font->can("face_name")
+>> before calling C<face_name>.
 
 =item glyph_names(string=>$string [, utf8=>$utf8 ][, reliable_only=>0 ] );
 
@@ -720,25 +868,43 @@ Returns a list of glyph names for each of the characters in the
 string.  If the character has no name then C<undef> is returned for
 the character.
 
-Some font files do not include glyph names, in this case Freetype 2
-will not return any names.  Freetype 1 can return standard names even
+Some font files do not include glyph names, in this case FreeType 2
+will not return any names.  FreeType 1 can return standard names even
 if there are no glyph names in the font.
 
-Freetype 2 has an API function that returns true only if the font has
+FreeType 2 has an API function that returns true only if the font has
 "reliable glyph names", unfortunately this always returns false for
-TTF fonts.  This can avoid the check of this API by supplying
+TrueType fonts.  This can avoid the check of this API by supplying
 C<reliable_only> as 0.  The consequences of using this on an unknown
-font may be unpredictable, since the Freetype documentation doesn't
+font may be unpredictable, since the FreeType documentation doesn't
 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
+Both FreeType 1.x and 2.x allow support for glyph names to not be
 included.
 
+If the supplied C<string> is marked as UTF-8 or the C<utf8> parameter
+is true and the supplied string does not contain valid UTF-8, returns
+an empty string and set an error message readable from C<<
+Imager->errstr >>,
+
+=item can_glyph_names()
+
+As a class method, returns true if the underlying library supports
+returning glyph names.
+
+As an object method, returns true if the supplied font supports
+returning glyph names.
+
+=item draw
+
+This is used by Imager's string() method to implement drawing text.
+See L<Imager::Draw/string()>.
+
 =back
 
 =head1 MULTIPLE MASTER FONTS
 
-The Freetype 2 driver supports multiple master fonts:
+The FreeType 2 driver supports multiple master fonts:
 
 =over
 
@@ -784,7 +950,7 @@ It's possible other drivers will support multiple master fonts in the
 future, check if your selected font object supports the is_mm() method
 using the can() method.
 
-=head1 UTF8
+=head1 UTF-8
 
 There are 2 ways of rendering Unicode characters with Imager:
 
@@ -792,48 +958,58 @@ There are 2 ways of rendering Unicode characters with Imager:
 
 =item *
 
-For versions of perl that support it, use perl's native UTF8 strings.
+For versions of perl that support it, use perl's native UTF-8 strings.
 This is the simplest method.
 
 =item *
 
-Hand build your own UTF8 encoded strings.  Only recommended if your
-version of perl has no UTF8 support.
+Hand build your own UTF-8 encoded strings.  Only recommended if your
+version of perl has no UTF-8 support.
 
 =back
 
 Imager won't construct characters for you, so if want to output
-unicode character 00C3 "LATIN CAPITAL LETTER A WITH DIAERESIS", and
+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".
 
-=head2 Native UTF8 Support
+To check if a driver supports UTF-8 call the utf8() method:
+
+=over
+
+=item utf8()
+
+Return true if the font supports UTF-8.
 
-If your version of perl supports UTF8 and the driver supports UTF8,
+=back
+
+=head2 Native UTF-8 Support
+
+If your version of perl supports UTF-8 and the driver supports UTF-8,
 just use the $im->string() method, and it should do the right thing.
 
 =head2 Build your own
 
-In this case you need to build your own UTF8 encoded characters.
+In this case you need to build your own UTF-8 encoded characters.
 
 For example:
 
  $x = pack("C*", 0xE2, 0x80, 0x90); # character code 0x2010 HYPHEN
 
-You need to be be careful with versions of perl that have UTF8
-support, since your string may end up doubly UTF8 encoded.
+You need to be careful with versions of perl that have UTF-8
+support, since your string may end up doubly UTF-8 encoded.
 
 For example:
 
  $x = "A\xE2\x80\x90\x41\x{2010}";
  substr($x, -1, 0) = ""; 
- # at this point $x is has the UTF8 flag set, but has 5 characters,
- # none, of which is the constructed UTF8 character
+ # at this point $x is has the UTF-8 flag set, but has 5 characters,
+ # none, of which is the constructed UTF-8 character
 
-The test script t/t38ft2font.t has a small example of this after the 
+The test script t/t38ft2font.t has a small example of this after the
 comment:
 
-  # an attempt using emulation of UTF8
+  # an attempt using emulation of UTF-8
 
 =head1 DRIVER CONTROL
 
@@ -845,7 +1021,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();
 
@@ -856,22 +1036,66 @@ You can set new priorities and save the old priorities with:
 If you supply driver names that are not currently supported, they will
 be ignored.
 
-Imager supports both T1Lib and Freetype2 for working with Type 1
+Imager supports both T1Lib and FreeType 2 for working with Type 1
 fonts, but currently only T1Lib does any caching, so by default T1Lib
-is given a higher priority.  Since Imager's Freetype2 support can also
+is given a higher priority.  Since Imager's FreeType 2 support can also
 do font transformations, you may want to give that a higher priority:
 
   my @old = Imager::Font->priorities(qw(tt ft2 t1));
 
+=item register
+
+Registers an extra font driver.  Accepts the following parameters:
+
+=over
+
+=item *
+
+type - a brief identifier for the font driver.  You can supply this
+value to C<< Imager::Font->new() >> to create fonts of this type.
+Required.
+
+=item *
+
+class - the font class name.  Imager will attempted to load this
+module by name.  Required.
+
+=item *
+
+files - a regular expression to match against file names.  If supplied
+this must be a valid perl regular expression.  If not supplied you can
+only create fonts of this type by supplying the C<type> parameter to
+C<< Imager::Font->new() >>
+
+=item *
+
+description - a brief description of the font driver.  Defaults to the
+value supplied in C<class>.
+
+=back
+
+=back
+
 =head1 AUTHOR
 
 Arnar M. Hrafnkelsson, addi@umich.edu
-And a great deal of help from others - see the README for a complete
+And a great deal of help from others - see the F<README> for a complete
 list.
 
 =head1 BUGS
 
-You need to modify this class to add new font types.
+The $pos_width member returned by the bounding_box() method has
+historically returned different values from different drivers.  The
+FreeType 1.x and 2.x, and the Win32 drivers return the max of the
+advance width and the right edge of the right-most glyph.  The Type 1
+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