source: branches/version-2_5-dev/data/module/fpdf/fpdf.php @ 20116

Revision 20116, 42.3 KB checked in by nanasess, 13 years ago (diff)
  • svn properties を再設定
  • 再設定用のスクリプト追加
  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
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 repository browser.