Changeset 19716
- Timestamp:
- 2010/12/11 12:15:20 (12 years ago)
- Location:
- branches/version-2_5-dev/data
- Files:
-
- 7 added
- 2 deleted
- 1 edited
- 8 moved
Legend:
- Unmodified
- Added
- Removed
-
branches/version-2_5-dev/data/class/SC_Fpdf.php
r19680 r19716 28 28 */ 29 29 30 require(DATA_PATH . 'pdf/japanese.php'); 30 require(DATA_PATH . 'module/fpdf/fpdf.php'); 31 require(DATA_PATH . 'module/fpdf/japanese.php'); 31 32 define('PDF_TEMPLATE_DIR', DATA_PATH . 'pdf/'); 32 33 -
branches/version-2_5-dev/data/module/fpdf/fpdf.php
r17259 r19716 1 1 <?php 2 2 /******************************************************************************* 3 * Software: FPDF * 4 * Version: 1.53 * 5 * Date: 2004-12-31 * 6 * Author: Olivier PLATHEY * 7 * License: Freeware * 3 * FPDF * 8 4 * * 9 * You may use, modify and redistribute this software as you wish. * 5 * Version: 1.6 * 6 * Date: 2008-08-03 * 7 * Author: Olivier PLATHEY * 10 8 *******************************************************************************/ 11 9 12 if(!class_exists('FPDF')) 13 { 14 define('FPDF_VERSION','1.53'); 10 define('FPDF_VERSION','1.6'); 15 11 16 12 class FPDF 17 13 { 18 //Private properties19 14 var $page; //current page number 20 15 var $n; //current object number … … 24 19 var $state; //current document state 25 20 var $compress; //compression flag 21 var $k; //scale factor (number of points in user unit) 26 22 var $DefOrientation; //default orientation 27 23 var $CurOrientation; //current orientation 28 var $ OrientationChanges; //array indicating orientation changes29 var $ k; //scale factor (number of points in user unit)30 var $ fwPt,$fhPt; //dimensions of page format in points31 var $ fw,$fh; //dimensions of page format in user unit32 var $wPt,$hPt; // current dimensions ofpage in points33 var $w,$h; // current dimensions ofpage in user unit24 var $PageFormats; //available page formats 25 var $DefPageFormat; //default page format 26 var $CurPageFormat; //current page format 27 var $PageSizes; //array storing non-default page sizes 28 var $wPt,$hPt; //dimensions of current page in points 29 var $w,$h; //dimensions of current page in user unit 34 30 var $lMargin; //left margin 35 31 var $tMargin; //top margin … … 37 33 var $bMargin; //page break margin 38 34 var $cMargin; //cell margin 39 var $x,$y; //current position in user unit for cell positioning40 var $lasth; //height of last cell printed35 var $x,$y; //current position in user unit 36 var $lasth; //height of last printed cell 41 37 var $LineWidth; //line width in user unit 42 38 var $CoreFonts; //array of standard font names … … 44 40 var $FontFiles; //array of font files 45 41 var $diffs; //array of encoding differences 46 var $images; //array of used images47 var $PageLinks; //array of links in pages48 var $links; //array of internal links49 42 var $FontFamily; //current font family 50 43 var $FontStyle; //current font style … … 58 51 var $ColorFlag; //indicates whether fill and text colors are different 59 52 var $ws; //word spacing 53 var $images; //array of used images 54 var $PageLinks; //array of links in pages 55 var $links; //array of internal links 60 56 var $AutoPageBreak; //automatic page breaking 61 57 var $PageBreakTrigger; //threshold used to trigger page breaks 58 var $InHeader; //flag set when processing header 62 59 var $InFooter; //flag set when processing footer 63 60 var $ZoomMode; //zoom display mode … … 76 73 * * 77 74 *******************************************************************************/ 78 function FPDF($orientation='P', $unit='mm',$format='A4')75 function FPDF($orientation='P', $unit='mm', $format='A4') 79 76 { 80 77 //Some checks … … 85 82 $this->buffer=''; 86 83 $this->pages=array(); 87 $this-> OrientationChanges=array();84 $this->PageSizes=array(); 88 85 $this->state=0; 89 86 $this->fonts=array(); … … 92 89 $this->images=array(); 93 90 $this->links=array(); 91 $this->InHeader=false; 94 92 $this->InFooter=false; 95 93 $this->lasth=0; … … 104 102 $this->ws=0; 105 103 //Standard fonts 106 $this->CoreFonts=array('courier'=>'Courier', 'courierB'=>'Courier-Bold','courierI'=>'Courier-Oblique','courierBI'=>'Courier-BoldOblique',107 'helvetica'=>'Helvetica', 'helveticaB'=>'Helvetica-Bold','helveticaI'=>'Helvetica-Oblique','helveticaBI'=>'Helvetica-BoldOblique',108 'times'=>'Times-Roman', 'timesB'=>'Times-Bold','timesI'=>'Times-Italic','timesBI'=>'Times-BoldItalic',109 'symbol'=>'Symbol', 'zapfdingbats'=>'ZapfDingbats');104 $this->CoreFonts=array('courier'=>'Courier', 'courierB'=>'Courier-Bold', 'courierI'=>'Courier-Oblique', 'courierBI'=>'Courier-BoldOblique', 105 'helvetica'=>'Helvetica', 'helveticaB'=>'Helvetica-Bold', 'helveticaI'=>'Helvetica-Oblique', 'helveticaBI'=>'Helvetica-BoldOblique', 106 'times'=>'Times-Roman', 'timesB'=>'Times-Bold', 'timesI'=>'Times-Italic', 'timesBI'=>'Times-BoldItalic', 107 'symbol'=>'Symbol', 'zapfdingbats'=>'ZapfDingbats'); 110 108 //Scale factor 111 109 if($unit=='pt') … … 120 118 $this->Error('Incorrect unit: '.$unit); 121 119 //Page format 120 $this->PageFormats=array('a3'=>array(841.89,1190.55), 'a4'=>array(595.28,841.89), 'a5'=>array(420.94,595.28), 121 'letter'=>array(612,792), 'legal'=>array(612,1008)); 122 122 if(is_string($format)) 123 { 124 $format=strtolower($format); 125 if($format=='a3') 126 $format=array(841.89,1190.55); 127 elseif($format=='a4') 128 $format=array(595.28,841.89); 129 elseif($format=='a5') 130 $format=array(420.94,595.28); 131 elseif($format=='letter') 132 $format=array(612,792); 133 elseif($format=='legal') 134 $format=array(612,1008); 135 else 136 $this->Error('Unknown page format: '.$format); 137 $this->fwPt=$format[0]; 138 $this->fhPt=$format[1]; 139 } 140 else 141 { 142 $this->fwPt=$format[0]*$this->k; 143 $this->fhPt=$format[1]*$this->k; 144 } 145 $this->fw=$this->fwPt/$this->k; 146 $this->fh=$this->fhPt/$this->k; 123 $format=$this->_getpageformat($format); 124 $this->DefPageFormat=$format; 125 $this->CurPageFormat=$format; 147 126 //Page orientation 148 127 $orientation=strtolower($orientation); … … 150 129 { 151 130 $this->DefOrientation='P'; 152 $this->w Pt=$this->fwPt;153 $this->h Pt=$this->fhPt;131 $this->w=$this->DefPageFormat[0]; 132 $this->h=$this->DefPageFormat[1]; 154 133 } 155 134 elseif($orientation=='l' || $orientation=='landscape') 156 135 { 157 136 $this->DefOrientation='L'; 158 $this->w Pt=$this->fhPt;159 $this->h Pt=$this->fwPt;137 $this->w=$this->DefPageFormat[1]; 138 $this->h=$this->DefPageFormat[0]; 160 139 } 161 140 else 162 141 $this->Error('Incorrect orientation: '.$orientation); 163 142 $this->CurOrientation=$this->DefOrientation; 164 $this->w =$this->wPt/$this->k;165 $this->h =$this->hPt/$this->k;143 $this->wPt=$this->w*$this->k; 144 $this->hPt=$this->h*$this->k; 166 145 //Page margins (1 cm) 167 146 $margin=28.35/$this->k; … … 181 160 } 182 161 183 function SetMargins($left, $top,$right=-1)162 function SetMargins($left, $top, $right=null) 184 163 { 185 164 //Set left, top and right margins 186 165 $this->lMargin=$left; 187 166 $this->tMargin=$top; 188 if($right== -1)167 if($right===null) 189 168 $right=$left; 190 169 $this->rMargin=$right; … … 211 190 } 212 191 213 function SetAutoPageBreak($auto, $margin=0)192 function SetAutoPageBreak($auto, $margin=0) 214 193 { 215 194 //Set auto page break mode and triggering margin … … 219 198 } 220 199 221 function SetDisplayMode($zoom, $layout='continuous')200 function SetDisplayMode($zoom, $layout='continuous') 222 201 { 223 202 //Set display mode in viewer … … 241 220 } 242 221 243 function SetTitle($title )222 function SetTitle($title, $isUTF8=false) 244 223 { 245 224 //Title of document 225 if($isUTF8) 226 $title=$this->_UTF8toUTF16($title); 246 227 $this->title=$title; 247 228 } 248 229 249 function SetSubject($subject )230 function SetSubject($subject, $isUTF8=false) 250 231 { 251 232 //Subject of document 233 if($isUTF8) 234 $subject=$this->_UTF8toUTF16($subject); 252 235 $this->subject=$subject; 253 236 } 254 237 255 function SetAuthor($author )238 function SetAuthor($author, $isUTF8=false) 256 239 { 257 240 //Author of document 241 if($isUTF8) 242 $author=$this->_UTF8toUTF16($author); 258 243 $this->author=$author; 259 244 } 260 245 261 function SetKeywords($keywords )246 function SetKeywords($keywords, $isUTF8=false) 262 247 { 263 248 //Keywords of document 249 if($isUTF8) 250 $keywords=$this->_UTF8toUTF16($keywords); 264 251 $this->keywords=$keywords; 265 252 } 266 253 267 function SetCreator($creator )254 function SetCreator($creator, $isUTF8=false) 268 255 { 269 256 //Creator of document 257 if($isUTF8) 258 $creator=$this->_UTF8toUTF16($creator); 270 259 $this->creator=$creator; 271 260 } … … 280 269 { 281 270 //Fatal error 282 die('< B>FPDF error: </B>'.$msg);271 die('<b>FPDF error:</b> '.$msg); 283 272 } 284 273 … … 306 295 } 307 296 308 function AddPage($orientation='' )297 function AddPage($orientation='', $format='') 309 298 { 310 299 //Start a new page … … 329 318 } 330 319 //Start new page 331 $this->_beginpage($orientation );320 $this->_beginpage($orientation,$format); 332 321 //Set line cap style to square 333 322 $this->_out('2 J'); 334 323 //Set line width 335 324 $this->LineWidth=$lw; 336 $this->_out(sprintf('%.2 fw',$lw*$this->k));325 $this->_out(sprintf('%.2F w',$lw*$this->k)); 337 326 //Set font 338 327 if($family) … … 348 337 $this->ColorFlag=$cf; 349 338 //Page header 339 $this->InHeader=true; 350 340 $this->Header(); 341 $this->InHeader=false; 351 342 //Restore line width 352 343 if($this->LineWidth!=$lw) 353 344 { 354 345 $this->LineWidth=$lw; 355 $this->_out(sprintf('%.2 fw',$lw*$this->k));346 $this->_out(sprintf('%.2F w',$lw*$this->k)); 356 347 } 357 348 //Restore font … … 389 380 } 390 381 391 function SetDrawColor($r, $g=-1,$b=-1)382 function SetDrawColor($r, $g=null, $b=null) 392 383 { 393 384 //Set color for all stroking operations 394 if(($r==0 && $g==0 && $b==0) || $g== -1)395 $this->DrawColor=sprintf('%.3 fG',$r/255);396 else 397 $this->DrawColor=sprintf('%.3 f %.3f %.3fRG',$r/255,$g/255,$b/255);385 if(($r==0 && $g==0 && $b==0) || $g===null) 386 $this->DrawColor=sprintf('%.3F G',$r/255); 387 else 388 $this->DrawColor=sprintf('%.3F %.3F %.3F RG',$r/255,$g/255,$b/255); 398 389 if($this->page>0) 399 390 $this->_out($this->DrawColor); 400 391 } 401 392 402 function SetFillColor($r, $g=-1,$b=-1)393 function SetFillColor($r, $g=null, $b=null) 403 394 { 404 395 //Set color for all filling operations 405 if(($r==0 && $g==0 && $b==0) || $g== -1)406 $this->FillColor=sprintf('%.3 fg',$r/255);407 else 408 $this->FillColor=sprintf('%.3 f %.3f %.3frg',$r/255,$g/255,$b/255);396 if(($r==0 && $g==0 && $b==0) || $g===null) 397 $this->FillColor=sprintf('%.3F g',$r/255); 398 else 399 $this->FillColor=sprintf('%.3F %.3F %.3F rg',$r/255,$g/255,$b/255); 409 400 $this->ColorFlag=($this->FillColor!=$this->TextColor); 410 401 if($this->page>0) … … 412 403 } 413 404 414 function SetTextColor($r, $g=-1,$b=-1)405 function SetTextColor($r, $g=null, $b=null) 415 406 { 416 407 //Set color for text 417 if(($r==0 && $g==0 && $b==0) || $g== -1)418 $this->TextColor=sprintf('%.3 fg',$r/255);419 else 420 $this->TextColor=sprintf('%.3 f %.3f %.3frg',$r/255,$g/255,$b/255);408 if(($r==0 && $g==0 && $b==0) || $g===null) 409 $this->TextColor=sprintf('%.3F g',$r/255); 410 else 411 $this->TextColor=sprintf('%.3F %.3F %.3F rg',$r/255,$g/255,$b/255); 421 412 $this->ColorFlag=($this->FillColor!=$this->TextColor); 422 413 } … … 430 421 $l=strlen($s); 431 422 for($i=0;$i<$l;$i++) 432 $w+=$cw[$s {$i}];423 $w+=$cw[$s[$i]]; 433 424 return $w*$this->FontSize/1000; 434 425 } … … 439 430 $this->LineWidth=$width; 440 431 if($this->page>0) 441 $this->_out(sprintf('%.2 fw',$width*$this->k));442 } 443 444 function Line($x1, $y1,$x2,$y2)432 $this->_out(sprintf('%.2F w',$width*$this->k)); 433 } 434 435 function Line($x1, $y1, $x2, $y2) 445 436 { 446 437 //Draw a line 447 $this->_out(sprintf('%.2 f %.2f m %.2f %.2fl S',$x1*$this->k,($this->h-$y1)*$this->k,$x2*$this->k,($this->h-$y2)*$this->k));448 } 449 450 function Rect($x, $y,$w,$h,$style='')438 $this->_out(sprintf('%.2F %.2F m %.2F %.2F l S',$x1*$this->k,($this->h-$y1)*$this->k,$x2*$this->k,($this->h-$y2)*$this->k)); 439 } 440 441 function Rect($x, $y, $w, $h, $style='') 451 442 { 452 443 //Draw a rectangle … … 457 448 else 458 449 $op='S'; 459 $this->_out(sprintf('%.2 f %.2f %.2f %.2fre %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));460 } 461 462 function AddFont($family, $style='',$file='')450 $this->_out(sprintf('%.2F %.2F %.2F %.2F re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op)); 451 } 452 453 function AddFont($family, $style='', $file='') 463 454 { 464 455 //Add a TrueType or Type1 font … … 473 464 $fontkey=$family.$style; 474 465 if(isset($this->fonts[$fontkey])) 475 $this->Error('Font already added: '.$family.' '.$style);466 return; 476 467 include($this->_getfontpath().$file); 477 468 if(!isset($name)) 478 469 $this->Error('Could not include font definition file'); 479 470 $i=count($this->fonts)+1; 480 $this->fonts[$fontkey]=array('i'=>$i, 'type'=>$type,'name'=>$name,'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw,'enc'=>$enc,'file'=>$file);471 $this->fonts[$fontkey]=array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'enc'=>$enc, 'file'=>$file); 481 472 if($diff) 482 473 { … … 504 495 $this->FontFiles[$file]=array('length1'=>$originalsize); 505 496 else 506 $this->FontFiles[$file]=array('length1'=>$size1, 'length2'=>$size2);507 } 508 } 509 510 function SetFont($family, $style='',$size=0)497 $this->FontFiles[$file]=array('length1'=>$size1, 'length2'=>$size2); 498 } 499 } 500 501 function SetFont($family, $style='', $size=0) 511 502 { 512 503 //Select a font; size given in points … … 553 544 } 554 545 $i=count($this->fonts)+1; 555 $this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'up'=>-100,'ut'=>50,'cw'=>$fpdf_charwidths[$fontkey]); 546 $name=$this->CoreFonts[$fontkey]; 547 $cw=$fpdf_charwidths[$fontkey]; 548 $this->fonts[$fontkey]=array('i'=>$i, 'type'=>'core', 'name'=>$name, 'up'=>-100, 'ut'=>50, 'cw'=>$cw); 556 549 } 557 550 else … … 565 558 $this->CurrentFont=&$this->fonts[$fontkey]; 566 559 if($this->page>0) 567 $this->_out(sprintf('BT /F%d %.2 fTf ET',$this->CurrentFont['i'],$this->FontSizePt));560 $this->_out(sprintf('BT /F%d %.2F Tf ET',$this->CurrentFont['i'],$this->FontSizePt)); 568 561 } 569 562 … … 576 569 $this->FontSize=$size/$this->k; 577 570 if($this->page>0) 578 $this->_out(sprintf('BT /F%d %.2 fTf ET',$this->CurrentFont['i'],$this->FontSizePt));571 $this->_out(sprintf('BT /F%d %.2F Tf ET',$this->CurrentFont['i'],$this->FontSizePt)); 579 572 } 580 573 … … 583 576 //Create a new internal link 584 577 $n=count($this->links)+1; 585 $this->links[$n]=array(0, 0);578 $this->links[$n]=array(0, 0); 586 579 return $n; 587 580 } 588 581 589 function SetLink($link, $y=0,$page=-1)582 function SetLink($link, $y=0, $page=-1) 590 583 { 591 584 //Set destination of internal link … … 594 587 if($page==-1) 595 588 $page=$this->page; 596 $this->links[$link]=array($page, $y);597 } 598 599 function Link($x, $y,$w,$h,$link)589 $this->links[$link]=array($page, $y); 590 } 591 592 function Link($x, $y, $w, $h, $link) 600 593 { 601 594 //Put a link on the page 602 $this->PageLinks[$this->page][]=array($x*$this->k, $this->hPt-$y*$this->k,$w*$this->k,$h*$this->k,$link);603 } 604 605 function Text($x, $y,$txt)595 $this->PageLinks[$this->page][]=array($x*$this->k, $this->hPt-$y*$this->k, $w*$this->k, $h*$this->k, $link); 596 } 597 598 function Text($x, $y, $txt) 606 599 { 607 600 //Output a string 608 $s=sprintf('BT %.2 f %.2fTd (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt));601 $s=sprintf('BT %.2F %.2F Td (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt)); 609 602 if($this->underline && $txt!='') 610 603 $s.=' '.$this->_dounderline($x,$y,$txt); … … 620 613 } 621 614 622 function Cell($w, $h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='')615 function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='') 623 616 { 624 617 //Output a cell 625 618 $k=$this->k; 626 if($this->y+$h>$this->PageBreakTrigger && !$this->In Footer && $this->AcceptPageBreak())619 if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak()) 627 620 { 628 621 //Automatic page break … … 634 627 $this->_out('0 Tw'); 635 628 } 636 $this->AddPage($this->CurOrientation );629 $this->AddPage($this->CurOrientation,$this->CurPageFormat); 637 630 $this->x=$x; 638 631 if($ws>0) 639 632 { 640 633 $this->ws=$ws; 641 $this->_out(sprintf('%.3 fTw',$ws*$k));634 $this->_out(sprintf('%.3F Tw',$ws*$k)); 642 635 } 643 636 } … … 645 638 $w=$this->w-$this->rMargin-$this->x; 646 639 $s=''; 647 if($fill ==1|| $border==1)648 { 649 if($fill ==1)640 if($fill || $border==1) 641 { 642 if($fill) 650 643 $op=($border==1) ? 'B' : 'f'; 651 644 else 652 645 $op='S'; 653 $s=sprintf('%.2 f %.2f %.2f %.2fre %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op);646 $s=sprintf('%.2F %.2F %.2F %.2F re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op); 654 647 } 655 648 if(is_string($border)) … … 658 651 $y=$this->y; 659 652 if(strpos($border,'L')!==false) 660 $s.=sprintf('%.2 f %.2f m %.2f %.2fl S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k);653 $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k); 661 654 if(strpos($border,'T')!==false) 662 $s.=sprintf('%.2 f %.2f m %.2f %.2fl S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k);655 $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k); 663 656 if(strpos($border,'R')!==false) 664 $s.=sprintf('%.2 f %.2f m %.2f %.2fl S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k);657 $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k); 665 658 if(strpos($border,'B')!==false) 666 $s.=sprintf('%.2 f %.2f m %.2f %.2fl S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k);659 $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k); 667 660 } 668 661 if($txt!=='') … … 677 670 $s.='q '.$this->TextColor.' '; 678 671 $txt2=str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt))); 679 $s.=sprintf('BT %.2 f %.2fTd (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2);672 $s.=sprintf('BT %.2F %.2F Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2); 680 673 if($this->underline) 681 674 $s.=' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt); … … 699 692 } 700 693 701 function MultiCell($w, $h,$txt,$border=0,$align='J',$fill=0, $ln = 2)694 function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false) 702 695 { 703 696 //Output text with automatic or explicit line breaks … … 735 728 $ns=0; 736 729 $nl=1; 737 $this->rise_h = 0; //³vZp738 739 730 while($i<$nb) 740 731 { 741 732 //Get next character 742 $c=$s {$i};733 $c=$s[$i]; 743 734 if($c=="\n") 744 735 { … … 756 747 $ns=0; 757 748 $nl++; 758 $this->rise_h += $h; //³vZp759 760 749 if($border && $nl==2) 761 750 $b=$b2; … … 788 777 { 789 778 $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0; 790 $this->_out(sprintf('%.3 fTw',$this->ws*$this->k));779 $this->_out(sprintf('%.3F Tw',$this->ws*$this->k)); 791 780 } 792 781 $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill); 793 782 $i=$sep+1; 794 783 } 795 $this->rise_h += $h; //³vZp796 784 $sep=-1; 797 785 $j=$i; … … 813 801 if($border && strpos($border,'B')!==false) 814 802 $b.='B'; 815 $this->Cell($w,$h,substr($s,$j,$i-$j),$b,$ln,$align,$fill); 816 $this->rise_h += $h; //ÁªÌ³ðvZ 817 //üsȵÝè©ÂA³ªKè̳ÈãÅ êÎY²ðÝèµÈ¨·B 818 if($ln == 0 and $h < $this->rise_h) { 819 $this->y = $this->y - $this->rise_h + $h; 820 } 821 822 //$this->x=$this->lMargin; 823 } 824 825 function Write($h,$txt,$link='') 803 $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); 804 $this->x=$this->lMargin; 805 } 806 807 function Write($h, $txt, $link='') 826 808 { 827 809 //Output text in flowing mode … … 839 821 { 840 822 //Get next character 841 $c=$s {$i};823 $c=$s[$i]; 842 824 if($c=="\n") 843 825 { … … 904 886 } 905 887 906 function Image($file,$x,$y,$w=0,$h=0,$type='',$link='') 888 function Ln($h=null) 889 { 890 //Line feed; default value is last cell height 891 $this->x=$this->lMargin; 892 if($h===null) 893 $this->y+=$this->lasth; 894 else 895 $this->y+=$h; 896 } 897 898 function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='') 907 899 { 908 900 //Put an image on the page 909 901 if(!isset($this->images[$file])) 910 902 { 911 //First use of image, get info903 //First use of this image, get info 912 904 if($type=='') 913 905 { … … 918 910 } 919 911 $type=strtolower($type); 920 $mqr=get_magic_quotes_runtime(); 921 set_magic_quotes_runtime(0); 922 if($type=='jpg' || $type=='jpeg') 923 $info=$this->_parsejpg($file); 924 elseif($type=='png') 925 $info=$this->_parsepng($file); 926 else 927 { 928 //Allow for additional formats 929 $mtd='_parse'.$type; 930 if(!method_exists($this,$mtd)) 931 $this->Error('Unsupported image type: '.$type); 932 $info=$this->$mtd($file); 933 } 934 set_magic_quotes_runtime($mqr); 912 if($type=='jpeg') 913 $type='jpg'; 914 $mtd='_parse'.$type; 915 if(!method_exists($this,$mtd)) 916 $this->Error('Unsupported image type: '.$type); 917 $info=$this->$mtd($file); 935 918 $info['i']=count($this->images)+1; 936 919 $this->images[$file]=$info; … … 945 928 $h=$info['h']/$this->k; 946 929 } 947 if($w==0)930 elseif($w==0) 948 931 $w=$h*$info['w']/$info['h']; 949 if($h==0)932 elseif($h==0) 950 933 $h=$w*$info['h']/$info['w']; 951 $this->_out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q',$w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i'])); 934 //Flowing mode 935 if($y===null) 936 { 937 if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak()) 938 { 939 //Automatic page break 940 $x2=$this->x; 941 $this->AddPage($this->CurOrientation,$this->CurPageFormat); 942 $this->x=$x2; 943 } 944 $y=$this->y; 945 $this->y+=$h; 946 } 947 if($x===null) 948 $x=$this->x; 949 $this->_out(sprintf('q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q',$w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i'])); 952 950 if($link) 953 951 $this->Link($x,$y,$w,$h,$link); 954 }955 956 function Ln($h='')957 {958 //Line feed; default value is last cell height959 $this->x=$this->lMargin;960 if(is_string($h))961 $this->y+=$this->lasth;962 else963 $this->y+=$h;964 952 } 965 953 … … 995 983 } 996 984 997 function SetXY($x, $y)985 function SetXY($x, $y) 998 986 { 999 987 //Set x and y positions … … 1002 990 } 1003 991 1004 function Output($name='', $dest='')992 function Output($name='', $dest='') 1005 993 { 1006 994 //Output PDF to some destination 1007 //Finish document if necessary1008 995 if($this->state<3) 1009 996 $this->Close(); 1010 //Normalize parameters1011 if(is_bool($dest))1012 $dest=$dest ? 'D' : 'F';1013 997 $dest=strtoupper($dest); 1014 998 if($dest=='') … … 1026 1010 case 'I': 1027 1011 //Send to standard output 1028 if(ob_get_ contents())1012 if(ob_get_length()) 1029 1013 $this->Error('Some data has already been output, can\'t send PDF file'); 1030 1014 if(php_sapi_name()!='cli') 1031 1015 { 1032 1016 //We send to a browser 1033 if(isset($_SERVER['HTTP_USER_AGENT']) and strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) { header('Pragma:'); }1034 1017 header('Content-Type: application/pdf'); 1035 1018 if(headers_sent()) 1036 $this->Error('Some data has already been output to browser, can\'t send PDF file');1019 $this->Error('Some data has already been output, can\'t send PDF file'); 1037 1020 header('Content-Length: '.strlen($this->buffer)); 1038 header('Content-disposition: inline; filename="'.$name.'"'); 1021 header('Content-Disposition: inline; filename="'.$name.'"'); 1022 header('Cache-Control: private, max-age=0, must-revalidate'); 1023 header('Pragma: public'); 1024 ini_set('zlib.output_compression','0'); 1039 1025 } 1040 1026 echo $this->buffer; … … 1042 1028 case 'D': 1043 1029 //Download file 1044 if(ob_get_ contents())1030 if(ob_get_length()) 1045 1031 $this->Error('Some data has already been output, can\'t send PDF file'); 1046 if(isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) { 1047 header('Pragma:'); 1048 header('Content-Type: application/force-download'); 1049 } 1050 else 1051 header('Content-Type: application/octet-stream'); 1032 header('Content-Type: application/x-download'); 1052 1033 if(headers_sent()) 1053 $this->Error('Some data has already been output to browser, can\'t send PDF file');1034 $this->Error('Some data has already been output, can\'t send PDF file'); 1054 1035 header('Content-Length: '.strlen($this->buffer)); 1055 header('Content-disposition: attachment; filename="'.$name.'"'); 1036 header('Content-Disposition: attachment; filename="'.$name.'"'); 1037 header('Cache-Control: private, max-age=0, must-revalidate'); 1038 header('Pragma: public'); 1039 ini_set('zlib.output_compression','0'); 1056 1040 echo $this->buffer; 1057 1041 break; … … 1080 1064 function _dochecks() 1081 1065 { 1082 //Check for locale-related bug 1083 if(1.1==1) 1084 $this->Error('Don\'t alter the locale before including class file'); 1085 //Check for decimal separator 1086 if(sprintf('%.1f',1.0)!='1.0') 1087 setlocale(LC_NUMERIC,'C'); 1066 //Check availability of %F 1067 if(sprintf('%.1F',1.0)!='1.0') 1068 $this->Error('This version of PHP is not supported'); 1069 //Check mbstring overloading 1070 if(ini_get('mbstring.func_overload') & 2) 1071 $this->Error('mbstring overloading must be disabled'); 1072 //Disable runtime magic quotes 1073 if(get_magic_quotes_runtime()) 1074 @set_magic_quotes_runtime(0); 1075 } 1076 1077 function _getpageformat($format) 1078 { 1079 $format=strtolower($format); 1080 if(!isset($this->PageFormats[$format])) 1081 $this->Error('Unknown page format: '.$format); 1082 $a=$this->PageFormats[$format]; 1083 return array($a[0]/$this->k, $a[1]/$this->k); 1088 1084 } 1089 1085 … … 1095 1091 } 1096 1092 1093 function _beginpage($orientation, $format) 1094 { 1095 $this->page++; 1096 $this->pages[$this->page]=''; 1097 $this->state=2; 1098 $this->x=$this->lMargin; 1099 $this->y=$this->tMargin; 1100 $this->FontFamily=''; 1101 //Check page size 1102 if($orientation=='') 1103 $orientation=$this->DefOrientation; 1104 else 1105 $orientation=strtoupper($orientation[0]); 1106 if($format=='') 1107 $format=$this->DefPageFormat; 1108 else 1109 { 1110 if(is_string($format)) 1111 $format=$this->_getpageformat($format); 1112 } 1113 if($orientation!=$this->CurOrientation || $format[0]!=$this->CurPageFormat[0] || $format[1]!=$this->CurPageFormat[1]) 1114 { 1115 //New size 1116 if($orientation=='P') 1117 { 1118 $this->w=$format[0]; 1119 $this->h=$format[1]; 1120 } 1121 else 1122 { 1123 $this->w=$format[1]; 1124 $this->h=$format[0]; 1125 } 1126 $this->wPt=$this->w*$this->k; 1127 $this->hPt=$this->h*$this->k; 1128 $this->PageBreakTrigger=$this->h-$this->bMargin; 1129 $this->CurOrientation=$orientation; 1130 $this->CurPageFormat=$format; 1131 } 1132 if($orientation!=$this->DefOrientation || $format[0]!=$this->DefPageFormat[0] || $format[1]!=$this->DefPageFormat[1]) 1133 $this->PageSizes[$this->page]=array($this->wPt, $this->hPt); 1134 } 1135 1136 function _endpage() 1137 { 1138 $this->state=1; 1139 } 1140 1141 function _escape($s) 1142 { 1143 //Escape special characters in strings 1144 $s=str_replace('\\','\\\\',$s); 1145 $s=str_replace('(','\\(',$s); 1146 $s=str_replace(')','\\)',$s); 1147 $s=str_replace("\r",'\\r',$s); 1148 return $s; 1149 } 1150 1151 function _textstring($s) 1152 { 1153 //Format a text string 1154 return '('.$this->_escape($s).')'; 1155 } 1156 1157 function _UTF8toUTF16($s) 1158 { 1159 //Convert UTF-8 to UTF-16BE with BOM 1160 $res="\xFE\xFF"; 1161 $nb=strlen($s); 1162 $i=0; 1163 while($i<$nb) 1164 { 1165 $c1=ord($s[$i++]); 1166 if($c1>=224) 1167 { 1168 //3-byte character 1169 $c2=ord($s[$i++]); 1170 $c3=ord($s[$i++]); 1171 $res.=chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2)); 1172 $res.=chr((($c2 & 0x03)<<6) + ($c3 & 0x3F)); 1173 } 1174 elseif($c1>=192) 1175 { 1176 //2-byte character 1177 $c2=ord($s[$i++]); 1178 $res.=chr(($c1 & 0x1C)>>2); 1179 $res.=chr((($c1 & 0x03)<<6) + ($c2 & 0x3F)); 1180 } 1181 else 1182 { 1183 //Single-byte character 1184 $res.="\0".chr($c1); 1185 } 1186 } 1187 return $res; 1188 } 1189 1190 function _dounderline($x, $y, $txt) 1191 { 1192 //Underline text 1193 $up=$this->CurrentFont['up']; 1194 $ut=$this->CurrentFont['ut']; 1195 $w=$this->GetStringWidth($txt)+$this->ws*substr_count($txt,' '); 1196 return sprintf('%.2F %.2F %.2F %.2F re f',$x*$this->k,($this->h-($y-$up/1000*$this->FontSize))*$this->k,$w*$this->k,-$ut/1000*$this->FontSizePt); 1197 } 1198 1199 function _parsejpg($file) 1200 { 1201 //Extract info from a JPEG file 1202 $a=GetImageSize($file); 1203 if(!$a) 1204 $this->Error('Missing or incorrect image file: '.$file); 1205 if($a[2]!=2) 1206 $this->Error('Not a JPEG file: '.$file); 1207 if(!isset($a['channels']) || $a['channels']==3) 1208 $colspace='DeviceRGB'; 1209 elseif($a['channels']==4) 1210 $colspace='DeviceCMYK'; 1211 else 1212 $colspace='DeviceGray'; 1213 $bpc=isset($a['bits']) ? $a['bits'] : 8; 1214 //Read whole file 1215 $f=fopen($file,'rb'); 1216 $data=''; 1217 while(!feof($f)) 1218 $data.=fread($f,8192); 1219 fclose($f); 1220 return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data); 1221 } 1222 1223 function _parsepng($file) 1224 { 1225 //Extract info from a PNG file 1226 $f=fopen($file,'rb'); 1227 if(!$f) 1228 $this->Error('Can\'t open image file: '.$file); 1229 //Check signature 1230 if($this->_readstream($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) 1231 $this->Error('Not a PNG file: '.$file); 1232 //Read header chunk 1233 $this->_readstream($f,4); 1234 if($this->_readstream($f,4)!='IHDR') 1235 $this->Error('Incorrect PNG file: '.$file); 1236 $w=$this->_readint($f); 1237 $h=$this->_readint($f); 1238 $bpc=ord($this->_readstream($f,1)); 1239 if($bpc>8) 1240 $this->Error('16-bit depth not supported: '.$file); 1241 $ct=ord($this->_readstream($f,1)); 1242 if($ct==0) 1243 $colspace='DeviceGray'; 1244 elseif($ct==2) 1245 $colspace='DeviceRGB'; 1246 elseif($ct==3) 1247 $colspace='Indexed'; 1248 else 1249 $this->Error('Alpha channel not supported: '.$file); 1250 if(ord($this->_readstream($f,1))!=0) 1251 $this->Error('Unknown compression method: '.$file); 1252 if(ord($this->_readstream($f,1))!=0) 1253 $this->Error('Unknown filter method: '.$file); 1254 if(ord($this->_readstream($f,1))!=0) 1255 $this->Error('Interlacing not supported: '.$file); 1256 $this->_readstream($f,4); 1257 $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>'; 1258 //Scan chunks looking for palette, transparency and image data 1259 $pal=''; 1260 $trns=''; 1261 $data=''; 1262 do 1263 { 1264 $n=$this->_readint($f); 1265 $type=$this->_readstream($f,4); 1266 if($type=='PLTE') 1267 { 1268 //Read palette 1269 $pal=$this->_readstream($f,$n); 1270 $this->_readstream($f,4); 1271 } 1272 elseif($type=='tRNS') 1273 { 1274 //Read transparency info 1275 $t=$this->_readstream($f,$n); 1276 if($ct==0) 1277 $trns=array(ord(substr($t,1,1))); 1278 elseif($ct==2) 1279 $trns=array(ord(substr($t,1,1)), ord(substr($t,3,1)), ord(substr($t,5,1))); 1280 else 1281 { 1282 $pos=strpos($t,chr(0)); 1283 if($pos!==false) 1284 $trns=array($pos); 1285 } 1286 $this->_readstream($f,4); 1287 } 1288 elseif($type=='IDAT') 1289 { 1290 //Read image data block 1291 $data.=$this->_readstream($f,$n); 1292 $this->_readstream($f,4); 1293 } 1294 elseif($type=='IEND') 1295 break; 1296 else 1297 $this->_readstream($f,$n+4); 1298 } 1299 while($n); 1300 if($colspace=='Indexed' && empty($pal)) 1301 $this->Error('Missing palette in '.$file); 1302 fclose($f); 1303 return array('w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'FlateDecode', 'parms'=>$parms, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$data); 1304 } 1305 1306 function _readstream($f, $n) 1307 { 1308 //Read n bytes from stream 1309 $res=''; 1310 while($n>0 && !feof($f)) 1311 { 1312 $s=fread($f,$n); 1313 if($s===false) 1314 $this->Error('Error while reading stream'); 1315 $n-=strlen($s); 1316 $res.=$s; 1317 } 1318 if($n>0) 1319 $this->Error('Unexpected end of stream'); 1320 return $res; 1321 } 1322 1323 function _readint($f) 1324 { 1325 //Read a 4-byte integer from stream 1326 $a=unpack('Ni',$this->_readstream($f,4)); 1327 return $a['i']; 1328 } 1329 1330 function _parsegif($file) 1331 { 1332 //Extract info from a GIF file (via PNG conversion) 1333 if(!function_exists('imagepng')) 1334 $this->Error('GD extension is required for GIF support'); 1335 if(!function_exists('imagecreatefromgif')) 1336 $this->Error('GD has no GIF read support'); 1337 $im=imagecreatefromgif($file); 1338 if(!$im) 1339 $this->Error('Missing or incorrect image file: '.$file); 1340 imageinterlace($im,0); 1341 $tmp=tempnam('.','gif'); 1342 if(!$tmp) 1343 $this->Error('Unable to create a temporary file'); 1344 if(!imagepng($im,$tmp)) 1345 $this->Error('Error while saving to temporary file'); 1346 imagedestroy($im); 1347 $info=$this->_parsepng($tmp); 1348 unlink($tmp); 1349 return $info; 1350 } 1351 1352 function _newobj() 1353 { 1354 //Begin a new object 1355 $this->n++; 1356 $this->offsets[$this->n]=strlen($this->buffer); 1357 $this->_out($this->n.' 0 obj'); 1358 } 1359 1360 function _putstream($s) 1361 { 1362 $this->_out('stream'); 1363 $this->_out($s); 1364 $this->_out('endstream'); 1365 } 1366 1367 function _out($s) 1368 { 1369 //Add a line to the document 1370 if($this->state==2) 1371 $this->pages[$this->page].=$s."\n"; 1372 else 1373 $this->buffer.=$s."\n"; 1374 } 1375 1097 1376 function _putpages() 1098 1377 { … … 1106 1385 if($this->DefOrientation=='P') 1107 1386 { 1108 $wPt=$this-> fwPt;1109 $hPt=$this-> fhPt;1110 } 1111 else 1112 { 1113 $wPt=$this-> fhPt;1114 $hPt=$this-> fwPt;1387 $wPt=$this->DefPageFormat[0]*$this->k; 1388 $hPt=$this->DefPageFormat[1]*$this->k; 1389 } 1390 else 1391 { 1392 $wPt=$this->DefPageFormat[1]*$this->k; 1393 $hPt=$this->DefPageFormat[0]*$this->k; 1115 1394 } 1116 1395 $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; … … 1121 1400 $this->_out('<</Type /Page'); 1122 1401 $this->_out('/Parent 1 0 R'); 1123 if(isset($this-> OrientationChanges[$n]))1124 $this->_out(sprintf('/MediaBox [0 0 %.2 f %.2f]',$hPt,$wPt));1402 if(isset($this->PageSizes[$n])) 1403 $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$this->PageSizes[$n][0],$this->PageSizes[$n][1])); 1125 1404 $this->_out('/Resources 2 0 R'); 1126 1405 if(isset($this->PageLinks[$n])) … … 1130 1409 foreach($this->PageLinks[$n] as $pl) 1131 1410 { 1132 $rect=sprintf('%.2 f %.2f %.2f %.2f',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);1411 $rect=sprintf('%.2F %.2F %.2F %.2F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]); 1133 1412 $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] '; 1134 1413 if(is_string($pl[4])) … … 1137 1416 { 1138 1417 $l=$this->links[$pl[4]]; 1139 $h=isset($this-> OrientationChanges[$l[0]]) ? $wPt: $hPt;1140 $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2 fnull]>>',1+2*$l[0],$h-$l[1]*$this->k);1418 $h=isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt; 1419 $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>',1+2*$l[0],$h-$l[1]*$this->k); 1141 1420 } 1142 1421 } … … 1161 1440 $this->_out($kids.']'); 1162 1441 $this->_out('/Count '.$nb); 1163 $this->_out(sprintf('/MediaBox [0 0 %.2 f %.2f]',$wPt,$hPt));1442 $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$wPt,$hPt)); 1164 1443 $this->_out('>>'); 1165 1444 $this->_out('endobj'); … … 1176 1455 $this->_out('endobj'); 1177 1456 } 1178 $mqr=get_magic_quotes_runtime();1179 set_magic_quotes_runtime(0);1180 1457 foreach($this->FontFiles as $file=>$info) 1181 1458 { … … 1193 1470 if(!$compressed && isset($info['length2'])) 1194 1471 { 1195 $header=(ord($font {0})==128);1472 $header=(ord($font[0])==128); 1196 1473 if($header) 1197 1474 { … … 1199 1476 $font=substr($font,6); 1200 1477 } 1201 if($header && ord($font {$info['length1']})==128)1478 if($header && ord($font[$info['length1']])==128) 1202 1479 { 1203 1480 //Strip second binary header … … 1215 1492 $this->_out('endobj'); 1216 1493 } 1217 set_magic_quotes_runtime($mqr);1218 1494 foreach($this->fonts as $k=>$font) 1219 1495 { … … 1375 1651 if(!empty($this->creator)) 1376 1652 $this->_out('/Creator '.$this->_textstring($this->creator)); 1377 $this->_out('/CreationDate '.$this->_textstring('D:'. date('YmdHis')));1653 $this->_out('/CreationDate '.$this->_textstring('D:'.@date('YmdHis'))); 1378 1654 } 1379 1655 … … 1444 1720 $this->state=3; 1445 1721 } 1446 1447 function _beginpage($orientation)1448 {1449 $this->page++;1450 $this->pages[$this->page]='';1451 $this->state=2;1452 $this->x=$this->lMargin;1453 $this->y=$this->tMargin;1454 $this->FontFamily='';1455 //Page orientation1456 if(!$orientation)1457 $orientation=$this->DefOrientation;1458 else1459 {1460 $orientation=strtoupper($orientation{0});1461 if($orientation!=$this->DefOrientation)1462 $this->OrientationChanges[$this->page]=true;1463 }1464 if($orientation!=$this->CurOrientation)1465 {1466 //Change orientation1467 if($orientation=='P')1468 {1469 $this->wPt=$this->fwPt;1470 $this->hPt=$this->fhPt;1471 $this->w=$this->fw;1472 $this->h=$this->fh;1473 }1474 else1475 {1476 $this->wPt=$this->fhPt;1477 $this->hPt=$this->fwPt;1478 $this->w=$this->fh;1479 $this->h=$this->fw;1480 }1481 $this->PageBreakTrigger=$this->h-$this->bMargin;1482 $this->CurOrientation=$orientation;1483 }1484 }1485 1486 function _endpage()1487 {1488 //End of page contents1489 $this->state=1;1490 }1491 1492 function _newobj()1493 {1494 //Begin a new object1495 $this->n++;1496 $this->offsets[$this->n]=strlen($this->buffer);1497 $this->_out($this->n.' 0 obj');1498 }1499 1500 function _dounderline($x,$y,$txt)1501 {1502 //Underline text1503 $up=$this->CurrentFont['up'];1504 $ut=$this->CurrentFont['ut'];1505 $w=$this->GetStringWidth($txt)+$this->ws*substr_count($txt,' ');1506 return sprintf('%.2f %.2f %.2f %.2f re f',$x*$this->k,($this->h-($y-$up/1000*$this->FontSize))*$this->k,$w*$this->k,-$ut/1000*$this->FontSizePt);1507 }1508 1509 function _parsejpg($file)1510 {1511 //Extract info from a JPEG file1512 $a=GetImageSize($file);1513 if(!$a)1514 $this->Error('Missing or incorrect image file: '.$file);1515 if($a[2]!=2)1516 $this->Error('Not a JPEG file: '.$file);1517 if(!isset($a['channels']) || $a['channels']==3)1518 $colspace='DeviceRGB';1519 elseif($a['channels']==4)1520 $colspace='DeviceCMYK';1521 else1522 $colspace='DeviceGray';1523 $bpc=isset($a['bits']) ? $a['bits'] : 8;1524 //Read whole file1525 $f=fopen($file,'rb');1526 $data='';1527 while(!feof($f))1528 $data.=fread($f,4096);1529 fclose($f);1530 return array('w'=>$a[0],'h'=>$a[1],'cs'=>$colspace,'bpc'=>$bpc,'f'=>'DCTDecode','data'=>$data);1531 }1532 1533 function _parsepng($file)1534 {1535 //Extract info from a PNG file1536 $f=fopen($file,'rb');1537 if(!$f)1538 $this->Error('Can\'t open image file: '.$file);1539 //Check signature1540 if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))1541 $this->Error('Not a PNG file: '.$file);1542 //Read header chunk1543 fread($f,4);1544 if(fread($f,4)!='IHDR')1545 $this->Error('Incorrect PNG file: '.$file);1546 $w=$this->_freadint($f);1547 $h=$this->_freadint($f);1548 $bpc=ord(fread($f,1));1549 if($bpc>8)1550 $this->Error('16-bit depth not supported: '.$file);1551 $ct=ord(fread($f,1));1552 if($ct==0)1553 $colspace='DeviceGray';1554 elseif($ct==2)1555 $colspace='DeviceRGB';1556 elseif($ct==3)1557 $colspace='Indexed';1558 else1559 $this->Error('Alpha channel not supported: '.$file);1560 if(ord(fread($f,1))!=0)1561 $this->Error('Unknown compression method: '.$file);1562 if(ord(fread($f,1))!=0)1563 $this->Error('Unknown filter method: '.$file);1564 if(ord(fread($f,1))!=0)1565 $this->Error('Interlacing not supported: '.$file);1566 fread($f,4);1567 $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';1568 //Scan chunks looking for palette, transparency and image data1569 $pal='';1570 $trns='';1571 $data='';1572 do1573 {1574 $n=$this->_freadint($f);1575 $type=fread($f,4);1576 if($type=='PLTE')1577 {1578 //Read palette1579 $pal=fread($f,$n);1580 fread($f,4);1581 }1582 elseif($type=='tRNS')1583 {1584 //Read transparency info1585 $t=fread($f,$n);1586 if($ct==0)1587 $trns=array(ord(substr($t,1,1)));1588 elseif($ct==2)1589 $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));1590 else1591 {1592 $pos=strpos($t,chr(0));1593 if($pos!==false)1594 $trns=array($pos);1595 }1596 fread($f,4);1597 }1598 elseif($type=='IDAT')1599 {1600 //Read image data block1601 $data.=fread($f,$n);1602 fread($f,4);1603 }1604 elseif($type=='IEND')1605 break;1606 else1607 fread($f,$n+4);1608 }1609 while($n);1610 if($colspace=='Indexed' && empty($pal))1611 $this->Error('Missing palette in '.$file);1612 fclose($f);1613 return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data);1614 }1615 1616 function _freadint($f)1617 {1618 //Read a 4-byte integer from file1619 $a=unpack('Ni',fread($f,4));1620 return $a['i'];1621 }1622 1623 function _textstring($s)1624 {1625 //Format a text string1626 return '('.$this->_escape($s).')';1627 }1628 1629 function _escape($s)1630 {1631 //Add \ before \, ( and )1632 return str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$s)));1633 }1634 1635 function _putstream($s)1636 {1637 $this->_out('stream');1638 $this->_out($s);1639 $this->_out('endstream');1640 }1641 1642 function _out($s)1643 {1644 //Add a line to the document1645 if($this->state==2)1646 $this->pages[$this->page].=$s."\n";1647 else1648 $this->buffer.=$s."\n";1649 }1650 1722 //End of class 1651 1723 } … … 1658 1730 } 1659 1731 1660 }1661 1732 ?> -
branches/version-2_5-dev/data/module/fpdf/fpdf_tpl.php
r18701 r19716 1 1 <?php 2 2 // 3 // FPDF_TPL - Version 1. 1.14 // 5 // Copyright 2004-20 07Setasign - Jan Slabon3 // FPDF_TPL - Version 1.2 4 // 5 // Copyright 2004-2010 Setasign - Jan Slabon 6 6 // 7 7 // Licensed under the Apache License, Version 2.0 (the "License"); … … 18 18 // 19 19 20 require_once("fpdf.php");21 22 20 class FPDF_TPL extends FPDF { 23 21 /** … … 52 50 53 51 /** 54 * Constructor 55 * See FPDF-Documentation 56 * @param string $orientation 57 * @param string $unit 58 * @param mixed $format 59 */ 60 function fpdf_tpl($orientation='P',$unit='mm',$format='A4') { 61 parent::fpdf($orientation,$unit,$format); 62 } 52 * Last used Template data 53 * 54 * @var array 55 */ 56 var $lastUsedTemplateData = array(); 63 57 64 58 /** … … 80 74 * @return int The ID of new created Template 81 75 */ 82 function beginTemplate($x=null,$y=null,$w=null,$h=null) { 76 function beginTemplate($x = null, $y = null, $w = null, $h = null) { 77 if (is_subclass_of($this, 'TCPDF')) { 78 $this->Error('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.'); 79 return; 80 } 81 83 82 if ($this->page <= 0) 84 83 $this->error("You have to add a page to fpdf first!"); … … 120 119 121 120 $this->_intpl = true; 122 $this->SetXY($x +$this->lMargin,$y+$this->tMargin);123 $this->SetRightMargin($this->w -$w+$this->rMargin);121 $this->SetXY($x + $this->lMargin, $y + $this->tMargin); 122 $this->SetRightMargin($this->w - $w + $this->rMargin); 124 123 125 124 return $this->tpl; … … 134 133 */ 135 134 function endTemplate() { 135 if (is_subclass_of($this, 'TCPDF')) { 136 $args = func_get_args(); 137 return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args); 138 } 139 136 140 if ($this->_intpl) { 137 141 $this->_intpl = false; … … 168 172 * @retrun array The height and width of the template 169 173 */ 170 function useTemplate($tplidx, $_x =null, $_y=null, $_w=0, $_h=0) {174 function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0) { 171 175 if ($this->page <= 0) 172 $this->error("You have to add a page to fpdf first!");173 176 $this->error('You have to add a page first!'); 177 174 178 if (!isset($this->tpls[$tplidx])) 175 $this->error( "Template does not exist!");179 $this->error('Template does not exist!'); 176 180 177 181 if ($this->_intpl) { … … 180 184 181 185 $tpl =& $this->tpls[$tplidx]; 182 $x = $tpl['x'];183 $y = $tpl['y'];184 186 $w = $tpl['w']; 185 187 $h = $tpl['h']; 186 188 187 189 if ($_x == null) 188 $_x = $x;190 $_x = 0; 189 191 if ($_y == null) 190 $_y = $y; 191 $wh = $this->getTemplateSize($tplidx,$_w,$_h); 192 $_y = 0; 193 194 $_x += $tpl['x']; 195 $_y += $tpl['y']; 196 197 $wh = $this->getTemplateSize($tplidx, $_w, $_h); 192 198 $_w = $wh['w']; 193 199 $_h = $wh['h']; 194 200 195 $this->_out(sprintf("q %.4f 0 0 %.4f %.2f %.2f cm", ($_w/$w), ($_h/$h), $_x*$this->k, ($this->h-($_y+$_h))*$this->k)); // Translate 196 $this->_out($this->tplprefix.$tplidx." Do Q"); 197 198 return array("w" => $_w, "h" => $_h); 201 $tData = array( 202 'x' => $this->x, 203 'y' => $this->y, 204 'w' => $_w, 205 'h' => $_h, 206 'scaleX' => ($_w / $w), 207 'scaleY' => ($_h / $h), 208 'tx' => $_x, 209 'ty' => ($this->h - $_y - $_h), 210 'lty' => ($this->h - $_y - $_h) - ($this->h - $h) * ($_h / $h) 211 ); 212 213 $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm', $tData['scaleX'], $tData['scaleY'], $tData['tx'] * $this->k, $tData['ty'] * $this->k)); // Translate 214 $this->_out(sprintf('%s%d Do Q', $this->tplprefix, $tplidx)); 215 216 // reset font in the outer graphic state 217 if ($this->FontFamily) { 218 $family = $this->FontFamily; 219 $this->FontFamily = ''; 220 $this->SetFont($family); 221 } 222 223 $this->lastUsedTemplateData = $tData; 224 225 return array('w' => $_w, 'h' => $_h); 199 226 } 200 227 … … 209 236 * @return array The height and width of the template 210 237 */ 211 function getTemplateSize($tplidx, $_w =0, $_h=0) {238 function getTemplateSize($tplidx, $_w = 0, $_h = 0) { 212 239 if (!$this->tpls[$tplidx]) 213 240 return false; … … 222 249 } 223 250 224 if($_w ==0)225 $_w =$_h*$w/$h;226 if($_h ==0)227 $_h =$_w*$h/$w;251 if($_w == 0) 252 $_w = $_h * $w / $h; 253 if($_h == 0) 254 $_h = $_w * $h / $w; 228 255 229 256 return array("w" => $_w, "h" => $_h); … … 231 258 232 259 /** 233 * See FPDF-Documentation ;-) 234 */ 235 function SetFont($family,$style='',$size=0) { 260 * See FPDF/TCPDF-Documentation ;-) 261 */ 262 public function SetFont($family, $style = '', $size = 0) { 263 if (is_subclass_of($this, 'TCPDF')) { 264 $args = func_get_args(); 265 return call_user_func_array(array($this, 'TCPDF::SetFont'), $args); 266 } 267 236 268 /** 237 269 * force the resetting of font changes in a template … … 242 274 parent::SetFont($family, $style, $size); 243 275 244 $fontkey = $this->FontFamily .$this->FontStyle;276 $fontkey = $this->FontFamily . $this->FontStyle; 245 277 246 278 if ($this->_intpl) { … … 252 284 253 285 /** 254 * See FPDF-Documentation ;-) 255 */ 256 function Image($file,$x,$y,$w=0,$h=0,$type='',$link='') { 257 parent::Image($file,$x,$y,$w,$h,$type,$link); 286 * See FPDF/TCPDF-Documentation ;-) 287 */ 288 function Image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '') { 289 if (is_subclass_of($this, 'TCPDF')) { 290 $args = func_get_args(); 291 return call_user_func_array(array($this, 'TCPDF::Image'), $args); 292 } 293 294 $ret = parent::Image($file, $x, $y, $w, $h, $type, $link); 258 295 if ($this->_intpl) { 259 296 $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file]; … … 261 298 $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file]; 262 299 } 300 301 return $ret; 263 302 } 264 303 … … 268 307 * AddPage is not available when you're "in" a template. 269 308 */ 270 function AddPage($orientation='') { 309 function AddPage($orientation = '', $format = '') { 310 if (is_subclass_of($this, 'TCPDF')) { 311 $args = func_get_args(); 312 return call_user_func_array(array($this, 'TCPDF::AddPage'), $args); 313 } 314 271 315 if ($this->_intpl) 272 316 $this->Error('Adding pages in templates isn\'t possible!'); 273 parent::AddPage($orientation); 317 318 parent::AddPage($orientation, $format); 274 319 } 275 320 … … 277 322 * Preserve adding Links in Templates ...won't work 278 323 */ 279 function Link($x,$y,$w,$h,$link) { 324 function Link($x, $y, $w, $h, $link) { 325 if (is_subclass_of($this, 'TCPDF')) { 326 $args = func_get_args(); 327 return call_user_func_array(array($this, 'TCPDF::Link'), $args); 328 } 329 280 330 if ($this->_intpl) 281 331 $this->Error('Using links in templates aren\'t possible!'); 282 parent::Link($x,$y,$w,$h,$link); 332 333 parent::Link($x, $y, $w, $h, $link); 283 334 } 284 335 285 336 function AddLink() { 337 if (is_subclass_of($this, 'TCPDF')) { 338 $args = func_get_args(); 339 return call_user_func_array(array($this, 'TCPDF::AddLink'), $args); 340 } 341 286 342 if ($this->_intpl) 287 343 $this->Error('Adding links in templates aren\'t possible!'); … … 289 345 } 290 346 291 function SetLink($link,$y=0,$page=-1) { 347 function SetLink($link, $y = 0, $page = -1) { 348 if (is_subclass_of($this, 'TCPDF')) { 349 $args = func_get_args(); 350 return call_user_func_array(array($this, 'TCPDF::SetLink'), $args); 351 } 352 292 353 if ($this->_intpl) 293 354 $this->Error('Setting links in templates aren\'t possible!'); 294 parent::SetLink($link, $y,$page);355 parent::SetLink($link, $y, $page); 295 356 } 296 357 … … 309 370 $this->_out('/Subtype /Form'); 310 371 $this->_out('/FormType 1'); 311 $this->_out(sprintf('/BBox [%.2f %.2f %.2f %.2f]',$tpl['x']*$this->k, ($tpl['h']-$tpl['y'])*$this->k, $tpl['w']*$this->k, ($tpl['h']-$tpl['y']-$tpl['h'])*$this->k)); 372 $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', 373 // llx 374 $tpl['x'] * $this->k, 375 // lly 376 -$tpl['y'] * $this->k, 377 // urx 378 ($tpl['w'] + $tpl['x']) * $this->k, 379 // ury 380 ($tpl['h'] - $tpl['y']) * $this->k 381 )); 382 383 if ($tpl['x'] != 0 || $tpl['y'] != 0) { 384 $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]', 385 -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2 386 )); 387 } 388 312 389 $this->_out('/Resources '); 313 390 … … 316 393 $this->_out('/Font <<'); 317 394 foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) 318 $this->_out('/F' .$font['i'].' '.$font['n'].' 0 R');395 $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); 319 396 $this->_out('>>'); 320 397 } … … 325 402 if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { 326 403 foreach($this->_res['tpl'][$tplidx]['images'] as $image) 327 $this->_out('/I' .$image['i'].' '.$image['n'].' 0 R');404 $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); 328 405 } 329 406 if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { 330 407 foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) 331 $this->_out($this->tplprefix .$i.' '.$tpl['n'].' 0 R');408 $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); 332 409 } 333 410 $this->_out('>>'); … … 335 412 $this->_out('>>'); 336 413 337 $this->_out('/Length ' .strlen($p).' >>');414 $this->_out('/Length ' . strlen($p) . ' >>'); 338 415 $this->_putstream($p); 339 416 $this->_out('endobj'); … … 342 419 343 420 /** 344 * Private Method 345 */ 346 function _putresources() { 347 $this->_putfonts(); 348 $this->_putimages(); 349 $this->_putformxobjects(); 350 //Resource dictionary 351 $this->offsets[2]=strlen($this->buffer); 352 $this->_out('2 0 obj'); 353 $this->_out('<<'); 354 $this->_putresourcedict(); 355 $this->_out('>>'); 356 $this->_out('endobj'); 421 * Overwritten to add _putformxobjects() after _putimages() 422 * 423 */ 424 function _putimages() { 425 parent::_putimages(); 426 $this->_putformxobjects(); 357 427 } 358 428 … … 362 432 if (count($this->tpls)) { 363 433 foreach($this->tpls as $tplidx => $tpl) { 364 $this->_out( $this->tplprefix.$tplidx.' '.$tpl['n'].' 0 R');434 $this->_out(sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n'])); 365 435 } 366 436 } … … 371 441 */ 372 442 function _out($s) { 373 //Add a line to the document 374 if ($this->state==2) { 375 if (!$this->_intpl) 376 $this->pages[$this->page].=$s."\n"; 377 else 378 $this->tpls[$this->tpl]['buffer'] .= $s."\n"; 379 } else { 380 $this->buffer.=$s."\n"; 381 } 443 if ($this->state == 2 && $this->_intpl) { 444 $this->tpls[$this->tpl]['buffer'] .= $s . "\n"; 445 } else { 446 parent::_out($s); 447 } 382 448 } 383 449 } 384 385 ?> -
branches/version-2_5-dev/data/module/fpdf/fpdi.php
r17260 r19716 1 1 <?php 2 2 // 3 // FPDI - Version 1. 23 // FPDI - Version 1.4 4 4 // 5 // Copyright 2004-20 07Setasign - Jan Slabon5 // Copyright 2004-2010 Setasign - Jan Slabon 6 6 // 7 7 // Licensed under the Apache License, Version 2.0 (the "License"); … … 18 18 // 19 19 20 define('FPDI_VERSION','1.2'); 21 22 ini_set('auto_detect_line_endings',1); // Strongly required! 23 24 require_once("fpdf_tpl.php"); 25 require_once("fpdi_pdf_parser.php"); 20 define('FPDI_VERSION', '1.4'); 21 22 // Check for TCPDF and remap TCPDF to FPDF 23 if (class_exists('TCPDF', false)) { 24 require_once('fpdi2tcpdf_bridge.php'); 25 } 26 27 require_once('fpdf_tpl.php'); 28 require_once('fpdi_pdf_parser.php'); 26 29 27 30 … … 46 49 47 50 /** 48 * Highest version of imported PDF49 * @var double50 */51 var $importVersion = 1.3;52 53 /**54 51 * object stack 55 52 * @var array … … 76 73 77 74 /** 78 * Constructor 79 * See FPDF-Manual 80 */ 81 function FPDI($orientation='P',$unit='mm',$format='A4') { 82 parent::FPDF_TPL($orientation,$unit,$format); 83 } 75 * Cache for imported pages/template ids 76 * @var array 77 */ 78 var $_importedPages = array(); 84 79 85 80 /** … … 91 86 function setSourceFile($filename) { 92 87 $this->current_filename = $filename; 93 $fn =& $this->current_filename; 94 95 if (!isset($this->parsers[$fn])) 96 $this->parsers[$fn] =& new fpdi_pdf_parser($fn,$this); 97 $this->current_parser =& $this->parsers[$fn]; 98 99 return $this->parsers[$fn]->getPageCount(); 100 } 101 88 89 if (!isset($this->parsers[$filename])) 90 $this->parsers[$filename] = $this->_getPdfParser($filename); 91 $this->current_parser =& $this->parsers[$filename]; 92 93 return $this->parsers[$filename]->getPageCount(); 94 } 95 96 /** 97 * Returns a PDF parser object 98 * 99 * @param string $filename 100 * @return fpdi_pdf_parser 101 */ 102 function _getPdfParser($filename) { 103 return new fpdi_pdf_parser($filename, $this); 104 } 105 106 /** 107 * Get the current PDF version 108 * 109 * @return string 110 */ 111 function getPDFVersion() { 112 return $this->PDFVersion; 113 } 114 115 /** 116 * Set the PDF version 117 * 118 * @return string 119 */ 120 function setPDFVersion($version = '1.3') { 121 $this->PDFVersion = $version; 122 } 123 102 124 /** 103 125 * Import a page … … 106 128 * @return int Index of imported page - to use with fpdf_tpl::useTemplate() 107 129 */ 108 function importPage($pageno, $boxName ='/CropBox') {130 function importPage($pageno, $boxName = '/CropBox') { 109 131 if ($this->_intpl) { 110 return $this->error("Please import the desired pages before creating a new template."); 111 } 112 113 $fn =& $this->current_filename; 132 return $this->error('Please import the desired pages before creating a new template.'); 133 } 134 135 $fn = $this->current_filename; 136 137 // check if page already imported 138 $pageKey = $fn . ((int)$pageno) . $boxName; 139 if (isset($this->_importedPages[$pageKey])) 140 return $this->_importedPages[$pageKey]; 114 141 115 142 $parser =& $this->parsers[$fn]; 116 143 $parser->setPageno($pageno); 117 144 118 $this->tpl++;119 $this->tpls[$this->tpl] = array();120 $tpl =& $this->tpls[$this->tpl];121 $tpl['parser'] =& $parser;122 $tpl['resources'] = $parser->getPageResources();123 $tpl['buffer'] = $parser->getContent();124 125 145 if (!in_array($boxName, $parser->availableBoxes)) 126 return $this->Error(sprintf( "Unknown box: %s", $boxName));127 $pageboxes = $parser->getPageBoxes($pageno );146 return $this->Error(sprintf('Unknown box: %s', $boxName)); 147 $pageboxes = $parser->getPageBoxes($pageno, $this->k); 128 148 129 149 /** … … 134 154 * ArtBox: Default -> CropBox 135 155 */ 136 if (!isset($pageboxes[$boxName]) && ($boxName == "/BleedBox" || $boxName == "/TrimBox" || $boxName == "/ArtBox"))137 $boxName = "/CropBox";138 if (!isset($pageboxes[$boxName]) && $boxName == "/CropBox")139 $boxName = "/MediaBox";156 if (!isset($pageboxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox')) 157 $boxName = '/CropBox'; 158 if (!isset($pageboxes[$boxName]) && $boxName == '/CropBox') 159 $boxName = '/MediaBox'; 140 160 141 161 if (!isset($pageboxes[$boxName])) … … 144 164 145 165 $box = $pageboxes[$boxName]; 166 167 $this->tpl++; 168 $this->tpls[$this->tpl] = array(); 169 $tpl =& $this->tpls[$this->tpl]; 170 $tpl['parser'] =& $parser; 171 $tpl['resources'] = $parser->getPageResources(); 172 $tpl['buffer'] = $parser->getContent(); 146 173 $tpl['box'] = $box; 147 174 148 175 // To build an array that can be used by PDF_TPL::useTemplate() 149 $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl],$box); 176 $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl], $box); 177 150 178 // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects() 151 179 $tpl['x'] = 0; 152 180 $tpl['y'] = 0; 153 181 154 $page =& $parser->pages[$parser->pageno]; 155 156 // fix for rotated pages 182 // handle rotated pages 157 183 $rotation = $parser->getPageRotation($pageno); 184 $tpl['_rotationAngle'] = 0; 158 185 if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) { 159 186 $steps = $angle / 90; 160 187 161 188 $_w = $tpl['w']; … … 164 191 $tpl['h'] = $steps % 2 == 0 ? $_h : $_w; 165 192 166 if ($steps % 2 != 0) { 167 $x = $y = ($steps == 1 || $steps == -3) ? $tpl['h'] : $tpl['w']; 168 } else { 169 $x = $tpl['w']; 170 $y = $tpl['h']; 171 } 172 173 $cx=($x/2+$tpl['box']['x'])*$this->k; 174 $cy=($y/2+$tpl['box']['y'])*$this->k; 175 176 $angle*=-1; 177 178 $angle*=M_PI/180; 179 $c=cos($angle); 180 $s=sin($angle); 181 182 $tpl['buffer'] = sprintf('q %.5f %.5f %.5f %.5f %.2f %.2f cm 1 0 0 1 %.2f %.2f cm %s Q',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy, $tpl['buffer']); 183 } 193 if ($angle < 0) 194 $angle += 360; 195 196 $tpl['_rotationAngle'] = $angle * -1; 197 } 198 199 $this->_importedPages[$pageKey] = $this->tpl; 184 200 185 201 return $this->tpl; … … 190 206 } 191 207 192 function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) { 193 $this->_out('q 0 J 1 w 0 j 0 G'); // reset standard values 208 function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0, $adjustPageSize = false) { 209 if ($adjustPageSize == true && is_null($_x) && is_null($_y)) { 210 $size = $this->getTemplateSize($tplidx, $_w, $_h); 211 $format = array($size['w'], $size['h']); 212 if (is_subclass_of($this, 'TCPDF')) { 213 $this->setPageFormat($format, $format[0] > $format[1] ? 'L' : 'P'); 214 } else { 215 if ($format[0] != $this->CurPageFormat[0] || $format[1] != $this->CurPageFormat[1]) { 216 $this->w = $format[0]; 217 $this->h = $format[1]; 218 $this->wPt = $this->w * $this->k; 219 $this->hPt = $this->h * $this->k; 220 $this->PageBreakTrigger = $this->h - $this->bMargin; 221 $this->CurPageFormat = $format; 222 $this->PageSizes[$this->page] = array($this->wPt, $this->hPt); 223 } 224 } 225 } 226 227 $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values 194 228 $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h); 195 229 $this->_out('Q'); 230 196 231 return $s; 197 232 } … … 204 239 foreach($this->parsers AS $filename => $p) { 205 240 $this->current_parser =& $this->parsers[$filename]; 206 if (is _array($this->_obj_stack[$filename])) {207 while( $n = key($this->_obj_stack[$filename])) {208 $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c, $this->_obj_stack[$filename][$n][1]);241 if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) { 242 while(($n = key($this->_obj_stack[$filename])) !== null) { 243 $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c, $this->_obj_stack[$filename][$n][1]); 209 244 210 245 $this->_newobj($this->_obj_stack[$filename][$n][0]); 211 246 212 247 if ($nObj[0] == PDF_TYPE_STREAM) { 213 $this->pdf_write_value 248 $this->pdf_write_value($nObj); 214 249 } else { 215 $this->pdf_write_value 250 $this->pdf_write_value($nObj[1]); 216 251 } 217 252 … … 226 261 } 227 262 228 /**229 * Sets the PDF Version to the highest of imported documents230 */231 function setVersion() {232 $this->PDFVersion = max($this->importVersion, $this->PDFVersion);233 }234 235 /**236 * Put resources237 */238 function _putresources() {239 $this->_putfonts();240 $this->_putimages();241 $this->_putformxobjects();242 $this->_putimportedobjects();243 //Resource dictionary244 $this->offsets[2]=strlen($this->buffer);245 $this->_out('2 0 obj');246 $this->_out('<<');247 $this->_putresourcedict();248 $this->_out('>>');249 $this->_out('endobj');250 }251 263 252 264 /** … … 259 271 $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; 260 272 $this->_newobj(); 273 $cN = $this->n; // TCPDF/Protection: rem current "n" 274 261 275 $this->tpls[$tplidx]['n'] = $this->n; 262 $this->_out('<<' .$filter.'/Type /XObject');276 $this->_out('<<' . $filter . '/Type /XObject'); 263 277 $this->_out('/Subtype /Form'); 264 278 $this->_out('/FormType 1'); 265 279 266 $this->_out(sprintf('/BBox [%.2f %.2f %.2f %.2f]', 267 ($tpl['x'] + (isset($tpl['box']['x'])?$tpl['box']['x']:0))*$this->k, 268 ($tpl['h'] + (isset($tpl['box']['y'])?$tpl['box']['y']:0) - $tpl['y'])*$this->k, 269 ($tpl['w'] + (isset($tpl['box']['x'])?$tpl['box']['x']:0))*$this->k, 270 ($tpl['h'] + (isset($tpl['box']['y'])?$tpl['box']['y']:0) - $tpl['y']-$tpl['h'])*$this->k) 271 ); 272 273 if (isset($tpl['box'])) 274 $this->_out(sprintf('/Matrix [1 0 0 1 %.5f %.5f]',-$tpl['box']['x']*$this->k, -$tpl['box']['y']*$this->k)); 280 $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', 281 (isset($tpl['box']['llx']) ? $tpl['box']['llx'] : $tpl['x']) * $this->k, 282 (isset($tpl['box']['lly']) ? $tpl['box']['lly'] : -$tpl['y']) * $this->k, 283 (isset($tpl['box']['urx']) ? $tpl['box']['urx'] : $tpl['w'] + $tpl['x']) * $this->k, 284 (isset($tpl['box']['ury']) ? $tpl['box']['ury'] : $tpl['h'] - $tpl['y']) * $this->k 285 )); 286 287 $c = 1; 288 $s = 0; 289 $tx = 0; 290 $ty = 0; 291 292 if (isset($tpl['box'])) { 293 $tx = -$tpl['box']['llx']; 294 $ty = -$tpl['box']['lly']; 295 296 if ($tpl['_rotationAngle'] <> 0) { 297 $angle = $tpl['_rotationAngle'] * M_PI/180; 298 $c=cos($angle); 299 $s=sin($angle); 300 301 switch($tpl['_rotationAngle']) { 302 case -90: 303 $tx = -$tpl['box']['lly']; 304 $ty = $tpl['box']['urx']; 305 break; 306 case -180: 307 $tx = $tpl['box']['urx']; 308 $ty = $tpl['box']['ury']; 309 break; 310 case -270: 311 $tx = $tpl['box']['ury']; 312 $ty = -$tpl['box']['llx']; 313 break; 314 } 315 } 316 } else if ($tpl['x'] != 0 || $tpl['y'] != 0) { 317 $tx = -$tpl['x']*2; 318 $ty = $tpl['y']*2; 319 } 320 321 $tx *= $this->k; 322 $ty *= $this->k; 323 324 if ($c != 1 || $s != 0 || $tx != 0 || $ty != 0) { 325 $this->_out(sprintf('/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]', 326 $c, $s, -$s, $c, $tx, $ty 327 )); 328 } 275 329 276 330 $this->_out('/Resources '); … … 278 332 if (isset($tpl['resources'])) { 279 333 $this->current_parser =& $tpl['parser']; 280 $this->pdf_write_value($tpl['resources']); 334 $this->pdf_write_value($tpl['resources']); // "n" will be changed 281 335 } else { 282 336 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); … … 284 338 $this->_out('/Font <<'); 285 339 foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) 286 $this->_out('/F' .$font['i'].' '.$font['n'].' 0 R');340 $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); 287 341 $this->_out('>>'); 288 342 } … … 293 347 if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { 294 348 foreach($this->_res['tpl'][$tplidx]['images'] as $image) 295 $this->_out('/I' .$image['i'].' '.$image['n'].' 0 R');349 $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); 296 350 } 297 351 if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { 298 352 foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) 299 $this->_out($this->tplprefix .$i.' '.$tpl['n'].' 0 R');353 $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); 300 354 } 301 355 $this->_out('>>'); … … 304 358 } 305 359 306 $this->_out('/Length '.strlen($p).' >>'); 360 $nN = $this->n; // TCPDF: rem new "n" 361 $this->n = $cN; // TCPDF: reset to current "n" 362 $this->_out('/Length ' . strlen($p) . ' >>'); 307 363 $this->_putstream($p); 308 364 $this->_out('endobj'); 309 } 365 $this->n = $nN; // TCPDF: reset to new "n" 366 } 367 368 $this->_putimportedobjects(); 310 369 } 311 370 … … 313 372 * Rewritten to handle existing own defined objects 314 373 */ 315 function _newobj($obj_id =false,$onlynewobj=false) {374 function _newobj($obj_id = false, $onlynewobj = false) { 316 375 if (!$obj_id) { 317 376 $obj_id = ++$this->n; 318 377 } 319 378 320 379 //Begin a new object 321 380 if (!$onlynewobj) { 322 $this->offsets[$obj_id] = strlen($this->buffer);323 $this->_out($obj_id .' 0 obj');381 $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer); 382 $this->_out($obj_id . ' 0 obj'); 324 383 $this->_current_obj_id = $obj_id; // for later use with encryption 325 384 } 326 385 386 return $obj_id; 327 387 } 328 388 … … 335 395 function pdf_write_value(&$value) 336 396 { 337 397 if (is_subclass_of($this, 'TCPDF')) { 398 parent::pdf_write_value($value); 399 } 400 338 401 switch ($value[0]) { 339 402 340 case PDF_TYPE_NUMERIC : 341 case PDF_TYPE_TOKEN : 342 // A numeric value or a token. 343 // Simply output them 344 $this->_out($value[1]." ", false); 345 break; 346 347 case PDF_TYPE_ARRAY : 403 case PDF_TYPE_TOKEN: 404 $this->_straightOut($value[1] . ' '); 405 break; 406 case PDF_TYPE_NUMERIC: 407 case PDF_TYPE_REAL: 408 if (is_float($value[1]) && $value[1] != 0) { 409 $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' '); 410 } else { 411 $this->_straightOut($value[1] . ' '); 412 } 413 break; 414 415 case PDF_TYPE_ARRAY: 348 416 349 417 // An array. Output the proper 350 418 // structure and move on. 351 419 352 $this->_ out("[",false);420 $this->_straightOut('['); 353 421 for ($i = 0; $i < count($value[1]); $i++) { 354 422 $this->pdf_write_value($value[1][$i]); 355 423 } 356 424 357 $this->_out( "]");358 break; 359 360 case PDF_TYPE_DICTIONARY 425 $this->_out(']'); 426 break; 427 428 case PDF_TYPE_DICTIONARY: 361 429 362 430 // A dictionary. 363 $this->_ out("<<",false);431 $this->_straightOut('<<'); 364 432 365 433 reset ($value[1]); 366 434 367 435 while (list($k, $v) = each($value[1])) { 368 $this->_ out($k . " ",false);436 $this->_straightOut($k . ' '); 369 437 $this->pdf_write_value($v); 370 438 } 371 439 372 $this->_ out(">>");373 break; 374 375 case PDF_TYPE_OBJREF 440 $this->_straightOut('>>'); 441 break; 442 443 case PDF_TYPE_OBJREF: 376 444 377 445 // An indirect object reference 378 446 // Fill the object stack if needed 379 447 $cpfn =& $this->current_parser->filename; 448 380 449 if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) { 381 $this->_newobj(false,true);382 383 $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); 450 $this->_newobj(false, true); 451 $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value); 452 $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!! 384 453 } 385 454 $objid = $this->_don_obj_stack[$cpfn][$value[1]][0]; 386 455 387 $this->_out( "{$objid} 0 R"); //{$value[2]}388 break; 389 390 case PDF_TYPE_STRING 456 $this->_out($objid . ' 0 R'); 457 break; 458 459 case PDF_TYPE_STRING: 391 460 392 461 // A string. 393 $this->_ out('('.$value[1].')');394 395 break; 396 397 case PDF_TYPE_STREAM 462 $this->_straightOut('(' . $value[1] . ')'); 463 464 break; 465 466 case PDF_TYPE_STREAM: 398 467 399 468 // A stream. First, output the … … 401 470 // stream data itself. 402 471 $this->pdf_write_value($value[1]); 403 $this->_out( "stream");472 $this->_out('stream'); 404 473 $this->_out($value[2][1]); 405 $this->_out( "endstream");406 break; 407 case PDF_TYPE_HEX :408 409 $this->_ out("<".$value[1].">");474 $this->_out('endstream'); 475 break; 476 477 case PDF_TYPE_HEX: 478 $this->_straightOut('<' . $value[1] . '>'); 410 479 break; 411 480 412 case PDF_TYPE_NULL : 481 case PDF_TYPE_BOOLEAN: 482 $this->_straightOut($value[1] ? 'true ' : 'false '); 483 break; 484 485 case PDF_TYPE_NULL: 413 486 // The null object. 414 487 415 $this->_ out("null");488 $this->_straightOut('null '); 416 489 break; 417 490 } … … 420 493 421 494 /** 422 * Private Method 423 */ 424 function _out($s,$ln=true) { 425 //Add a line to the document 426 if ($this->state==2) { 427 if (!$this->_intpl) 428 $this->pages[$this->page] .= $s.($ln == true ? "\n" : ''); 429 else 430 $this->tpls[$this->tpl]['buffer'] .= $s.($ln == true ? "\n" : ''); 431 } else { 432 $this->buffer.=$s.($ln == true ? "\n" : ''); 433 } 495 * Modified so not each call will add a newline to the output. 496 */ 497 function _straightOut($s) { 498 if (!is_subclass_of($this, 'TCPDF')) { 499 if($this->state==2) 500 $this->pages[$this->page] .= $s; 501 else 502 $this->buffer .= $s; 503 } else { 504 if ($this->state == 2) { 505 if (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { 506 // puts data before page footer 507 $page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]); 508 $footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]); 509 $this->setPageBuffer($this->page, $page . ' ' . $s . "\n" . $footer); 510 } else { 511 $this->setPageBuffer($this->page, $s, true); 512 } 513 } else { 514 $this->setBuffer($s); 515 } 516 } 434 517 } 435 518 … … 457 540 return false; 458 541 } 459 460 542 } 461 462 // for PHP5463 if (version_compare("5", PHP_VERSION, "<")) {464 if (!class_exists('fpdi')) {465 class fpdi extends FPDI {}466 }467 }468 ?> -
branches/version-2_5-dev/data/module/fpdf/fpdi_pdf_parser.php
r18701 r19716 1 1 <?php 2 2 // 3 // FPDI - Version 1. 24 // 5 // Copyright 2004-20 07Setasign - Jan Slabon3 // FPDI - Version 1.4 4 // 5 // Copyright 2004-2010 Setasign - Jan Slabon 6 6 // 7 7 // Licensed under the Apache License, Version 2.0 (the "License"); … … 18 18 // 19 19 20 require_once( "pdf_parser.php");20 require_once('pdf_parser.php'); 21 21 22 22 class fpdi_pdf_parser extends pdf_parser { … … 59 59 * @var array 60 60 */ 61 var $availableBoxes = array( "/MediaBox","/CropBox","/BleedBox","/TrimBox","/ArtBox");61 var $availableBoxes = array('/MediaBox', '/CropBox', '/BleedBox', '/TrimBox', '/ArtBox'); 62 62 63 63 /** … … 67 67 * @param object $fpdi Object of type fpdi 68 68 */ 69 function fpdi_pdf_parser($filename, &$fpdi) {69 function fpdi_pdf_parser($filename, &$fpdi) { 70 70 $this->fpdi =& $fpdi; 71 $this->filename = $filename;72 71 73 72 parent::pdf_parser($filename); … … 111 110 112 111 if ($pageno < 0 || $pageno >= $this->getPageCount()) { 113 $this->fpdi->error( "Pagenumber is wrong!");112 $this->fpdi->error('Pagenumber is wrong!'); 114 113 } 115 114 … … 164 163 */ 165 164 function getContent() { 166 $buffer = "";165 $buffer = ''; 167 166 168 167 if (isset($this->pages[$this->pageno][1][1]['/Contents'])) { 169 168 $contents = $this->_getPageContent($this->pages[$this->pageno][1][1]['/Contents']); 170 169 foreach($contents AS $tmp_content) { 171 $buffer .= $this->_rebuildContentStream($tmp_content) .' ';170 $buffer .= $this->_rebuildContentStream($tmp_content) . ' '; 172 171 } 173 172 } … … 215 214 $_filter = $obj[1][1]['/Filter']; 216 215 216 if ($_filter[0] == PDF_TYPE_OBJREF) { 217 $tmpFilter = $this->pdf_resolve_object($this->c, $_filter); 218 $_filter = $tmpFilter[1]; 219 } 220 217 221 if ($_filter[0] == PDF_TYPE_TOKEN) { 218 222 $filters[] = $_filter; … … 226 230 foreach ($filters AS $_filter) { 227 231 switch ($_filter[1]) { 228 case "/FlateDecode": 229 if (function_exists('gzuncompress')) { 230 $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : ''; 232 case '/FlateDecode': 233 // $stream .= "\x0F\x0D"; // in an errorious stream this suffix could work 234 if (function_exists('gzuncompress')) { 235 $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : ''; 231 236 } else { 232 $this-> fpdi->error(sprintf("To handle %s filter, please compile php with zlib support.",$_filter[1]));237 $this->error(sprintf('To handle %s filter, please compile php with zlib support.',$_filter[1])); 233 238 } 239 234 240 if ($stream === false) { 235 $this->fpdi->error("Error while decompressing stream.");241 $this->error('Error while decompressing stream.'); 236 242 } 237 243 break; 244 case '/LZWDecode': 245 include_once('filters/FilterLZW_FPDI.php'); 246 $decoder = new FilterLZW_FPDI($this->fpdi); 247 $stream = $decoder->decode($stream); 248 break; 249 case '/ASCII85Decode': 250 include_once('filters/FilterASCII85_FPDI.php'); 251 $decoder = new FilterASCII85_FPDI($this->fpdi); 252 $stream = $decoder->decode($stream); 253 break; 238 254 case null: 239 255 $stream = $stream; 240 256 break; 241 257 default: 242 if (preg_match("/^\/[a-z85]*$/i", $_filter[1], $filterName) && @include_once('decoders'.$_filter[1].'.php')) { 243 $filterName = substr($_filter[1],1); 244 if (class_exists($filterName)) { 245 $decoder =& new $filterName($this->fpdi); 246 $stream = $decoder->decode(trim($stream)); 247 } else { 248 $this->fpdi->error(sprintf("Unsupported Filter: %s",$_filter[1])); 249 } 250 } else { 251 $this->fpdi->error(sprintf("Unsupported Filter: %s",$_filter[1])); 252 } 258 $this->error(sprintf('Unsupported Filter: %s',$_filter[1])); 253 259 } 254 260 } … … 264 270 * @param array $page a /Page 265 271 * @param string $box_index Type of Box @see $availableBoxes 266 * @return array 267 */ 268 function getPageBox($page, $box_index) { 269 $page = $this->pdf_resolve_object($this->c,$page); 272 * @param float Scale factor from user space units to points 273 * @return array 274 */ 275 function getPageBox($page, $box_index, $k) { 276 $page = $this->pdf_resolve_object($this->c, $page); 270 277 $box = null; 271 278 if (isset($page[1][1][$box_index])) … … 273 280 274 281 if (!is_null($box) && $box[0] == PDF_TYPE_OBJREF) { 275 $tmp_box = $this->pdf_resolve_object($this->c, $box);282 $tmp_box = $this->pdf_resolve_object($this->c, $box); 276 283 $box = $tmp_box[1]; 277 284 } … … 279 286 if (!is_null($box) && $box[0] == PDF_TYPE_ARRAY) { 280 287 $b =& $box[1]; 281 return array("x" => $b[0][1]/$this->fpdi->k, 282 "y" => $b[1][1]/$this->fpdi->k, 283 "w" => abs($b[0][1]-$b[2][1])/$this->fpdi->k, 284 "h" => abs($b[1][1]-$b[3][1])/$this->fpdi->k); 288 return array('x' => $b[0][1]/$k, 289 'y' => $b[1][1]/$k, 290 'w' => abs($b[0][1]-$b[2][1])/$k, 291 'h' => abs($b[1][1]-$b[3][1])/$k, 292 'llx' => min($b[0][1], $b[2][1])/$k, 293 'lly' => min($b[1][1], $b[3][1])/$k, 294 'urx' => max($b[0][1], $b[2][1])/$k, 295 'ury' => max($b[1][1], $b[3][1])/$k, 296 ); 285 297 } else if (!isset ($page[1][1]['/Parent'])) { 286 298 return false; 287 299 } else { 288 return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index); 289 } 290 } 291 292 function getPageBoxes($pageno) { 293 return $this->_getPageBoxes($this->pages[$pageno-1]); 294 } 295 296 /** 297 * Get all Boxes from /Page 300 return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index, $k); 301 } 302 } 303 304 /** 305 * Get all page boxes by page no 306 * 307 * @param int The page number 308 * @param float Scale factor from user space units to points 309 * @return array 310 */ 311 function getPageBoxes($pageno, $k) { 312 return $this->_getPageBoxes($this->pages[$pageno-1], $k); 313 } 314 315 /** 316 * Get all boxes from /Page 298 317 * 299 318 * @param array a /Page 300 319 * @return array 301 320 */ 302 function _getPageBoxes($page ) {321 function _getPageBoxes($page, $k) { 303 322 $boxes = array(); 304 323 305 324 foreach($this->availableBoxes AS $box) { 306 if ($_box = $this->getPageBox($page, $box)) {325 if ($_box = $this->getPageBox($page, $box, $k)) { 307 326 $boxes[$box] = $_box; 308 327 } … … 312 331 } 313 332 333 /** 334 * Get the page rotation by pageno 335 * 336 * @param integer $pageno 337 * @return array 338 */ 314 339 function getPageRotation($pageno) { 315 340 return $this->_getPageRotation($this->pages[$pageno-1]); 316 341 } 317 342 318 function _getPageRotation 343 function _getPageRotation($obj) { // $obj = /Page 319 344 $obj = $this->pdf_resolve_object($this->c, $obj); 320 345 if (isset ($obj[1][1]['/Rotate'])) { … … 342 367 * @param array the result-array 343 368 */ 344 function read_pages 369 function read_pages(&$c, &$pages, &$result) { 345 370 // Get the kids dictionary 346 $kids = $this->pdf_resolve_object ($c, $pages[1][1]['/Kids']); 347 348 if (!is_array($kids)) 349 $this->fpdi->Error("Cannot find /Kids in current /Page-Dictionary"); 350 foreach ($kids[1] as $v) { 371 $_kids = $this->pdf_resolve_object ($c, $pages[1][1]['/Kids']); 372 373 if (!is_array($_kids)) 374 $this->error('Cannot find /Kids in current /Page-Dictionary'); 375 376 if ($_kids[1][0] == PDF_TYPE_ARRAY) { 377 $kids = $_kids[1][1]; 378 } else { 379 $kids = $_kids[1]; 380 } 381 382 foreach ($kids as $v) { 351 383 $pg = $this->pdf_resolve_object ($c, $v); 352 384 if ($pg[1][1]['/Type'][1] === '/Pages') { 353 385 // If one of the kids is an embedded 354 386 // /Pages array, resolve it as well. 355 $this->read_pages 387 $this->read_pages($c, $pg, $result); 356 388 } else { 357 389 $result[] = $pg; … … 369 401 function getPDFVersion() { 370 402 parent::getPDFVersion(); 371 372 if (isset($this->fpdi->importVersion) && $this->pdfVersion > $this->fpdi->importVersion) { 373 $this->fpdi->importVersion = $this->pdfVersion; 374 } 403 $this->fpdi->setPDFVersion(max($this->fpdi->getPDFVersion(), $this->pdfVersion)); 375 404 } 376 405 377 406 } 378 379 ?> -
branches/version-2_5-dev/data/module/fpdf/pdf_context.php
r18701 r19716 1 1 <?php 2 2 // 3 // FPDI - Version 1. 23 // FPDI - Version 1.4 4 4 // 5 // Copyright 2004-20 07Setasign - Jan Slabon5 // Copyright 2004-2010 Setasign - Jan Slabon 6 6 // 7 7 // Licensed under the Apache License, Version 2.0 (the "License"); … … 18 18 // 19 19 20 class pdf_context { 21 22 var $file; 23 var $buffer; 24 var $offset; 25 var $length; 26 27 var $stack; 28 29 // Constructor 30 31 function pdf_context($f) { 32 $this->file = $f; 33 $this->reset(); 34 } 35 36 // Optionally move the file 37 // pointer to a new location 38 // and reset the buffered data 39 40 function reset($pos = null, $l = 100) { 41 if (!is_null ($pos)) { 42 fseek ($this->file, $pos); 43 } 44 45 $this->buffer = $l > 0 ? fread($this->file, $l) : ''; 46 $this->offset = 0; 47 $this->length = strlen($this->buffer); 48 $this->stack = array(); 49 } 50 51 // Make sure that there is at least one 52 // character beyond the current offset in 53 // the buffer to prevent the tokenizer 54 // from attempting to access data that does 55 // not exist 56 57 function ensure_content() { 58 if ($this->offset >= $this->length - 1) { 59 return $this->increase_length(); 60 } else { 61 return true; 62 } 63 } 64 65 // Forcefully read more data into the buffer 66 67 function increase_length($l=100) { 68 if (feof($this->file)) { 69 return false; 70 } else { 71 $this->buffer .= fread($this->file, $l); 72 $this->length = strlen($this->buffer); 73 return true; 74 } 75 } 76 20 if (!class_exists('pdf_context', false)) { 21 22 class pdf_context { 23 24 /** 25 * Modi 26 * 27 * @var integer 0 = file | 1 = string 28 */ 29 var $_mode = 0; 30 31 var $file; 32 var $buffer; 33 var $offset; 34 var $length; 35 36 var $stack; 37 38 // Constructor 39 40 function pdf_context(&$f) { 41 $this->file =& $f; 42 if (is_string($this->file)) 43 $this->_mode = 1; 44 $this->reset(); 45 } 46 47 // Optionally move the file 48 // pointer to a new location 49 // and reset the buffered data 50 51 function reset($pos = null, $l = 100) { 52 if ($this->_mode == 0) { 53 if (!is_null ($pos)) { 54 fseek ($this->file, $pos); 55 } 56 57 $this->buffer = $l > 0 ? fread($this->file, $l) : ''; 58 $this->length = strlen($this->buffer); 59 if ($this->length < $l) 60 $this->increase_length($l - $this->length); 61 } else { 62 $this->buffer = $this->file; 63 $this->length = strlen($this->buffer); 64 } 65 $this->offset = 0; 66 $this->stack = array(); 67 } 68 69 // Make sure that there is at least one 70 // character beyond the current offset in 71 // the buffer to prevent the tokenizer 72 // from attempting to access data that does 73 // not exist 74 75 function ensure_content() { 76 if ($this->offset >= $this->length - 1) { 77 return $this->increase_length(); 78 } else { 79 return true; 80 } 81 } 82 83 // Forcefully read more data into the buffer 84 85 function increase_length($l = 100) { 86 if ($this->_mode == 0 && feof($this->file)) { 87 return false; 88 } else if ($this->_mode == 0) { 89 $totalLength = $this->length + $l; 90 do { 91 $this->buffer .= fread($this->file, $totalLength-$this->length); 92 } while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file)); 93 94 return true; 95 } else { 96 return false; 97 } 98 } 99 } 77 100 } 78 ?> -
branches/version-2_5-dev/data/module/fpdf/pdf_parser.php
r18701 r19716 1 1 <?php 2 2 // 3 // FPDI - Version 1. 23 // FPDI - Version 1.4 4 4 // 5 // Copyright 2004-20 07Setasign - Jan Slabon5 // Copyright 2004-2010 Setasign - Jan Slabon 6 6 // 7 7 // Licensed under the Apache License, Version 2.0 (the "License"); … … 40 40 if (!defined ('PDF_TYPE_STREAM')) 41 41 define ('PDF_TYPE_STREAM', 10); 42 if (!defined ('PDF_TYPE_BOOLEAN')) 43 define ('PDF_TYPE_BOOLEAN', 11); 44 if (!defined ('PDF_TYPE_REAL')) 45 define ('PDF_TYPE_REAL', 12); 46 47 require_once('pdf_context.php'); 42 48 43 require_once("pdf_context.php"); 44 require_once("wrapper_functions.php"); 45 46 class pdf_parser { 47 48 /** 49 * Filename 50 * @var string 51 */ 52 var $filename; 53 54 /** 55 * File resource 56 * @var resource 57 */ 58 var $f; 59 60 /** 61 * PDF Context 62 * @var object pdf_context-Instance 63 */ 64 var $c; 65 66 /** 67 * xref-Data 68 * @var array 69 */ 70 var $xref; 71 72 /** 73 * root-Object 74 * @var array 75 */ 76 var $root; 77 78 79 /** 80 * Constructor 81 * 82 * @param string $filename Source-Filename 83 */ 84 function pdf_parser($filename) { 85 $this->filename = $filename; 86 87 $this->f = @fopen($this->filename, "rb"); 88 89 if (!$this->f) 90 $this->error(sprintf("Cannot open %s !", $filename)); 91 92 $this->getPDFVersion(); 93 94 $this->c =& new pdf_context($this->f); 95 // Read xref-Data 96 $this->pdf_read_xref($this->xref, $this->pdf_find_xref()); 97 98 // Check for Encryption 99 $this->getEncryption(); 100 101 // Read root 102 $this->pdf_read_root(); 103 } 104 105 /** 106 * Close the opened file 107 */ 108 function closeFile() { 109 if (isset($this->f)) { 110 fclose($this->f); 111 unset($this->f); 112 } 113 } 114 115 /** 116 * Print Error and die 117 * 118 * @param string $msg Error-Message 119 */ 120 function error($msg) { 121 die("<b>PDF-Parser Error:</b> ".$msg); 122 } 123 124 /** 125 * Check Trailer for Encryption 126 */ 127 function getEncryption() { 128 if (isset($this->xref['trailer'][1]['/Encrypt'])) { 129 $this->error("File is encrypted!"); 130 } 131 } 132 133 /** 134 * Find/Return /Root 135 * 136 * @return array 137 */ 138 function pdf_find_root() { 139 if ($this->xref['trailer'][1]['/Root'][0] != PDF_TYPE_OBJREF) { 140 $this->error("Wrong Type of Root-Element! Must be an indirect reference"); 141 } 142 return $this->xref['trailer'][1]['/Root']; 143 } 144 145 /** 146 * Read the /Root 147 */ 148 function pdf_read_root() { 149 // read root 150 $this->root = $this->pdf_resolve_object($this->c, $this->pdf_find_root()); 151 } 152 153 /** 154 * Get PDF-Version 155 * 156 * And reset the PDF Version used in FPDI if needed 157 */ 158 function getPDFVersion() { 159 fseek($this->f, 0); 160 preg_match("/\d\.\d/",fread($this->f,16),$m); 161 $this->pdfVersion = $m[0]; 162 } 163 164 /** 165 * Find the xref-Table 166 */ 167 function pdf_find_xref() { 168 fseek ($this->f, -min(filesize($this->filename),1500), SEEK_END); 169 $data = fread($this->f, 1500); 170 171 $pos = strlen($data) - strpos(strrev($data), strrev('startxref')); 172 $data = substr($data, $pos); 173 174 if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { 175 $this->error("Unable to find pointer to xref table"); 176 } 177 178 return (int) $matches[1]; 179 } 180 181 /** 182 * Read xref-table 183 * 184 * @param array $result Array of xref-table 185 * @param integer $offset of xref-table 186 * @param integer $start start-position in xref-table 187 * @param integer $end end-position in xref-table 188 */ 189 function pdf_read_xref(&$result, $offset, $start = null, $end = null) { 190 if (is_null ($start) || is_null ($end)) { 191 fseek($this->f, $o_pos = $offset); 192 $data = trim(fgets($this->f,1024)); 193 194 if (strlen($data) == 0) 195 $data = trim(fgets($this->f,1024)); 196 197 if ($data !== 'xref') { 198 fseek($this->f, $o_pos); 199 $data = trim(_fgets($this->f, true)); 200 if ($data !== 'xref') { 201 if (preg_match('/(.*xref)(.*)/m', $data, $m)) { // xref 0 128 - in one line 202 fseek($this->f, $o_pos+strlen($m[1])); 203 } elseif (preg_match('/(x|r|e|f)+/', $data, $m)) { // correct invalid xref-pointer 204 $tmpOffset = $offset-4+strlen($m[0]); 205 $this->pdf_read_xref($result, $tmpOffset, $start, $end); 206 return; 207 } else { 208 $this->error("Unable to find xref table - Maybe a Problem with 'auto_detect_line_endings'"); 209 } 210 } 211 } 212 213 $o_pos = ftell($this->f); 214 $data = explode(' ', trim(fgets($this->f,1024))); 215 if (count($data) != 2) { 216 fseek($this->f, $o_pos); 217 $data = explode(' ', trim(_fgets($this->f, true))); 218 219 if (count($data) != 2) { 220 if (count($data) > 2) { // no lineending 221 $n_pos = $o_pos+strlen($data[0])+strlen($data[1])+2; 222 fseek($this->f, $n_pos); 223 } else { 224 $this->error("Unexpected header in xref table"); 225 } 226 } 49 if (!class_exists('pdf_parser', false)) { 50 51 class pdf_parser { 52 53 /** 54 * Filename 55 * @var string 56 */ 57 var $filename; 58 59 /** 60 * File resource 61 * @var resource 62 */ 63 var $f; 64 65 /** 66 * PDF Context 67 * @var object pdf_context-Instance 68 */ 69 var $c; 70 71 /** 72 * xref-Data 73 * @var array 74 */ 75 var $xref; 76 77 /** 78 * root-Object 79 * @var array 80 */ 81 var $root; 82 83 /** 84 * PDF version of the loaded document 85 * @var string 86 */ 87 var $pdfVersion; 88 89 /** 90 * For reading encrypted documents and xref/objectstreams are in use 91 * 92 * @var boolean 93 */ 94 var $readPlain = true; 95 96 /** 97 * Constructor 98 * 99 * @param string $filename Source-Filename 100 */ 101 function pdf_parser($filename) { 102 $this->filename = $filename; 103 104 $this->f = @fopen($this->filename, 'rb'); 105 106 if (!$this->f) 107 $this->error(sprintf('Cannot open %s !', $filename)); 108 109 $this->getPDFVersion(); 110 111 $this->c = new pdf_context($this->f); 112 113 // Read xref-Data 114 $this->xref = array(); 115 $this->pdf_read_xref($this->xref, $this->pdf_find_xref()); 116 117 // Check for Encryption 118 $this->getEncryption(); 119 120 // Read root 121 $this->pdf_read_root(); 122 } 123 124 /** 125 * Close the opened file 126 */ 127 function closeFile() { 128 if (isset($this->f) && is_resource($this->f)) { 129 fclose($this->f); 130 unset($this->f); 131 } 132 } 133 134 /** 135 * Print Error and die 136 * 137 * @param string $msg Error-Message 138 */ 139 function error($msg) { 140 die('<b>PDF-Parser Error:</b> '.$msg); 141 } 142 143 /** 144 * Check Trailer for Encryption 145 */ 146 function getEncryption() { 147 if (isset($this->xref['trailer'][1]['/Encrypt'])) { 148 $this->error('File is encrypted!'); 227 149 } 228 $start = $data[0]; 229 $end = $start + $data[1]; 230 } 231 232 if (!isset($result['xref_location'])) { 233 $result['xref_location'] = $offset; 234 } 235 236 if (!isset($result['max_object']) || $end > $result['max_object']) { 237 $result['max_object'] = $end; 238 } 239 240 for (; $start < $end; $start++) { 241 $data = ltrim(fread($this->f, 20)); // Spezifications says: 20 bytes including newlines 242 $offset = substr($data, 0, 10); 243 $generation = substr($data, 11, 5); 244 245 if (!isset ($result['xref'][$start][(int) $generation])) { 246 $result['xref'][$start][(int) $generation] = (int) $offset; 247 } 248 } 249 250 $o_pos = ftell($this->f); 251 $data = fgets($this->f,1024); 252 if (strlen(trim($data)) == 0) 253 $data = fgets($this->f, 1024); 254 255 if (preg_match("/trailer/",$data)) { 256 if (preg_match("/(.*trailer[ \n\r]*)/",$data,$m)) { 257 fseek($this->f, $o_pos+strlen($m[1])); 258 } 259 260 $c =& new pdf_context($this->f); 150 } 151 152 /** 153 * Find/Return /Root 154 * 155 * @return array 156 */ 157 function pdf_find_root() { 158 if ($this->xref['trailer'][1]['/Root'][0] != PDF_TYPE_OBJREF) { 159 $this->error('Wrong Type of Root-Element! Must be an indirect reference'); 160 } 161 162 return $this->xref['trailer'][1]['/Root']; 163 } 164 165 /** 166 * Read the /Root 167 */ 168 function pdf_read_root() { 169 // read root 170 $this->root = $this->pdf_resolve_object($this->c, $this->pdf_find_root()); 171 } 172 173 /** 174 * Get PDF-Version 175 * 176 * And reset the PDF Version used in FPDI if needed 177 */ 178 function getPDFVersion() { 179 fseek($this->f, 0); 180 preg_match('/\d\.\d/',fread($this->f,16),$m); 181 if (isset($m[0])) 182 $this->pdfVersion = $m[0]; 183 return $this->pdfVersion; 184 } 185 186 /** 187 * Find the xref-Table 188 */ 189 function pdf_find_xref() { 190 $toRead = 1500; 191 192 $stat = fseek ($this->f, -$toRead, SEEK_END); 193 if ($stat === -1) { 194 fseek ($this->f, 0); 195 } 196 $data = fread($this->f, $toRead); 197 198 $pos = strlen($data) - strpos(strrev($data), strrev('startxref')); 199 $data = substr($data, $pos); 200 201 if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { 202 $this->error('Unable to find pointer to xref table'); 203 } 204 205 return (int) $matches[1]; 206 } 207 208 /** 209 * Read xref-table 210 * 211 * @param array $result Array of xref-table 212 * @param integer $offset of xref-table 213 */ 214 function pdf_read_xref(&$result, $offset) { 215 $o_pos = $offset-min(20, $offset); 216 fseek($this->f, $o_pos); // set some bytes backwards to fetch errorious docs 217 218 $data = fread($this->f, 100); 219 220 $xrefPos = strrpos($data, 'xref'); 221 222 if ($xrefPos === false) { 223 fseek($this->f, $offset); 224 $c = new pdf_context($this->f); 225 $xrefStreamObjDec = $this->pdf_read_value($c); 226 227 if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == PDF_TYPE_OBJDEC) { 228 $this->error(sprintf('This document (%s) probably uses a compression technique which is not supported by the free parser shipped with FPDI.', $this->filename)); 229 } else { 230 $this->error('Unable to find xref table.'); 231 } 232 } 233 234 if (!isset($result['xref_location'])) { 235 $result['xref_location'] = $o_pos+$xrefPos; 236 $result['max_object'] = 0; 237 } 238 239 $cylces = -1; 240 $bytesPerCycle = 100; 241 242 fseek($this->f, $o_pos = $o_pos+$xrefPos+4); // set the handle directly after the "xref"-keyword 243 $data = fread($this->f, $bytesPerCycle); 244 245 while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle*$cylces++, 0))) === false && !feof($this->f)) { 246 $data .= fread($this->f, $bytesPerCycle); 247 } 248 249 if ($trailerPos === false) { 250 $this->error('Trailer keyword not found after xref table'); 251 } 252 253 $data = substr($data, 0, $trailerPos); 254 255 // get Line-Ending 256 preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for linebreaks 257 258 $differentLineEndings = count(array_unique($m[0])); 259 if ($differentLineEndings > 1) { 260 $lines = preg_split("/(\r\n|\n|\r)/", $data, -1, PREG_SPLIT_NO_EMPTY); 261 } else { 262 $lines = explode($m[0][1], $data); 263 } 264 265 $data = $differentLineEndings = $m = null; 266 unset($data, $differentLineEndings, $m); 267 268 $linesCount = count($lines); 269 270 $start = 1; 271 272 for ($i = 0; $i < $linesCount; $i++) { 273 $line = trim($lines[$i]); 274 if ($line) { 275 $pieces = explode(' ', $line); 276 $c = count($pieces); 277 switch($c) { 278 case 2: 279 $start = (int)$pieces[0]; 280 $end = $start+(int)$pieces[1]; 281 if ($end > $result['max_object']) 282 $result['max_object'] = $end; 283 break; 284 case 3: 285 if (!isset($result['xref'][$start])) 286 $result['xref'][$start] = array(); 287 288 if (!array_key_exists($gen = (int) $pieces[1], $result['xref'][$start])) { 289 $result['xref'][$start][$gen] = $pieces[2] == 'n' ? (int) $pieces[0] : null; 290 } 291 $start++; 292 break; 293 default: 294 $this->error('Unexpected data in xref table'); 295 } 296 } 297 } 298 299 $lines = $pieces = $line = $start = $end = $gen = null; 300 unset($lines, $pieces, $line, $start, $end, $gen); 301 302 fseek($this->f, $o_pos+$trailerPos+7); 303 304 $c = new pdf_context($this->f); 261 305 $trailer = $this->pdf_read_value($c); 262 306 307 $c = null; 308 unset($c); 309 310 if (!isset($result['trailer'])) { 311 $result['trailer'] = $trailer; 312 } 313 263 314 if (isset($trailer[1]['/Prev'])) { 264 $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); 265 $result['trailer'][1] = array_merge($result['trailer'][1], $trailer[1]); 266 } else { 267 $result['trailer'] = $trailer; 268 } 269 } else { 270 $data = explode(' ', trim($data)); 271 272 if (count($data) != 2) { 273 fseek($this->f, $o_pos); 274 $data = explode(' ', trim (_fgets ($this->f, true))); 275 276 if (count($data) != 2) { 277 $this->error("Unexpected data in xref table"); 315 $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); 316 } 317 318 $trailer = null; 319 unset($trailer); 320 321 return true; 322 } 323 324 /** 325 * Reads an Value 326 * 327 * @param object $c pdf_context 328 * @param string $token a Token 329 * @return mixed 330 */ 331 function pdf_read_value(&$c, $token = null) { 332 if (is_null($token)) { 333 $token = $this->pdf_read_token($c); 334 } 335 336 if ($token === false) { 337 return false; 338 } 339 340 switch ($token) { 341 case '<': 342 // This is a hex string. 343 // Read the value, then the terminator 344 345 $pos = $c->offset; 346 347 while(1) { 348 349 $match = strpos ($c->buffer, '>', $pos); 350 351 // If you can't find it, try 352 // reading more data from the stream 353 354 if ($match === false) { 355 if (!$c->increase_length()) { 356 return false; 357 } else { 358 continue; 359 } 360 } 361 362 $result = substr ($c->buffer, $c->offset, $match - $c->offset); 363 $c->offset = $match + 1; 364 365 return array (PDF_TYPE_HEX, $result); 366 } 367 368 break; 369 case '<<': 370 // This is a dictionary. 371 372 $result = array(); 373 374 // Recurse into this function until we reach 375 // the end of the dictionary. 376 while (($key = $this->pdf_read_token($c)) !== '>>') { 377 if ($key === false) { 378 return false; 379 } 380 381 if (($value = $this->pdf_read_value($c)) === false) { 382 return false; 383 } 384 385 // Catch missing value 386 if ($value[0] == PDF_TYPE_TOKEN && $value[1] == '>>') { 387 $result[$key] = array(PDF_TYPE_NULL); 388 break; 389 } 390 391 $result[$key] = $value; 392 } 393 394 return array (PDF_TYPE_DICTIONARY, $result); 395 396 case '[': 397 // This is an array. 398 399 $result = array(); 400 401 // Recurse into this function until we reach 402 // the end of the array. 403 while (($token = $this->pdf_read_token($c)) !== ']') { 404 if ($token === false) { 405 return false; 406 } 407 408 if (($value = $this->pdf_read_value($c, $token)) === false) { 409 return false; 410 } 411 412 $result[] = $value; 413 } 414 415 return array (PDF_TYPE_ARRAY, $result); 416 417 case '(' : 418 // This is a string 419 $pos = $c->offset; 420 421 $openBrackets = 1; 422 do { 423 for (; $openBrackets != 0 && $pos < $c->length; $pos++) { 424 switch (ord($c->buffer[$pos])) { 425 case 0x28: // '(' 426 $openBrackets++; 427 break; 428 case 0x29: // ')' 429 $openBrackets--; 430 break; 431 case 0x5C: // backslash 432 $pos++; 433 } 434 } 435 } while($openBrackets != 0 && $c->increase_length()); 436 437 $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1); 438 $c->offset = $pos; 439 440 return array (PDF_TYPE_STRING, $result); 441 442 case 'stream': 443 $o_pos = ftell($c->file)-strlen($c->buffer); 444 $o_offset = $c->offset; 445 446 $c->reset($startpos = $o_pos + $o_offset); 447 448 $e = 0; // ensure line breaks in front of the stream 449 if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13)) 450 $e++; 451 if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10)) 452 $e++; 453 454 if ($this->actual_obj[1][1]['/Length'][0] == PDF_TYPE_OBJREF) { 455 $tmp_c = new pdf_context($this->f); 456 $tmp_length = $this->pdf_resolve_object($tmp_c, $this->actual_obj[1][1]['/Length']); 457 $length = $tmp_length[1][1]; 458 } else { 459 $length = $this->actual_obj[1][1]['/Length'][1]; 460 } 461 462 if ($length > 0) { 463 $c->reset($startpos+$e,$length); 464 $v = $c->buffer; 465 } else { 466 $v = ''; 467 } 468 $c->reset($startpos+$e+$length+9); // 9 = strlen("endstream") 469 470 return array(PDF_TYPE_STREAM, $v); 471 472 default : 473 if (is_numeric ($token)) { 474 // A numeric token. Make sure that 475 // it is not part of something else. 476 if (($tok2 = $this->pdf_read_token ($c)) !== false) { 477 if (is_numeric ($tok2)) { 478 479 // Two numeric tokens in a row. 480 // In this case, we're probably in 481 // front of either an object reference 482 // or an object specification. 483 // Determine the case and return the data 484 if (($tok3 = $this->pdf_read_token ($c)) !== false) { 485 switch ($tok3) { 486 case 'obj' : 487 return array (PDF_TYPE_OBJDEC, (int) $token, (int) $tok2); 488 case 'R' : 489 return array (PDF_TYPE_OBJREF, (int) $token, (int) $tok2); 490 } 491 // If we get to this point, that numeric value up 492 // there was just a numeric value. Push the extra 493 // tokens back into the stack and return the value. 494 array_push ($c->stack, $tok3); 495 } 496 } 497 498 array_push ($c->stack, $tok2); 499 } 500 501 if ($token === (string)((int)$token)) 502 return array (PDF_TYPE_NUMERIC, (int)$token); 503 else 504 return array (PDF_TYPE_REAL, (float)$token); 505 } else if ($token == 'true' || $token == 'false') { 506 return array (PDF_TYPE_BOOLEAN, $token == 'true'); 507 } else if ($token == 'null') { 508 return array (PDF_TYPE_NULL); 509 } else { 510 // Just a token. Return it. 511 return array (PDF_TYPE_TOKEN, $token); 512 } 513 } 514 } 515 516 /** 517 * Resolve an object 518 * 519 * @param object $c pdf_context 520 * @param array $obj_spec The object-data 521 * @param boolean $encapsulate Must set to true, cause the parsing and fpdi use this method only without this para 522 */ 523 function pdf_resolve_object(&$c, $obj_spec, $encapsulate = true) { 524 // Exit if we get invalid data 525 if (!is_array($obj_spec)) { 526 $ret = false; 527 return $ret; 528 } 529 530 if ($obj_spec[0] == PDF_TYPE_OBJREF) { 531 532 // This is a reference, resolve it 533 if (isset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]])) { 534 535 // Save current file position 536 // This is needed if you want to resolve 537 // references while you're reading another object 538 // (e.g.: if you need to determine the length 539 // of a stream) 540 541 $old_pos = ftell($c->file); 542 543 // Reposition the file pointer and 544 // load the object header. 545 546 $c->reset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]]); 547 548 $header = $this->pdf_read_value($c); 549 550 if ($header[0] != PDF_TYPE_OBJDEC || $header[1] != $obj_spec[1] || $header[2] != $obj_spec[2]) { 551 $toSearchFor = $obj_spec[1].' '.$obj_spec[2].' obj'; 552 if (preg_match('/'.$toSearchFor.'/', $c->buffer)) { 553 $c->offset = strpos($c->buffer, $toSearchFor) + strlen($toSearchFor); 554 // reset stack 555 $c->stack = array(); 556 } else { 557 $this->error("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location"); 558 } 559 } 560 561 // If we're being asked to store all the information 562 // about the object, we add the object ID and generation 563 // number for later use 564 $result = array(); 565 $this->actual_obj =& $result; 566 if ($encapsulate) { 567 $result = array ( 568 PDF_TYPE_OBJECT, 569 'obj' => $obj_spec[1], 570 'gen' => $obj_spec[2] 571 ); 572 } 573 574 // Now simply read the object data until 575 // we encounter an end-of-object marker 576 while(1) { 577 $value = $this->pdf_read_value($c); 578 if ($value === false || count($result) > 4) { 579 // in this case the parser coudn't find an endobj so we break here 580 break; 581 } 582 583 if ($value[0] == PDF_TYPE_TOKEN && $value[1] === 'endobj') { 584 break; 585 } 586 587 $result[] = $value; 588 } 589 590 $c->reset($old_pos); 591 592 if (isset($result[2][0]) && $result[2][0] == PDF_TYPE_STREAM) { 593 $result[0] = PDF_TYPE_STREAM; 594 } 595 596 return $result; 278 597 } 279 } 280 281 $this->pdf_read_xref($result, null, (int) $data[0], (int) $data[0] + (int) $data[1]); 282 } 598 } else { 599 return $obj_spec; 600 } 601 } 602 603 604 605 /** 606 * Reads a token from the file 607 * 608 * @param object $c pdf_context 609 * @return mixed 610 */ 611 function pdf_read_token(&$c) 612 { 613 // If there is a token available 614 // on the stack, pop it out and 615 // return it. 616 617 if (count($c->stack)) { 618 return array_pop($c->stack); 619 } 620 621 // Strip away any whitespace 622 623 do { 624 if (!$c->ensure_content()) { 625 return false; 626 } 627 $c->offset += strspn($c->buffer, " \n\r\t", $c->offset); 628 } while ($c->offset >= $c->length - 1); 629 630 // Get the first character in the stream 631 632 $char = $c->buffer[$c->offset++]; 633 634 switch ($char) { 635 636 case '[': 637 case ']': 638 case '(': 639 case ')': 640 641 // This is either an array or literal string 642 // delimiter, Return it 643 644 return $char; 645 646 case '<': 647 case '>': 648 649 // This could either be a hex string or 650 // dictionary delimiter. Determine the 651 // appropriate case and return the token 652 653 if ($c->buffer[$c->offset] == $char) { 654 if (!$c->ensure_content()) { 655 return false; 656 } 657 $c->offset++; 658 return $char . $char; 659 } else { 660 return $char; 661 } 662 663 case '%': 664 665 // This is a comment - jump over it! 666 667 $pos = $c->offset; 668 while(1) { 669 $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos); 670 if ($match === 0) { 671 if (!$c->increase_length()) { 672 return false; 673 } else { 674 continue; 675 } 676 } 677 678 $c->offset = $m[0][1]+strlen($m[0][0]); 679 680 return $this->pdf_read_token($c); 681 } 682 683 default: 684 685 // This is "another" type of token (probably 686 // a dictionary entry or a numeric value) 687 // Find the end and return it. 688 689 if (!$c->ensure_content()) { 690 return false; 691 } 692 693 while(1) { 694 695 // Determine the length of the token 696 697 $pos = strcspn($c->buffer, " %[]<>()\r\n\t/", $c->offset); 698 699 if ($c->offset + $pos <= $c->length - 1) { 700 break; 701 } else { 702 // If the script reaches this point, 703 // the token may span beyond the end 704 // of the current buffer. Therefore, 705 // we increase the size of the buffer 706 // and try again--just to be safe. 707 708 $c->increase_length(); 709 } 710 } 711 712 $result = substr($c->buffer, $c->offset - 1, $pos + 1); 713 714 $c->offset += $pos; 715 return $result; 716 } 717 } 283 718 } 284 285 286 /**287 * Reads an Value288 *289 * @param object $c pdf_context290 * @param string $token a Token291 * @return mixed292 */293 function pdf_read_value(&$c, $token = null) {294 if (is_null($token)) {295 $token = $this->pdf_read_token($c);296 }297 298 if ($token === false) {299 return false;300 }301 302 switch ($token) {303 case '<':304 // This is a hex string.305 // Read the value, then the terminator306 307 $pos = $c->offset;308 309 while(1) {310 311 $match = strpos ($c->buffer, '>', $pos);312 313 // If you can't find it, try314 // reading more data from the stream315 316 if ($match === false) {317 if (!$c->increase_length()) {318 return false;319 } else {320 continue;321 }322 }323 324 $result = substr ($c->buffer, $c->offset, $match - $c->offset);325 $c->offset = $match+1;326 327 return array (PDF_TYPE_HEX, $result);328 }329 330 break;331 case '<<':332 // This is a dictionary.333 334 $result = array();335 336 // Recurse into this function until we reach337 // the end of the dictionary.338 while (($key = $this->pdf_read_token($c)) !== '>>') {339 if ($key === false) {340 return false;341 }342 343 if (($value = $this->pdf_read_value($c)) === false) {344 return false;345 }346 $result[$key] = $value;347 }348 349 return array (PDF_TYPE_DICTIONARY, $result);350 351 case '[':352 // This is an array.353 354 $result = array();355 356 // Recurse into this function until we reach357 // the end of the array.358 while (($token = $this->pdf_read_token($c)) !== ']') {359 if ($token === false) {360 return false;361 }362 363 if (($value = $this->pdf_read_value($c, $token)) === false) {364 return false;365 }366 367 $result[] = $value;368 }369 370 return array (PDF_TYPE_ARRAY, $result);371 372 case '(' :373 // This is a string374 375 $pos = $c->offset;376 377 while(1) {378 379 // Start by finding the next closed380 // parenthesis381 382 $match = strpos ($c->buffer, ')', $pos);383 384 // If you can't find it, try385 // reading more data from the stream386 387 if ($match === false) {388 if (!$c->increase_length()) {389 return false;390 } else {391 continue;392 }393 }394 395 // Make sure that there is no backslash396 // before the parenthesis. If there is,397 // move on. Otherwise, return the string.398 $esc = preg_match('/([\\\\]+)$/', $tmpresult = substr($c->buffer, $c->offset, $match - $c->offset), $m);399 400 if ($esc === 0 || strlen($m[1]) % 2 == 0) {401 $result = $tmpresult;402 $c->offset = $match + 1;403 return array (PDF_TYPE_STRING, $result);404 } else {405 $pos = $match + 1;406 407 if ($pos > $c->offset + $c->length) {408 $c->increase_length();409 }410 }411 }412 413 case "stream":414 $o_pos = ftell($c->file)-strlen($c->buffer);415 $o_offset = $c->offset;416 417 $c->reset($startpos = $o_pos + $o_offset);418 419 $e = 0; // ensure line breaks in front of the stream420 if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13))421 $e++;422 if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10))423 $e++;424 425 if ($this->actual_obj[1][1]['/Length'][0] == PDF_TYPE_OBJREF) {426 $tmp_c =& new pdf_context($this->f);427 $tmp_length = $this->pdf_resolve_object($tmp_c,$this->actual_obj[1][1]['/Length']);428 $length = $tmp_length[1][1];429 } else {430 $length = $this->actual_obj[1][1]['/Length'][1];431 }432 433 if ($length > 0) {434 $c->reset($startpos+$e,$length);435 $v = $c->buffer;436 } else {437 $v = '';438 }439 $c->reset($startpos+$e+$length+9); // 9 = strlen("endstream")440 441 return array(PDF_TYPE_STREAM, $v);442 443 default :444 if (is_numeric ($token)) {445 // A numeric token. Make sure that446 // it is not part of something else.447 if (($tok2 = $this->pdf_read_token ($c)) !== false) {448 if (is_numeric ($tok2)) {449 450 // Two numeric tokens in a row.451 // In this case, we're probably in452 // front of either an object reference453 // or an object specification.454 // Determine the case and return the data455 if (($tok3 = $this->pdf_read_token ($c)) !== false) {456 switch ($tok3) {457 case 'obj' :458 return array (PDF_TYPE_OBJDEC, (int) $token, (int) $tok2);459 case 'R' :460 return array (PDF_TYPE_OBJREF, (int) $token, (int) $tok2);461 }462 // If we get to this point, that numeric value up463 // there was just a numeric value. Push the extra464 // tokens back into the stack and return the value.465 array_push ($c->stack, $tok3);466 }467 }468 469 array_push ($c->stack, $tok2);470 }471 472 return array (PDF_TYPE_NUMERIC, $token);473 } else {474 475 // Just a token. Return it.476 return array (PDF_TYPE_TOKEN, $token);477 }478 479 }480 }481 482 /**483 * Resolve an object484 *485 * @param object $c pdf_context486 * @param array $obj_spec The object-data487 * @param boolean $encapsulate Must set to true, cause the parsing and fpdi use this method only without this para488 */489 function pdf_resolve_object(&$c, $obj_spec, $encapsulate = true) {490 // Exit if we get invalid data491 if (!is_array($obj_spec)) {492 return false;493 }494 495 if ($obj_spec[0] == PDF_TYPE_OBJREF) {496 497 // This is a reference, resolve it498 if (isset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]])) {499 500 // Save current file position501 // This is needed if you want to resolve502 // references while you're reading another object503 // (e.g.: if you need to determine the length504 // of a stream)505 506 $old_pos = ftell($c->file);507 508 // Reposition the file pointer and509 // load the object header.510 511 $c->reset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]]);512 513 $header = $this->pdf_read_value($c,null,true);514 515 if ($header[0] != PDF_TYPE_OBJDEC || $header[1] != $obj_spec[1] || $header[2] != $obj_spec[2]) {516 $this->error("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location");517 }518 519 // If we're being asked to store all the information520 // about the object, we add the object ID and generation521 // number for later use522 $this->actual_obj =& $result;523 if ($encapsulate) {524 $result = array (525 PDF_TYPE_OBJECT,526 'obj' => $obj_spec[1],527 'gen' => $obj_spec[2]528 );529 } else {530 $result = array();531 }532 533 // Now simply read the object data until534 // we encounter an end-of-object marker535 while(1) {536 $value = $this->pdf_read_value($c);537 if ($value === false || count($result) > 4) {538 // in this case the parser coudn't find an endobj so we break here539 break;540 }541 542 if ($value[0] == PDF_TYPE_TOKEN && $value[1] === 'endobj') {543 break;544 }545 546 $result[] = $value;547 }548 549 $c->reset($old_pos);550 551 if (isset($result[2][0]) && $result[2][0] == PDF_TYPE_STREAM) {552 $result[0] = PDF_TYPE_STREAM;553 }554 555 return $result;556 }557 } else {558 return $obj_spec;559 }560 }561 562 563 564 /**565 * Reads a token from the file566 *567 * @param object $c pdf_context568 * @return mixed569 */570 function pdf_read_token(&$c)571 {572 // If there is a token available573 // on the stack, pop it out and574 // return it.575 576 if (count($c->stack)) {577 return array_pop($c->stack);578 }579 580 // Strip away any whitespace581 582 do {583 if (!$c->ensure_content()) {584 return false;585 }586 $c->offset += _strspn($c->buffer, " \n\r\t", $c->offset);587 } while ($c->offset >= $c->length - 1);588 589 // Get the first character in the stream590 591 $char = $c->buffer[$c->offset++];592 593 switch ($char) {594 595 case '[' :596 case ']' :597 case '(' :598 case ')' :599 600 // This is either an array or literal string601 // delimiter, Return it602 603 return $char;604 605 case '<' :606 case '>' :607 608 // This could either be a hex string or609 // dictionary delimiter. Determine the610 // appropriate case and return the token611 612 if ($c->buffer[$c->offset] == $char) {613 if (!$c->ensure_content()) {614 return false;615 }616 $c->offset++;617 return $char . $char;618 } else {619 return $char;620 }621 622 default :623 624 // This is "another" type of token (probably625 // a dictionary entry or a numeric value)626 // Find the end and return it.627 628 if (!$c->ensure_content()) {629 return false;630 }631 632 while(1) {633 634 // Determine the length of the token635 636 $pos = _strcspn($c->buffer, " []<>()\r\n\t/", $c->offset);637 if ($c->offset + $pos <= $c->length - 1) {638 break;639 } else {640 // If the script reaches this point,641 // the token may span beyond the end642 // of the current buffer. Therefore,643 // we increase the size of the buffer644 // and try again--just to be safe.645 646 $c->increase_length();647 }648 }649 650 $result = substr($c->buffer, $c->offset - 1, $pos + 1);651 652 $c->offset += $pos;653 return $result;654 }655 }656 657 658 719 } 659 660 ?>
Note: See TracChangeset
for help on using the changeset viewer.