fc964e271a74a05f1ea726910387d1dbc13f8e16
[imager.git] / FT2 / FT2.pm
1 package Imager::Font::FT2;
2 use strict;
3 use Imager;
4 use vars qw($VERSION @ISA);
5 @ISA = qw(Imager::Font);
6
7 BEGIN {
8   $VERSION = "0.79";
9
10   eval {
11     require XSLoader;
12     XSLoader::load('Imager::Font::FT2', $VERSION);
13     1;
14   } or do {
15     require DynaLoader;
16     push @ISA, 'DynaLoader';
17     bootstrap Imager::Font::FT2 $VERSION;
18   };
19 }
20
21 *_first = \&Imager::Font::_first;
22
23 sub new {
24   my $class = shift;
25   my %hsh=(color=>Imager::Color->new(255,0,0,0),
26            size=>15,
27            @_);
28
29   unless ($hsh{file}) {
30     $Imager::ERRSTR = "No font file specified";
31     return;
32   }
33   unless (-e $hsh{file}) {
34     $Imager::ERRSTR = "Font file $hsh{file} not found";
35     return;
36   }
37   unless ($Imager::formats{ft2}) {
38     $Imager::ERRSTR = "Freetype2 not supported in this build";
39     return;
40   }
41   my $id = i_ft2_new($hsh{file}, $hsh{'index'} || 0);
42   unless ($id) { # the low-level code may miss some error handling
43     $Imager::ERRSTR = Imager::_error_as_msg();
44     return;
45   }
46   return bless {
47                 id       => $id,
48                 aa       => $hsh{aa} || 0,
49                 file     => $hsh{file},
50                 type     => 't1',
51                 size     => $hsh{size},
52                 color    => $hsh{color},
53                 utf8     => $hsh{utf8},
54                 vlayout  => $hsh{vlayout},
55                }, $class;
56 }
57
58 sub _draw {
59   my $self = shift;
60   my %input = @_;
61   if (exists $input{channel}) {
62     i_ft2_cp($self->{id}, $input{image}{IMG}, $input{'x'}, $input{'y'},
63              $input{channel}, $input{size}, $input{sizew} || 0,
64              $input{string}, , $input{align}, $input{aa}, $input{vlayout},
65              $input{utf8});
66   } else {
67     i_ft2_text($self->{id}, $input{image}{IMG},
68                $input{'x'}, $input{'y'},
69                $input{color}, $input{size}, $input{sizew} || 0,
70                $input{string}, $input{align}, $input{aa}, $input{vlayout},
71                $input{utf8});
72   }
73 }
74
75 sub _bounding_box {
76   my $self = shift;
77   my %input = @_;
78
79   return i_ft2_bbox($self->{id}, $input{size}, $input{sizew}, $input{string}, 
80                     $input{utf8});
81 }
82
83 sub dpi {
84   my $self = shift;
85   my @old = i_ft2_getdpi($self->{id});
86   if (@_) {
87     my %hsh = @_;
88     my $result;
89     unless ($hsh{xdpi} && $hsh{ydpi}) {
90       if ($hsh{dpi}) {
91         $hsh{xdpi} = $hsh{ydpi} = $hsh{dpi};
92       }
93       else {
94         $Imager::ERRSTR = "dpi method requires xdpi and ydpi or just dpi";
95         return;
96       }
97       i_ft2_setdpi($self->{id}, $hsh{xdpi}, $hsh{ydpi}) or return;
98     }
99   }
100   
101   return @old;
102 }
103
104 sub hinting {
105   my ($self, %opts) = @_;
106
107   i_ft2_sethinting($self->{id}, $opts{hinting} || 0);
108 }
109
110 sub _transform {
111   my $self = shift;
112
113   my %hsh = @_;
114   my $matrix = $hsh{matrix} or return undef;
115
116   return i_ft2_settransform($self->{id}, $matrix)
117 }
118
119 sub utf8 {
120   return 1;
121 }
122
123 # check if the font has the characters in the given string
124 sub has_chars {
125   my ($self, %hsh) = @_;
126
127   unless (defined $hsh{string} && length $hsh{string}) {
128     $Imager::ERRSTR = "No string supplied to \$font->has_chars()";
129     return;
130   }
131   return i_ft2_has_chars($self->{id}, $hsh{string}, 
132                          _first($hsh{'utf8'}, $self->{utf8}, 0));
133 }
134
135 sub face_name {
136   my ($self) = @_;
137
138   i_ft2_face_name($self->{id});
139 }
140
141 sub can_glyph_names {
142   i_ft2_can_do_glyph_names();
143 }
144
145 sub glyph_names {
146   my ($self, %input) = @_;
147
148   my $string = $input{string};
149   defined $string
150     or return Imager->_set_error("no string parameter passed to glyph_names");
151   my $utf8 = _first($input{utf8}, 0);
152   my $reliable_only = _first($input{reliable_only}, 1);
153
154   my @names = i_ft2_glyph_name($self->{id}, $string, $utf8, $reliable_only);
155   @names or return Imager->_set_error(Imager->_error_as_msg);
156
157   return @names if wantarray;
158   return pop @names;
159 }
160
161 sub is_mm {
162   my ($self) = @_;
163
164   i_ft2_is_multiple_master($self->{id});
165 }
166
167 sub mm_axes {
168   my ($self) = @_;
169
170   my ($num_axis, $num_design, @axes) =
171     i_ft2_get_multiple_masters($self->{id})
172       or return Imager->_set_error(Imager->_error_as_msg);
173
174   return @axes;
175 }
176
177 sub set_mm_coords {
178   my ($self, %opts) = @_;
179
180   $opts{coords}
181     or return Imager->_set_error("Missing coords parameter");
182   ref($opts{coords}) && $opts{coords} =~ /ARRAY\(0x[\da-f]+\)$/
183     or return Imager->_set_error("coords parameter must be an ARRAY ref");
184
185   i_ft2_set_mm_coords($self->{id}, @{$opts{coords}})
186     or return Imager->_set_error(Imager->_error_as_msg);
187
188   return 1;
189 }
190 1;
191
192 __END__
193
194 =head1 NAME
195
196 Imager::Font::FT2 - font support using FreeType 2
197
198 =head1 SYNOPSIS
199
200   use Imager;
201
202   my $img = Imager->new;
203   my $font = Imager::Font->new(file => "foo.ttf", type => "ft2");
204
205   $img->string(... font => $font);
206
207 =head1 DESCRIPTION
208
209 This provides font support on FreeType 2.
210
211 =head1 CAVEATS
212
213 Unfortunately, older versions of Imager would install
214 C<Imager::Font::FreeType2> even if FreeType 2 wasn't available, and if
215 no font was created would succeed in loading the module.  This means
216 that an existing C<FreeType2.pm> could cause a probe success for
217 supported font files, so I've renamed it.
218
219 =head1 AUTHOR
220
221 Tony Cook <tonyc@cpan.org>
222
223 =head1 SEE ALSO
224
225 Imager, Imager::Font.
226
227 =cut