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