]>
Commit | Line | Data |
---|---|---|
a556912d TC |
1 | package Imager::Font::T1; |
2 | use strict; | |
3 | use Imager::Color; | |
4 | use vars qw(@ISA $VERSION); | |
5 | @ISA = qw(Imager::Font); | |
1aaae40f | 6 | use Scalar::Util (); |
a556912d TC |
7 | |
8 | BEGIN { | |
08a0751c | 9 | $VERSION = "1.027"; |
a556912d | 10 | |
a5919365 TC |
11 | require XSLoader; |
12 | XSLoader::load('Imager::Font::T1', $VERSION); | |
a556912d TC |
13 | } |
14 | ||
15 | ||
16 | *_first = \&Imager::Font::_first; | |
17 | ||
5cb09ff7 | 18 | my $t1aa = 2; |
d03fd5a4 | 19 | |
a556912d TC |
20 | sub new { |
21 | my $class = shift; | |
61e5a61a | 22 | my %hsh=(color=>Imager::Color->new(255,0,0,255), |
a556912d TC |
23 | size=>15, |
24 | @_); | |
25 | ||
26 | unless ($hsh{file}) { | |
27 | $Imager::ERRSTR = "No font file specified"; | |
28 | return; | |
29 | } | |
30 | unless (-e $hsh{file}) { | |
31 | $Imager::ERRSTR = "Font file $hsh{file} not found"; | |
32 | return; | |
33 | } | |
34 | unless ($Imager::formats{t1}) { | |
35 | $Imager::ERRSTR = "Type 1 fonts not supported in this build"; | |
36 | return; | |
37 | } | |
38 | # we want to avoid T1Lib's file search mechanism | |
39 | unless ($hsh{file} =~ m!^/! | |
40 | || $hsh{file} =~ m!^\.\/?/! | |
43233e13 | 41 | || $^O =~ /^(MSWin32|cygwin)$/ && $hsh{file} =~ /^[a-z]:/i) { |
a556912d TC |
42 | $hsh{file} = './' . $hsh{file}; |
43 | } | |
44 | ||
45 | if($hsh{afm}) { | |
46 | unless (-e $hsh{afm}) { | |
47 | $Imager::ERRSTR = "Afm file $hsh{afm} not found"; | |
48 | return; | |
49 | } | |
50 | unless ($hsh{afm} =~ m!^/! | |
51 | || $hsh{afm} =~ m!^\./! | |
43233e13 | 52 | || $^O =~ /^(MSWin32|cygwin)$/ && $hsh{file} =~ /^[a-z]:/i) { |
a556912d TC |
53 | $hsh{file} = './' . $hsh{file}; |
54 | } | |
55 | } else { | |
56 | $hsh{afm} = 0; | |
57 | } | |
58 | ||
1aaae40f TC |
59 | my $font = Imager::Font::T1xs->new($hsh{file},$hsh{afm}); |
60 | unless ($font) { # the low-level code may miss some error handling | |
73e3ff55 | 61 | Imager->_set_error(Imager->_error_as_msg); |
a556912d TC |
62 | return; |
63 | } | |
64 | return bless { | |
1aaae40f | 65 | t1font => $font, |
a556912d TC |
66 | aa => $hsh{aa} || 0, |
67 | file => $hsh{file}, | |
68 | type => 't1', | |
69 | size => $hsh{size}, | |
70 | color => $hsh{color}, | |
5cb09ff7 | 71 | t1aa => $t1aa, |
a556912d TC |
72 | }, $class; |
73 | } | |
74 | ||
75 | sub _draw { | |
76 | my $self = shift; | |
1aaae40f TC |
77 | |
78 | $self->_valid | |
79 | or return; | |
80 | ||
a556912d | 81 | my %input = @_; |
a556912d TC |
82 | my $flags = ''; |
83 | $flags .= 'u' if $input{underline}; | |
84 | $flags .= 's' if $input{strikethrough}; | |
85 | $flags .= 'o' if $input{overline}; | |
5cb09ff7 | 86 | my $aa = $input{aa} ? $self->{t1aa} : 0; |
a556912d | 87 | if (exists $input{channel}) { |
1aaae40f TC |
88 | $self->{t1font}->cp($input{image}{IMG}, $input{'x'}, $input{'y'}, |
89 | $input{channel}, $input{size}, | |
b3f71a5b | 90 | $input{string}, $input{align}, |
5cb09ff7 TC |
91 | $input{utf8}, $flags, $aa) |
92 | or return; | |
a556912d | 93 | } else { |
1aaae40f TC |
94 | $self->{t1font}->text($input{image}{IMG}, $input{'x'}, $input{'y'}, |
95 | $input{color}, $input{size}, | |
b3f71a5b | 96 | $input{string}, $input{align}, $input{utf8}, $flags, $aa) |
5cb09ff7 | 97 | or return; |
a556912d TC |
98 | } |
99 | ||
100 | return $self; | |
101 | } | |
102 | ||
103 | sub _bounding_box { | |
104 | my $self = shift; | |
1aaae40f TC |
105 | |
106 | $self->_valid | |
107 | or return; | |
108 | ||
a556912d TC |
109 | my %input = @_; |
110 | my $flags = ''; | |
111 | $flags .= 'u' if $input{underline}; | |
112 | $flags .= 's' if $input{strikethrough}; | |
113 | $flags .= 'o' if $input{overline}; | |
932f9afb TC |
114 | my @bbox = $self->{t1font}->bbox($input{size}, $input{string}, |
115 | $input{utf8}, $flags); | |
116 | unless (@bbox) { | |
117 | Imager->_set_error(Imager->_error_as_msg); | |
118 | return; | |
119 | } | |
120 | ||
121 | return @bbox; | |
a556912d TC |
122 | } |
123 | ||
124 | # check if the font has the characters in the given string | |
125 | sub has_chars { | |
126 | my ($self, %hsh) = @_; | |
127 | ||
1aaae40f TC |
128 | $self->_valid |
129 | or return; | |
130 | ||
b3f71a5b | 131 | unless (defined $hsh{string}) { |
a556912d TC |
132 | $Imager::ERRSTR = "No string supplied to \$font->has_chars()"; |
133 | return; | |
134 | } | |
932f9afb TC |
135 | if (wantarray) { |
136 | my @result = $self->{t1font} | |
137 | ->has_chars($hsh{string}, _first($hsh{'utf8'}, $self->{utf8}, 0)); | |
138 | unless (@result) { | |
139 | Imager->_set_error(Imager->_error_as_msg); | |
140 | return; | |
141 | } | |
142 | ||
143 | return @result; | |
144 | } | |
145 | else { | |
146 | my $result = $self->{t1font} | |
147 | ->has_chars($hsh{string}, _first($hsh{'utf8'}, $self->{utf8}, 0)); | |
148 | unless (defined $result) { | |
149 | Imager->_set_error(Imager->_error_as_msg); | |
150 | return; | |
151 | } | |
152 | return $result; | |
153 | } | |
a556912d TC |
154 | } |
155 | ||
156 | sub utf8 { | |
157 | 1; | |
158 | } | |
159 | ||
76ae98a6 TC |
160 | sub can_glyph_names { |
161 | 1; | |
162 | } | |
163 | ||
a556912d TC |
164 | sub face_name { |
165 | my ($self) = @_; | |
166 | ||
1aaae40f TC |
167 | $self->_valid |
168 | or return; | |
169 | ||
170 | return $self->{t1font}->face_name(); | |
a556912d TC |
171 | } |
172 | ||
173 | sub glyph_names { | |
174 | my ($self, %input) = @_; | |
175 | ||
1aaae40f TC |
176 | $self->_valid |
177 | or return; | |
178 | ||
a556912d TC |
179 | my $string = $input{string}; |
180 | defined $string | |
181 | or return Imager->_set_error("no string parameter passed to glyph_names"); | |
182 | my $utf8 = _first($input{utf8} || 0); | |
183 | ||
932f9afb TC |
184 | my @result = $self->{t1font}->glyph_names($string, $utf8); |
185 | unless (@result) { | |
186 | Imager->_set_error(Imager->_error_as_msg); | |
187 | return; | |
188 | } | |
189 | ||
190 | return @result; | |
a556912d TC |
191 | } |
192 | ||
5cb09ff7 TC |
193 | sub set_aa_level { |
194 | my ($self, $new_t1aa) = @_; | |
195 | ||
196 | if (!defined $new_t1aa || | |
197 | ($new_t1aa != 1 && $new_t1aa != 2)) { | |
198 | Imager->_set_error("set_aa_level: parameter must be 1 or 2"); | |
199 | return; | |
200 | } | |
201 | ||
202 | if (ref $self) { | |
203 | $self->_valid | |
204 | or return; | |
205 | ||
206 | $self->{t1aa} = $new_t1aa; | |
207 | } | |
208 | else { | |
209 | $t1aa = $new_t1aa; | |
210 | } | |
211 | ||
212 | return 1; | |
213 | } | |
a556912d | 214 | |
1aaae40f TC |
215 | sub _valid { |
216 | my $self = shift; | |
217 | ||
218 | unless ($self->{t1font} && Scalar::Util::blessed($self->{t1font})) { | |
219 | Imager->_set_error("font object was created in another thread"); | |
220 | return; | |
221 | } | |
222 | ||
223 | return 1; | |
224 | } | |
225 | ||
a556912d TC |
226 | 1; |
227 | ||
228 | __END__ | |
229 | ||
230 | =head1 NAME | |
231 | ||
232 | Imager::Font::Type1 - low-level functions for Type1 fonts | |
233 | ||
234 | =head1 DESCRIPTION | |
235 | ||
ef1a1df1 TC |
236 | =for stopwords Freetype |
237 | ||
a40b0805 TC |
238 | Imager::Font::T1 is deprecated. |
239 | ||
240 | F<T1Lib> is unmaintained and has serious bugs when built on 64-bit | |
241 | systems. Freetype 2 has Type 1 font support and is supported by | |
ef1a1df1 | 242 | Imager via L<Imager::Font::FT2>. |
a40b0805 | 243 | |
ef1a1df1 | 244 | L<Imager::Font> creates a C<Imager::Font::Type1 object> when asked to create |
a556912d TC |
245 | a font object based on a C<.pfb> file. |
246 | ||
247 | See Imager::Font to see how to use this type. | |
248 | ||
249 | This class provides low-level functions that require the caller to | |
250 | perform data validation | |
251 | ||
252 | By default Imager no longer creates the F<t1lib.log> log file. You | |
253 | can re-enable that by calling Imager::init() with the C<t1log> option: | |
254 | ||
255 | Imager::init(t1log=>1); | |
256 | ||
257 | This must be called before creating any fonts. | |
258 | ||
259 | Currently specific to Imager::Font::Type1, you can use the following | |
260 | flags when drawing text or calculating a bounding box: | |
261 | ||
262 | =for stopwords overline strikethrough | |
263 | ||
264 | =over | |
265 | ||
266 | =item * | |
267 | ||
268 | C<underline> - Draw the text with an underline. | |
269 | ||
270 | =item * | |
271 | ||
272 | C<overline> - Draw the text with an overline. | |
273 | ||
274 | =item * | |
275 | ||
276 | C<strikethrough> - Draw the text with a strikethrough. | |
277 | ||
278 | =back | |
279 | ||
280 | Obviously, if you're calculating the bounding box the size of the line | |
281 | is included in the box, and the line isn't drawn :) | |
282 | ||
5cb09ff7 TC |
283 | =head2 Anti-aliasing |
284 | ||
285 | T1Lib supports multiple levels of anti-aliasing, by default, if you | |
286 | request anti-aliased output, Imager::Font::T1 will use the maximum | |
287 | level. | |
288 | ||
289 | You can override this with the set_t1_aa() method: | |
290 | ||
291 | =over | |
292 | ||
293 | =item set_aa_level() | |
294 | ||
295 | Usage: | |
296 | ||
297 | $font->set_aa_level(1); | |
298 | Imager::Font::T1->set_aa_level(2); | |
299 | ||
300 | Sets the T1Lib anti-aliasing level either for the specified font, or | |
301 | for new font objects. | |
302 | ||
303 | The only parameter must be 1 or 2. | |
304 | ||
305 | Returns true on success. | |
306 | ||
307 | =back | |
308 | ||
a556912d TC |
309 | =head1 AUTHOR |
310 | ||
311 | Addi, Tony | |
312 | ||
313 | =cut |