]> 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 fab3e474883a44d2b7afe5eb24f11f63633314df..66a4b7e44d6cc040cb0780713625ff34e06b05cb 100644 (file)
@@ -2,11 +2,52 @@ package Imager::Font;
 
 use Imager::Color;
 use strict;
-use File::Spec;
-
-# This class is a container
-# and works for both truetype and t1 fonts.
-
+use vars qw($VERSION);
+
+$VERSION = "1.033";
+
+# the aim here is that we can:
+#  - add file based types in one place: here
+#  - make sure we only attempt to create types that exist
+#  - give reasonable defaults
+#  - give the user some control over which types get used
+my %drivers =
+  (
+   tt=>{
+        class=>'Imager::Font::Truetype',
+        module=>'Imager/Font/Truetype.pm',
+        files=>'.*\.ttf$',
+       },
+   t1=>{
+        class=>'Imager::Font::Type1',
+        module=>'Imager/Font/Type1.pm',
+        files=>'.*\.pfb$',
+       },
+   ft2=>{
+         class=>'Imager::Font::FreeType2',
+         module=>'Imager/Font/FreeType2.pm',
+         files=>'.*\.(pfa|pfb|otf|ttf|fon|fnt|dfont|pcf(\.gz)?)$',
+        },
+   ifs=>{
+         class=>'Imager::Font::Image',
+         module=>'Imager/Font/Image.pm',
+         files=>'.*\.ifs$',
+        },
+   w32=>{
+         class=>'Imager::Font::Win32',
+         module=>'Imager/Font/Win32.pm',
+        },
+  );
+
+# 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
@@ -16,58 +57,55 @@ use File::Spec;
 
 sub new {
   my $class = shift;
-  my $self ={};
-  my ($file,$type,$id);
-  my %hsh=(color=>Imager::Color->new(255,0,0,0),
-          size=>15,
+  my $self = {};
+  my ($file, $type, $id);
+  my %hsh=(color => Imager::Color->new(255,0,0,0),
+          size => 15,
           @_);
 
   bless $self,$class;
 
-  if ($hsh{'file'}) { 
-    $file=$hsh{'file'};
+  if ($hsh{'file'}) {
+    $file = $hsh{'file'};
     if ( $file !~ m/^\// ) {
-      $file='./'.$file;
+      $file = './'.$file;
       if (! -e $file) {
-       $Imager::ERRSTR="Font $file not found";
+       $Imager::ERRSTR = "Font $file not found";
        return();
       }
     }
 
-    $type=$hsh{'type'};
-    if (!defined($type) or $type !~ m/^(t1|tt)/) {
-      $type='tt' if $file =~ m/\.ttf$/i;
-      $type='t1' if $file =~ m/\.pfb$/i;
+    $type = $hsh{'type'};
+    if (!defined($type) or !$drivers{$type}) {
+      for my $drv (@priority) {
+        undef $type;
+        my $re = $drivers{$drv}{files} or next;
+        if ($file =~ /$re/i) {
+          $type = $drv;
+          last;
+        }
+      }
     }
     if (!defined($type)) {
-      $Imager::ERRSTR="Font type not found";
+      $Imager::ERRSTR = "Font type not found";
       return;
     }
+  } elsif ($hsh{face}) {
+    $type = "w32";
   } else {
     $Imager::ERRSTR="No font file specified";
     return;
   }
 
-  if (!$Imager::formats{$type}) { 
-    $Imager::ERRSTR="`$type' not enabled";
+  if (!$Imager::formats{$type}) {
+    $Imager::ERRSTR = "`$type' not enabled";
     return;
   }
 
   # here we should have the font type or be dead already.
 
-  if ($type eq 't1') {
-    require 'Imager/Font/Type1.pm';
-    return Imager::Font::Type1->new(%hsh);
-  }
-
-  if ($type eq 'tt') {
-    require 'Imager/Font/Truetype.pm';
-    return Imager::Font::Truetype->new(%hsh);
-  }
-  # it would be nice to have some generic mechanism to select the
-  # class
-  
-  return undef;
+  require $drivers{$type}{module};
+  return $drivers{$type}{class}->new(%hsh);
 }
 
 # returns first defined parameter
@@ -80,27 +118,111 @@ sub _first {
 
 sub draw {
   my $self = shift;
-  my %input = (x => 0, 'y' => 0, @_);
+  my %input = ('x' => 0, 'y' => 0, @_);
   unless ($input{image}) {
     $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 require parameter 'string'";
+    $image->_set_error("Missing required parameter 'string'");
     return;
   }
   $input{aa} = _first($input{aa}, $input{antialias}, $self->{aa}, 1);
   # the original draw code worked this out but didn't use it
   $input{align} = _first($input{align}, $self->{align});
   $input{color} = _first($input{color}, $self->{color});
+  $input{color} = Imager::_color($input{'color'});
+
   $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);
-  $self->_draw(%input);
+  $input{utf8} = _first($input{utf8}, $self->{utf8}, 0);
+  $input{vlayout} = _first($input{vlayout}, $self->{vlayout}, 0);
+
+  my $result = $self->_draw(%input);
+  unless ($result) {
+    $image->_set_error($image->_error_as_msg());
+  }
+
+  return $result;
+}
+
+sub align {
+  my $self = shift;
+  my %input = ( halign => 'left', valign => 'baseline', 
+                'x' => 0, 'y' => 0, @_ );
+
+  # 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);
+
+  my $bbox = $self->bounding_box(string=>$text, size=>$size, utf8=>$utf8);
+  my $valign = $input{valign};
+  $valign = 'baseline'
+    unless $valign && $valign =~ /^(?:top|center|bottom|baseline)$/;
+
+  my $halign = $input{halign};
+  $halign = 'start' 
+    unless $halign && $halign =~ /^(?:left|start|center|end|right)$/;
+
+  my $x = $input{'x'};
+  my $y = $input{'y'};
+
+  if ($valign eq 'top') {
+    $y += $bbox->ascent;
+  }
+  elsif ($valign eq 'center') {
+    $y += $bbox->ascent - $bbox->text_height / 2;
+  }
+  elsif ($valign eq 'bottom') {
+    $y += $bbox->descent;
+  }
+  # else baseline is the default
+
+  if ($halign eq 'left') {
+    $x -= $bbox->start_offset;
+  }
+  elsif ($halign eq 'start') {
+    # nothing to do
+  }
+  elsif ($halign eq 'center') {
+    $x -= $bbox->start_offset + $bbox->total_width / 2;
+  }
+  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);
+
+  if ($input{image}) {
+    delete @input{qw/x y/};
+    $self->draw(%input, 'x' => $x, 'y' => $y, align=>1)
+      or return;
+  }
+
+  return ($x+$bbox->start_offset, $y-$bbox->ascent, 
+          $x+$bbox->end_offset, $y-$bbox->descent+1);
 }
 
 sub bounding_box {
@@ -112,20 +234,78 @@ sub bounding_box {
     return;
   }
   $input{size} ||= $self->{size};
+  $input{sizew} = _first($input{sizew}, $self->{sizew}, 0);
+  $input{utf8} = _first($input{utf8}, $self->{utf8}, 0);
 
   my @box = $self->_bounding_box(%input);
 
-  if(exists $input{'x'} and exists $input{'y'}) {
-    my($gdescent, $gascent)=@box[1,3];
-    $box[1]=$input{'y'}-$gascent;      # top = base - ascent (Y is down)
-    $box[3]=$input{'y'}-$gdescent;     # bottom = base - descent (Y is down, descent is negative)
-    $box[0]+=$input{'x'};
-    $box[2]+=$input{'x'};
-  } elsif (exists $input{'canon'}) {
-    $box[3]-=$box[1];    # make it cannoical (ie (0,0) - (width, height))
-    $box[2]-=$box[0];
+  if (wantarray) {
+    if(@box && exists $input{'x'} and exists $input{'y'}) {
+      my($gdescent, $gascent)=@box[1,3];
+      $box[1]=$input{'y'}-$gascent;      # top = base - ascent (Y is down)
+      $box[3]=$input{'y'}-$gdescent;     # bottom = base - descent (Y is down, descent is negative)
+      $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[2]-=$box[0];
+    }
+    return @box;
+  }
+  else {
+    require Imager::Font::BBox;
+
+    return Imager::Font::BBox->new(@box);
+  }
+}
+
+sub dpi {
+  my $self = shift;
+
+  # I'm assuming a default of 72 dpi
+  my @old = (72, 72);
+  if (@_) {
+    $Imager::ERRSTR = "Setting dpi not implemented for this font type";
+    return;
+  }
+
+  return @old;
+}
+
+sub transform {
+  my $self = shift;
+
+  my %hsh = @_;
+
+  # this is split into transform() and _transform() so we can 
+  # implement other tags like: degrees=>12, which would build a
+  # 12 degree rotation matrix
+  # but I'll do that later
+  unless ($hsh{matrix}) {
+    $Imager::ERRSTR = "You need to supply a matrix";
+    return;
+  }
+
+  return $self->_transform(%hsh);
+}
+
+sub _transform {
+  $Imager::ERRSTR = "This type of font cannot be transformed";
+  return;
+}
+
+sub utf8 {
+  return 0;
+}
+
+sub priorities {
+  my $self = shift;
+  my @old = @priority;
+
+  if (@_) {
+    @priority = grep Imager::i_has_format($_), @_;
   }
-  return @box;
+  return @old;
 }
 
 1;
@@ -140,6 +320,7 @@ Imager::Font - Font handling for Imager.
 
   $t1font = Imager::Font->new(file => 'pathtofont.pfb');
   $ttfont = Imager::Font->new(file => 'pathtofont.ttf');
+  $w32font = Imager::Font->new(face => 'Times New Roman');
 
   $blue = Imager::Color->new("#0000FF");
   $font = Imager::Font->new(file  => 'pathtofont.ttf',
@@ -151,25 +332,21 @@ Imager::Font - Font handling for Imager.
    $pos_width,
    $global_ascent,
    $descent,
-   $ascent) = $font->bounding_box(string=>"Foo");
-
-  $logo = $font->logo(text   => "Slartibartfast Enterprises",
-                     size   => 40,
-                     border => 5,
-                     color  => $green);
-  # logo is proposed - doesn't exist yet
+   $ascent,
+   $advance_width,
+   $right_bearing) = $font->bounding_box(string=>"Foo");
 
+  my $bbox_object = $font->bounding_box(string=>"Foo");
 
+  # documented in Imager::Draw
   $img->string(font  => $font,
             text  => "Model-XYZ",
             x     => 15,
             y     => 40,
             size  => 40,
-            color => $red
+            color => $red,
             aa    => 1);
 
-  # Documentation in Imager.pm
-
 =head1 DESCRIPTION
 
 This module handles creating Font objects used by imager.  The module
@@ -182,7 +359,8 @@ this:
   use Imager;
   print "Has truetype"      if $Imager::formats{tt};
   print "Has t1 postscript" if $Imager::formats{t1};
-
+  print "Has Win32 fonts"   if $Imager::formats{w32};
+  print "Has Freetype2"     if $Imager::formats{ft2};
 
 =over 4
 
@@ -191,6 +369,7 @@ this:
 This creates a font object to pass to functions that take a font argument.
 
   $font = Imager::Font->new(file  => 'denmark.ttf',
+                            index => 0,
                            color => $blue,
                            size  => 30,
                            aa    => 1);
@@ -206,35 +385,165 @@ 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.
+
 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:
 
-
   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:
+
+  $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.
+
+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:
 
-  ($neg_width,
-   $global_descent,
-   $pos_width,
-   $global_ascent,
-   $descent,
-   $ascent) = $font->bounding_box(string => "A Fool");
+  my ($neg_width,
+      $global_descent,
+      $pos_width,
+      $global_ascent,
+      $descent,
+      $ascent,
+      $advance_width,
+      $right_bearing) = $font->bounding_box(string => "A Fool");
+
+  my $bbox_object = $font->bounding_box(string => "A Fool");
+
+=over
 
-The C<$neg_width> is the relative start of a the string.  In some
+=item C<$neg_width>
+
+the relative start of a the string.  In some
 cases this can be a negative number, in that case the first letter
 stretches to the left of the starting position that is specified in
-the string method of the Imager class.  <$global_descent> is the how
-far down the lowest letter of the entire font reaches below the
-baseline (this is often j).  C<$pos_width> is how wide the string from
-from the starting position is.  The total width of the string is
-C<$pos_width-$neg_width>.  C<$descent> and C<$ascent> are the as
-<$global_descent> and <$global_ascent> except that they are only for
-the characters that appear in the string.  Obviously we can stuff all
-the results into an array just as well:
+the string method of the Imager class
+
+=item C<$global_descent> 
+
+how far down the lowest letter of the entire font reaches below the
+baseline (this is often j).
+
+=item C<$pos_width>
+
+how wide the string from
+the starting position is.  The total width of the string is
+C<$pos_width-$neg_width>.
+
+=item C<$descent> 
+
+=item C<$ascent> 
+
+the same as <$global_descent> and <$global_ascent> except that they
+are only for the characters that appear in the string.
+
+=item C<$advance_width>
+
+the distance from the start point that the next string output should
+start at, this is often the same as C<$pos_width>, but can be
+different if the final character overlaps the right side of its
+character cell.
+
+=item C<$right_bearing>
+
+The distance from the right side of the final glyph to the end of the
+advance width.  If the final glyph overflows the advance width this
+value is negative.
+
+=back
+
+Obviously we can stuff all the results into an array just as well:
 
   @metrics = $font->bounding_box(string => "testing 123");
 
@@ -256,59 +565,385 @@ 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,
+with some extra convenience methods.
+
+Parameters are:
+
+=over
+
+=item *
+
+string - the string to calculate the bounding box for.  Required.
+
+=item *
+
+size - the font size to use.  Default: value set in
+Imager::Font->new(), or 15.
+
+=item *
+
+sizew - the font width to use.  Default to the value of the C<size>
+parameter.
 
+=item *
+
+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 *
+
+x, y - offsets applied to @box[0..3] to give you a adjusted bounding
+box.  Ignored in scalar context.
+
+=item *
+
+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
 
 =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:
+The $img->string(...) method is now documented in
+L<Imager::Draw/string>
+
+=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, $right, $bottom) = 
+    $font->align(string=>"Hello",
+                 x=>100, y=>100, 
+                 halign=>'center', valign=>'center', 
+                 image=>$image);
+
+Takes the same parameters as $font->draw(), and the following extra
+parameters:
+
+=over
+
+=item valign
+
+Possible values are:
+
+=over
+
+=item top
+
+Point is at the top of the text.
+
+=item bottom
+
+Point is at the bottom of the text.
+
+=item baseline
+
+Point is on the baseline of the text (default.)
+
+=item center
+
+Point is vertically centered within the text.
+
+=back
+
+=item halign
+
+=over
+
+=item left
+
+The point is at the left of the text.
+
+=item start
+
+The point is at the start point of the text.
+
+=item center
+
+The point is horizontally centered within the text.
+
+=item right
+
+The point is at the right end of the text.
+
+=item end
 
-  $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");
+The point is at the end point of the text.
 
-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.
+=back
+
+=item 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.
+
+=item dpi()
+
+=item dpi(xdpi=>$xdpi, ydpi=>$ydpi)
+
+=item dpi(dpi=>$dpi)
+
+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
+numbers representing a 2 x 3 matrix:
+
+  [  $matrix->[0],  $matrix->[1],  $matrix->[2],
+     $matrix->[3],  $matrix->[4],  $matrix->[5]   ]
+
+Not all font types support transformations, these will return false.
+
+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()
+method.
+
+See samples/slant_text.pl for a sample using this function.
 
-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.
+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.
 
-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.
+=item has_chars(string=>$text)
 
+Checks if the characters in $text are defined by the font.
 
-=item logo
+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.
 
-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:
+Not all fonts support this method (use $font->can("has_chars") to
+check.)
 
-  $img = $font->logo(string=>"Plan XYZ", color=>$blue, border=>7);
+=over
 
-This would be nice for writing (admittedly multiline) one liners like:
+=item *
 
-Imager::Font->new(file=>"arial.ttf", color=>$blue, aa=>1)
-            ->string(text=>"Plan XYZ", border=>5)
-            ->write(file=>"xyz.png");
+string - string of characters to check for.  Required.  Must contain
+at least one character.
 
+=item *
 
+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.
 
 =back
 
+=item face_name()
+
+Returns the internal name of the face.  Not all font types support
+this method yet.
+
+=item glyph_names(string=>$string [, utf8=>$utf8 ][, reliable_only=>0 ] );
+
+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
+if there are no glyph names in the font.
+
+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
+C<reliable_only> as 0.  The consequences of using this on an unknown
+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
+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
+
+The Freetype 2 driver supports multiple master fonts:
+
+=over
+
+=item is_mm()
+
+Test if the font is a multiple master font.
+
+=item mm_axes()
+
+Returns a list of the axes that can be changes in the font.  Each
+entry is an array reference which contains:
+
+=over
+
+=item 1.
+
+Name of the axis.
+
+=item 2.
+
+minimum value for this axis.
+
+=item 3.
+
+maximum value for this axis
+
+=back
+
+=item set_mm_coords(coords=>\@values)
+
+Blends an interpolated design from the master fonts.  @values must
+contain as many values as there are axes in the font.
+
+=back
+
+For example, to select the minimum value in each axis:
+
+  my @axes = $font->mm_axes;
+  my @coords = map $_->[1], @axes;
+  $font->set_mm_coords(coords=>\@coords);
+
+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
+
+There are 2 ways of rendering Unicode characters with Imager:
+
+=over
+
+=item *
+
+For versions of perl that support it, use perl's native UTF8 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.
+
+=back
+
+Imager won't construct characters for you, so if want to output
+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,
+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.
+
+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.
+
+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
+
+The test script t/t38ft2font.t has a small example of this after the 
+comment:
+
+  # an attempt using emulation of UTF8
+
+=head1 DRIVER CONTROL
+
+If you don't supply a 'type' parameter to Imager::Font->new(), but you
+do supply a 'file' parameter, Imager will attempt to guess which font
+driver to used based on the extension of the font file.
+
+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.
+
+=over
+
+=item priorities
+
+The current priorities can be retrieved with:
+
+  @drivers = Imager::Font->priorities();
+
+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.
+
+Imager supports both T1Lib and Freetype2 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
+do font transformations, you may want to give that a higher priority:
+
+  my @old = Imager::Font->priorities(qw(tt ft2 t1));
+
 =head1 AUTHOR
 
 Arnar M. Hrafnkelsson, addi@umich.edu
@@ -319,10 +954,25 @@ list.
 
 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
 
-Imager(3)
-http://www.eecs.umich.edu/~addi/perl/Imager/
+Imager(3), Imager::Font::FreeType2(3), Imager::Font::Type1(3),
+Imager::Font::Win32(3), Imager::Font::Truetype(3), Imager::Font::BBox(3)
+
+ http://imager.perl.org/
 
 =cut