use strict;
use vars qw($VERSION);
-$VERSION = "1.033";
+$VERSION = "1.038";
# the aim here is that we can:
# - add file based types in one place: here
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',
},
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;
- for my $driver_name (grep Imager::i_has_format($_), keys %drivers) {
- $drivers{$driver_name}{enabled} = 1;
- }
-}
-
-# 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.
-#
-
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,
@_);
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} or !$drivers{$type}{enabled}) {
+ 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;
+ }
}
}
}
return;
}
- if (!$Imager::formats{$type}) {
+ if ($drivers{$type}{checktype} && !$Imager::formats{$type}) {
$Imager::ERRSTR = "`$type' not enabled";
return;
}
$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'}) {
$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;
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__
=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;
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:
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 *
-file - name of the file to load the font from.
+C<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
+=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 *
-type - font driver to use. Currently the permitted values for this are:
+C<type> - font driver to use. Currently the permitted values for this are:
=over
=item *
-tt - Freetype 1.x driver. Supports TTF fonts.
+C<tt> - FreeType 1.x driver. Supports TrueType (C<.ttf>) fonts.
=item *
-t1 - T1 Lib driver. Supports Postscript Type 1 fonts. Allows for
+=for stopwords strikethrough overline
+
+C<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.
+C<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.
+C<color> - the default color used with this font. Default: red.
=item *
-size - the default size used with this font. Default: 15.
+C<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.
+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 *
-align - the default value for the $img->string(...) C<align>
+C<align> - the default value for the $img->string(...) C<align>
parameter. Default: 1.
=item *
-vlayout - the default value for the $img->string(...) C<vlayout>
+C<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.
+C<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
+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
=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
+=item bounding_box()
Returns the bounding box for the specified string. Example:
@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.
Parameters are:
=item *
-string - the string to calculate the bounding box for. Required.
+C<string> - the string to calculate the bounding box for. Required.
=item *
-size - the font size to use. Default: value set in
+C<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>
+C<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.
+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 UTF8
-string. See L<UTF8> for more information. Default: the C<utf8> value
+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 *
-x, y - offsets applied to @box[0..3] to give you a adjusted bounding
+C<x>, C<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,
+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.
=back
-=item string
+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 >>.
+
+The transformation matrix set by L</transform()> has no effect on the
+result of this method - the bounds of the untransformed text is
+returned.
+
+=item string()
The $img->string(...) method is now documented in
-L<Imager::Draw/string>
+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).
=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 end point of the text.
+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()
=item *
-xdpi, ydpi - set the horizontal and vertical resolution in dots per
-inch.
+C<xdpi>, C<ydpi> - set the horizontal and vertical resolution in dots
+per inch.
=item *
-dpi - set both horizontal and vertical resolution to this value.
+C<dpi> - set both horizontal and vertical resolution to this value.
=back
-Returns a list containing the previous xdpi, ydpi values.
+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(matrix=>$matrix)
+=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:
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.
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.)
+On error, returns an empty list or undef in scalar context, and sets
+an error message readable with C<< Imager->errstr >>.
+
=over
=item *
-string - string of characters to check for. Required. Must contain
+C<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.
+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.
=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 ] );
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>.
+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
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:
=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".
-To check if a driver supports UTF8 call the utf8 method:
+To check if a driver supports UTF-8 call the utf8() method:
=over
-=item utf8
+=item utf8()
-Return true if the font supports UTF8.
+Return true if the font supports UTF-8.
=back
-=head2 Native UTF8 Support
+=head2 Native UTF-8 Support
-If your version of perl supports UTF8 and the driver supports UTF8,
+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
@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
+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
+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.