]> git.imager.perl.org - imager.git/blob - lib/Imager/Font/FreeType2.pm
beac6372b402efa8e391c6ac27656d93d5e8a28c
[imager.git] / lib / Imager / Font / FreeType2.pm
1 package Imager::Font::FreeType2;
2 use strict;
3 use Imager::Color;
4 use vars qw(@ISA $VERSION);
5 @ISA = qw(Imager::Font);
6
7 $VERSION = "1.014";
8
9 *_first = \&Imager::Font::_first;
10
11 sub new {
12   my $class = shift;
13   my %hsh=(color=>Imager::Color->new(255,0,0,0),
14            size=>15,
15            @_);
16
17   unless ($hsh{file}) {
18     $Imager::ERRSTR = "No font file specified";
19     return;
20   }
21   unless (-e $hsh{file}) {
22     $Imager::ERRSTR = "Font file $hsh{file} not found";
23     return;
24   }
25   unless ($Imager::formats{ft2}) {
26     $Imager::ERRSTR = "Freetype2 not supported in this build";
27     return;
28   }
29   my $id = i_ft2_new($hsh{file}, $hsh{'index'} || 0);
30   unless ($id) { # the low-level code may miss some error handling
31     $Imager::ERRSTR = Imager::_error_as_msg();
32     return;
33   }
34   return bless {
35                 id       => $id,
36                 aa       => $hsh{aa} || 0,
37                 file     => $hsh{file},
38                 type     => 't1',
39                 size     => $hsh{size},
40                 color    => $hsh{color},
41                 utf8     => $hsh{utf8},
42                 vlayout  => $hsh{vlayout},
43                }, $class;
44 }
45
46 sub _draw {
47   my $self = shift;
48   my %input = @_;
49   if (exists $input{channel}) {
50     i_ft2_cp($self->{id}, $input{image}{IMG}, $input{'x'}, $input{'y'},
51              $input{channel}, $input{size}, $input{sizew} || 0,
52              $input{string}, , $input{align}, $input{aa}, $input{vlayout},
53              $input{utf8});
54   } else {
55     i_ft2_text($self->{id}, $input{image}{IMG},
56                $input{'x'}, $input{'y'},
57                $input{color}, $input{size}, $input{sizew} || 0,
58                $input{string}, $input{align}, $input{aa}, $input{vlayout},
59                $input{utf8});
60   }
61 }
62
63 sub _bounding_box {
64   my $self = shift;
65   my %input = @_;
66
67   return i_ft2_bbox($self->{id}, $input{size}, $input{sizew}, $input{string}, 
68                     $input{utf8});
69 }
70
71 sub dpi {
72   my $self = shift;
73   my @old = i_ft2_getdpi($self->{id});
74   if (@_) {
75     my %hsh = @_;
76     my $result;
77     unless ($hsh{xdpi} && $hsh{ydpi}) {
78       if ($hsh{dpi}) {
79         $hsh{xdpi} = $hsh{ydpi} = $hsh{dpi};
80       }
81       else {
82         $Imager::ERRSTR = "dpi method requires xdpi and ydpi or just dpi";
83         return;
84       }
85       i_ft2_setdpi($self->{id}, $hsh{xdpi}, $hsh{ydpi}) or return;
86     }
87   }
88   
89   return @old;
90 }
91
92 sub hinting {
93   my ($self, %opts) = @_;
94
95   i_ft2_sethinting($self->{id}, $opts{hinting} || 0);
96 }
97
98 sub _transform {
99   my $self = shift;
100
101   my %hsh = @_;
102   my $matrix = $hsh{matrix} or return undef;
103
104   return i_ft2_settransform($self->{id}, $matrix)
105 }
106
107 sub utf8 {
108   return 1;
109 }
110
111 # check if the font has the characters in the given string
112 sub has_chars {
113   my ($self, %hsh) = @_;
114
115   unless (defined $hsh{string} && length $hsh{string}) {
116     $Imager::ERRSTR = "No string supplied to \$font->has_chars()";
117     return;
118   }
119   return i_ft2_has_chars($self->{id}, $hsh{string}, 
120                          _first($hsh{'utf8'}, $self->{utf8}, 0));
121 }
122
123 sub face_name {
124   my ($self) = @_;
125
126   i_ft2_face_name($self->{id});
127 }
128
129 sub can_glyph_names {
130   i_ft2_can_do_glyph_names();
131 }
132
133 sub glyph_names {
134   my ($self, %input) = @_;
135
136   my $string = $input{string};
137   defined $string
138     or return Imager->_set_error("no string parameter passed to glyph_names");
139   my $utf8 = _first($input{utf8}, 0);
140   my $reliable_only = _first($input{reliable_only}, 1);
141
142   my @names = i_ft2_glyph_name($self->{id}, $string, $utf8, $reliable_only);
143   @names or return Imager->_set_error(Imager->_error_as_msg);
144
145   return @names if wantarray;
146   return pop @names;
147 }
148
149 sub is_mm {
150   my ($self) = @_;
151
152   i_ft2_is_multiple_master($self->{id});
153 }
154
155 sub mm_axes {
156   my ($self) = @_;
157
158   my ($num_axis, $num_design, @axes) =
159     i_ft2_get_multiple_masters($self->{id})
160       or return Imager->_set_error(Imager->_error_as_msg);
161
162   return @axes;
163 }
164
165 sub set_mm_coords {
166   my ($self, %opts) = @_;
167
168   $opts{coords}
169     or return Imager->_set_error("Missing coords parameter");
170   ref($opts{coords}) && $opts{coords} =~ /ARRAY\(0x[\da-f]+\)$/
171     or return Imager->_set_error("coords parameter must be an ARRAY ref");
172
173   i_ft2_set_mm_coords($self->{id}, @{$opts{coords}})
174     or return Imager->_set_error(Imager->_error_as_msg);
175
176   return 1;
177 }
178
179 1;
180
181 __END__
182
183 =head1 NAME
184
185   Imager::Font::FreeType2 - low-level functions for FreeType2 text output
186
187 =head1 DESCRIPTION
188
189 Imager::Font creates a Imager::Font::FreeType2 object when asked to.
190
191 See Imager::Font to see how to use this type.
192
193 This class provides low-level functions that require the caller to
194 perform data validation.
195
196 This driver supports:
197
198 =over
199
200 =item transform()
201
202 =item dpi()
203
204 =item draw()
205
206 The following parameters:
207
208 =over
209
210 =item *
211
212 C<utf8>
213
214 =item *
215
216 C<vlayout>
217
218 =item *
219
220 C<sizew>
221
222 =back
223
224 =back
225
226 =head2 Special behaviors
227
228 If you call transform() to set a transformation matrix, hinting will
229 be switched off.  This prevents sudden jumps in the size of the text
230 caused by the hinting when the transformation is the identity matrix.
231 If for some reason you want hinting enabled, use
232 $font->hinting(hinting=>1) to re-enable hinting.  This will need to be
233 called after I<each> call to transform().
234
235 =head1 AUTHOR
236
237 Addi, Tony
238
239 =cut