source: trunk/workflow/inc/fpdf/fpdf.php @ 7655

Revision 7655, 39.7 KB checked in by douglasz, 11 years ago (diff)

Ticket #3236 - Melhorias de performance no codigo do Expresso.

  • Property svn:executable set to *
Line 
1<?php
2/*******************************************************************************
3* Software: FPDF                                                               *
4* Version:  1.53                                                               *
5* Date:     2004-12-31                                                         *
6* Author:   Olivier PLATHEY                                                    *
7* License:  Freeware
8* @package      Workflow
9* @subpackage   fpdf                                                           *
10*                                                                              *
11* You may use, modify and redistribute this software as you wish.              *
12*******************************************************************************/
13
14if(!class_exists('FPDF'))
15{
16define('FPDF_VERSION','1.53');
17
18class FPDF
19{
20//Private properties
21var $page;               //current page number
22var $n;                  //current object number
23var $offsets;            //array of object offsets
24var $buffer;             //buffer holding in-memory PDF
25var $pages;              //array containing pages
26var $state;              //current document state
27var $compress;           //compression flag
28var $DefOrientation;     //default orientation
29var $CurOrientation;     //current orientation
30var $OrientationChanges; //array indicating orientation changes
31var $k;                  //scale factor (number of points in user unit)
32var $fwPt,$fhPt;         //dimensions of page format in points
33var $fw,$fh;             //dimensions of page format in user unit
34var $wPt,$hPt;           //current dimensions of page in points
35var $w,$h;               //current dimensions of page in user unit
36var $lMargin;            //left margin
37var $tMargin;            //top margin
38var $rMargin;            //right margin
39var $bMargin;            //page break margin
40var $cMargin;            //cell margin
41var $x,$y;               //current position in user unit for cell positioning
42var $lasth;              //height of last cell printed
43var $LineWidth;          //line width in user unit
44var $CoreFonts;          //array of standard font names
45var $fonts;              //array of used fonts
46var $FontFiles;          //array of font files
47var $diffs;              //array of encoding differences
48var $images;             //array of used images
49var $PageLinks;          //array of links in pages
50var $links;              //array of internal links
51var $FontFamily;         //current font family
52var $FontStyle;          //current font style
53var $underline;          //underlining flag
54var $CurrentFont;        //current font info
55var $FontSizePt;         //current font size in points
56var $FontSize;           //current font size in user unit
57var $DrawColor;          //commands for drawing color
58var $FillColor;          //commands for filling color
59var $TextColor;          //commands for text color
60var $ColorFlag;          //indicates whether fill and text colors are different
61var $ws;                 //word spacing
62var $AutoPageBreak;      //automatic page breaking
63var $PageBreakTrigger;   //threshold used to trigger page breaks
64var $InFooter;           //flag set when processing footer
65var $ZoomMode;           //zoom display mode
66var $LayoutMode;         //layout display mode
67var $title;              //title
68var $subject;            //subject
69var $author;             //author
70var $keywords;           //keywords
71var $creator;            //creator
72var $AliasNbPages;       //alias for total number of pages
73var $PDFVersion;         //PDF version number
74
75/*******************************************************************************
76*                                                                              *
77*                               Public methods                                 *
78*                                                                              *
79*******************************************************************************/
80function FPDF($orientation='P',$unit='mm',$format='A4')
81{
82        //Some checks
83        $this->_dochecks();
84        //Initialization of properties
85        $this->page=0;
86        $this->n=2;
87        $this->buffer='';
88        $this->pages=array();
89        $this->OrientationChanges=array();
90        $this->state=0;
91        $this->fonts=array();
92        $this->FontFiles=array();
93        $this->diffs=array();
94        $this->images=array();
95        $this->links=array();
96        $this->InFooter=false;
97        $this->lasth=0;
98        $this->FontFamily='';
99        $this->FontStyle='';
100        $this->FontSizePt=12;
101        $this->underline=false;
102        $this->DrawColor='0 G';
103        $this->FillColor='0 g';
104        $this->TextColor='0 g';
105        $this->ColorFlag=false;
106        $this->ws=0;
107        //Standard fonts
108        $this->CoreFonts=array('courier'=>'Courier','courierB'=>'Courier-Bold','courierI'=>'Courier-Oblique','courierBI'=>'Courier-BoldOblique',
109                'helvetica'=>'Helvetica','helveticaB'=>'Helvetica-Bold','helveticaI'=>'Helvetica-Oblique','helveticaBI'=>'Helvetica-BoldOblique',
110                'times'=>'Times-Roman','timesB'=>'Times-Bold','timesI'=>'Times-Italic','timesBI'=>'Times-BoldItalic',
111                'symbol'=>'Symbol','zapfdingbats'=>'ZapfDingbats');
112        //Scale factor
113        if($unit=='pt')
114                $this->k=1;
115        elseif($unit=='mm')
116                $this->k=72/25.4;
117        elseif($unit=='cm')
118                $this->k=72/2.54;
119        elseif($unit=='in')
120                $this->k=72;
121        else
122                $this->Error('Incorrect unit: '.$unit);
123        //Page format
124        if(is_string($format))
125        {
126                $format=strtolower($format);
127                if($format=='a3')
128                        $format=array(841.89,1190.55);
129                elseif($format=='a4')
130                        $format=array(595.28,841.89);
131                elseif($format=='a5')
132                        $format=array(420.94,595.28);
133                elseif($format=='letter')
134                        $format=array(612,792);
135                elseif($format=='legal')
136                        $format=array(612,1008);
137                else
138                        $this->Error('Unknown page format: '.$format);
139                $this->fwPt=$format[0];
140                $this->fhPt=$format[1];
141        }
142        else
143        {
144                $this->fwPt=$format[0]*$this->k;
145                $this->fhPt=$format[1]*$this->k;
146        }
147        $this->fw=$this->fwPt/$this->k;
148        $this->fh=$this->fhPt/$this->k;
149        //Page orientation
150        $orientation=strtolower($orientation);
151        if($orientation=='p' || $orientation=='portrait')
152        {
153                $this->DefOrientation='P';
154                $this->wPt=$this->fwPt;
155                $this->hPt=$this->fhPt;
156        }
157        elseif($orientation=='l' || $orientation=='landscape')
158        {
159                $this->DefOrientation='L';
160                $this->wPt=$this->fhPt;
161                $this->hPt=$this->fwPt;
162        }
163        else
164                $this->Error('Incorrect orientation: '.$orientation);
165        $this->CurOrientation=$this->DefOrientation;
166        $this->w=$this->wPt/$this->k;
167        $this->h=$this->hPt/$this->k;
168        //Page margins (1 cm)
169        $margin=28.35/$this->k;
170        $this->SetMargins($margin,$margin);
171        //Interior cell margin (1 mm)
172        $this->cMargin=$margin/10;
173        //Line width (0.2 mm)
174        $this->LineWidth=.567/$this->k;
175        //Automatic page break
176        $this->SetAutoPageBreak(true,2*$margin);
177        //Full width display mode
178        $this->SetDisplayMode('fullwidth');
179        //Enable compression
180        $this->SetCompression(true);
181        //Set default PDF version number
182        $this->PDFVersion='1.3';
183}
184
185function SetMargins($left,$top,$right=-1)
186{
187        //Set left, top and right margins
188        $this->lMargin=$left;
189        $this->tMargin=$top;
190        if($right==-1)
191                $right=$left;
192        $this->rMargin=$right;
193}
194
195function SetLeftMargin($margin)
196{
197        //Set left margin
198        $this->lMargin=$margin;
199        if($this->page>0 && $this->x<$margin)
200                $this->x=$margin;
201}
202
203function SetTopMargin($margin)
204{
205        //Set top margin
206        $this->tMargin=$margin;
207}
208
209function SetRightMargin($margin)
210{
211        //Set right margin
212        $this->rMargin=$margin;
213}
214
215function SetAutoPageBreak($auto,$margin=0)
216{
217        //Set auto page break mode and triggering margin
218        $this->AutoPageBreak=$auto;
219        $this->bMargin=$margin;
220        $this->PageBreakTrigger=$this->h-$margin;
221}
222
223function SetDisplayMode($zoom,$layout='continuous')
224{
225        //Set display mode in viewer
226        if($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom))
227                $this->ZoomMode=$zoom;
228        else
229                $this->Error('Incorrect zoom display mode: '.$zoom);
230        if($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default')
231                $this->LayoutMode=$layout;
232        else
233                $this->Error('Incorrect layout display mode: '.$layout);
234}
235
236function SetCompression($compress)
237{
238        //Set page compression
239        if(function_exists('gzcompress'))
240                $this->compress=$compress;
241        else
242                $this->compress=false;
243}
244
245function SetTitle($title)
246{
247        //Title of document
248        $this->title=$title;
249}
250
251function SetSubject($subject)
252{
253        //Subject of document
254        $this->subject=$subject;
255}
256
257function SetAuthor($author)
258{
259        //Author of document
260        $this->author=$author;
261}
262
263function SetKeywords($keywords)
264{
265        //Keywords of document
266        $this->keywords=$keywords;
267}
268
269function SetCreator($creator)
270{
271        //Creator of document
272        $this->creator=$creator;
273}
274
275function AliasNbPages($alias='{nb}')
276{
277        //Define an alias for total number of pages
278        $this->AliasNbPages=$alias;
279}
280
281function Error($msg)
282{
283        //Fatal error
284        die('<B>FPDF error: </B>'.$msg);
285}
286
287function Open()
288{
289        //Begin document
290        $this->state=1;
291}
292
293function Close()
294{
295        //Terminate document
296        if($this->state==3)
297                return;
298        if($this->page==0)
299                $this->AddPage();
300        //Page footer
301        $this->InFooter=true;
302        $this->Footer();
303        $this->InFooter=false;
304        //Close page
305        $this->_endpage();
306        //Close document
307        $this->_enddoc();
308}
309
310function AddPage($orientation='')
311{
312        //Start a new page
313        if($this->state==0)
314                $this->Open();
315        $family=$this->FontFamily;
316        $style=$this->FontStyle.($this->underline ? 'U' : '');
317        $size=$this->FontSizePt;
318        $lw=$this->LineWidth;
319        $dc=$this->DrawColor;
320        $fc=$this->FillColor;
321        $tc=$this->TextColor;
322        $cf=$this->ColorFlag;
323        if($this->page>0)
324        {
325                //Page footer
326                $this->InFooter=true;
327                $this->Footer();
328                $this->InFooter=false;
329                //Close page
330                $this->_endpage();
331        }
332        //Start new page
333        $this->_beginpage($orientation);
334        //Set line cap style to square
335        $this->_out('2 J');
336        //Set line width
337        $this->LineWidth=$lw;
338        $this->_out(sprintf('%.2f w',$lw*$this->k));
339        //Set font
340        if($family)
341                $this->SetFont($family,$style,$size);
342        //Set colors
343        $this->DrawColor=$dc;
344        if($dc!='0 G')
345                $this->_out($dc);
346        $this->FillColor=$fc;
347        if($fc!='0 g')
348                $this->_out($fc);
349        $this->TextColor=$tc;
350        $this->ColorFlag=$cf;
351        //Page header
352        $this->Header();
353        //Restore line width
354        if($this->LineWidth!=$lw)
355        {
356                $this->LineWidth=$lw;
357                $this->_out(sprintf('%.2f w',$lw*$this->k));
358        }
359        //Restore font
360        if($family)
361                $this->SetFont($family,$style,$size);
362        //Restore colors
363        if($this->DrawColor!=$dc)
364        {
365                $this->DrawColor=$dc;
366                $this->_out($dc);
367        }
368        if($this->FillColor!=$fc)
369        {
370                $this->FillColor=$fc;
371                $this->_out($fc);
372        }
373        $this->TextColor=$tc;
374        $this->ColorFlag=$cf;
375}
376
377function Header()
378{
379        //To be implemented in your own inherited class
380}
381
382function Footer()
383{
384        //To be implemented in your own inherited class
385}
386
387function PageNo()
388{
389        //Get current page number
390        return $this->page;
391}
392
393function SetDrawColor($r,$g=-1,$b=-1)
394{
395        //Set color for all stroking operations
396        if(($r==0 && $g==0 && $b==0) || $g==-1)
397                $this->DrawColor=sprintf('%.3f G',$r/255);
398        else
399                $this->DrawColor=sprintf('%.3f %.3f %.3f RG',$r/255,$g/255,$b/255);
400        if($this->page>0)
401                $this->_out($this->DrawColor);
402}
403
404function SetFillColor($r,$g=-1,$b=-1)
405{
406        //Set color for all filling operations
407        if(($r==0 && $g==0 && $b==0) || $g==-1)
408                $this->FillColor=sprintf('%.3f g',$r/255);
409        else
410                $this->FillColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255);
411        $this->ColorFlag=($this->FillColor!=$this->TextColor);
412        if($this->page>0)
413                $this->_out($this->FillColor);
414}
415
416function SetTextColor($r,$g=-1,$b=-1)
417{
418        //Set color for text
419        if(($r==0 && $g==0 && $b==0) || $g==-1)
420                $this->TextColor=sprintf('%.3f g',$r/255);
421        else
422                $this->TextColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255);
423        $this->ColorFlag=($this->FillColor!=$this->TextColor);
424}
425
426function GetStringWidth($s)
427{
428        //Get width of a string in the current font
429        $s=(string)$s;
430        $cw=&$this->CurrentFont['cw'];
431        $w=0;
432        $l=strlen($s);
433        for($i=0;$i<$l;++$i)
434                $w+=$cw[$s{$i}];
435        return $w*$this->FontSize/1000;
436}
437
438function SetLineWidth($width)
439{
440        //Set line width
441        $this->LineWidth=$width;
442        if($this->page>0)
443                $this->_out(sprintf('%.2f w',$width*$this->k));
444}
445
446function Line($x1,$y1,$x2,$y2)
447{
448        //Draw a line
449        $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));
450}
451
452function Rect($x,$y,$w,$h,$style='')
453{
454        //Draw a rectangle
455        if($style=='F')
456                $op='f';
457        elseif($style=='FD' || $style=='DF')
458                $op='B';
459        else
460                $op='S';
461        $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));
462}
463
464function AddFont($family,$style='',$file='')
465{
466        //Add a TrueType or Type1 font
467        $family=strtolower($family);
468        if($file=='')
469                $file=str_replace(' ','',$family).strtolower($style).'.php';
470        if($family=='arial')
471                $family='helvetica';
472        $style=strtoupper($style);
473        if($style=='IB')
474                $style='BI';
475        $fontkey=$family.$style;
476        if(isset($this->fonts[$fontkey]))
477                $this->Error('Font already added: '.$family.' '.$style);
478        include($this->_getfontpath().$file);
479        if(!isset($name))
480                $this->Error('Could not include font definition file');
481        $i=count($this->fonts)+1;
482        $this->fonts[$fontkey]=array('i'=>$i,'type'=>$type,'name'=>$name,'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw,'enc'=>$enc,'file'=>$file);
483        if($diff)
484        {
485                //Search existing encodings
486                $d=0;
487                $nb=count($this->diffs);
488                for($i=1;$i<=$nb;++$i)
489                {
490                        if($this->diffs[$i]==$diff)
491                        {
492                                $d=$i;
493                                break;
494                        }
495                }
496                if($d==0)
497                {
498                        $d=$nb+1;
499                        $this->diffs[$d]=$diff;
500                }
501                $this->fonts[$fontkey]['diff']=$d;
502        }
503        if($file)
504        {
505                if($type=='TrueType')
506                        $this->FontFiles[$file]=array('length1'=>$originalsize);
507                else
508                        $this->FontFiles[$file]=array('length1'=>$size1,'length2'=>$size2);
509        }
510}
511
512function SetFont($family,$style='',$size=0)
513{
514        //Select a font; size given in points
515        global $fpdf_charwidths;
516
517        $family=strtolower($family);
518        if($family=='')
519                $family=$this->FontFamily;
520        if($family=='arial')
521                $family='helvetica';
522        elseif($family=='symbol' || $family=='zapfdingbats')
523                $style='';
524        $style=strtoupper($style);
525        if(strpos($style,'U')!==false)
526        {
527                $this->underline=true;
528                $style=str_replace('U','',$style);
529        }
530        else
531                $this->underline=false;
532        if($style=='IB')
533                $style='BI';
534        if($size==0)
535                $size=$this->FontSizePt;
536        //Test if font is already selected
537        if($this->FontFamily==$family && $this->FontStyle==$style && $this->FontSizePt==$size)
538                return;
539        //Test if used for the first time
540        $fontkey=$family.$style;
541        if(!isset($this->fonts[$fontkey]))
542        {
543                //Check if one of the standard fonts
544                if(isset($this->CoreFonts[$fontkey]))
545                {
546                        if(!isset($fpdf_charwidths[$fontkey]))
547                        {
548                                //Load metric file
549                                $file=$family;
550                                if($family=='times' || $family=='helvetica')
551                                        $file.=strtolower($style);
552                                include($this->_getfontpath().$file.'.php');
553                                if(!isset($fpdf_charwidths[$fontkey]))
554                                        $this->Error('Could not include font metric file');
555                        }
556                        $i=count($this->fonts)+1;
557                        $this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'up'=>-100,'ut'=>50,'cw'=>$fpdf_charwidths[$fontkey]);
558                }
559                else
560                        $this->Error('Undefined font: '.$family.' '.$style);
561        }
562        //Select it
563        $this->FontFamily=$family;
564        $this->FontStyle=$style;
565        $this->FontSizePt=$size;
566        $this->FontSize=$size/$this->k;
567        $this->CurrentFont=&$this->fonts[$fontkey];
568        if($this->page>0)
569                $this->_out(sprintf('BT /F%d %.2f Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
570}
571
572function SetFontSize($size)
573{
574        //Set font size in points
575        if($this->FontSizePt==$size)
576                return;
577        $this->FontSizePt=$size;
578        $this->FontSize=$size/$this->k;
579        if($this->page>0)
580                $this->_out(sprintf('BT /F%d %.2f Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
581}
582
583function AddLink()
584{
585        //Create a new internal link
586        $n=count($this->links)+1;
587        $this->links[$n]=array(0,0);
588        return $n;
589}
590
591function SetLink($link,$y=0,$page=-1)
592{
593        //Set destination of internal link
594        if($y==-1)
595                $y=$this->y;
596        if($page==-1)
597                $page=$this->page;
598        $this->links[$link]=array($page,$y);
599}
600
601function Link($x,$y,$w,$h,$link)
602{
603        //Put a link on the page
604        $this->PageLinks[$this->page][]=array($x*$this->k,$this->hPt-$y*$this->k,$w*$this->k,$h*$this->k,$link);
605}
606
607function Text($x,$y,$txt)
608{
609        //Output a string
610        $s=sprintf('BT %.2f %.2f Td (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt));
611        if($this->underline && $txt!='')
612                $s.=' '.$this->_dounderline($x,$y,$txt);
613        if($this->ColorFlag)
614                $s='q '.$this->TextColor.' '.$s.' Q';
615        $this->_out($s);
616}
617
618function AcceptPageBreak()
619{
620        //Accept automatic page break or not
621        return $this->AutoPageBreak;
622}
623
624function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='')
625{
626        //Output a cell
627        $k=$this->k;
628        if($this->y+$h>$this->PageBreakTrigger && !$this->InFooter && $this->AcceptPageBreak())
629        {
630                //Automatic page break
631                $x=$this->x;
632                $ws=$this->ws;
633                if($ws>0)
634                {
635                        $this->ws=0;
636                        $this->_out('0 Tw');
637                }
638                $this->AddPage($this->CurOrientation);
639                $this->x=$x;
640                if($ws>0)
641                {
642                        $this->ws=$ws;
643                        $this->_out(sprintf('%.3f Tw',$ws*$k));
644                }
645        }
646        if($w==0)
647                $w=$this->w-$this->rMargin-$this->x;
648        $s='';
649        if($fill==1 || $border==1)
650        {
651                if($fill==1)
652                        $op=($border==1) ? 'B' : 'f';
653                else
654                        $op='S';
655                $s=sprintf('%.2f %.2f %.2f %.2f re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op);
656        }
657        if(is_string($border))
658        {
659                $x=$this->x;
660                $y=$this->y;
661                if(strpos($border,'L')!==false)
662                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k);
663                if(strpos($border,'T')!==false)
664                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k);
665                if(strpos($border,'R')!==false)
666                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
667                if(strpos($border,'B')!==false)
668                        $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
669        }
670        if($txt!=='')
671        {
672                if($align=='R')
673                        $dx=$w-$this->cMargin-$this->GetStringWidth($txt);
674                elseif($align=='C')
675                        $dx=($w-$this->GetStringWidth($txt))/2;
676                else
677                        $dx=$this->cMargin;
678                if($this->ColorFlag)
679                        $s.='q '.$this->TextColor.' ';
680                $txt2=str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt)));
681                $s.=sprintf('BT %.2f %.2f Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2);
682                if($this->underline)
683                        $s.=' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt);
684                if($this->ColorFlag)
685                        $s.=' Q';
686                if($link)
687                        $this->Link($this->x+$dx,$this->y+.5*$h-.5*$this->FontSize,$this->GetStringWidth($txt),$this->FontSize,$link);
688        }
689        if($s)
690                $this->_out($s);
691        $this->lasth=$h;
692        if($ln>0)
693        {
694                //Go to next line
695                $this->y+=$h;
696                if($ln==1)
697                        $this->x=$this->lMargin;
698        }
699        else
700                $this->x+=$w;
701}
702
703function MultiCell($w,$h,$txt,$border=0,$align='J',$fill=0)
704{
705        //Output text with automatic or explicit line breaks
706        $cw=&$this->CurrentFont['cw'];
707        if($w==0)
708                $w=$this->w-$this->rMargin-$this->x;
709        $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
710        $s=str_replace("\r",'',$txt);
711        $nb=strlen($s);
712        if($nb>0 && $s[$nb-1]=="\n")
713                $nb--;
714        $b=0;
715        if($border)
716        {
717                if($border==1)
718                {
719                        $border='LTRB';
720                        $b='LRT';
721                        $b2='LR';
722                }
723                else
724                {
725                        $b2='';
726                        if(strpos($border,'L')!==false)
727                                $b2.='L';
728                        if(strpos($border,'R')!==false)
729                                $b2.='R';
730                        $b=(strpos($border,'T')!==false) ? $b2.'T' : $b2;
731                }
732        }
733        $sep=-1;
734        $i=0;
735        $j=0;
736        $l=0;
737        $ns=0;
738        $nl=1;
739        while($i<$nb)
740        {
741                //Get next character
742                $c=$s{$i};
743                if($c=="\n")
744                {
745                        //Explicit line break
746                        if($this->ws>0)
747                        {
748                                $this->ws=0;
749                                $this->_out('0 Tw');
750                        }
751                        $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
752                        ++$i;
753                        $sep=-1;
754                        $j=$i;
755                        $l=0;
756                        $ns=0;
757                        ++$nl;
758                        if($border && $nl==2)
759                                $b=$b2;
760                        continue;
761                }
762                if($c==' ')
763                {
764                        $sep=$i;
765                        $ls=$l;
766                        ++$ns;
767                }
768                $l+=$cw[$c];
769                if($l>$wmax)
770                {
771                        //Automatic line break
772                        if($sep==-1)
773                        {
774                                if($i==$j)
775                                        ++$i;
776                                if($this->ws>0)
777                                {
778                                        $this->ws=0;
779                                        $this->_out('0 Tw');
780                                }
781                                $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
782                        }
783                        else
784                        {
785                                if($align=='J')
786                                {
787                                        $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
788                                        $this->_out(sprintf('%.3f Tw',$this->ws*$this->k));
789                                }
790                                $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
791                                $i=$sep+1;
792                        }
793                        $sep=-1;
794                        $j=$i;
795                        $l=0;
796                        $ns=0;
797                        ++$nl;
798                        if($border && $nl==2)
799                                $b=$b2;
800                }
801                else
802                        ++$i;
803        }
804        //Last chunk
805        if($this->ws>0)
806        {
807                $this->ws=0;
808                $this->_out('0 Tw');
809        }
810        if($border && strpos($border,'B')!==false)
811                $b.='B';
812        $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
813        $this->x=$this->lMargin;
814}
815
816function Write($h,$txt,$link='')
817{
818        //Output text in flowing mode
819        $cw=&$this->CurrentFont['cw'];
820        $w=$this->w-$this->rMargin-$this->x;
821        $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
822        $s=str_replace("\r",'',$txt);
823        $nb=strlen($s);
824        $sep=-1;
825        $i=0;
826        $j=0;
827        $l=0;
828        $nl=1;
829        while($i<$nb)
830        {
831                //Get next character
832                $c=$s{$i};
833                if($c=="\n")
834                {
835                        //Explicit line break
836                        $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link);
837                        ++$i;
838                        $sep=-1;
839                        $j=$i;
840                        $l=0;
841                        if($nl==1)
842                        {
843                                $this->x=$this->lMargin;
844                                $w=$this->w-$this->rMargin-$this->x;
845                                $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
846                        }
847                        ++$nl;
848                        continue;
849                }
850                if($c==' ')
851                        $sep=$i;
852                $l+=$cw[$c];
853                if($l>$wmax)
854                {
855                        //Automatic line break
856                        if($sep==-1)
857                        {
858                                if($this->x>$this->lMargin)
859                                {
860                                        //Move to next line
861                                        $this->x=$this->lMargin;
862                                        $this->y+=$h;
863                                        $w=$this->w-$this->rMargin-$this->x;
864                                        $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
865                                        ++$i;
866                                        ++$nl;
867                                        continue;
868                                }
869                                if($i==$j)
870                                        ++$i;
871                                $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link);
872                        }
873                        else
874                        {
875                                $this->Cell($w,$h,substr($s,$j,$sep-$j),0,2,'',0,$link);
876                                $i=$sep+1;
877                        }
878                        $sep=-1;
879                        $j=$i;
880                        $l=0;
881                        if($nl==1)
882                        {
883                                $this->x=$this->lMargin;
884                                $w=$this->w-$this->rMargin-$this->x;
885                                $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
886                        }
887                        ++$nl;
888                }
889                else
890                        ++$i;
891        }
892        //Last chunk
893        if($i!=$j)
894                $this->Cell($l/1000*$this->FontSize,$h,substr($s,$j),0,0,'',0,$link);
895}
896
897function Image($file,$x,$y,$w=0,$h=0,$type='',$link='')
898{
899        //Put an image on the page
900        if(!isset($this->images[$file]))
901        {
902                //First use of image, get info
903                if($type=='')
904                {
905                        $pos=strrpos($file,'.');
906                        if(!$pos)
907                                $this->Error('Image file has no extension and no type was specified: '.$file);
908                        $type=substr($file,$pos+1);
909                }
910                $type=strtolower($type);
911                $mqr=get_magic_quotes_runtime();
912                set_magic_quotes_runtime(0);
913                if($type=='jpg' || $type=='jpeg')
914                        $info=$this->_parsejpg($file);
915                elseif($type=='png')
916                        $info=$this->_parsepng($file);
917                else
918                {
919                        //Allow for additional formats
920                        $mtd='_parse'.$type;
921                        if(!method_exists($this,$mtd))
922                                $this->Error('Unsupported image type: '.$type);
923                        $info=$this->$mtd($file);
924                }
925                set_magic_quotes_runtime($mqr);
926                $info['i']=count($this->images)+1;
927                $this->images[$file]=$info;
928        }
929        else
930                $info=$this->images[$file];
931        //Automatic width and height calculation if needed
932        if($w==0 && $h==0)
933        {
934                //Put image at 72 dpi
935                $w=$info['w']/$this->k;
936                $h=$info['h']/$this->k;
937        }
938        if($w==0)
939                $w=$h*$info['w']/$info['h'];
940        if($h==0)
941                $h=$w*$info['h']/$info['w'];
942        $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']));
943        if($link)
944                $this->Link($x,$y,$w,$h,$link);
945}
946
947function Ln($h='')
948{
949        //Line feed; default value is last cell height
950        $this->x=$this->lMargin;
951        if(is_string($h))
952                $this->y+=$this->lasth;
953        else
954                $this->y+=$h;
955}
956
957function GetX()
958{
959        //Get x position
960        return $this->x;
961}
962
963function SetX($x)
964{
965        //Set x position
966        if($x>=0)
967                $this->x=$x;
968        else
969                $this->x=$this->w+$x;
970}
971
972function GetY()
973{
974        //Get y position
975        return $this->y;
976}
977
978function SetY($y)
979{
980        //Set y position and reset x
981        $this->x=$this->lMargin;
982        if($y>=0)
983                $this->y=$y;
984        else
985                $this->y=$this->h+$y;
986}
987
988function SetXY($x,$y)
989{
990        //Set x and y positions
991        $this->SetY($y);
992        $this->SetX($x);
993}
994
995function Output($name='',$dest='')
996{
997        //Output PDF to some destination
998        //Finish document if necessary
999        if($this->state<3)
1000                $this->Close();
1001        //Normalize parameters
1002        if(is_bool($dest))
1003                $dest=$dest ? 'D' : 'F';
1004        $dest=strtoupper($dest);
1005        if($dest=='')
1006        {
1007                if($name=='')
1008                {
1009                        $name='doc.pdf';
1010                        $dest='I';
1011                }
1012                else
1013                        $dest='F';
1014        }
1015        switch($dest)
1016        {
1017                case 'I':
1018                        //Send to standard output
1019                        if(ob_get_contents())
1020                                $this->Error('Some data has already been output, can\'t send PDF file');
1021                        if(php_sapi_name()!='cli')
1022                        {
1023                                //We send to a browser
1024                                header('Content-Type: application/pdf');
1025                                if(headers_sent())
1026                                        $this->Error('Some data has already been output to browser, can\'t send PDF file');
1027                                header('Content-Length: '.strlen($this->buffer));
1028                                header('Content-disposition: inline; filename="'.$name.'"');
1029                        }
1030                        echo $this->buffer;
1031                        break;
1032                case 'D':
1033                        //Download file
1034                        if(ob_get_contents())
1035                                $this->Error('Some data has already been output, can\'t send PDF file');
1036                        if(isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'],'MSIE'))
1037                                header('Content-Type: application/force-download');
1038                        else
1039                                header('Content-Type: application/octet-stream');
1040                        if(headers_sent())
1041                                $this->Error('Some data has already been output to browser, can\'t send PDF file');
1042                        header('Content-Length: '.strlen($this->buffer));
1043                        header('Content-disposition: attachment; filename="'.$name.'"');
1044                        echo $this->buffer;
1045                        break;
1046                case 'F':
1047                        //Save to local file
1048                        $f=fopen($name,'wb');
1049                        if(!$f)
1050                                $this->Error('Unable to create output file: '.$name);
1051                        fwrite($f,$this->buffer,strlen($this->buffer));
1052                        fclose($f);
1053                        break;
1054                case 'S':
1055                        //Return as a string
1056                        return $this->buffer;
1057                default:
1058                        $this->Error('Incorrect output destination: '.$dest);
1059        }
1060        return '';
1061}
1062
1063/*******************************************************************************
1064*                                                                              *
1065*                              Protected methods                               *
1066*                                                                              *
1067*******************************************************************************/
1068function _dochecks()
1069{
1070        //Check for locale-related bug
1071        if(1.1==1)
1072                $this->Error('Don\'t alter the locale before including class file');
1073        //Check for decimal separator
1074        if(sprintf('%.1f',1.0)!='1.0')
1075                setlocale(LC_NUMERIC,'C');
1076}
1077
1078function _getfontpath()
1079{
1080        if(!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font'))
1081                define('FPDF_FONTPATH',dirname(__FILE__).'/font/');
1082        return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
1083}
1084
1085function _putpages()
1086{
1087        $nb=$this->page;
1088        if(!empty($this->AliasNbPages))
1089        {
1090                //Replace number of pages
1091                for($n=1;$n<=$nb;++$n)
1092                        $this->pages[$n]=str_replace($this->AliasNbPages,$nb,$this->pages[$n]);
1093        }
1094        if($this->DefOrientation=='P')
1095        {
1096                $wPt=$this->fwPt;
1097                $hPt=$this->fhPt;
1098        }
1099        else
1100        {
1101                $wPt=$this->fhPt;
1102                $hPt=$this->fwPt;
1103        }
1104        $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
1105        for($n=1;$n<=$nb;++$n)
1106        {
1107                //Page
1108                $this->_newobj();
1109                $this->_out('<</Type /Page');
1110                $this->_out('/Parent 1 0 R');
1111                if(isset($this->OrientationChanges[$n]))
1112                        $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$hPt,$wPt));
1113                $this->_out('/Resources 2 0 R');
1114                if(isset($this->PageLinks[$n]))
1115                {
1116                        //Links
1117                        $annots='/Annots [';
1118                        foreach($this->PageLinks[$n] as $pl)
1119                        {
1120                                $rect=sprintf('%.2f %.2f %.2f %.2f',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
1121                                $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
1122                                if(is_string($pl[4]))
1123                                        $annots.='/A <</S /URI /URI '.$this->_textstring($pl[4]).'>>>>';
1124                                else
1125                                {
1126                                        $l=$this->links[$pl[4]];
1127                                        $h=isset($this->OrientationChanges[$l[0]]) ? $wPt : $hPt;
1128                                        $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>',1+2*$l[0],$h-$l[1]*$this->k);
1129                                }
1130                        }
1131                        $this->_out($annots.']');
1132                }
1133                $this->_out('/Contents '.($this->n+1).' 0 R>>');
1134                $this->_out('endobj');
1135                //Page content
1136                $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
1137                $this->_newobj();
1138                $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
1139                $this->_putstream($p);
1140                $this->_out('endobj');
1141        }
1142        //Pages root
1143        $this->offsets[1]=strlen($this->buffer);
1144        $this->_out('1 0 obj');
1145        $this->_out('<</Type /Pages');
1146        $kids='/Kids [';
1147        for($i=0;$i<$nb;++$i)
1148                $kids.=(3+2*$i).' 0 R ';
1149        $this->_out($kids.']');
1150        $this->_out('/Count '.$nb);
1151        $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$wPt,$hPt));
1152        $this->_out('>>');
1153        $this->_out('endobj');
1154}
1155
1156function _putfonts()
1157{
1158        $nf=$this->n;
1159        foreach($this->diffs as $diff)
1160        {
1161                //Encodings
1162                $this->_newobj();
1163                $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
1164                $this->_out('endobj');
1165        }
1166        $mqr=get_magic_quotes_runtime();
1167        set_magic_quotes_runtime(0);
1168        foreach($this->FontFiles as $file=>$info)
1169        {
1170                //Font file embedding
1171                $this->_newobj();
1172                $this->FontFiles[$file]['n']=$this->n;
1173                $font='';
1174                $f=fopen($this->_getfontpath().$file,'rb',1);
1175                if(!$f)
1176                        $this->Error('Font file not found');
1177                while(!feof($f))
1178                        $font.=fread($f,8192);
1179                fclose($f);
1180                $compressed=(substr($file,-2)=='.z');
1181                if(!$compressed && isset($info['length2']))
1182                {
1183                        $header=(ord($font{0})==128);
1184                        if($header)
1185                        {
1186                                //Strip first binary header
1187                                $font=substr($font,6);
1188                        }
1189                        if($header && ord($font{$info['length1']})==128)
1190                        {
1191                                //Strip second binary header
1192                                $font=substr($font,0,$info['length1']).substr($font,$info['length1']+6);
1193                        }
1194                }
1195                $this->_out('<</Length '.strlen($font));
1196                if($compressed)
1197                        $this->_out('/Filter /FlateDecode');
1198                $this->_out('/Length1 '.$info['length1']);
1199                if(isset($info['length2']))
1200                        $this->_out('/Length2 '.$info['length2'].' /Length3 0');
1201                $this->_out('>>');
1202                $this->_putstream($font);
1203                $this->_out('endobj');
1204        }
1205        set_magic_quotes_runtime($mqr);
1206        foreach($this->fonts as $k=>$font)
1207        {
1208                //Font objects
1209                $this->fonts[$k]['n']=$this->n+1;
1210                $type=$font['type'];
1211                $name=$font['name'];
1212                if($type=='core')
1213                {
1214                        //Standard font
1215                        $this->_newobj();
1216                        $this->_out('<</Type /Font');
1217                        $this->_out('/BaseFont /'.$name);
1218                        $this->_out('/Subtype /Type1');
1219                        if($name!='Symbol' && $name!='ZapfDingbats')
1220                                $this->_out('/Encoding /WinAnsiEncoding');
1221                        $this->_out('>>');
1222                        $this->_out('endobj');
1223                }
1224                elseif($type=='Type1' || $type=='TrueType')
1225                {
1226                        //Additional Type1 or TrueType font
1227                        $this->_newobj();
1228                        $this->_out('<</Type /Font');
1229                        $this->_out('/BaseFont /'.$name);
1230                        $this->_out('/Subtype /'.$type);
1231                        $this->_out('/FirstChar 32 /LastChar 255');
1232                        $this->_out('/Widths '.($this->n+1).' 0 R');
1233                        $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
1234                        if($font['enc'])
1235                        {
1236                                if(isset($font['diff']))
1237                                        $this->_out('/Encoding '.($nf+$font['diff']).' 0 R');
1238                                else
1239                                        $this->_out('/Encoding /WinAnsiEncoding');
1240                        }
1241                        $this->_out('>>');
1242                        $this->_out('endobj');
1243                        //Widths
1244                        $this->_newobj();
1245                        $cw=&$font['cw'];
1246                        $s='[';
1247                        for($i=32;$i<=255;++$i)
1248                                $s.=$cw[chr($i)].' ';
1249                        $this->_out($s.']');
1250                        $this->_out('endobj');
1251                        //Descriptor
1252                        $this->_newobj();
1253                        $s='<</Type /FontDescriptor /FontName /'.$name;
1254                        foreach($font['desc'] as $k=>$v)
1255                                $s.=' /'.$k.' '.$v;
1256                        $file=$font['file'];
1257                        if($file)
1258                                $s.=' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->FontFiles[$file]['n'].' 0 R';
1259                        $this->_out($s.'>>');
1260                        $this->_out('endobj');
1261                }
1262                else
1263                {
1264                        //Allow for additional types
1265                        $mtd='_put'.strtolower($type);
1266                        if(!method_exists($this,$mtd))
1267                                $this->Error('Unsupported font type: '.$type);
1268                        $this->$mtd($font);
1269                }
1270        }
1271}
1272
1273function _putimages()
1274{
1275        $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
1276        reset($this->images);
1277        while(list($file,$info)=each($this->images))
1278        {
1279                $this->_newobj();
1280                $this->images[$file]['n']=$this->n;
1281                $this->_out('<</Type /XObject');
1282                $this->_out('/Subtype /Image');
1283                $this->_out('/Width '.$info['w']);
1284                $this->_out('/Height '.$info['h']);
1285                if($info['cs']=='Indexed')
1286                        $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
1287                else
1288                {
1289                        $this->_out('/ColorSpace /'.$info['cs']);
1290                        if($info['cs']=='DeviceCMYK')
1291                                $this->_out('/Decode [1 0 1 0 1 0 1 0]');
1292                }
1293                $this->_out('/BitsPerComponent '.$info['bpc']);
1294                if(isset($info['f']))
1295                        $this->_out('/Filter /'.$info['f']);
1296                if(isset($info['parms']))
1297                        $this->_out($info['parms']);
1298                if(isset($info['trns']) && is_array($info['trns']))
1299                {
1300                        $trns='';
1301            $info_count = count($info['trns']);
1302                        for($i=0;$i<$info_count;++$i)
1303                                $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
1304                        $this->_out('/Mask ['.$trns.']');
1305                }
1306                $this->_out('/Length '.strlen($info['data']).'>>');
1307                $this->_putstream($info['data']);
1308                unset($this->images[$file]['data']);
1309                $this->_out('endobj');
1310                //Palette
1311                if($info['cs']=='Indexed')
1312                {
1313                        $this->_newobj();
1314                        $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
1315                        $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
1316                        $this->_putstream($pal);
1317                        $this->_out('endobj');
1318                }
1319        }
1320}
1321
1322function _putxobjectdict()
1323{
1324        foreach($this->images as $image)
1325                $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
1326}
1327
1328function _putresourcedict()
1329{
1330        $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
1331        $this->_out('/Font <<');
1332        foreach($this->fonts as $font)
1333                $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
1334        $this->_out('>>');
1335        $this->_out('/XObject <<');
1336        $this->_putxobjectdict();
1337        $this->_out('>>');
1338}
1339
1340function _putresources()
1341{
1342        $this->_putfonts();
1343        $this->_putimages();
1344        //Resource dictionary
1345        $this->offsets[2]=strlen($this->buffer);
1346        $this->_out('2 0 obj');
1347        $this->_out('<<');
1348        $this->_putresourcedict();
1349        $this->_out('>>');
1350        $this->_out('endobj');
1351}
1352
1353function _putinfo()
1354{
1355        $this->_out('/Producer '.$this->_textstring('FPDF '.FPDF_VERSION));
1356        if(!empty($this->title))
1357                $this->_out('/Title '.$this->_textstring($this->title));
1358        if(!empty($this->subject))
1359                $this->_out('/Subject '.$this->_textstring($this->subject));
1360        if(!empty($this->author))
1361                $this->_out('/Author '.$this->_textstring($this->author));
1362        if(!empty($this->keywords))
1363                $this->_out('/Keywords '.$this->_textstring($this->keywords));
1364        if(!empty($this->creator))
1365                $this->_out('/Creator '.$this->_textstring($this->creator));
1366        $this->_out('/CreationDate '.$this->_textstring('D:'.date('YmdHis')));
1367}
1368
1369function _putcatalog()
1370{
1371        $this->_out('/Type /Catalog');
1372        $this->_out('/Pages 1 0 R');
1373        if($this->ZoomMode=='fullpage')
1374                $this->_out('/OpenAction [3 0 R /Fit]');
1375        elseif($this->ZoomMode=='fullwidth')
1376                $this->_out('/OpenAction [3 0 R /FitH null]');
1377        elseif($this->ZoomMode=='real')
1378                $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
1379        elseif(!is_string($this->ZoomMode))
1380                $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
1381        if($this->LayoutMode=='single')
1382                $this->_out('/PageLayout /SinglePage');
1383        elseif($this->LayoutMode=='continuous')
1384                $this->_out('/PageLayout /OneColumn');
1385        elseif($this->LayoutMode=='two')
1386                $this->_out('/PageLayout /TwoColumnLeft');
1387}
1388
1389function _putheader()
1390{
1391        $this->_out('%PDF-'.$this->PDFVersion);
1392}
1393
1394function _puttrailer()
1395{
1396        $this->_out('/Size '.($this->n+1));
1397        $this->_out('/Root '.$this->n.' 0 R');
1398        $this->_out('/Info '.($this->n-1).' 0 R');
1399}
1400
1401function _enddoc()
1402{
1403        $this->_putheader();
1404        $this->_putpages();
1405        $this->_putresources();
1406        //Info
1407        $this->_newobj();
1408        $this->_out('<<');
1409        $this->_putinfo();
1410        $this->_out('>>');
1411        $this->_out('endobj');
1412        //Catalog
1413        $this->_newobj();
1414        $this->_out('<<');
1415        $this->_putcatalog();
1416        $this->_out('>>');
1417        $this->_out('endobj');
1418        //Cross-ref
1419        $o=strlen($this->buffer);
1420        $this->_out('xref');
1421        $this->_out('0 '.($this->n+1));
1422        $this->_out('0000000000 65535 f ');
1423        for($i=1;$i<=$this->n;++$i)
1424                $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
1425        //Trailer
1426        $this->_out('trailer');
1427        $this->_out('<<');
1428        $this->_puttrailer();
1429        $this->_out('>>');
1430        $this->_out('startxref');
1431        $this->_out($o);
1432        $this->_out('%%EOF');
1433        $this->state=3;
1434}
1435
1436function _beginpage($orientation)
1437{
1438        $this->page++;
1439        $this->pages[$this->page]='';
1440        $this->state=2;
1441        $this->x=$this->lMargin;
1442        $this->y=$this->tMargin;
1443        $this->FontFamily='';
1444        //Page orientation
1445        if(!$orientation)
1446                $orientation=$this->DefOrientation;
1447        else
1448        {
1449                $orientation=strtoupper($orientation{0});
1450                if($orientation!=$this->DefOrientation)
1451                        $this->OrientationChanges[$this->page]=true;
1452        }
1453        if($orientation!=$this->CurOrientation)
1454        {
1455                //Change orientation
1456                if($orientation=='P')
1457                {
1458                        $this->wPt=$this->fwPt;
1459                        $this->hPt=$this->fhPt;
1460                        $this->w=$this->fw;
1461                        $this->h=$this->fh;
1462                }
1463                else
1464                {
1465                        $this->wPt=$this->fhPt;
1466                        $this->hPt=$this->fwPt;
1467                        $this->w=$this->fh;
1468                        $this->h=$this->fw;
1469                }
1470                $this->PageBreakTrigger=$this->h-$this->bMargin;
1471                $this->CurOrientation=$orientation;
1472        }
1473}
1474
1475function _endpage()
1476{
1477        //End of page contents
1478        $this->state=1;
1479}
1480
1481function _newobj()
1482{
1483        //Begin a new object
1484        $this->n++;
1485        $this->offsets[$this->n]=strlen($this->buffer);
1486        $this->_out($this->n.' 0 obj');
1487}
1488
1489function _dounderline($x,$y,$txt)
1490{
1491        //Underline text
1492        $up=$this->CurrentFont['up'];
1493        $ut=$this->CurrentFont['ut'];
1494        $w=$this->GetStringWidth($txt)+$this->ws*substr_count($txt,' ');
1495        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);
1496}
1497
1498function _parsejpg($file)
1499{
1500        //Extract info from a JPEG file
1501        $a=GetImageSize($file);
1502        if(!$a)
1503                $this->Error('Missing or incorrect image file: '.$file);
1504        if($a[2]!=2)
1505                $this->Error('Not a JPEG file: '.$file);
1506        if(!isset($a['channels']) || $a['channels']==3)
1507                $colspace='DeviceRGB';
1508        elseif($a['channels']==4)
1509                $colspace='DeviceCMYK';
1510        else
1511                $colspace='DeviceGray';
1512        $bpc=isset($a['bits']) ? $a['bits'] : 8;
1513        //Read whole file
1514        $f=fopen($file,'rb');
1515        $data='';
1516        while(!feof($f))
1517                $data.=fread($f,4096);
1518        fclose($f);
1519        return array('w'=>$a[0],'h'=>$a[1],'cs'=>$colspace,'bpc'=>$bpc,'f'=>'DCTDecode','data'=>$data);
1520}
1521
1522function _parsepng($file)
1523{
1524        //Extract info from a PNG file
1525        $f=fopen($file,'rb');
1526        if(!$f)
1527                $this->Error('Can\'t open image file: '.$file);
1528        //Check signature
1529        if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
1530                $this->Error('Not a PNG file: '.$file);
1531        //Read header chunk
1532        fread($f,4);
1533        if(fread($f,4)!='IHDR')
1534                $this->Error('Incorrect PNG file: '.$file);
1535        $w=$this->_freadint($f);
1536        $h=$this->_freadint($f);
1537        $bpc=ord(fread($f,1));
1538        if($bpc>8)
1539                $this->Error('16-bit depth not supported: '.$file);
1540        $ct=ord(fread($f,1));
1541        if($ct==0)
1542                $colspace='DeviceGray';
1543        elseif($ct==2)
1544                $colspace='DeviceRGB';
1545        elseif($ct==3)
1546                $colspace='Indexed';
1547        else
1548                $this->Error('Alpha channel not supported: '.$file);
1549        if(ord(fread($f,1))!=0)
1550                $this->Error('Unknown compression method: '.$file);
1551        if(ord(fread($f,1))!=0)
1552                $this->Error('Unknown filter method: '.$file);
1553        if(ord(fread($f,1))!=0)
1554                $this->Error('Interlacing not supported: '.$file);
1555        fread($f,4);
1556        $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
1557        //Scan chunks looking for palette, transparency and image data
1558        $pal='';
1559        $trns='';
1560        $data='';
1561        do
1562        {
1563                $n=$this->_freadint($f);
1564                $type=fread($f,4);
1565                if($type=='PLTE')
1566                {
1567                        //Read palette
1568                        $pal=fread($f,$n);
1569                        fread($f,4);
1570                }
1571                elseif($type=='tRNS')
1572                {
1573                        //Read transparency info
1574                        $t=fread($f,$n);
1575                        if($ct==0)
1576                                $trns=array(ord(substr($t,1,1)));
1577                        elseif($ct==2)
1578                                $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
1579                        else
1580                        {
1581                                $pos=strpos($t,chr(0));
1582                                if($pos!==false)
1583                                        $trns=array($pos);
1584                        }
1585                        fread($f,4);
1586                }
1587                elseif($type=='IDAT')
1588                {
1589                        //Read image data block
1590                        $data.=fread($f,$n);
1591                        fread($f,4);
1592                }
1593                elseif($type=='IEND')
1594                        break;
1595                else
1596                        fread($f,$n+4);
1597        }
1598        while($n);
1599        if($colspace=='Indexed' && empty($pal))
1600                $this->Error('Missing palette in '.$file);
1601        fclose($f);
1602        return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data);
1603}
1604
1605function _freadint($f)
1606{
1607        //Read a 4-byte integer from file
1608        $a=unpack('Ni',fread($f,4));
1609        return $a['i'];
1610}
1611
1612function _textstring($s)
1613{
1614        //Format a text string
1615        return '('.$this->_escape($s).')';
1616}
1617
1618function _escape($s)
1619{
1620        //Add \ before \, ( and )
1621        return str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$s)));
1622}
1623
1624function _putstream($s)
1625{
1626        $this->_out('stream');
1627        $this->_out($s);
1628        $this->_out('endstream');
1629}
1630
1631function _out($s)
1632{
1633        //Add a line to the document
1634        if($this->state==2)
1635                $this->pages[$this->page].=$s."\n";
1636        else
1637                $this->buffer.=$s."\n";
1638}
1639//End of class
1640}
1641
1642//Handle special IE contype request
1643if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']=='contype')
1644{
1645        header('Content-Type: application/pdf');
1646        exit;
1647}
1648
1649}
1650?>
Note: See TracBrowser for help on using the repository browser.