source: spip-zone/_plugins_/_stable_/mon_diplome/html2pdf/_fpdf/fpdf.php @ 28615

Last change on this file since 28615 was 28615, checked in by paladin@…, 12 years ago

Formats d'impression complémentaires

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