1#=======================================================================
2#    ____  ____  _____              _    ____ ___   ____
3#   |  _ \|  _ \|  ___|  _   _     / \  |  _ \_ _| |___ \
4#   | |_) | | | | |_    (_) (_)   / _ \ | |_) | |    __) |
5#   |  __/| |_| |  _|    _   _   / ___ \|  __/| |   / __/
6#   |_|   |____/|_|     (_) (_) /_/   \_\_|  |___| |_____|
7#
8#   A Perl Module Chain to faciliate the Creation and Modification
9#   of High-Quality "Portable Document Format (PDF)" Files.
10#
11#   Copyright 1999-2005 Alfred Reibenschuh <areibens@cpan.org>.
12#
13#=======================================================================
14#
15#   THIS LIBRARY IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR
16#   MODIFY IT UNDER THE TERMS OF THE GNU LESSER GENERAL PUBLIC
17#   LICENSE AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION; EITHER
18#   VERSION 2 OF THE LICENSE, OR (AT YOUR OPTION) ANY LATER VERSION.
19#
20#   THIS FILE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
21#   AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
23#   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24#   SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR CONTRIBUTORS
25#   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26#   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28#   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29#   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30#   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31#   ARISING IN ANY WAY OUT OF THE USE OF THIS FILE, EVEN IF
32#   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33#
34#   SEE THE GNU LESSER GENERAL PUBLIC LICENSE FOR MORE DETAILS.
35#
36#   YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC
37#   LICENSE ALONG WITH THIS LIBRARY; IF NOT, WRITE TO THE
38#   FREE SOFTWARE FOUNDATION, INC., 59 TEMPLE PLACE - SUITE 330,
39#   BOSTON, MA 02111-1307, USA.
40#
41#   $Id: CoreFont.pm,v 2.0 2005/11/16 02:18:14 areibens Exp $
42#
43#=======================================================================
44package PDF::API3::Compat::API2::Resource::Font::CoreFont;
45
46=head1 NAME
47
48PDF::API3::Compat::API2::Resource::Font::CoreFont - Module for using the 14 PDF built-in Fonts.
49
50=head1 SYNOPSIS
51
52    #
53    use PDF::API3::Compat::API2;
54    #
55    $pdf = PDF::API3::Compat::API2->new;
56    $cft = $pdf->corefont('Times-Roman');
57    #
58
59=head1 METHODS
60
61=over 4
62
63=cut
64
65BEGIN {
66
67    use utf8;
68    use Encode qw(:all);
69
70    use File::Basename;
71
72    use vars qw( @ISA $fonts $alias $subs $encodings $VERSION );
73    use PDF::API3::Compat::API2::Resource::Font;
74    use PDF::API3::Compat::API2::Util;
75    use PDF::API3::Compat::API2::Basic::PDF::Utils;
76
77    @ISA=qw(PDF::API3::Compat::API2::Resource::Font);
78
79    ( $VERSION ) = sprintf '%i.%03i', split(/\./,('$Revision: 2.0 $' =~ /Revision: (\S+)\s/)[0]); # $Date: 2005/11/16 02:18:14 $
80
81}
82no warnings qw[ deprecated recursion uninitialized ];
83
84=item $font = PDF::API3::Compat::API2::Resource::Font::CoreFont->new $pdf, $fontname, %options
85
86Returns a corefont object.
87
88=cut
89
90=pod
91
92Valid %options are:
93
94I<-encode>
95... changes the encoding of the font from its default.
96See I<perl's Encode> for the supported values.
97
98I<-pdfname> ... changes the reference-name of the font from its default.
99The reference-name is normally generated automatically and can be
100retrived via $pdfname=$font->name.
101
102=cut
103
104sub _look_for_font ($)
105{
106    my $fname=shift;
107    ## return(%{$fonts->{$fname}}) if(defined $fonts->{$fname});
108    eval "require PDF::API3::Compat::API2::Resource::Font::CoreFont::$fname; ";
109    unless($@)
110    {
111    no strict 'refs';
112        my $obj = "PDF::API3::Compat::API2::Resource::Font::CoreFont::".$fname;
113    $fonts->{$fname} = deep_copy(${$obj."::FONTDATA"});
114        $fonts->{$fname}->{uni}||=[];
115        foreach my $n (0..255)
116        {
117            $fonts->{$fname}->{uni}->[$n]=uniByName($fonts->{$fname}->{char}->[$n]) unless(defined $fonts->{$fname}->{uni}->[$n]);
118        }
119        return(%{$fonts->{$fname}});
120    }
121    else
122    {
123        die "requested font '$fname' not installed ";
124    }
125}
126
127#
128# Deep copy something, thanks to Randal L. Schwartz
129# Changed to deal w/ CODE refs, in which case it doesn't try to deep copy
130#
131sub deep_copy
132{
133    my $this = shift;
134    if (not ref $this)
135    {
136    $this;
137    }
138    elsif (ref $this eq "ARRAY")
139    {
140    [map &deep_copy($_), @$this];
141    }
142    elsif (ref $this eq "HASH")
143    {
144    +{map { $_ => &deep_copy($this->{$_}) } keys %$this};
145    }
146    elsif (ref $this eq "CODE")
147    {
148    # Can't deep copy code refs
149    return $this;
150    }
151    else
152    {
153    die "what type is $_?";
154    }
155}
156
157sub _look_for_fontfile ($)
158{
159    my $fname=shift;
160    my $fpath=undef;
161    foreach my $dir (@INC)
162    {
163        $fpath="$dir/PDF/API3/Compat/API2/Resource/Font/CoreFont/$fname";
164        last if(-f $fpath);
165        $fpath=undef;
166    }
167    return($fpath);
168}
169
170sub _look_for_fontmetricfile ($)
171{
172    my $fname=shift;
173    my $fpath=undef;
174    foreach my $dir (@INC)
175    {
176        $fpath="$dir/PDF/API3/Compat/API2/Resource/Font/CoreFont/$fname.fm";
177        last if(-f $fpath);
178        $fpath=undef;
179    }
180    return($fpath);
181}
182
183sub new
184{
185    my ($class,$pdf,$name,@opts) = @_;
186    my ($self,$data);
187    my %opts=();
188    if(-f $name)
189    {
190        eval "require '$name'; ";
191        $name=basename($name,'.pm');
192    }
193    my $lookname=lc($name);
194    $lookname=~s/[^a-z0-9]+//gi;
195    %opts=@opts if((scalar @opts)%2 == 0);
196    $opts{-encode}||='asis';
197
198    $lookname = defined($alias->{$lookname}) ? $alias->{$lookname} : $lookname ;
199
200    if(defined $subs->{$lookname})
201    {
202        $data={_look_for_font($subs->{$lookname}->{-alias})};
203        foreach my $k (keys %{$subs->{$lookname}})
204        {
205            next if($k=~/^\-/);
206            $data->{$k}=$subs->{$lookname}->{$k};
207        }
208    }
209    else
210    {
211        unless(defined $opts{-metrics})
212        {
213            $data={_look_for_font($lookname)};
214        }
215        else
216        {
217            $data={%{$opts{-metrics}}};
218        }
219    }
220
221    die "Undefined Font '$name($lookname)'" unless($data->{fontname});
222
223    # we have data now here so we need to check if
224    # there is a -ttfile or -afmfile/-pfmfile/-pfbfile
225    # and proxy the call to the relevant modules
226    #
227    #if(defined $data->{-ttfile} && $data->{-ttfile}=_look_for_fontfile($data->{-ttfile}))
228    #{
229    #    return(PDF::API3::Compat::API2::Resource::CIDFont::TrueType->new($pdf,$data->{-ttfile},@opts));
230    #}
231    #elsif(defined $data->{-pfbfile} && $data->{-pfbfile}=_look_for_fontfile($data->{-pfbfile}))
232    #{
233    #    $data->{-afmfile}=_look_for_fontfile($data->{-afmfile});
234    #    return(PDF::API3::Compat::API2::Resource::Font::Postscript->new($pdf,$data->{-pfbfile},$data->{-afmfile},@opts));
235    #}
236    #elsif(defined $data->{-gfx})
237    #{ # to be written and tested in 'Maki' first!
238    #    return(PDF::API3::Compat::API2::Resource::Font::gFont->new($pdf,$data,@opts);
239    #}
240
241    $class = ref $class if ref $class;
242    $self = $class->SUPER::new($pdf, $data->{apiname}.pdfkey().'~'.time());
243    $pdf->new_obj($self) unless($self->is_obj($pdf));
244    $self->{' data'}=$data;
245    $self->{-dokern}=1 if($opts{-dokern});
246
247    $self->{'Subtype'} = PDFName($self->data->{type});
248    $self->{'BaseFont'} = PDFName($self->fontname);
249    if($opts{-pdfname})
250    {
251        $self->name($opts{-pdfname});
252    }
253
254    unless($self->data->{iscore})
255    {
256        $self->{'FontDescriptor'}=$self->descrByData();
257    }
258
259    $self->encodeByData($opts{-encode});
260
261    return($self);
262}
263
264=item $font = PDF::API3::Compat::API2::Resource::Font::CoreFont->new_api $api, $fontname, %options
265
266Returns a corefont object. This method is different from 'new' that
267it needs an PDF::API3::Compat::API2-object rather than a PDF::API3::Compat::API2::PDF::File-object.
268
269=cut
270
271sub new_api
272{
273    my ($class,$api,@opts)=@_;
274
275    my $obj=$class->new($api->{pdf},@opts);
276
277    $api->{pdf}->new_obj($obj) unless($obj->is_obj($api->{pdf}));
278
279##  $api->resource('Font',$obj->name,$obj);
280
281    $api->{pdf}->out_obj($api->{pages});
282    return($obj);
283}
284
285=item PDF::API3::Compat::API2::Resource::Font::CoreFont->loadallfonts()
286
287"Requires in" all fonts available as corefonts.
288
289=cut
290
291sub loadallfonts
292{
293    foreach my $f (qw[
294        courier courierbold courierboldoblique courieroblique
295        georgia georgiabold georgiabolditalic georgiaitalic
296        helveticaboldoblique helveticaoblique helveticabold helvetica
297        symbol
298        timesbolditalic timesitalic timesroman timesbold
299        verdana verdanabold verdanabolditalic verdanaitalic
300        webdings
301        wingdings
302        zapfdingbats
303    ])
304    {
305        _look_for_font($f);
306    }
307}
308
309#    andalemono
310#    arialrounded
311#    bankgothic
312#    impact
313#    ozhandicraft
314#    trebuchet
315#    trebuchetbold
316#    trebuchetbolditalic
317#    trebuchetitalic
318
319BEGIN
320{
321
322    $alias = {
323        ## Windows Fonts with Type1 equivalence
324        'arial'                     => 'helvetica',
325        'arialitalic'               => 'helveticaoblique',
326        'arialbold'                 => 'helveticabold',
327        'arialbolditalic'           => 'helveticaboldoblique',
328
329        'times'                     => 'timesroman',
330        'timesnewromanbolditalic'   => 'timesbolditalic',
331        'timesnewromanbold'         => 'timesbold',
332        'timesnewromanitalic'       => 'timesitalic',
333        'timesnewroman'             => 'timesroman',
334
335        'couriernewbolditalic'      => 'courierboldoblique',
336        'couriernewbold'            => 'courierbold',
337        'couriernewitalic'          => 'courieroblique',
338        'couriernew'                => 'courier',
339    };
340
341    $subs = {
342        #'bankgothicbold' => {
343        #    'apiname'       => 'Bg2',
344        #    '-alias'        => 'bankgothic',
345        #    'fontname'      => 'BankGothicMediumBT,Bold',
346        #    'flags'         => 32+262144,
347        #},
348        #'bankgothicbolditalic' => {
349        #    'apiname'       => 'Bg3',
350        #    '-alias'        => 'bankgothic',
351        #    'fontname'      => 'BankGothicMediumBT,BoldItalic',
352        #    'italicangle'   => -15,
353        #    'flags'         => 96+262144,
354        #},
355        #'bankgothicitalic' => {
356        #    'apiname'       => 'Bg4',
357        #    '-alias'        => 'bankgothic',
358        #    'fontname'      => 'BankGothicMediumBT,Italic',
359        #    'italicangle'   => -15,
360        #    'flags'         => 96,
361        #},
362        #  'impactitalic'      => {
363        #            'apiname' => 'Imp2',
364        #            '-alias'  => 'impact',
365        #            'fontname'  => 'Impact,Italic',
366        #            'italicangle' => -12,
367        #          },
368        #  'ozhandicraftbold'    => {
369        #            'apiname' => 'Oz2',
370        #            '-alias'  => 'ozhandicraft',
371        #            'fontname'  => 'OzHandicraftBT,Bold',
372        #            'italicangle' => 0,
373        #            'flags' => 32+262144,
374        #          },
375        #  'ozhandicraftitalic'    => {
376        #            'apiname' => 'Oz3',
377        #            '-alias'  => 'ozhandicraft',
378        #            'fontname'  => 'OzHandicraftBT,Italic',
379        #            'italicangle' => -15,
380        #            'flags' => 96,
381        #          },
382        #  'ozhandicraftbolditalic'  => {
383        #            'apiname' => 'Oz4',
384        #            '-alias'  => 'ozhandicraft',
385        #            'fontname'  => 'OzHandicraftBT,BoldItalic',
386        #            'italicangle' => -15,
387        #            'flags' => 96+262144,
388        #          },
389        #  'arialroundeditalic'  => {
390        #            'apiname' => 'ArRo2',
391        #            '-alias'  => 'arialrounded',
392        #            'fontname'  => 'ArialRoundedMTBold,Italic',
393        #            'italicangle' => -15,
394        #            'flags' => 96+262144,
395        #          },
396        #  'arialitalic'  => {
397        #            'apiname' => 'Ar2',
398        #            '-alias'  => 'arial',
399        #            'fontname'  => 'Arial,Italic',
400        #            'italicangle' => -15,
401        #            'flags' => 96,
402        #          },
403        #  'arialbolditalic'  => {
404        #            'apiname' => 'Ar3',
405        #            '-alias'  => 'arial',
406        #            'fontname'  => 'Arial,BoldItalic',
407        #            'italicangle' => -15,
408        #            'flags' => 96+262144,
409        #          },
410        #  'arialbold'  => {
411        #            'apiname' => 'Ar4',
412        #            '-alias'  => 'arial',
413        #            'fontname'  => 'Arial,Bold',
414        #            'flags' => 32+262144,
415        #          },
416    };
417
418    $fonts = { };
419
420}
421
4221;
423
424__END__
425
426=back
427
428=head1 SUPPORTED FONTS
429
430=item PDF::API::CoreFont supports the following 'Adobe Core Fonts':
431
432  Courier
433  Courier-Bold
434  Courier-BoldOblique
435  Courier-Oblique
436  Helvetica
437  Helvetica-Bold
438  Helvetica-BoldOblique
439  Helvetica-Oblique
440  Symbol
441  Times-Bold
442  Times-BoldItalic
443  Times-Italic
444  Times-Roman
445  ZapfDingbats
446
447=item PDF::API::CoreFont supports the following 'Windows Fonts':
448
449  Georgia
450  Georgia,Bold
451  Georgia,BoldItalic
452  Georgia,Italic
453  Verdana
454  Verdana,Bold
455  Verdana,BoldItalic
456  Verdana,Italic
457  Webdings
458  Wingdings
459
460=head1 AUTHOR
461
462alfred reibenschuh
463
464=head1 HISTORY
465
466    $Log: CoreFont.pm,v $
467    Revision 2.0  2005/11/16 02:18:14  areibens
468    revision workaround for SF cvs import not to screw up CPAN
469
470    Revision 1.2  2005/11/16 01:27:50  areibens
471    genesis2
472
473    Revision 1.1  2005/11/16 01:19:27  areibens
474    genesis
475
476    Revision 1.17  2005/10/19 19:15:12  fredo
477    added handling of optional kerning
478
479    Revision 1.16  2005/10/01 22:41:07  fredo
480    fixed font-naming race condition for multiple document updates
481
482    Revision 1.15  2005/09/26 20:07:19  fredo
483    added fontmetric stub
484
485    Revision 1.14  2005/09/12 16:56:20  fredo
486    applied mod_perl patch by Paul Schilling <pfschill@sbcglobal.net>
487
488    Revision 1.13  2005/06/17 19:44:03  fredo
489    fixed CPAN modulefile versioning (again)
490
491    Revision 1.12  2005/06/17 18:53:34  fredo
492    fixed CPAN modulefile versioning (dislikes cvs)
493
494    Revision 1.11  2005/05/29 09:47:38  fredo
495    cosmetic changes
496
497    Revision 1.10  2005/03/14 22:01:27  fredo
498    upd 2005
499
500    Revision 1.9  2005/01/21 10:04:15  fredo
501    rewrite fontproxy comment
502
503    Revision 1.8  2004/12/16 00:30:54  fredo
504    added no warn for recursion
505
506    Revision 1.7  2004/11/22 02:08:42  fredo
507    aaa
508
509    Revision 1.6  2004/06/21 22:25:44  fredo
510    added custom corefont handling
511
512    Revision 1.5  2004/06/15 09:14:53  fredo
513    removed cr+lf
514
515    Revision 1.4  2004/06/07 19:44:43  fredo
516    cleaned out cr+lf for lf
517
518    Revision 1.3  2003/12/08 13:06:01  Administrator
519    corrected to proper licencing statement
520
521    Revision 1.2  2003/11/30 17:32:48  Administrator
522    merged into default
523
524    Revision 1.1.1.1.2.2  2003/11/30 16:57:05  Administrator
525    merged into default
526
527    Revision 1.1.1.1.2.1  2003/11/30 14:45:22  Administrator
528    added CVS id/log
529
530
531=cut
532
533
534