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