phpBMS

root/trunk/phpbms/fpdf/fpdf.php

Revision 693, 44.0 KB (checked in by brieb, 2 years ago)
  • Introduced administratively changeable settings to indvidual reports
  • Modified all reports to work with new settings system
  • Altered invoice and line item total reports to accept parameters from reportsettings: You can now bypass the grouping/column dialog by providing the infrmation administratively
  • Altered all sales order PDF reports to accept parameters from reportsettings: You can now administratively change certain aspects of the print outs, including what parts of the top of the report to show, and what to title the report
  • Altered label reports to accept parameters from reportsettings: printed data as well

as label measurements and layout are now defined by administratively

  • Altered export and tableprint reports to accept parameters from reportsettings: You can specify individual columns and from table instead of just the defaults (all fields, main table only)
  • Added var_dump-esque 'debug' function for development purposes to common functions
  • Integrated FPDI functionality with sales order PDF reports: It is now possible to use a PDF saved in the files table as a background template for your invoices (e.g. watermarks)
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}
375
376function PageNo()
377{
378        //Get current page number
379        return $this->page;
380}
381
382function SetDrawColor($r, $g=null, $b=null)
383{
384        //Set color for all stroking operations
385        if(($r==0 && $g==0 && $b==0) || $g===null)
386                $this->DrawColor=sprintf('%.3F G',$r/255);
387        else
388                $this->DrawColor=sprintf('%.3F %.3F %.3F RG',$r/255,$g/255,$b/255);
389        if($this->page>0)
390                $this->_out($this->DrawColor);
391}
392
393function SetFillColor($r, $g=null, $b=null)
394{
395        //Set color for all filling operations
396        if(($r==0 && $g==0 && $b==0) || $g===null)
397                $this->FillColor=sprintf('%.3F g',$r/255);
398        else
399                $this->FillColor=sprintf('%.3F %.3F %.3F rg',$r/255,$g/255,$b/255);
400        $this->ColorFlag=($this->FillColor!=$this->TextColor);
401        if($this->page>0)
402                $this->_out($this->FillColor);
403}
404
405function SetTextColor($r, $g=null, $b=null)
406{
407        //Set color for text
408        if(($r==0 && $g==0 && $b==0) || $g===null)
409                $this->TextColor=sprintf('%.3F g',$r/255);
410        else
411                $this->TextColor=sprintf('%.3F %.3F %.3F rg',$r/255,$g/255,$b/255);
412        $this->ColorFlag=($this->FillColor!=$this->TextColor);
413}
414
415function GetStringWidth($s)
416{
417        //Get width of a string in the current font
418        $s=(string)$s;
419        $cw=&$this->CurrentFont['cw'];
420        $w=0;
421        $l=strlen($s);
422        for($i=0;$i<$l;$i++)
423                $w+=$cw[$s[$i]];
424        return $w*$this->FontSize/1000;
425}
426
427function SetLineWidth($width)
428{
429        //Set line width
430        $this->LineWidth=$width;
431        if($this->page>0)
432                $this->_out(sprintf('%.2F w',$width*$this->k));
433}
434
435function Line($x1, $y1, $x2, $y2)
436{
437        //Draw a line
438        $this->_out(sprintf('%.2F %.2F m %.2F %.2F l S',$x1*$this->k,($this->h-$y1)*$this->k,$x2*$this->k,($this->h-$y2)*$this->k));
439}
440
441function Rect($x, $y, $w, $h, $style='')
442{
443        //Draw a rectangle
444        if($style=='F')
445                $op='f';
446        elseif($style=='FD' || $style=='DF')
447                $op='B';
448        else
449                $op='S';
450        $this->_out(sprintf('%.2F %.2F %.2F %.2F re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));
451}
452
453function AddFont($family, $style='', $file='')
454{
455        //Add a TrueType or Type1 font
456        $family=strtolower($family);
457        if($file=='')
458                $file=str_replace(' ','',$family).strtolower($style).'.php';
459        if($family=='arial')
460                $family='helvetica';
461        $style=strtoupper($style);
462        if($style=='IB')
463                $style='BI';
464        $fontkey=$family.$style;
465        if(isset($this->fonts[$fontkey]))
466                return;
467        include($this->_getfontpath().$file);
468        if(!isset($name))
469                $this->Error('Could not include font definition file');
470        $i=count($this->fonts)+1;
471        $this->fonts[$fontkey]=array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'enc'=>$enc, 'file'=>$file);
472        if($diff)
473        {
474                //Search existing encodings
475                $d=0;
476                $nb=count($this->diffs);
477                for($i=1;$i<=$nb;$i++)
478                {
479                        if($this->diffs[$i]==$diff)
480                        {
481                                $d=$i;
482                                break;
483                        }
484                }
485                if($d==0)
486                {
487                        $d=$nb+1;
488                        $this->diffs[$d]=$diff;
489                }
490                $this->fonts[$fontkey]['diff']=$d;
491        }
492        if($file)
493        {
494                if($type=='TrueType')
495                        $this->FontFiles[$file]=array('length1'=>$originalsize);
496                else
497                        $this->FontFiles[$file]=array('length1'=>$size1, 'length2'=>$size2);
498        }
499}
500
501function SetFont($family, $style='', $size=0)
502{
503        //Select a font; size given in points
504        global $fpdf_charwidths;
505
506        $family=strtolower($family);
507        if($family=='')
508                $family=$this->FontFamily;
509        if($family=='arial')
510                $family='helvetica';
511        elseif($family=='symbol' || $family=='zapfdingbats')
512                $style='';
513        $style=strtoupper($style);
514        if(strpos($style,'U')!==false)
515        {
516                $this->underline=true;
517                $style=str_replace('U','',$style);
518        }
519        else
520                $this->underline=false;
521        if($style=='IB')
522                $style='BI';
523        if($size==0)
524                $size=$this->FontSizePt;
525        //Test if font is already selected
526        if($this->FontFamily==$family && $this->FontStyle==$style && $this->FontSizePt==$size)
527                return;
528        //Test if used for the first time
529        $fontkey=$family.$style;
530        if(!isset($this->fonts[$fontkey]))
531        {
532                //Check if one of the standard fonts
533                if(isset($this->CoreFonts[$fontkey]))
534                {
535                        if(!isset($fpdf_charwidths[$fontkey]))
536                        {
537                                //Load metric file
538                                $file=$family;
539                                if($family=='times' || $family=='helvetica')
540                                        $file.=strtolower($style);
541                                include($this->_getfontpath().$file.'.php');
542                                if(!isset($fpdf_charwidths[$fontkey]))
543                                        $this->Error('Could not include font metric file');
544                        }
545                        $i=count($this->fonts)+1;
546                        $name=$this->CoreFonts[$fontkey];
547                        $cw=$fpdf_charwidths[$fontkey];
548                        $this->fonts[$fontkey]=array('i'=>$i, 'type'=>'core', 'name'=>$name, 'up'=>-100, 'ut'=>50, 'cw'=>$cw);
549                }
550                else
551                        $this->Error('Undefined font: '.$family.' '.$style);
552        }
553        //Select it
554        $this->FontFamily=$family;
555        $this->FontStyle=$style;
556        $this->FontSizePt=$size;
557        $this->FontSize=$size/$this->k;
558        $this->CurrentFont=&$this->fonts[$fontkey];
559        if($this->page>0)
560                $this->_out(sprintf('BT /F%d %.2F Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
561}
562
563function SetFontSize($size)
564{
565        //Set font size in points
566        if($this->FontSizePt==$size)
567                return;
568        $this->FontSizePt=$size;
569        $this->FontSize=$size/$this->k;
570        if($this->page>0)
571                $this->_out(sprintf('BT /F%d %.2F Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
572}
573
574function AddLink()
575{
576        //Create a new internal link
577        $n=count($this->links)+1;
578        $this->links[$n]=array(0, 0);
579        return $n;
580}
581
582function SetLink($link, $y=0, $page=-1)
583{
584        //Set destination of internal link
585        if($y==-1)
586                $y=$this->y;
587        if($page==-1)
588                $page=$this->page;
589        $this->links[$link]=array($page, $y);
590}
591
592function Link($x, $y, $w, $h, $link)
593{
594        //Put a link on the page
595        $this->PageLinks[$this->page][]=array($x*$this->k, $this->hPt-$y*$this->k, $w*$this->k, $h*$this->k, $link);
596}
597
598function Text($x, $y, $txt)
599{
600        //Output a string
601        $s=sprintf('BT %.2F %.2F Td (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt));
602        if($this->underline && $txt!='')
603                $s.=' '.$this->_dounderline($x,$y,$txt);
604        if($this->ColorFlag)
605                $s='q '.$this->TextColor.' '.$s.' Q';
606        $this->_out($s);
607}
608
609function AcceptPageBreak()
610{
611        //Accept automatic page break or not
612        return $this->AutoPageBreak;
613}
614
615function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='')
616{
617        //Output a cell
618        $k=$this->k;
619        if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak())
620        {
621                //Automatic page break
622                $x=$this->x;
623                $ws=$this->ws;
624                if($ws>0)
625                {
626                        $this->ws=0;
627                        $this->_out('0 Tw');
628                }
629                $this->AddPage($this->CurOrientation,$this->CurPageFormat);
630                $this->x=$x;
631                if($ws>0)
632                {
633                        $this->ws=$ws;
634                        $this->_out(sprintf('%.3F Tw',$ws*$k));
635                }
636        }
637        if($w==0)
638                $w=$this->w-$this->rMargin-$this->x;
639        $s='';
640        if($fill || $border==1)
641        {
642                if($fill)
643                        $op=($border==1) ? 'B' : 'f';
644                else
645                        $op='S';
646                $s=sprintf('%.2F %.2F %.2F %.2F re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op);
647        }
648        if(is_string($border))
649        {
650                $x=$this->x;
651                $y=$this->y;
652                if(strpos($border,'L')!==false)
653                        $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k);
654                if(strpos($border,'T')!==false)
655                        $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k);
656                if(strpos($border,'R')!==false)
657                        $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
658                if(strpos($border,'B')!==false)
659                        $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
660        }
661        if($txt!=='')
662        {
663                if($align=='R')
664                        $dx=$w-$this->cMargin-$this->GetStringWidth($txt);
665                elseif($align=='C')
666                        $dx=($w-$this->GetStringWidth($txt))/2;
667                else
668                        $dx=$this->cMargin;
669                if($this->ColorFlag)
670                        $s.='q '.$this->TextColor.' ';
671                $txt2=str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt)));
672                $s.=sprintf('BT %.2F %.2F Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2);
673                if($this->underline)
674                        $s.=' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt);
675                if($this->ColorFlag)
676                        $s.=' Q';
677                if($link)
678                        $this->Link($this->x+$dx,$this->y+.5*$h-.5*$this->FontSize,$this->GetStringWidth($txt),$this->FontSize,$link);
679        }
680        if($s)
681                $this->_out($s);
682        $this->lasth=$h;
683        if($ln>0)
684        {
685                //Go to next line
686                $this->y+=$h;
687                if($ln==1)
688                        $this->x=$this->lMargin;
689        }
690        else
691                $this->x+=$w;
692}
693
694function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false)
695{
696        //Output text with automatic or explicit line breaks
697        $cw=&$this->CurrentFont['cw'];
698        if($w==0)
699                $w=$this->w-$this->rMargin-$this->x;
700        $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
701        $s=str_replace("\r",'',$txt);
702        $nb=strlen($s);
703        if($nb>0 && $s[$nb-1]=="\n")
704                $nb--;
705        $b=0;
706        if($border)
707        {
708                if($border==1)
709                {
710                        $border='LTRB';
711                        $b='LRT';
712                        $b2='LR';
713                }
714                else
715                {
716                        $b2='';
717                        if(strpos($border,'L')!==false)
718                                $b2.='L';
719                        if(strpos($border,'R')!==false)
720                                $b2.='R';
721                        $b=(strpos($border,'T')!==false) ? $b2.'T' : $b2;
722                }
723        }
724        $sep=-1;
725        $i=0;
726        $j=0;
727        $l=0;
728        $ns=0;
729        $nl=1;
730        while($i<$nb)
731        {
732                //Get next character
733                $c=$s[$i];
734                if($c=="\n")
735                {
736                        //Explicit line break
737                        if($this->ws>0)
738                        {
739                                $this->ws=0;
740                                $this->_out('0 Tw');
741                        }
742                        $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
743                        $i++;
744                        $sep=-1;
745                        $j=$i;
746                        $l=0;
747                        $ns=0;
748                        $nl++;
749                        if($border && $nl==2)
750                                $b=$b2;
751                        continue;
752                }
753                if($c==' ')
754                {
755                        $sep=$i;
756                        $ls=$l;
757                        $ns++;
758                }
759                $l+=$cw[$c];
760                if($l>$wmax)
761                {
762                        //Automatic line break
763                        if($sep==-1)
764                        {
765                                if($i==$j)
766                                        $i++;
767                                if($this->ws>0)
768                                {
769                                        $this->ws=0;
770                                        $this->_out('0 Tw');
771                                }
772                                $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
773                        }
774                        else
775                        {
776                                if($align=='J')
777                                {
778                                        $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
779                                        $this->_out(sprintf('%.3F Tw',$this->ws*$this->k));
780                                }
781                                $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
782                                $i=$sep+1;
783                        }
784                        $sep=-1;
785                        $j=$i;
786                        $l=0;
787                        $ns=0;
788                        $nl++;
789                        if($border && $nl==2)
790                                $b=$b2;
791                }
792                else
793                        $i++;
794        }
795        //Last chunk
796        if($this->ws>0)
797        {
798                $this->ws=0;
799                $this->_out('0 Tw');
800        }
801        if($border && strpos($border,'B')!==false)
802                $b.='B';
803        $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
804        $this->x=$this->lMargin;
805}
806
807function Write($h, $txt, $link='')
808{
809        //Output text in flowing mode
810        $cw=&$this->CurrentFont['cw'];
811        $w=$this->w-$this->rMargin-$this->x;
812        $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
813        $s=str_replace("\r",'',$txt);
814        $nb=strlen($s);
815        $sep=-1;
816        $i=0;
817        $j=0;
818        $l=0;
819        $nl=1;
820        while($i<$nb)
821        {
822                //Get next character
823                $c=$s[$i];
824                if($c=="\n")
825                {
826                        //Explicit line break
827                        $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link);
828                        $i++;
829                        $sep=-1;
830                        $j=$i;
831                        $l=0;
832                        if($nl==1)
833                        {
834                                $this->x=$this->lMargin;
835                                $w=$this->w-$this->rMargin-$this->x;
836                                $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
837                        }
838                        $nl++;
839                        continue;
840                }
841                if($c==' ')
842                        $sep=$i;
843                $l+=$cw[$c];
844                if($l>$wmax)
845                {
846                        //Automatic line break
847                        if($sep==-1)
848                        {
849                                if($this->x>$this->lMargin)
850                                {
851                                        //Move to next line
852                                        $this->x=$this->lMargin;
853                                        $this->y+=$h;
854                                        $w=$this->w-$this->rMargin-$this->x;
855                                        $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
856                                        $i++;
857                                        $nl++;
858                                        continue;
859                                }
860                                if($i==$j)
861                                        $i++;
862                                $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link);
863                        }
864                        else
865                        {
866                                $this->Cell($w,$h,substr($s,$j,$sep-$j),0,2,'',0,$link);
867                                $i=$sep+1;
868                        }
869                        $sep=-1;
870                        $j=$i;
871                        $l=0;
872                        if($nl==1)
873                        {
874                                $this->x=$this->lMargin;
875                                $w=$this->w-$this->rMargin-$this->x;
876                                $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
877                        }
878                        $nl++;
879                }
880                else
881                        $i++;
882        }
883        //Last chunk
884        if($i!=$j)
885                $this->Cell($l/1000*$this->FontSize,$h,substr($s,$j),0,0,'',0,$link);
886}
887
888function Ln($h=null)
889{
890        //Line feed; default value is last cell height
891        $this->x=$this->lMargin;
892        if($h===null)
893                $this->y+=$this->lasth;
894        else
895                $this->y+=$h;
896}
897
898function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='')
899{
900        //Put an image on the page
901        if(!isset($this->images[$file]))
902        {
903                //First use of this image, get info
904                if($type=='')
905                {
906                        $pos=strrpos($file,'.');
907                        if(!$pos)
908                                $this->Error('Image file has no extension and no type was specified: '.$file);
909                        $type=substr($file,$pos+1);
910                }
911                $type=strtolower($type);
912                if($type=='jpeg')
913                        $type='jpg';
914                $mtd='_parse'.$type;
915                if(!method_exists($this,$mtd))
916                        $this->Error('Unsupported image type: '.$type);
917                $info=$this->$mtd($file);
918                $info['i']=count($this->images)+1;
919                $this->images[$file]=$info;
920        }
921        else
922                $info=$this->images[$file];
923        //Automatic width and height calculation if needed
924        if($w==0 && $h==0)
925        {
926                //Put image at 72 dpi
927                $w=$info['w']/$this->k;
928                $h=$info['h']/$this->k;
929        }
930        elseif($w==0)
931                $w=$h*$info['w']/$info['h'];
932        elseif($h==0)
933                $h=$w*$info['h']/$info['w'];
934        //Flowing mode
935        if($y===null)
936        {
937                if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak())
938                {
939                        //Automatic page break
940                        $x2=$this->x;
941                        $this->AddPage($this->CurOrientation,$this->CurPageFormat);
942                        $this->x=$x2;
943                }
944                $y=$this->y;
945                $this->y+=$h;
946        }
947        if($x===null)
948                $x=$this->x;
949        $this->_out(sprintf('q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q',$w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i']));
950        if($link)
951                $this->Link($x,$y,$w,$h,$link);
952}
953
954function GetX()
955{
956        //Get x position
957        return $this->x;
958}
959
960function SetX($x)
961{
962        //Set x position
963        if($x>=0)
964                $this->x=$x;
965        else
966                $this->x=$this->w+$x;
967}
968
969function GetY()
970{
971        //Get y position
972        return $this->y;
973}
974
975function SetY($y)
976{
977        //Set y position and reset x
978        $this->x=$this->lMargin;
979        if($y>=0)
980                $this->y=$y;
981        else
982                $this->y=$this->h+$y;
983}
984
985function SetXY($x, $y)
986{
987        //Set x and y positions
988        $this->SetY($y);
989        $this->SetX($x);
990}
991
992function Output($name='', $dest='')
993{
994        //Output PDF to some destination
995        if($this->state<3)
996                $this->Close();
997        $dest=strtoupper($dest);
998        if($dest=='')
999        {
1000                if($name=='')
1001                {
1002                        $name='doc.pdf';
1003                        $dest='I';
1004                }
1005                else
1006                        $dest='F';
1007        }
1008        switch($dest)
1009        {
1010                case 'I':
1011                        //Send to standard output
1012                        if(ob_get_length())
1013                                $this->Error('Some data has already been output, can\'t send PDF file');
1014                        if(php_sapi_name()!='cli')
1015                        {
1016                                //We send to a browser
1017                                header('Content-Type: application/pdf');
1018                                if(headers_sent())
1019                                        $this->Error('Some data has already been output, can\'t send PDF file');
1020                                header('Content-Length: '.strlen($this->buffer));
1021                                header('Content-Disposition: inline; filename="'.$name.'"');
1022                                header('Cache-Control: private, max-age=0, must-revalidate');
1023                                header('Pragma: public');
1024                                ini_set('zlib.output_compression','0');
1025                        }
1026                        echo $this->buffer;
1027                        break;
1028                case 'D':
1029                        //Download file
1030                        if(ob_get_length())
1031                                $this->Error('Some data has already been output, can\'t send PDF file');
1032                        header('Content-Type: application/x-download');
1033                        if(headers_sent())
1034                                $this->Error('Some data has already been output, can\'t send PDF file');
1035                        header('Content-Length: '.strlen($this->buffer));
1036                        header('Content-Disposition: attachment; filename="'.$name.'"');
1037                        header('Cache-Control: private, max-age=0, must-revalidate');
1038                        header('Pragma: public');
1039                        ini_set('zlib.output_compression','0');
1040                        echo $this->buffer;
1041                        break;
1042                case 'F':
1043                        //Save to local file
1044                        $f=fopen($name,'wb');
1045                        if(!$f)
1046                                $this->Error('Unable to create output file: '.$name);
1047                        fwrite($f,$this->buffer,strlen($this->buffer));
1048                        fclose($f);
1049                        break;
1050                case 'S':
1051                        //Return as a string
1052                        return $this->buffer;
1053                default:
1054                        $this->Error('Incorrect output destination: '.$dest);
1055        }
1056        return '';
1057}
1058
1059/*******************************************************************************
1060*                                                                              *
1061*                              Protected methods                               *
1062*                                                                              *
1063*******************************************************************************/
1064function _dochecks()
1065{
1066        //Check availability of %F
1067        if(sprintf('%.1F',1.0)!='1.0')
1068                $this->Error('This version of PHP is not supported');
1069        //Check mbstring overloading
1070        if(ini_get('mbstring.func_overload') & 2)
1071                $this->Error('mbstring overloading must be disabled');
1072        //Disable runtime magic quotes
1073        if(get_magic_quotes_runtime())
1074                @set_magic_quotes_runtime(0);
1075}
1076
1077function _getpageformat($format)
1078{
1079        $format=strtolower($format);
1080        if(!isset($this->PageFormats[$format]))
1081                $this->Error('Unknown page format: '.$format);
1082        $a=$this->PageFormats[$format];
1083        return array($a[0]/$this->k, $a[1]/$this->k);
1084}
1085
1086function _getfontpath()
1087{
1088        if(!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font'))
1089                define('FPDF_FONTPATH',dirname(__FILE__).'/font/');
1090        return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
1091}
1092
1093function _beginpage($orientation, $format)
1094{
1095        $this->page++;
1096        $this->pages[$this->page]='';
1097        $this->state=2;
1098        $this->x=$this->lMargin;
1099        $this->y=$this->tMargin;
1100        $this->FontFamily='';
1101        //Check page size
1102        if($orientation=='')
1103                $orientation=$this->DefOrientation;
1104        else
1105                $orientation=strtoupper($orientation[0]);
1106        if($format=='')
1107                $format=$this->DefPageFormat;
1108        else
1109        {
1110                if(is_string($format))
1111                        $format=$this->_getpageformat($format);
1112        }
1113        if($orientation!=$this->CurOrientation || $format[0]!=$this->CurPageFormat[0] || $format[1]!=$this->CurPageFormat[1])
1114        {
1115                //New size
1116                if($orientation=='P')
1117                {
1118                        $this->w=$format[0];
1119                        $this->h=$format[1];
1120                }
1121                else
1122                {
1123                        $this->w=$format[1];
1124                        $this->h=$format[0];
1125                }
1126                $this->wPt=$this->w*$this->k;
1127                $this->hPt=$this->h*$this->k;
1128                $this->PageBreakTrigger=$this->h-$this->bMargin;
1129                $this->CurOrientation=$orientation;
1130                $this->CurPageFormat=$format;
1131        }
1132        if($orientation!=$this->DefOrientation || $format[0]!=$this->DefPageFormat[0] || $format[1]!=$this->DefPageFormat[1])
1133                $this->PageSizes[$this->page]=array($this->wPt, $this->hPt);
1134}
1135
1136function _endpage()
1137{
1138        $this->state=1;
1139}
1140
1141function _escape($s)
1142{
1143        //Escape special characters in strings
1144        $s=str_replace('\\','\\\\',$s);
1145        $s=str_replace('(','\\(',$s);
1146        $s=str_replace(')','\\)',$s);
1147        $s=str_replace("\r",'\\r',$s);
1148        return $s;
1149}
1150
1151function _textstring($s)
1152{
1153        //Format a text string
1154        return '('.$this->_escape($s).')';
1155}
1156
1157function _UTF8toUTF16($s)
1158{
1159        //Convert UTF-8 to UTF-16BE with BOM
1160        $res="\xFE\xFF";
1161        $nb=strlen($s);
1162        $i=0;
1163        while($i<$nb)
1164        {
1165                $c1=ord($s[$i++]);
1166                if($c1>=224)
1167                {
1168                        //3-byte character
1169                        $c2=ord($s[$i++]);
1170                        $c3=ord($s[$i++]);
1171                        $res.=chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2));
1172                        $res.=chr((($c2 & 0x03)<<6) + ($c3 & 0x3F));
1173                }
1174                elseif($c1>=192)
1175                {
1176                        //2-byte character
1177                        $c2=ord($s[$i++]);
1178                        $res.=chr(($c1 & 0x1C)>>2);
1179                        $res.=chr((($c1 & 0x03)<<6) + ($c2 & 0x3F));
1180                }
1181                else
1182                {
1183                        //Single-byte character
1184                        $res.="\0".chr($c1);
1185                }
1186        }
1187        return $res;
1188}
1189
1190function _dounderline($x, $y, $txt)
1191{
1192        //Underline text
1193        $up=$this->CurrentFont['up'];
1194        $ut=$this->CurrentFont['ut'];
1195        $w=$this->GetStringWidth($txt)+$this->ws*substr_count($txt,' ');
1196        return sprintf('%.2F %.2F %.2F %.2F re f',$x*$this->k,($this->h-($y-$up/1000*$this->FontSize))*$this->k,$w*$this->k,-$ut/1000*$this->FontSizePt);
1197}
1198
1199function _parsejpg($file)
1200{
1201        //Extract info from a JPEG file
1202        $a=GetImageSize($file);
1203        if(!$a)
1204                $this->Error('Missing or incorrect image file: '.$file);
1205        if($a[2]!=2)
1206                $this->Error('Not a JPEG file: '.$file);
1207        if(!isset($a['channels']) || $a['channels']==3)
1208                $colspace='DeviceRGB';
1209        elseif($a['channels']==4)
1210                $colspace='DeviceCMYK';
1211        else
1212                $colspace='DeviceGray';
1213        $bpc=isset($a['bits']) ? $a['bits'] : 8;
1214        //Read whole file
1215        $f=fopen($file,'rb');
1216        $data='';
1217        while(!feof($f))
1218                $data.=fread($f,8192);
1219        fclose($f);
1220        return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data);
1221}
1222
1223function _parsepng($file)
1224{
1225        //Extract info from a PNG file
1226        $f=fopen($file,'rb');
1227        if(!$f)
1228                $this->Error('Can\'t open image file: '.$file);
1229        //Check signature
1230        if($this->_readstream($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
1231                $this->Error('Not a PNG file: '.$file);
1232        //Read header chunk
1233        $this->_readstream($f,4);
1234        if($this->_readstream($f,4)!='IHDR')
1235                $this->Error('Incorrect PNG file: '.$file);
1236        $w=$this->_readint($f);
1237        $h=$this->_readint($f);
1238        $bpc=ord($this->_readstream($f,1));
1239        if($bpc>8)
1240                $this->Error('16-bit depth not supported: '.$file);
1241        $ct=ord($this->_readstream($f,1));
1242        if($ct==0)
1243                $colspace='DeviceGray';
1244        elseif($ct==2)
1245                $colspace='DeviceRGB';
1246        elseif($ct==3)
1247                $colspace='Indexed';
1248        else
1249                $this->Error('Alpha channel not supported: '.$file);
1250        if(ord($this->_readstream($f,1))!=0)
1251                $this->Error('Unknown compression method: '.$file);
1252        if(ord($this->_readstream($f,1))!=0)
1253                $this->Error('Unknown filter method: '.$file);
1254        if(ord($this->_readstream($f,1))!=0)
1255                $this->Error('Interlacing not supported: '.$file);
1256        $this->_readstream($f,4);
1257        $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
1258        //Scan chunks looking for palette, transparency and image data
1259        $pal='';
1260        $trns='';
1261        $data='';
1262        do
1263        {
1264                $n=$this->_readint($f);
1265                $type=$this->_readstream($f,4);
1266                if($type=='PLTE')
1267                {
1268                        //Read palette
1269                        $pal=$this->_readstream($f,$n);
1270                        $this->_readstream($f,4);
1271                }
1272                elseif($type=='tRNS')
1273                {
1274                        //Read transparency info
1275                        $t=$this->_readstream($f,$n);
1276                        if($ct==0)
1277                                $trns=array(ord(substr($t,1,1)));
1278                        elseif($ct==2)
1279                                $trns=array(ord(substr($t,1,1)), ord(substr($t,3,1)), ord(substr($t,5,1)));
1280                        else
1281                        {
1282                                $pos=strpos($t,chr(0));
1283                                if($pos!==false)
1284                                        $trns=array($pos);
1285                        }
1286                        $this->_readstream($f,4);
1287                }
1288                elseif($type=='IDAT')
1289                {
1290                        //Read image data block
1291                        $data.=$this->_readstream($f,$n);
1292                        $this->_readstream($f,4);
1293                }
1294                elseif($type=='IEND')
1295                        break;
1296                else
1297                        $this->_readstream($f,$n+4);
1298        }
1299        while($n);
1300        if($colspace=='Indexed' && empty($pal))
1301                $this->Error('Missing palette in '.$file);
1302        fclose($f);
1303        return array('w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'FlateDecode', 'parms'=>$parms, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$data);
1304}
1305
1306function _readstream($f, $n)
1307{
1308        //Read n bytes from stream
1309        $res='';
1310        while($n>0 && !feof($f))
1311        {
1312                $s=fread($f,$n);
1313                if($s===false)
1314                        $this->Error('Error while reading stream');
1315                $n-=strlen($s);
1316                $res.=$s;
1317        }
1318        if($n>0)
1319                $this->Error('Unexpected end of stream');
1320        return $res;
1321}
1322
1323function _readint($f)
1324{
1325        //Read a 4-byte integer from stream
1326        $a=unpack('Ni',$this->_readstream($f,4));
1327        return $a['i'];
1328}
1329
1330function _parsegif($file)
1331{
1332        //Extract info from a GIF file (via PNG conversion)
1333        if(!function_exists('imagepng'))
1334                $this->Error('GD extension is required for GIF support');
1335        if(!function_exists('imagecreatefromgif'))
1336                $this->Error('GD has no GIF read support');
1337        $im=imagecreatefromgif($file);
1338        if(!$im)
1339                $this->Error('Missing or incorrect image file: '.$file);
1340        imageinterlace($im,0);
1341        $tmp=tempnam('.','gif');
1342        if(!$tmp)
1343                $this->Error('Unable to create a temporary file');
1344        if(!imagepng($im,$tmp))
1345                $this->Error('Error while saving to temporary file');
1346        imagedestroy($im);
1347        $info=$this->_parsepng($tmp);
1348        unlink($tmp);
1349        return $info;
1350}
1351
1352function _newobj()
1353{
1354        //Begin a new object
1355        $this->n++;
1356        $this->offsets[$this->n]=strlen($this->buffer);
1357        $this->_out($this->n.' 0 obj');
1358}
1359
1360function _putstream($s)
1361{
1362        $this->_out('stream');
1363        $this->_out($s);
1364        $this->_out('endstream');
1365}
1366
1367function _out($s)
1368{
1369        //Add a line to the document
1370        if($this->state==2)
1371                $this->pages[$this->page].=$s."\n";
1372        else
1373                $this->buffer.=$s."\n";
1374}
1375
1376function _putpages()
1377{
1378        $nb=$this->page;
1379        if(!empty($this->AliasNbPages))
1380        {
1381                //Replace number of pages
1382                for($n=1;$n<=$nb;$n++)
1383                        $this->pages[$n]=str_replace($this->AliasNbPages,$nb,$this->pages[$n]);
1384        }
1385        if($this->DefOrientation=='P')
1386        {
1387                $wPt=$this->DefPageFormat[0]*$this->k;
1388                $hPt=$this->DefPageFormat[1]*$this->k;
1389        }
1390        else
1391        {
1392                $wPt=$this->DefPageFormat[1]*$this->k;
1393                $hPt=$this->DefPageFormat[0]*$this->k;
1394        }
1395        $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
1396        for($n=1;$n<=$nb;$n++)
1397        {
1398                //Page
1399                $this->_newobj();
1400                $this->_out('<</Type /Page');
1401                $this->_out('/Parent 1 0 R');
1402                if(isset($this->PageSizes[$n]))
1403                        $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$this->PageSizes[$n][0],$this->PageSizes[$n][1]));
1404                $this->_out('/Resources 2 0 R');
1405                if(isset($this->PageLinks[$n]))
1406                {
1407                        //Links
1408                        $annots='/Annots [';
1409                        foreach($this->PageLinks[$n] as $pl)
1410                        {
1411                                $rect=sprintf('%.2F %.2F %.2F %.2F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
1412                                $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
1413                                if(is_string($pl[4]))
1414                                        $annots.='/A <</S /URI /URI '.$this->_textstring($pl[4]).'>>>>';
1415                                else
1416                                {
1417                                        $l=$this->links[$pl[4]];
1418                                        $h=isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt;
1419                                        $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>',1+2*$l[0],$h-$l[1]*$this->k);
1420                                }
1421                        }
1422                        $this->_out($annots.']');
1423                }
1424                $this->_out('/Contents '.($this->n+1).' 0 R>>');
1425                $this->_out('endobj');
1426                //Page content
1427                $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
1428                $this->_newobj();
1429                $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
1430                $this->_putstream($p);
1431                $this->_out('endobj');
1432        }
1433        //Pages root
1434        $this->offsets[1]=strlen($this->buffer);
1435        $this->_out('1 0 obj');
1436        $this->_out('<</Type /Pages');
1437        $kids='/Kids [';
1438        for($i=0;$i<$nb;$i++)
1439                $kids.=(3+2*$i).' 0 R ';
1440        $this->_out($kids.']');
1441        $this->_out('/Count '.$nb);
1442        $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$wPt,$hPt));
1443        $this->_out('>>');
1444        $this->_out('endobj');
1445}
1446
1447function _putfonts()
1448{
1449        $nf=$this->n;
1450        foreach($this->diffs as $diff)
1451        {
1452                //Encodings
1453                $this->_newobj();
1454                $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
1455                $this->_out('endobj');
1456        }
1457        foreach($this->FontFiles as $file=>$info)
1458        {
1459                //Font file embedding
1460                $this->_newobj();
1461                $this->FontFiles[$file]['n']=$this->n;
1462                $font='';
1463                $f=fopen($this->_getfontpath().$file,'rb',1);
1464                if(!$f)
1465                        $this->Error('Font file not found');
1466                while(!feof($f))
1467                        $font.=fread($f,8192);
1468                fclose($f);
1469                $compressed=(substr($file,-2)=='.z');
1470                if(!$compressed && isset($info['length2']))
1471                {
1472                        $header=(ord($font[0])==128);
1473                        if($header)
1474                        {
1475                                //Strip first binary header
1476                                $font=substr($font,6);
1477                        }
1478                        if($header && ord($font[$info['length1']])==128)
1479                        {
1480                                //Strip second binary header
1481                                $font=substr($font,0,$info['length1']).substr($font,$info['length1']+6);
1482                        }
1483                }
1484                $this->_out('<</Length '.strlen($font));
1485                if($compressed)
1486                        $this->_out('/Filter /FlateDecode');
1487                $this->_out('/Length1 '.$info['length1']);
1488                if(isset($info['length2']))
1489                        $this->_out('/Length2 '.$info['length2'].' /Length3 0');
1490                $this->_out('>>');
1491                $this->_putstream($font);
1492                $this->_out('endobj');
1493        }
1494        foreach($this->fonts as $k=>$font)
1495        {
1496                //Font objects
1497                $this->fonts[$k]['n']=$this->n+1;
1498                $type=$font['type'];
1499                $name=$font['name'];
1500                if($type=='core')
1501                {
1502                        //Standard font
1503                        $this->_newobj();
1504                        $this->_out('<</Type /Font');
1505                        $this->_out('/BaseFont /'.$name);
1506                        $this->_out('/Subtype /Type1');
1507                        if($name!='Symbol' && $name!='ZapfDingbats')
1508                                $this->_out('/Encoding /WinAnsiEncoding');
1509                        $this->_out('>>');
1510                        $this->_out('endobj');
1511                }
1512                elseif($type=='Type1' || $type=='TrueType')
1513                {
1514                        //Additional Type1 or TrueType font
1515                        $this->_newobj();
1516                        $this->_out('<</Type /Font');
1517                        $this->_out('/BaseFont /'.$name);
1518                        $this->_out('/Subtype /'.$type);
1519                        $this->_out('/FirstChar 32 /LastChar 255');
1520                        $this->_out('/Widths '.($this->n+1).' 0 R');
1521                        $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
1522                        if($font['enc'])
1523                        {
1524                                if(isset($font['diff']))
1525                                        $this->_out('/Encoding '.($nf+$font['diff']).' 0 R');
1526                                else
1527                                        $this->_out('/Encoding /WinAnsiEncoding');
1528                        }
1529                        $this->_out('>>');
1530                        $this->_out('endobj');
1531                        //Widths
1532                        $this->_newobj();
1533                        $cw=&$font['cw'];
1534                        $s='[';
1535                        for($i=32;$i<=255;$i++)
1536                                $s.=$cw[chr($i)].' ';
1537                        $this->_out($s.']');
1538                        $this->_out('endobj');
1539                        //Descriptor
1540                        $this->_newobj();
1541                        $s='<</Type /FontDescriptor /FontName /'.$name;
1542                        foreach($font['desc'] as $k=>$v)
1543                                $s.=' /'.$k.' '.$v;
1544                        $file=$font['file'];
1545                        if($file)
1546                                $s.=' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->FontFiles[$file]['n'].' 0 R';
1547                        $this->_out($s.'>>');
1548                        $this->_out('endobj');
1549                }
1550                else
1551                {
1552                        //Allow for additional types
1553                        $mtd='_put'.strtolower($type);
1554                        if(!method_exists($this,$mtd))
1555                                $this->Error('Unsupported font type: '.$type);
1556                        $this->$mtd($font);
1557                }
1558        }
1559}
1560
1561function _putimages()
1562{
1563        $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
1564        reset($this->images);
1565        while(list($file,$info)=each($this->images))
1566        {
1567                $this->_newobj();
1568                $this->images[$file]['n']=$this->n;
1569                $this->_out('<</Type /XObject');
1570                $this->_out('/Subtype /Image');
1571                $this->_out('/Width '.$info['w']);
1572                $this->_out('/Height '.$info['h']);
1573                if($info['cs']=='Indexed')
1574                        $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
1575                else
1576                {
1577                        $this->_out('/ColorSpace /'.$info['cs']);
1578                        if($info['cs']=='DeviceCMYK')
1579                                $this->_out('/Decode [1 0 1 0 1 0 1 0]');
1580                }
1581                $this->_out('/BitsPerComponent '.$info['bpc']);
1582                if(isset($info['f']))
1583                        $this->_out('/Filter /'.$info['f']);
1584                if(isset($info['parms']))
1585                        $this->_out($info['parms']);
1586                if(isset($info['trns']) && is_array($info['trns']))
1587                {
1588                        $trns='';
1589                        for($i=0;$i<count($info['trns']);$i++)
1590                                $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
1591                        $this->_out('/Mask ['.$trns.']');
1592                }
1593                $this->_out('/Length '.strlen($info['data']).'>>');
1594                $this->_putstream($info['data']);
1595                unset($this->images[$file]['data']);
1596                $this->_out('endobj');
1597                //Palette
1598                if($info['cs']=='Indexed')
1599                {
1600                        $this->_newobj();
1601                        $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
1602                        $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
1603                        $this->_putstream($pal);
1604                        $this->_out('endobj');
1605                }
1606        }
1607}
1608
1609function _putxobjectdict()
1610{
1611        foreach($this->images as $image)
1612                $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
1613}
1614
1615function _putresourcedict()
1616{
1617        $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
1618        $this->_out('/Font <<');
1619        foreach($this->fonts as $font)
1620                $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
1621        $this->_out('>>');
1622        $this->_out('/XObject <<');
1623        $this->_putxobjectdict();
1624        $this->_out('>>');
1625}
1626
1627function _putresources()
1628{
1629        $this->_putfonts();
1630        $this->_putimages();
1631        //Resource dictionary
1632        $this->offsets[2]=strlen($this->buffer);
1633        $this->_out('2 0 obj');
1634        $this->_out('<<');
1635        $this->_putresourcedict();
1636        $this->_out('>>');
1637        $this->_out('endobj');
1638}
1639
1640function _putinfo()
1641{
1642        $this->_out('/Producer '.$this->_textstring('FPDF '.FPDF_VERSION));
1643        if(!empty($this->title))
1644                $this->_out('/Title '.$this->_textstring($this->title));
1645        if(!empty($this->subject))
1646                $this->_out('/Subject '.$this->_textstring($this->subject));
1647        if(!empty($this->author))
1648                $this->_out('/Author '.$this->_textstring($this->author));
1649        if(!empty($this->keywords))
1650                $this->_out('/Keywords '.$this->_textstring($this->keywords));
1651        if(!empty($this->creator))
1652                $this->_out('/Creator '.$this->_textstring($this->creator));
1653        $this->_out('/CreationDate '.$this->_textstring('D:'.@date('YmdHis')));
1654}
1655
1656function _putcatalog()
1657{
1658        $this->_out('/Type /Catalog');
1659        $this->_out('/Pages 1 0 R');
1660        if($this->ZoomMode=='fullpage')
1661                $this->_out('/OpenAction [3 0 R /Fit]');
1662        elseif($this->ZoomMode=='fullwidth')
1663                $this->_out('/OpenAction [3 0 R /FitH null]');
1664        elseif($this->ZoomMode=='real')
1665                $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
1666        elseif(!is_string($this->ZoomMode))
1667                $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
1668        if($this->LayoutMode=='single')
1669                $this->_out('/PageLayout /SinglePage');
1670        elseif($this->LayoutMode=='continuous')
1671                $this->_out('/PageLayout /OneColumn');
1672        elseif($this->LayoutMode=='two')
1673                $this->_out('/PageLayout /TwoColumnLeft');
1674}
1675
1676function _putheader()
1677{
1678        $this->_out('%PDF-'.$this->PDFVersion);
1679}
1680
1681function _puttrailer()
1682{
1683        $this->_out('/Size '.($this->n+1));
1684        $this->_out('/Root '.$this->n.' 0 R');
1685        $this->_out('/Info '.($this->n-1).' 0 R');
1686}
1687
1688function _enddoc()
1689{
1690        $this->_putheader();
1691        $this->_putpages();
1692        $this->_putresources();
1693        //Info
1694        $this->_newobj();
1695        $this->_out('<<');
1696        $this->_putinfo();
1697        $this->_out('>>');
1698        $this->_out('endobj');
1699        //Catalog
1700        $this->_newobj();
1701        $this->_out('<<');
1702        $this->_putcatalog();
1703        $this->_out('>>');
1704        $this->_out('endobj');
1705        //Cross-ref
1706        $o=strlen($this->buffer);
1707        $this->_out('xref');
1708        $this->_out('0 '.($this->n+1));
1709        $this->_out('0000000000 65535 f ');
1710        for($i=1;$i<=$this->n;$i++)
1711                $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
1712        //Trailer
1713        $this->_out('trailer');
1714        $this->_out('<<');
1715        $this->_puttrailer();
1716        $this->_out('>>');
1717        $this->_out('startxref');
1718        $this->_out($o);
1719        $this->_out('%%EOF');
1720        $this->state=3;
1721}
1722//End of class
1723}
1724
1725//Handle special IE contype request
1726if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']=='contype')
1727{
1728        header('Content-Type: application/pdf');
1729        exit;
1730}
1731
1732?>
Note: See TracBrowser for help on using the browser.
phpBMS vulnerability assesment provided by Orvant Inc. Copyright © 2010 Kreotek, LLC. All Rights reserved.