File Coverage

blib/lib/PDF/Builder/Resource/Font/CoreFont.pm
Criterion Covered Total %
statement 63 80 78.7
branch 21 38 55.2
condition 4 4 100.0
subroutine 10 11 90.9
pod 2 3 66.6
total 100 136 73.5


line stmt bran cond sub pod time code
1             package PDF::Builder::Resource::Font::CoreFont;
2              
3 8     8   1167 use base 'PDF::Builder::Resource::Font';
  8         20  
  8         3997  
4              
5 8     8   70 use strict;
  8         21  
  8         192  
6 8     8   38 use warnings;
  8         21  
  8         432  
7             #no warnings qw[ deprecated recursion uninitialized ];
8              
9             our $VERSION = '3.023'; # VERSION
10             our $LAST_UPDATE = '3.021'; # manually update whenever code is changed
11              
12 8     8   53 use File::Basename;
  8         19  
  8         592  
13              
14 8     8   53 use PDF::Builder::Util;
  8         16  
  8         1095  
15 8     8   64 use PDF::Builder::Basic::PDF::Utils;
  8         19  
  8         9392  
16              
17             our $fonts;
18             our $alias;
19             our $subs;
20              
21             =head1 NAME
22              
23             PDF::Builder::Resource::Font::CoreFont - Module for using the 14 PDF built-in Fonts.
24              
25             =head1 SYNOPSIS
26              
27             #
28             use PDF::Builder;
29             #
30             $pdf = PDF::Builder->new();
31             $cft = $pdf->corefont('Times-Roman');
32             #
33              
34             =head1 METHODS
35              
36             =over
37              
38             =item $font = PDF::Builder::Resource::Font::CoreFont->new($pdf, $fontname, %options)
39              
40             =item $font = PDF::Builder::Resource::Font::CoreFont->new($pdf, $fontname)
41              
42             Returns a corefont object.
43              
44             =cut
45              
46             =pod
47              
48             Valid %options are:
49              
50             I<-encode>
51             ... changes the encoding of the font from its default.
52             See I for the supported values. B only single byte
53             encodings are permitted. Multibyte encodings such as 'utf8' are forbidden.
54              
55             I<-pdfname> ... changes the reference-name of the font from its default.
56             The reference-name is normally generated automatically and can be
57             retrieved via C<$pdfname=$font->name()>.
58              
59             =back
60              
61             =head2 Supported typefaces
62              
63             B
64              
65             =over
66              
67             =item helvetica helveticaoblique helveticabold helvetiaboldoblique
68              
69             May have Arial substituted on some systems (e.g., Windows)
70              
71             =item courier courieroblique courierbold courierboldoblique
72              
73             Fixed pitch, may have Courier New substituted on some systems (e.g., Windows)
74              
75             =item timesroman timesitalic timesbold timesbolditalic
76              
77             May have Times New Roman substituted on some systems (e.g., Windows)
78              
79             =item symbol zapfdingbats
80              
81             =back
82              
83             B
84              
85             =over
86              
87             =item georgia georgiaitalic georgiabold georgiabolditalic
88              
89             =item verdana verdanaitalic verdanabold verdanabolditalic
90              
91             =item trebuchet trebuchetitalic trebuchetbold trebuchetbolditalic
92              
93             =item bankgothic bankgothicitalic bankgothicbold bankgothicitalic
94              
95             Free versions of Bank Gothic are often only medium weight.
96              
97             =item webdings wingdings
98              
99             =back
100              
101             Keep in mind that only font metrics (widths) are provided with PDF::Builder;
102             the fonts themselves are provided by the reader's machine (often packaged
103             with the operating system, or obtained separately by the user). To use a
104             specific font may require you to obtain one or more files from some source.
105              
106             If a font (typeface and variant) is not available on a given reader's
107             machine, a substitution I be automatically made. For example, Helvetica is
108             usually not shipped with Windows machines, and Arial might be substituted.
109             For most characters, the glyph widths will be the same, but this can not be
110             guaranteed!
111              
112             PDF::Builder currently uses the [typeface].pm files to map glyph names to
113             code points (single byte encodings only) and to look up the glyph widths for
114             character positioning. There is no guarantee that a given font file includes
115             all the desired glyphs, nor that the widths will be absolutely the same, even
116             in different releases of the same font.
117              
118             =cut
119              
120             sub _look_for_font {
121 52     52   142 my $fname = shift;
122              
123             ## return %{$fonts->{$fname}} if defined $fonts->{$fname};
124 52         6274 eval "require PDF::Builder::Resource::Font::CoreFont::$fname; "; ## no critic
125 52 50       457 unless($@) {
126 52         234 my $class = "PDF::Builder::Resource::Font::CoreFont::$fname";
127 52         627 $fonts->{$fname} = deep_copy($class->data());
128 52   100     13182 $fonts->{$fname}->{'uni'} ||= [];
129 52         351 foreach my $n (0..255) {
130 13312 100       33765 $fonts->{$fname}->{'uni'}->[$n] = uniByName($fonts->{$fname}->{'char'}->[$n]) unless defined $fonts->{$fname}->{'uni'}->[$n];
131             }
132 52         169 return %{$fonts->{$fname}};
  52         1233  
133             } else {
134 0         0 die "requested core font '$fname' not installed ";
135             }
136             }
137              
138             #
139             # Deep copy something, thanks to Randal L. Schwartz
140             # Changed to deal w/ CODE refs, in which case it doesn't try to deep copy
141             #
142             sub deep_copy {
143 148040     148040 0 196912 my $this = shift;
144              
145 148040 100       220566 if (not ref $this) {
    100          
    50          
    0          
146 147600         357104 return $this;
147             } elsif (ref $this eq "ARRAY") {
148 289         841 return [map &deep_copy($_), @$this]; ## no critic
149             } elsif (ref $this eq "HASH") {
150 151         22333 return +{map { $_ => &deep_copy($this->{$_}) } keys %$this};
  133108         227320  
151             } elsif (ref $this eq "CODE") {
152             # Can't deep copy code refs
153 0         0 return $this;
154             } else {
155 0         0 die "what type is $_?";
156             }
157             }
158              
159             sub new {
160 52     52 1 220 my ($class, $pdf, $name, @opts) = @_;
161              
162 52         126 my ($self,$data);
163 52         126 my %opts = ();
164              
165 52 50       2149 if (-f $name) {
166 0         0 eval "require '$name'; "; ## no critic
167 0         0 $name = basename($name,'.pm');
168             }
169 52         255 my $lookname = lc($name);
170 52         249 $lookname =~ s/[^a-z0-9]+//gi;
171 52 50       351 %opts = @opts if (scalar @opts)%2 == 0;
172 52   100     401 $opts{'-encode'} ||= 'asis';
173              
174 52 50       251 $lookname = defined($alias->{$lookname})? $alias->{$lookname}: $lookname ;
175              
176 52 50       194 if (defined $subs->{$lookname}) {
177 0         0 $data = {_look_for_font($subs->{$lookname}->{'-alias'})};
178 0         0 foreach my $k (keys %{$subs->{$lookname}}) {
  0         0  
179 0 0       0 next if $k =~ /^\-/;
180 0         0 $data->{$k} = $subs->{$lookname}->{$k};
181             }
182             } else {
183 52 50       147 unless (defined $opts{'-metrics'}) {
184 52         204 $data = {_look_for_font($lookname)};
185             } else {
186 0         0 $data = {%{$opts{'-metrics'}}};
  0         0  
187             }
188             }
189              
190 52 50       334 die "Undefined Core Font '$name($lookname)'" unless $data->{'fontname'};
191              
192             # we have data now here so we need to check if
193             # there is a -ttfile or -afmfile/-pfmfile/-pfbfile
194             # and proxy the call to the relevant modules
195             #
196             #if (defined $data->{'-ttfile'} && $data->{'-ttfile'} = _look_for_fontfile($data->{'-ttfile'})) {
197             # return PDF::Builder::Resource::CIDFont::TrueType->new($pdf, $data->{'-ttfile'}, @opts);
198             #} elsif (defined $data->{'-pfbfile'} && $data->{'-pfbfile'} = _look_for_fontfile($data->{'-pfbfile'})) {
199             # $data->{'-afmfile'} = _look_for_fontfile($data->{'-afmfile'});
200             # return PDF::Builder::Resource::Font::Postscript->new($pdf, $data->{'-pfbfile'}, $data->{'-afmfile'}, @opts));
201             #} elsif (defined $data->{'-gfx'}) { # to be written and tested in 'Maki' first!
202             # return PDF::Builder::Resource::Font::gFont->new($pdf, $data, @opts);
203             #}
204              
205 52 50       247 $class = ref $class if ref $class;
206             # $self = $class->SUPER::new($pdf, $data->{'apiname'}.pdfkey().'~'.time());
207 52         358 $self = $class->SUPER::new($pdf, $data->{'apiname'}.pdfkey());
208 52 50       206 $pdf->new_obj($self) unless $self->is_obj($pdf);
209 52         191 $self->{' data'} = $data;
210 52 50       274 $self->{'-dokern'} = 1 if $opts{'-dokern'};
211              
212 52         590 $self->{'Subtype'} = PDFName($self->data()->{'type'});
213 52         304 $self->{'BaseFont'} = PDFName($self->fontname());
214 52 50       228 if ($opts{'-pdfname'}) {
215 0         0 $self->name($opts{'-pdfname'});
216             }
217              
218 52 100       192 unless ($self->data()->{'iscore'}) {
219 15         65 $self->{'FontDescriptor'} = $self->descrByData();
220             }
221              
222 52 50       505 if ($opts{'-encode'} =~ m/^utf/i) {
223 0         0 die "Invalid multibyte encoding for corefont: $opts{'-encode'}\n";
224             # probably more encodings to check
225             }
226 52         426 $self->encodeByData($opts{'-encode'});
227              
228 52         486 return $self;
229             }
230              
231             =over
232              
233             =item PDF::Builder::Resource::Font::CoreFont->loadallfonts()
234              
235             "Requires in" all fonts available as corefonts.
236              
237             =cut
238              
239             sub loadallfonts {
240 0     0 1   foreach my $f (qw[
241             bankgothic bankgothicbold bankgothicbolditalic bankgothicitalic
242             courier courierbold courierboldoblique courieroblique
243             georgia georgiabold georgiabolditalic georgiaitalic
244             helveticaboldoblique helveticaoblique helveticabold helvetica
245             symbol
246             timesbolditalic timesitalic timesroman timesbold
247             verdana verdanabold verdanabolditalic verdanaitalic
248             trebuchet trebuchetbold trebuchetbolditalic trebuchetitalic
249             webdings
250             wingdings
251             zapfdingbats
252             ]) {
253 0           _look_for_font($f);
254             }
255 0           return;
256             }
257              
258             # not yet supported
259             # andalemono
260             # arialrounded
261             # impact
262             # ozhandicraft
263              
264             BEGIN
265             {
266              
267 8     8   112 $alias = {
268             ## Windows Fonts with Type1 equivalence
269             'arial' => 'helvetica',
270             'arialitalic' => 'helveticaoblique',
271             'arialbold' => 'helveticabold',
272             'arialbolditalic' => 'helveticaboldoblique',
273              
274             'times' => 'timesroman',
275             'timesnewromanbolditalic' => 'timesbolditalic',
276             'timesnewromanbold' => 'timesbold',
277             'timesnewromanitalic' => 'timesitalic',
278             'timesnewroman' => 'timesroman',
279              
280             'couriernewbolditalic' => 'courierboldoblique',
281             'couriernewbold' => 'courierbold',
282             'couriernewitalic' => 'courieroblique',
283             'couriernew' => 'courier',
284             };
285              
286 8         74 $subs = {
287             'bankgothicbold' => {
288             'apiname' => 'Bg2',
289             '-alias' => 'bankgothic',
290             'fontname' => 'BankGothicMediumBT,Bold',
291             'flags' => 32+262144,
292             },
293             'bankgothicbolditalic' => {
294             'apiname' => 'Bg3',
295             '-alias' => 'bankgothic',
296             'fontname' => 'BankGothicMediumBT,BoldItalic',
297             'italicangle' => -15,
298             'flags' => 96+262144,
299             },
300             'bankgothicitalic' => {
301             'apiname' => 'Bg4',
302             '-alias' => 'bankgothic',
303             'fontname' => 'BankGothicMediumBT,Italic',
304             'italicangle' => -15,
305             'flags' => 96,
306             },
307             # 'impactitalic' => {
308             # 'apiname' => 'Imp2',
309             # '-alias' => 'impact',
310             # 'fontname' => 'Impact,Italic',
311             # 'italicangle' => -12,
312             # },
313             # 'ozhandicraftbold' => {
314             # 'apiname' => 'Oz2',
315             # '-alias' => 'ozhandicraft',
316             # 'fontname' => 'OzHandicraftBT,Bold',
317             # 'italicangle' => 0,
318             # 'flags' => 32+262144,
319             # },
320             # 'ozhandicraftitalic' => {
321             # 'apiname' => 'Oz3',
322             # '-alias' => 'ozhandicraft',
323             # 'fontname' => 'OzHandicraftBT,Italic',
324             # 'italicangle' => -15,
325             # 'flags' => 96,
326             # },
327             # 'ozhandicraftbolditalic' => {
328             # 'apiname' => 'Oz4',
329             # '-alias' => 'ozhandicraft',
330             # 'fontname' => 'OzHandicraftBT,BoldItalic',
331             # 'italicangle' => -15,
332             # 'flags' => 96+262144,
333             # },
334             # 'arialroundeditalic' => {
335             # 'apiname' => 'ArRo2',
336             # '-alias' => 'arialrounded',
337             # 'fontname' => 'ArialRoundedMTBold,Italic',
338             # 'italicangle' => -15,
339             # 'flags' => 96+262144,
340             # },
341             # 'arialitalic' => {
342             # 'apiname' => 'Ar2',
343             # '-alias' => 'arial',
344             # 'fontname' => 'Arial,Italic',
345             # 'italicangle' => -15,
346             # 'flags' => 96,
347             # },
348             # 'arialbolditalic' => {
349             # 'apiname' => 'Ar3',
350             # '-alias' => 'arial',
351             # 'fontname' => 'Arial,BoldItalic',
352             # 'italicangle' => -15,
353             # 'flags' => 96+262144,
354             # },
355             # 'arialbold' => {
356             # 'apiname' => 'Ar4',
357             # '-alias' => 'arial',
358             # 'fontname' => 'Arial,Bold',
359             # 'flags' => 32+262144,
360             # },
361             };
362              
363 8         238 $fonts = { };
364              
365             }
366              
367             1;
368              
369             __END__