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