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