package PDF::API2::Resource::Font::CoreFont; our $VERSION = '2.026'; # VERSION use base 'PDF::API2::Resource::Font'; use File::Basename; use PDF::API2::Util; use PDF::API2::Basic::PDF::Utils; no warnings qw[ deprecated recursion uninitialized ]; our $fonts; our $alias; our $subs; =head1 NAME PDF::API2::Resource::Font::CoreFont - Module for using the 14 PDF built-in Fonts. =head1 SYNOPSIS # use PDF::API2; # $pdf = PDF::API2->new; $cft = $pdf->corefont('Times-Roman'); # =head1 METHODS =over =item $font = PDF::API2::Resource::Font::CoreFont->new $pdf, $fontname, %options Returns a corefont object. =cut =pod Valid %options are: I<-encode> ... changes the encoding of the font from its default. See I for the supported values. I<-pdfname> ... changes the reference-name of the font from its default. The reference-name is normally generated automatically and can be retrived via $pdfname=$font->name. =cut sub _look_for_font ($) { my $fname=shift; ## return(%{$fonts->{$fname}}) if(defined $fonts->{$fname}); eval "require PDF::API2::Resource::Font::CoreFont::$fname; "; unless($@) { no strict 'refs'; my $obj = "PDF::API2::Resource::Font::CoreFont::".$fname; $fonts->{$fname} = deep_copy(${$obj."::FONTDATA"}); $fonts->{$fname}->{uni}||=[]; foreach my $n (0..255) { $fonts->{$fname}->{uni}->[$n]=uniByName($fonts->{$fname}->{char}->[$n]) unless(defined $fonts->{$fname}->{uni}->[$n]); } return(%{$fonts->{$fname}}); } else { die "requested font '$fname' not installed "; } } # # Deep copy something, thanks to Randal L. Schwartz # Changed to deal w/ CODE refs, in which case it doesn't try to deep copy # sub deep_copy { my $this = shift; if (not ref $this) { $this; } elsif (ref $this eq "ARRAY") { [map &deep_copy($_), @$this]; } elsif (ref $this eq "HASH") { +{map { $_ => &deep_copy($this->{$_}) } keys %$this}; } elsif (ref $this eq "CODE") { # Can't deep copy code refs return $this; } else { die "what type is $_?"; } } sub new { my ($class,$pdf,$name,@opts) = @_; my ($self,$data); my %opts=(); if(-f $name) { eval "require '$name'; "; $name=basename($name,'.pm'); } my $lookname=lc($name); $lookname=~s/[^a-z0-9]+//gi; %opts=@opts if((scalar @opts)%2 == 0); $opts{-encode}||='asis'; $lookname = defined($alias->{$lookname}) ? $alias->{$lookname} : $lookname ; if(defined $subs->{$lookname}) { $data={_look_for_font($subs->{$lookname}->{-alias})}; foreach my $k (keys %{$subs->{$lookname}}) { next if($k=~/^\-/); $data->{$k}=$subs->{$lookname}->{$k}; } } else { unless(defined $opts{-metrics}) { $data={_look_for_font($lookname)}; } else { $data={%{$opts{-metrics}}}; } } die "Undefined Font '$name($lookname)'" unless($data->{fontname}); # we have data now here so we need to check if # there is a -ttfile or -afmfile/-pfmfile/-pfbfile # and proxy the call to the relevant modules # #if(defined $data->{-ttfile} && $data->{-ttfile}=_look_for_fontfile($data->{-ttfile})) #{ # return(PDF::API2::Resource::CIDFont::TrueType->new($pdf,$data->{-ttfile},@opts)); #} #elsif(defined $data->{-pfbfile} && $data->{-pfbfile}=_look_for_fontfile($data->{-pfbfile})) #{ # $data->{-afmfile}=_look_for_fontfile($data->{-afmfile}); # return(PDF::API2::Resource::Font::Postscript->new($pdf,$data->{-pfbfile},$data->{-afmfile},@opts)); #} #elsif(defined $data->{-gfx}) #{ # to be written and tested in 'Maki' first! # return(PDF::API2::Resource::Font::gFont->new($pdf,$data,@opts); #} $class = ref $class if ref $class; $self = $class->SUPER::new($pdf, $data->{apiname}.pdfkey().'~'.time()); $pdf->new_obj($self) unless($self->is_obj($pdf)); $self->{' data'}=$data; $self->{-dokern}=1 if($opts{-dokern}); $self->{'Subtype'} = PDFName($self->data->{type}); $self->{'BaseFont'} = PDFName($self->fontname); if($opts{-pdfname}) { $self->name($opts{-pdfname}); } unless($self->data->{iscore}) { $self->{'FontDescriptor'}=$self->descrByData(); } $self->encodeByData($opts{-encode}); return($self); } =item $font = PDF::API2::Resource::Font::CoreFont->new_api $api, $fontname, %options Returns a corefont object. This method is different from 'new' that it needs an PDF::API2-object rather than a PDF::API2::PDF::File-object. =cut sub new_api { my ($class,$api,@opts)=@_; my $obj=$class->new($api->{pdf},@opts); $api->{pdf}->new_obj($obj) unless($obj->is_obj($api->{pdf})); ## $api->resource('Font',$obj->name,$obj); $api->{pdf}->out_obj($api->{pages}); return($obj); } =item PDF::API2::Resource::Font::CoreFont->loadallfonts() "Requires in" all fonts available as corefonts. =cut sub loadallfonts { foreach my $f (qw[ courier courierbold courierboldoblique courieroblique georgia georgiabold georgiabolditalic georgiaitalic helveticaboldoblique helveticaoblique helveticabold helvetica symbol timesbolditalic timesitalic timesroman timesbold verdana verdanabold verdanabolditalic verdanaitalic webdings wingdings zapfdingbats ]) { _look_for_font($f); } } # andalemono # arialrounded # bankgothic # impact # ozhandicraft # trebuchet # trebuchetbold # trebuchetbolditalic # trebuchetitalic BEGIN { $alias = { ## Windows Fonts with Type1 equivalence 'arial' => 'helvetica', 'arialitalic' => 'helveticaoblique', 'arialbold' => 'helveticabold', 'arialbolditalic' => 'helveticaboldoblique', 'times' => 'timesroman', 'timesnewromanbolditalic' => 'timesbolditalic', 'timesnewromanbold' => 'timesbold', 'timesnewromanitalic' => 'timesitalic', 'timesnewroman' => 'timesroman', 'couriernewbolditalic' => 'courierboldoblique', 'couriernewbold' => 'courierbold', 'couriernewitalic' => 'courieroblique', 'couriernew' => 'courier', }; $subs = { #'bankgothicbold' => { # 'apiname' => 'Bg2', # '-alias' => 'bankgothic', # 'fontname' => 'BankGothicMediumBT,Bold', # 'flags' => 32+262144, #}, #'bankgothicbolditalic' => { # 'apiname' => 'Bg3', # '-alias' => 'bankgothic', # 'fontname' => 'BankGothicMediumBT,BoldItalic', # 'italicangle' => -15, # 'flags' => 96+262144, #}, #'bankgothicitalic' => { # 'apiname' => 'Bg4', # '-alias' => 'bankgothic', # 'fontname' => 'BankGothicMediumBT,Italic', # 'italicangle' => -15, # 'flags' => 96, #}, # 'impactitalic' => { # 'apiname' => 'Imp2', # '-alias' => 'impact', # 'fontname' => 'Impact,Italic', # 'italicangle' => -12, # }, # 'ozhandicraftbold' => { # 'apiname' => 'Oz2', # '-alias' => 'ozhandicraft', # 'fontname' => 'OzHandicraftBT,Bold', # 'italicangle' => 0, # 'flags' => 32+262144, # }, # 'ozhandicraftitalic' => { # 'apiname' => 'Oz3', # '-alias' => 'ozhandicraft', # 'fontname' => 'OzHandicraftBT,Italic', # 'italicangle' => -15, # 'flags' => 96, # }, # 'ozhandicraftbolditalic' => { # 'apiname' => 'Oz4', # '-alias' => 'ozhandicraft', # 'fontname' => 'OzHandicraftBT,BoldItalic', # 'italicangle' => -15, # 'flags' => 96+262144, # }, # 'arialroundeditalic' => { # 'apiname' => 'ArRo2', # '-alias' => 'arialrounded', # 'fontname' => 'ArialRoundedMTBold,Italic', # 'italicangle' => -15, # 'flags' => 96+262144, # }, # 'arialitalic' => { # 'apiname' => 'Ar2', # '-alias' => 'arial', # 'fontname' => 'Arial,Italic', # 'italicangle' => -15, # 'flags' => 96, # }, # 'arialbolditalic' => { # 'apiname' => 'Ar3', # '-alias' => 'arial', # 'fontname' => 'Arial,BoldItalic', # 'italicangle' => -15, # 'flags' => 96+262144, # }, # 'arialbold' => { # 'apiname' => 'Ar4', # '-alias' => 'arial', # 'fontname' => 'Arial,Bold', # 'flags' => 32+262144, # }, }; $fonts = { }; } 1; __END__ =back =head1 SUPPORTED FONTS =over =item PDF::API2::CoreFont supports the following 'Adobe Core Fonts': Courier Courier-Bold Courier-BoldOblique Courier-Oblique Helvetica Helvetica-Bold Helvetica-BoldOblique Helvetica-Oblique Symbol Times-Bold Times-BoldItalic Times-Italic Times-Roman ZapfDingbats =item PDF::API2::CoreFont supports the following 'Windows Fonts': Georgia Georgia,Bold Georgia,BoldItalic Georgia,Italic Verdana Verdana,Bold Verdana,BoldItalic Verdana,Italic Webdings Wingdings =back =head1 AUTHOR Alfred Reibenschuh =cut