source: trunk/client/inc/hpdf/_fpdf/fpdf.php@ 2

Last change on this file since 2 was 2, checked in by root, 15 years ago

importo il progetto

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