source: trunk/reports/inc/class.fpdf.inc.php @ 7673

Revision 7673, 44.1 KB checked in by douglasz, 11 years ago (diff)

Ticket #3236 - Correcoes para Performance: Function Within Loop Declaration.

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