Profile
MAJ is an Open Source, PHP-based content management system (CMS) that can be deployed as a blog, bulletin or message board, Internet forum, and wiki. It is extensible via PHP panels and is HTML5 and CSS3 ready.
Git
This blob has been accessed 60 times via Git panel.

  1. <?php
  2. /*******************************************************************************
  3. * Software: FPDF                                                               *
  4. * Version:  1.53                                                               *
  5. * Date:     2004-12-31                                                         *
  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.53');
  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. var $PDFVersion;         //PDF version number
  72.  
  73. /*******************************************************************************
  74. *                                                                              *
  75. *                               Public methods                                 *
  76. *                                                                              *
  77. *******************************************************************************/
  78. function FPDF($orientation='P',$unit='mm',$format='A4')
  79. {
  80.         //Some checks
  81.         $this->_dochecks();
  82.         //Initialization of properties
  83.         $this->page=0;
  84.         $this->n=2;
  85.         $this->buffer='';
  86.         $this->pages=array();
  87.         $this->OrientationChanges=array();
  88.         $this->state=0;
  89.         $this->fonts=array();
  90.         $this->FontFiles=array();
  91.         $this->diffs=array();
  92.         $this->images=array();
  93.         $this->links=array();
  94.         $this->InFooter=false;
  95.         $this->lasth=0;
  96.         $this->FontFamily='';
  97.         $this->FontStyle='';
  98.         $this->FontSizePt=12;
  99.         $this->underline=false;
  100.         $this->DrawColor='0 G';
  101.         $this->FillColor='0 g';
  102.         $this->TextColor='0 g';
  103.         $this->ColorFlag=false;
  104.         $this->ws=0;
  105.         //Standard fonts
  106.         $this->CoreFonts=array('courier'=>'Courier','courierB'=>'Courier-Bold','courierI'=>'Courier-Oblique','courierBI'=>'Courier-BoldOblique',
  107.                 'helvetica'=>'Helvetica','helveticaB'=>'Helvetica-Bold','helveticaI'=>'Helvetica-Oblique','helveticaBI'=>'Helvetica-BoldOblique',
  108.                 'times'=>'Times-Roman','timesB'=>'Times-Bold','timesI'=>'Times-Italic','timesBI'=>'Times-BoldItalic',
  109.                 'symbol'=>'Symbol','zapfdingbats'=>'ZapfDingbats');
  110.         //Scale factor
  111.         if($unit=='pt')
  112.                 $this->k=1;
  113.         elseif($unit=='mm')
  114.                 $this->k=72/25.4;
  115.         elseif($unit=='cm')
  116.                 $this->k=72/2.54;
  117.         elseif($unit=='in')
  118.                 $this->k=72;
  119.         else
  120.                 $this->Error('Incorrect unit: '.$unit);
  121.         //Page format
  122.         if(is_string($format))
  123.         {
  124.                 $format=strtolower($format);
  125.                 if($format=='a3')
  126.                         $format=array(841.89,1190.55);
  127.                 elseif($format=='a4')
  128.                         $format=array(595.28,841.89);
  129.                 elseif($format=='a5')
  130.                         $format=array(420.94,595.28);
  131.                 elseif($format=='letter')
  132.                         $format=array(612,792);
  133.                 elseif($format=='legal')
  134.                         $format=array(612,1008);
  135.                 else
  136.                         $this->Error('Unknown page format: '.$format);
  137.                 $this->fwPt=$format[0];
  138.                 $this->fhPt=$format[1];
  139.         }
  140.         else
  141.         {
  142.                 $this->fwPt=$format[0]*$this->k;
  143.                 $this->fhPt=$format[1]*$this->k;
  144.         }
  145.         $this->fw=$this->fwPt/$this->k;
  146.         $this->fh=$this->fhPt/$this->k;
  147.         //Page orientation
  148.         $orientation=strtolower($orientation);
  149.         if($orientation=='p' || $orientation=='portrait')
  150.         {
  151.                 $this->DefOrientation='P';
  152.                 $this->wPt=$this->fwPt;
  153.                 $this->hPt=$this->fhPt;
  154.         }
  155.         elseif($orientation=='l' || $orientation=='landscape')
  156.         {
  157.                 $this->DefOrientation='L';
  158.                 $this->wPt=$this->fhPt;
  159.                 $this->hPt=$this->fwPt;
  160.         }
  161.         else
  162.                 $this->Error('Incorrect orientation: '.$orientation);
  163.         $this->CurOrientation=$this->DefOrientation;
  164.         $this->w=$this->wPt/$this->k;
  165.         $this->h=$this->hPt/$this->k;
  166.         //Page margins (1 cm)
  167.         $margin=28.35/$this->k;
  168.         $this->SetMargins($margin,$margin);
  169.         //Interior cell margin (1 mm)
  170.         $this->cMargin=$margin/10;
  171.         //Line width (0.2 mm)
  172.         $this->LineWidth=.567/$this->k;
  173.         //Automatic page break
  174.         $this->SetAutoPageBreak(true,2*$margin);
  175.         //Full width display mode
  176.         $this->SetDisplayMode('fullwidth');
  177.         //Enable compression
  178.         $this->SetCompression(true);
  179.         //Set default PDF version number
  180.         $this->PDFVersion='1.3';
  181. }
  182.  
  183. function SetMargins($left,$top,$right=-1)
  184. {
  185.         //Set left, top and right margins
  186.         $this->lMargin=$left;
  187.         $this->tMargin=$top;
  188.         if($right==-1)
  189.                 $right=$left;
  190.         $this->rMargin=$right;
  191. }
  192.  
  193. function SetLeftMargin($margin)
  194. {
  195.         //Set left margin
  196.         $this->lMargin=$margin;
  197.         if($this->page>0 && $this->x<$margin)
  198.                 $this->x=$margin;
  199. }
  200.  
  201. function SetTopMargin($margin)
  202. {
  203.         //Set top margin
  204.         $this->tMargin=$margin;
  205. }
  206.  
  207. function SetRightMargin($margin)
  208. {
  209.         //Set right margin
  210.         $this->rMargin=$margin;
  211. }
  212.  
  213. function SetAutoPageBreak($auto,$margin=0)
  214. {
  215.         //Set auto page break mode and triggering margin
  216.         $this->AutoPageBreak=$auto;
  217.         $this->bMargin=$margin;
  218.         $this->PageBreakTrigger=$this->h-$margin;
  219. }
  220.  
  221. function SetDisplayMode($zoom,$layout='continuous')
  222. {
  223.         //Set display mode in viewer
  224.         if($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom))
  225.                 $this->ZoomMode=$zoom;
  226.         else
  227.                 $this->Error('Incorrect zoom display mode: '.$zoom);
  228.         if($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default')
  229.                 $this->LayoutMode=$layout;
  230.         else
  231.                 $this->Error('Incorrect layout display mode: '.$layout);
  232. }
  233.  
  234. function SetCompression($compress)
  235. {
  236.         //Set page compression
  237.         if(function_exists('gzcompress'))
  238.                 $this->compress=$compress;
  239.         else
  240.                 $this->compress=false;
  241. }
  242.  
  243. function SetTitle($title)
  244. {
  245.         //Title of document
  246.         $this->title=$title;
  247. }
  248.  
  249. function SetSubject($subject)
  250. {
  251.         //Subject of document
  252.         $this->subject=$subject;
  253. }
  254.  
  255. function SetAuthor($author)
  256. {
  257.         //Author of document
  258.         $this->author=$author;
  259. }
  260.  
  261. function SetKeywords($keywords)
  262. {
  263.         //Keywords of document
  264.         $this->keywords=$keywords;
  265. }
  266.  
  267. function SetCreator($creator)
  268. {
  269.         //Creator of document
  270.         $this->creator=$creator;
  271. }
  272.  
  273. function AliasNbPages($alias='{nb}')
  274. {
  275.         //Define an alias for total number of pages
  276.         $this->AliasNbPages=$alias;
  277. }
  278.  
  279. function Error($msg)
  280. {
  281.         //Fatal error
  282.         die('<B>FPDF error: </B>'.$msg);
  283. }
  284.  
  285. function Open()
  286. {
  287.         //Begin document
  288.         $this->state=1;
  289. }
  290.  
  291. function Close()
  292. {
  293.         //Terminate document
  294.         if($this->state==3)
  295.                 return;
  296.         if($this->page==0)
  297.                 $this->AddPage();
  298.         //Page footer
  299.         $this->InFooter=true;
  300.         $this->Footer();
  301.         $this->InFooter=false;
  302.         //Close page
  303.         $this->_endpage();
  304.         //Close document
  305.         $this->_enddoc();
  306. }
  307.  
  308. function AddPage($orientation='')
  309. {
  310.         //Start a new page
  311.         if($this->state==0)
  312.                 $this->Open();
  313.         $family=$this->FontFamily;
  314.         $style=$this->FontStyle.($this->underline ? 'U' : '');
  315.         $size=$this->FontSizePt;
  316.         $lw=$this->LineWidth;
  317.         $dc=$this->DrawColor;
  318.         $fc=$this->FillColor;
  319.         $tc=$this->TextColor;
  320.         $cf=$this->ColorFlag;
  321.         if($this->page>0)
  322.         {
  323.                 //Page footer
  324.                 $this->InFooter=true;
  325.                 $this->Footer();
  326.                 $this->InFooter=false;
  327.                 //Close page
  328.                 $this->_endpage();
  329.         }
  330.         //Start new page
  331.         $this->_beginpage($orientation);
  332.         //Set line cap style to square
  333.         $this->_out('2 J');
  334.         //Set line width
  335.         $this->LineWidth=$lw;
  336.         $this->_out(sprintf('%.2f w',$lw*$this->k));
  337.         //Set font
  338.         if($family)
  339.                 $this->SetFont($family,$style,$size);
  340.         //Set colors
  341.         $this->DrawColor=$dc;
  342.         if($dc!='0 G')
  343.                 $this->_out($dc);
  344.         $this->FillColor=$fc;
  345.         if($fc!='0 g')
  346.                 $this->_out($fc);
  347.         $this->TextColor=$tc;
  348.         $this->ColorFlag=$cf;
  349.         //Page header
  350.         $this->Header();
  351.         //Restore line width
  352.         if($this->LineWidth!=$lw)
  353.         {
  354.                 $this->LineWidth=$lw;
  355.                 $this->_out(sprintf('%.2f w',$lw*$this->k));
  356.         }
  357.         //Restore font
  358.         if($family)
  359.                 $this->SetFont($family,$style,$size);
  360.         //Restore colors
  361.         if($this->DrawColor!=$dc)
  362.         {
  363.                 $this->DrawColor=$dc;
  364.                 $this->_out($dc);
  365.         }
  366.         if($this->FillColor!=$fc)
  367.         {
  368.                 $this->FillColor=$fc;
  369.                 $this->_out($fc);
  370.         }
  371.         $this->TextColor=$tc;
  372.         $this->ColorFlag=$cf;
  373. }
  374.  
  375. function Header()
  376. {
  377.         //To be implemented in your own inherited class
  378. }
  379.  
  380. function Footer()
  381. {
  382.         //To be implemented in your own inherited class
  383. }
  384.  
  385. function PageNo()
  386. {
  387.         //Get current page number
  388.         return $this->page;
  389. }
  390.  
  391. function SetDrawColor($r,$g=-1,$b=-1)
  392. {
  393.         //Set color for all stroking operations
  394.         if(($r==0 && $g==0 && $b==0) || $g==-1)
  395.                 $this->DrawColor=sprintf('%.3f G',$r/255);
  396.         else
  397.                 $this->DrawColor=sprintf('%.3f %.3f %.3f RG',$r/255,$g/255,$b/255);
  398.         if($this->page>0)
  399.                 $this->_out($this->DrawColor);
  400. }
  401.  
  402. function SetFillColor($r,$g=-1,$b=-1)
  403. {
  404.         //Set color for all filling operations
  405.         if(($r==0 && $g==0 && $b==0) || $g==-1)
  406.                 $this->FillColor=sprintf('%.3f g',$r/255);
  407.         else
  408.                 $this->FillColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255);
  409.         $this->ColorFlag=($this->FillColor!=$this->TextColor);
  410.         if($this->page>0)
  411.                 $this->_out($this->FillColor);
  412. }
  413.  
  414. function SetTextColor($r,$g=-1,$b=-1)
  415. {
  416.         //Set color for text
  417.         if(($r==0 && $g==0 && $b==0) || $g==-1)
  418.                 $this->TextColor=sprintf('%.3f g',$r/255);
  419.         else
  420.                 $this->TextColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255);
  421.         $this->ColorFlag=($this->FillColor!=$this->TextColor);
  422. }
  423.  
  424. function GetStringWidth($s)
  425. {
  426.         //Get width of a string in the current font
  427.         $s=(string)$s;
  428.         $cw=&$this->CurrentFont['cw'];
  429.         $w=0;
  430.         $l=strlen($s);
  431.         for($i=0;$i<$l;$i++)
  432.                 $w+=$cw[$s{$i}];
  433.         return $w*$this->FontSize/1000;
  434. }
  435.  
  436. function SetLineWidth($width)
  437. {
  438.         //Set line width
  439.         $this->LineWidth=$width;
  440.         if($this->page>0)
  441.                 $this->_out(sprintf('%.2f w',$width*$this->k));
  442. }
  443.  
  444. function Line($x1,$y1,$x2,$y2)
  445. {
  446.         //Draw a line
  447.         $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));
  448. }
  449.  
  450. function Rect($x,$y,$w,$h,$style='')
  451. {
  452.         //Draw a rectangle
  453.         if($style=='F')
  454.                 $op='f';
  455.         elseif($style=='FD' || $style=='DF')
  456.                 $op='B';
  457.         else
  458.                 $op='S';
  459.         $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));
  460. }
  461.  
  462. function AddFont($family,$style='',$file='')
  463. {
  464.         //Add a TrueType or Type1 font
  465.         $family=strtolower($family);
  466.         if($file=='')
  467.                 $file=str_replace(' ','',$family).strtolower($style).'.php';
  468.         if($family=='arial')
  469.                 $family='helvetica';
  470.         $style=strtoupper($style);
  471.         if($style=='IB')
  472.                 $style='BI';
  473.         $fontkey=$family.$style;
  474.         if(isset($this->fonts[$fontkey]))
  475.                 $this->Error('Font already added: '.$family.' '.$style);
  476.         include($this->_getfontpath().$file);
  477.         if(!isset($name))
  478.                 $this->Error('Could not include font definition file');
  479.         $i=count($this->fonts)+1;
  480.         $this->fonts[$fontkey]=array('i'=>$i,'type'=>$type,'name'=>$name,'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw,'enc'=>$enc,'file'=>$file);
  481.         if($diff)
  482.         {
  483.                 //Search existing encodings
  484.                 $d=0;
  485.                 $nb=count($this->diffs);
  486.                 for($i=1;$i<=$nb;$i++)
  487.                 {
  488.                         if($this->diffs[$i]==$diff)
  489.                         {
  490.                                 $d=$i;
  491.                                 break;
  492.                         }
  493.                 }
  494.                 if($d==0)
  495.                 {
  496.                         $d=$nb+1;
  497.                         $this->diffs[$d]=$diff;
  498.                 }
  499.                 $this->fonts[$fontkey]['diff']=$d;
  500.         }
  501.         if($file)
  502.         {
  503.                 if($type=='TrueType')
  504.                         $this->FontFiles[$file]=array('length1'=>$originalsize);
  505.                 else
  506.                         $this->FontFiles[$file]=array('length1'=>$size1,'length2'=>$size2);
  507.         }
  508. }
  509.  
  510. function SetFont($family,$style='',$size=0)
  511. {
  512.         //Select a font; size given in points
  513.         global $fpdf_charwidths;
  514.  
  515.         $family=strtolower($family);
  516.         if($family=='')
  517.                 $family=$this->FontFamily;
  518.         if($family=='arial')
  519.                 $family='helvetica';
  520.         elseif($family=='symbol' || $family=='zapfdingbats')
  521.                 $style='';
  522.         $style=strtoupper($style);
  523.         if(strpos($style,'U')!==false)
  524.         {
  525.                 $this->underline=true;
  526.                 $style=str_replace('U','',$style);
  527.         }
  528.         else
  529.                 $this->underline=false;
  530.         if($style=='IB')
  531.                 $style='BI';
  532.         if($size==0)
  533.                 $size=$this->FontSizePt;
  534.         //Test if font is already selected
  535.         if($this->FontFamily==$family && $this->FontStyle==$style && $this->FontSizePt==$size)
  536.                 return;
  537.         //Test if used for the first time
  538.         $fontkey=$family.$style;
  539.         if(!isset($this->fonts[$fontkey]))
  540.         {
  541.                 //Check if one of the standard fonts
  542.                 if(isset($this->CoreFonts[$fontkey]))
  543.                 {
  544.                         if(!isset($fpdf_charwidths[$fontkey]))
  545.                         {
  546.                                 //Load metric file
  547.                                 $file=$family;
  548.                                 if($family=='times' || $family=='helvetica')
  549.                                         $file.=strtolower($style);
  550.                                 include($this->_getfontpath().$file.'.php');
  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 && $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 && !$this->InFooter && $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 || $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(strpos($border,'L')!==false)
  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(strpos($border,'T')!==false)
  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(strpos($border,'R')!==false)
  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(strpos($border,'B')!==false)
  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 && $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(strpos($border,'L')!==false)
  725.                                 $b2.='L';
  726.                         if(strpos($border,'R')!==false)
  727.                                 $b2.='R';
  728.                         $b=(strpos($border,'T')!==false) ? $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 && $nl==2)
  757.                                 $b=$b2;
  758.                         continue;
  759.                 }
  760.                 if($c==' ')
  761.                 {
  762.                         $sep=$i;
  763.                         $ls=$l;
  764.                         $ns++;
  765.                 }
  766.                 $l+=$cw[$c];
  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 && $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 && strpos($border,'B')!==false)
  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' || $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 && $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.         //Finish document if necessary
  997.         if($this->state<3)
  998.                 $this->Close();
  999.         //Normalize parameters
  1000.         if(is_bool($dest))
  1001.                 $dest=$dest ? 'D' : 'F';
  1002.         $dest=strtoupper($dest);
  1003.         if($dest=='')
  1004.         {
  1005.                 if($name=='')
  1006.                 {
  1007.                         $name='doc.pdf';
  1008.                         $dest='I';
  1009.                 }
  1010.                 else
  1011.                         $dest='F';
  1012.         }
  1013.         switch($dest)
  1014.         {
  1015.                 case 'I':
  1016.                         //Send to standard output
  1017.                         if(ob_get_contents())
  1018.                                 $this->Error('Some data has already been output, can\'t send PDF file');
  1019.                         if(php_sapi_name()!='cli')
  1020.                         {
  1021.                                 //We send to a browser
  1022.                                 header('Content-Type: application/pdf');
  1023.                                 if(headers_sent())
  1024.                                         $this->Error('Some data has already been output to browser, can\'t send PDF file');
  1025.                                 header('Content-Length: '.strlen($this->buffer));
  1026.                                 header('Content-disposition: inline; filename="'.$name.'"');
  1027.                         }
  1028.                         echo $this->buffer;
  1029.                         break;
  1030.                 case 'D':
  1031.                         //Download file
  1032.                         if(ob_get_contents())
  1033.                                 $this->Error('Some data has already been output, can\'t send PDF file');
  1034.                         if(isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'],'MSIE'))
  1035.                                 header('Content-Type: application/force-download');
  1036.                         else
  1037.                                 header('Content-Type: application/octet-stream');
  1038.                         if(headers_sent())
  1039.                                 $this->Error('Some data has already been output to browser, can\'t send PDF file');
  1040.                         header('Content-Length: '.strlen($this->buffer));
  1041.                         header('Content-disposition: attachment; filename="'.$name.'"');
  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. *******************************************************************************/
  1066. function _dochecks()
  1067. {
  1068.         //Check for locale-related bug
  1069.         if(1.1==1)
  1070.                 $this->Error('Don\'t alter the locale before including class file');
  1071.         //Check for decimal separator
  1072.         if(sprintf('%.1f',1.0)!='1.0')
  1073.                 setlocale(LC_NUMERIC,'C');
  1074. }
  1075.  
  1076. function _getfontpath()
  1077. {
  1078.         if(!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font'))
  1079.                 define('FPDF_FONTPATH',dirname(__FILE__).'/font/');
  1080.         return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
  1081. }
  1082.  
  1083. function _putpages()
  1084. {
  1085.         $nb=$this->page;
  1086.         if(!empty($this->AliasNbPages))
  1087.         {
  1088.                 //Replace number of pages
  1089.                 for($n=1;$n<=$nb;$n++)
  1090.                         $this->pages[$n]=str_replace($this->AliasNbPages,$nb,$this->pages[$n]);
  1091.         }
  1092.         if($this->DefOrientation=='P')
  1093.         {
  1094.                 $wPt=$this->fwPt;
  1095.                 $hPt=$this->fhPt;
  1096.         }
  1097.         else
  1098.         {
  1099.                 $wPt=$this->fhPt;
  1100.                 $hPt=$this->fwPt;
  1101.         }
  1102.         $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
  1103.         for($n=1;$n<=$nb;$n++)
  1104.         {
  1105.                 //Page
  1106.                 $this->_newobj();
  1107.                 $this->_out('<</Type /Page');
  1108.                 $this->_out('/Parent 1 0 R');
  1109.                 if(isset($this->OrientationChanges[$n]))
  1110.                         $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$hPt,$wPt));
  1111.                 $this->_out('/Resources 2 0 R');
  1112.                 if(isset($this->PageLinks[$n]))
  1113.                 {
  1114.                         //Links
  1115.                         $annots='/Annots [';
  1116.                         foreach($this->PageLinks[$n] as $pl)
  1117.                         {
  1118.                                 $rect=sprintf('%.2f %.2f %.2f %.2f',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
  1119.                                 $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
  1120.                                 if(is_string($pl[4]))
  1121.                                         $annots.='/A <</S /URI /URI '.$this->_textstring($pl[4]).'>>>>';
  1122.                                 else
  1123.                                 {
  1124.                                         $l=$this->links[$pl[4]];
  1125.                                         $h=isset($this->OrientationChanges[$l[0]]) ? $wPt : $hPt;
  1126.                                         $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>',1+2*$l[0],$h-$l[1]*$this->k);
  1127.                                 }
  1128.                         }
  1129.                         $this->_out($annots.']');
  1130.                 }
  1131.                 $this->_out('/Contents '.($this->n+1).' 0 R>>');
  1132.                 $this->_out('endobj');
  1133.                 //Page content
  1134.                 $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
  1135.                 $this->_newobj();
  1136.                 $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
  1137.                 $this->_putstream($p);
  1138.                 $this->_out('endobj');
  1139.         }
  1140.         //Pages root
  1141.         $this->offsets[1]=strlen($this->buffer);
  1142.         $this->_out('1 0 obj');
  1143.         $this->_out('<</Type /Pages');
  1144.         $kids='/Kids [';
  1145.         for($i=0;$i<$nb;$i++)
  1146.                 $kids.=(3+2*$i).' 0 R ';
  1147.         $this->_out($kids.']');
  1148.         $this->_out('/Count '.$nb);
  1149.         $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$wPt,$hPt));
  1150.         $this->_out('>>');
  1151.         $this->_out('endobj');
  1152. }
  1153.  
  1154. function _putfonts()
  1155. {
  1156.         $nf=$this->n;
  1157.         foreach($this->diffs as $diff)
  1158.         {
  1159.                 //Encodings
  1160.                 $this->_newobj();
  1161.                 $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
  1162.                 $this->_out('endobj');
  1163.         }
  1164.         $mqr=get_magic_quotes_runtime();
  1165.         set_magic_quotes_runtime(0);
  1166.         foreach($this->FontFiles as $file=>$info)
  1167.         {
  1168.                 //Font file embedding
  1169.                 $this->_newobj();
  1170.                 $this->FontFiles[$file]['n']=$this->n;
  1171.                 $font='';
  1172.                 $f=fopen($this->_getfontpath().$file,'rb',1);
  1173.                 if(!$f)
  1174.                         $this->Error('Font file not found');
  1175.                 while(!feof($f))
  1176.                         $font.=fread($f,8192);
  1177.                 fclose($f);
  1178.                 $compressed=(substr($file,-2)=='.z');
  1179.                 if(!$compressed && isset($info['length2']))
  1180.                 {
  1181.                         $header=(ord($font{0})==128);
  1182.                         if($header)
  1183.                         {
  1184.                                 //Strip first binary header
  1185.                                 $font=substr($font,6);
  1186.                         }
  1187.                         if($header && ord($font{$info['length1']})==128)
  1188.                         {
  1189.                                 //Strip second binary header
  1190.                                 $font=substr($font,0,$info['length1']).substr($font,$info['length1']+6);
  1191.                         }
  1192.                 }
  1193.                 $this->_out('<</Length '.strlen($font));
  1194.                 if($compressed)
  1195.                         $this->_out('/Filter /FlateDecode');
  1196.                 $this->_out('/Length1 '.$info['length1']);
  1197.                 if(isset($info['length2']))
  1198.                         $this->_out('/Length2 '.$info['length2'].' /Length3 0');
  1199.                 $this->_out('>>');
  1200.                 $this->_putstream($font);
  1201.                 $this->_out('endobj');
  1202.         }
  1203.         set_magic_quotes_runtime($mqr);
  1204.         foreach($this->fonts as $k=>$font)
  1205.         {
  1206.                 //Font objects
  1207.                 $this->fonts[$k]['n']=$this->n+1;
  1208.                 $type=$font['type'];
  1209.                 $name=$font['name'];
  1210.                 if($type=='core')
  1211.                 {
  1212.                         //Standard font
  1213.                         $this->_newobj();
  1214.                         $this->_out('<</Type /Font');
  1215.                         $this->_out('/BaseFont /'.$name);
  1216.                         $this->_out('/Subtype /Type1');
  1217.                         if($name!='Symbol' && $name!='ZapfDingbats')
  1218.                                 $this->_out('/Encoding /WinAnsiEncoding');
  1219.                         $this->_out('>>');
  1220.                         $this->_out('endobj');
  1221.                 }
  1222.                 elseif($type=='Type1' || $type=='TrueType')
  1223.                 {
  1224.                         //Additional Type1 or TrueType font
  1225.                         $this->_newobj();
  1226.                         $this->_out('<</Type /Font');
  1227.                         $this->_out('/BaseFont /'.$name);
  1228.                         $this->_out('/Subtype /'.$type);
  1229.                         $this->_out('/FirstChar 32 /LastChar 255');
  1230.                         $this->_out('/Widths '.($this->n+1).' 0 R');
  1231.                         $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
  1232.                         if($font['enc'])
  1233.                         {
  1234.                                 if(isset($font['diff']))
  1235.                                         $this->_out('/Encoding '.($nf+$font['diff']).' 0 R');
  1236.                                 else
  1237.                                         $this->_out('/Encoding /WinAnsiEncoding');
  1238.                         }
  1239.                         $this->_out('>>');
  1240.                         $this->_out('endobj');
  1241.                         //Widths
  1242.                         $this->_newobj();
  1243.                         $cw=&$font['cw'];
  1244.                         $s='[';
  1245.                         for($i=32;$i<=255;$i++)
  1246.                                 $s.=$cw[chr($i)].' ';
  1247.                         $this->_out($s.']');
  1248.                         $this->_out('endobj');
  1249.                         //Descriptor
  1250.                         $this->_newobj();
  1251.                         $s='<</Type /FontDescriptor /FontName /'.$name;
  1252.                         foreach($font['desc'] as $k=>$v)
  1253.                                 $s.=' /'.$k.' '.$v;
  1254.                         $file=$font['file'];
  1255.                         if($file)
  1256.                                 $s.=' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->FontFiles[$file]['n'].' 0 R';
  1257.                         $this->_out($s.'>>');
  1258.                         $this->_out('endobj');
  1259.                 }
  1260.                 else
  1261.                 {
  1262.                         //Allow for additional types
  1263.                         $mtd='_put'.strtolower($type);
  1264.                         if(!method_exists($this,$mtd))
  1265.                                 $this->Error('Unsupported font type: '.$type);
  1266.                         $this->$mtd($font);
  1267.                 }
  1268.         }
  1269. }
  1270.  
  1271. function _putimages()
  1272. {
  1273.         $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
  1274.         reset($this->images);
  1275.         while(list($file,$info)=each($this->images))
  1276.         {
  1277.                 $this->_newobj();
  1278.                 $this->images[$file]['n']=$this->n;
  1279.                 $this->_out('<</Type /XObject');
  1280.                 $this->_out('/Subtype /Image');
  1281.                 $this->_out('/Width '.$info['w']);
  1282.                 $this->_out('/Height '.$info['h']);
  1283.                 if($info['cs']=='Indexed')
  1284.                         $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
  1285.                 else
  1286.                 {
  1287.                         $this->_out('/ColorSpace /'.$info['cs']);
  1288.                         if($info['cs']=='DeviceCMYK')
  1289.                                 $this->_out('/Decode [1 0 1 0 1 0 1 0]');
  1290.                 }
  1291.                 $this->_out('/BitsPerComponent '.$info['bpc']);
  1292.                 if(isset($info['f']))
  1293.                         $this->_out('/Filter /'.$info['f']);
  1294.                 if(isset($info['parms']))
  1295.                         $this->_out($info['parms']);
  1296.                 if(isset($info['trns']) && is_array($info['trns']))
  1297.                 {
  1298.                         $trns='';
  1299.                         for($i=0;$i<count($info['trns']);$i++)
  1300.                                 $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
  1301.                         $this->_out('/Mask ['.$trns.']');
  1302.                 }
  1303.                 $this->_out('/Length '.strlen($info['data']).'>>');
  1304.                 $this->_putstream($info['data']);
  1305.                 unset($this->images[$file]['data']);
  1306.                 $this->_out('endobj');
  1307.                 //Palette
  1308.                 if($info['cs']=='Indexed')
  1309.                 {
  1310.                         $this->_newobj();
  1311.                         $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
  1312.                         $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
  1313.                         $this->_putstream($pal);
  1314.                         $this->_out('endobj');
  1315.                 }
  1316.         }
  1317. }
  1318.  
  1319. function _putxobjectdict()
  1320. {
  1321.         foreach($this->images as $image)
  1322.                 $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
  1323. }
  1324.  
  1325. function _putresourcedict()
  1326. {
  1327.         $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
  1328.         $this->_out('/Font <<');
  1329.         foreach($this->fonts as $font)
  1330.                 $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
  1331.         $this->_out('>>');
  1332.         $this->_out('/XObject <<');
  1333.         $this->_putxobjectdict();
  1334.         $this->_out('>>');
  1335. }
  1336.  
  1337. function _putresources()
  1338. {
  1339.         $this->_putfonts();
  1340.         $this->_putimages();
  1341.         //Resource dictionary
  1342.         $this->offsets[2]=strlen($this->buffer);
  1343.         $this->_out('2 0 obj');
  1344.         $this->_out('<<');
  1345.         $this->_putresourcedict();
  1346.         $this->_out('>>');
  1347.         $this->_out('endobj');
  1348. }
  1349.  
  1350. function _putinfo()
  1351. {
  1352.         $this->_out('/Producer '.$this->_textstring('FPDF '.FPDF_VERSION));
  1353.         if(!empty($this->title))
  1354.                 $this->_out('/Title '.$this->_textstring($this->title));
  1355.         if(!empty($this->subject))
  1356.                 $this->_out('/Subject '.$this->_textstring($this->subject));
  1357.         if(!empty($this->author))
  1358.                 $this->_out('/Author '.$this->_textstring($this->author));
  1359.         if(!empty($this->keywords))
  1360.                 $this->_out('/Keywords '.$this->_textstring($this->keywords));
  1361.         if(!empty($this->creator))
  1362.                 $this->_out('/Creator '.$this->_textstring($this->creator));
  1363.         $this->_out('/CreationDate '.$this->_textstring('D:'.date('YmdHis')));
  1364. }
  1365.  
  1366. function _putcatalog()
  1367. {
  1368.         $this->_out('/Type /Catalog');
  1369.         $this->_out('/Pages 1 0 R');
  1370.         if($this->ZoomMode=='fullpage')
  1371.                 $this->_out('/OpenAction [3 0 R /Fit]');
  1372.         elseif($this->ZoomMode=='fullwidth')
  1373.                 $this->_out('/OpenAction [3 0 R /FitH null]');
  1374.         elseif($this->ZoomMode=='real')
  1375.                 $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
  1376.         elseif(!is_string($this->ZoomMode))
  1377.                 $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
  1378.         if($this->LayoutMode=='single')
  1379.                 $this->_out('/PageLayout /SinglePage');
  1380.         elseif($this->LayoutMode=='continuous')
  1381.                 $this->_out('/PageLayout /OneColumn');
  1382.         elseif($this->LayoutMode=='two')
  1383.                 $this->_out('/PageLayout /TwoColumnLeft');
  1384. }
  1385.  
  1386. function _putheader()
  1387. {
  1388.         $this->_out('%PDF-'.$this->PDFVersion);
  1389. }
  1390.  
  1391. function _puttrailer()
  1392. {
  1393.         $this->_out('/Size '.($this->n+1));
  1394.         $this->_out('/Root '.$this->n.' 0 R');
  1395.         $this->_out('/Info '.($this->n-1).' 0 R');
  1396. }
  1397.  
  1398. function _enddoc()
  1399. {
  1400.         $this->_putheader();
  1401.         $this->_putpages();
  1402.         $this->_putresources();
  1403.         //Info
  1404.         $this->_newobj();
  1405.         $this->_out('<<');
  1406.         $this->_putinfo();
  1407.         $this->_out('>>');
  1408.         $this->_out('endobj');
  1409.         //Catalog
  1410.         $this->_newobj();
  1411.         $this->_out('<<');
  1412.         $this->_putcatalog();
  1413.         $this->_out('>>');
  1414.         $this->_out('endobj');
  1415.         //Cross-ref
  1416.         $o=strlen($this->buffer);
  1417.         $this->_out('xref');
  1418.         $this->_out('0 '.($this->n+1));
  1419.         $this->_out('0000000000 65535 f ');
  1420.         for($i=1;$i<=$this->n;$i++)
  1421.                 $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
  1422.         //Trailer
  1423.         $this->_out('trailer');
  1424.         $this->_out('<<');
  1425.         $this->_puttrailer();
  1426.         $this->_out('>>');
  1427.         $this->_out('startxref');
  1428.         $this->_out($o);
  1429.         $this->_out('%%EOF');
  1430.         $this->state=3;
  1431. }
  1432.  
  1433. function _beginpage($orientation)
  1434. {
  1435.         $this->page++;
  1436.         $this->pages[$this->page]='';
  1437.         $this->state=2;
  1438.         $this->x=$this->lMargin;
  1439.         $this->y=$this->tMargin;
  1440.         $this->FontFamily='';
  1441.         //Page orientation
  1442.         if(!$orientation)
  1443.                 $orientation=$this->DefOrientation;
  1444.         else
  1445.         {
  1446.                 $orientation=strtoupper($orientation{0});
  1447.                 if($orientation!=$this->DefOrientation)
  1448.                         $this->OrientationChanges[$this->page]=true;
  1449.         }
  1450.         if($orientation!=$this->CurOrientation)
  1451.         {
  1452.                 //Change orientation
  1453.                 if($orientation=='P')
  1454.                 {
  1455.                         $this->wPt=$this->fwPt;
  1456.                         $this->hPt=$this->fhPt;
  1457.                         $this->w=$this->fw;
  1458.                         $this->h=$this->fh;
  1459.                 }
  1460.                 else
  1461.                 {
  1462.                         $this->wPt=$this->fhPt;
  1463.                         $this->hPt=$this->fwPt;
  1464.                         $this->w=$this->fh;
  1465.                         $this->h=$this->fw;
  1466.                 }
  1467.                 $this->PageBreakTrigger=$this->h-$this->bMargin;
  1468.                 $this->CurOrientation=$orientation;
  1469.         }
  1470. }
  1471.  
  1472. function _endpage()
  1473. {
  1474.         //End of page contents
  1475.         $this->state=1;
  1476. }
  1477.  
  1478. function _newobj()
  1479. {
  1480.         //Begin a new object
  1481.         $this->n++;
  1482.         $this->offsets[$this->n]=strlen($this->buffer);
  1483.         $this->_out($this->n.' 0 obj');
  1484. }
  1485.  
  1486. function _dounderline($x,$y,$txt)
  1487. {
  1488.         //Underline text
  1489.         $up=$this->CurrentFont['up'];
  1490.         $ut=$this->CurrentFont['ut'];
  1491.         $w=$this->GetStringWidth($txt)+$this->ws*substr_count($txt,' ');
  1492.         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);
  1493. }
  1494.  
  1495. function _parsejpg($file)
  1496. {
  1497.         //Extract info from a JPEG file
  1498.         $a=GetImageSize($file);
  1499.         if(!$a)
  1500.                 $this->Error('Missing or incorrect image file: '.$file);
  1501.         if($a[2]!=2)
  1502.                 $this->Error('Not a JPEG file: '.$file);
  1503.         if(!isset($a['channels']) || $a['channels']==3)
  1504.                 $colspace='DeviceRGB';
  1505.         elseif($a['channels']==4)
  1506.                 $colspace='DeviceCMYK';
  1507.         else
  1508.                 $colspace='DeviceGray';
  1509.         $bpc=isset($a['bits']) ? $a['bits'] : 8;
  1510.         //Read whole file
  1511.         $f=fopen($file,'rb');
  1512.         $data='';
  1513.         while(!feof($f))
  1514.                 $data.=fread($f,4096);
  1515.         fclose($f);
  1516.         return array('w'=>$a[0],'h'=>$a[1],'cs'=>$colspace,'bpc'=>$bpc,'f'=>'DCTDecode','data'=>$data);
  1517. }
  1518.  
  1519. function _parsepng($file)
  1520. {
  1521.         //Extract info from a PNG file
  1522.         $f=fopen($file,'rb');
  1523.         if(!$f)
  1524.                 $this->Error('Can\'t open image file: '.$file);
  1525.         //Check signature
  1526.         if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
  1527.                 $this->Error('Not a PNG file: '.$file);
  1528.         //Read header chunk
  1529.         fread($f,4);
  1530.         if(fread($f,4)!='IHDR')
  1531.                 $this->Error('Incorrect PNG file: '.$file);
  1532.         $w=$this->_freadint($f);
  1533.         $h=$this->_freadint($f);
  1534.         $bpc=ord(fread($f,1));
  1535.         if($bpc>8)
  1536.                 $this->Error('16-bit depth not supported: '.$file);
  1537.         $ct=ord(fread($f,1));
  1538.         if($ct==0)
  1539.                 $colspace='DeviceGray';
  1540.         elseif($ct==2)
  1541.                 $colspace='DeviceRGB';
  1542.         elseif($ct==3)
  1543.                 $colspace='Indexed';
  1544.         else
  1545.                 $this->Error('Alpha channel not supported: '.$file);
  1546.         if(ord(fread($f,1))!=0)
  1547.                 $this->Error('Unknown compression method: '.$file);
  1548.         if(ord(fread($f,1))!=0)
  1549.                 $this->Error('Unknown filter method: '.$file);
  1550.         if(ord(fread($f,1))!=0)
  1551.                 $this->Error('Interlacing not supported: '.$file);
  1552.         fread($f,4);
  1553.         $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
  1554.         //Scan chunks looking for palette, transparency and image data
  1555.         $pal='';
  1556.         $trns='';
  1557.         $data='';
  1558.         do
  1559.         {
  1560.                 $n=$this->_freadint($f);
  1561.                 $type=fread($f,4);
  1562.                 if($type=='PLTE')
  1563.                 {
  1564.                         //Read palette
  1565.                         $pal=fread($f,$n);
  1566.                         fread($f,4);
  1567.                 }
  1568.                 elseif($type=='tRNS')
  1569.                 {
  1570.                         //Read transparency info
  1571.                         $t=fread($f,$n);
  1572.                         if($ct==0)
  1573.                                 $trns=array(ord(substr($t,1,1)));
  1574.                         elseif($ct==2)
  1575.                                 $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
  1576.                         else
  1577.                         {
  1578.                                 $pos=strpos($t,chr(0));
  1579.                                 if($pos!==false)
  1580.                                         $trns=array($pos);
  1581.                         }
  1582.                         fread($f,4);
  1583.                 }
  1584.                 elseif($type=='IDAT')
  1585.                 {
  1586.                         //Read image data block
  1587.                         $data.=fread($f,$n);
  1588.                         fread($f,4);
  1589.                 }
  1590.                 elseif($type=='IEND')
  1591.                         break;
  1592.                 else
  1593.                         fread($f,$n+4);
  1594.         }
  1595.         while($n);
  1596.         if($colspace=='Indexed' && empty($pal))
  1597.                 $this->Error('Missing palette in '.$file);
  1598.         fclose($f);
  1599.         return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data);
  1600. }
  1601.  
  1602. function _freadint($f)
  1603. {
  1604.         //Read a 4-byte integer from file
  1605.         $a=unpack('Ni',fread($f,4));
  1606.         return $a['i'];
  1607. }
  1608.  
  1609. function _textstring($s)
  1610. {
  1611.         //Format a text string
  1612.         return '('.$this->_escape($s).')';
  1613. }
  1614.  
  1615. function _escape($s)
  1616. {
  1617.         //Add \ before \, ( and )
  1618.         return str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$s)));
  1619. }
  1620.  
  1621. function _putstream($s)
  1622. {
  1623.         $this->_out('stream');
  1624.         $this->_out($s);
  1625.         $this->_out('endstream');
  1626. }
  1627.  
  1628. function _out($s)
  1629. {
  1630.         //Add a line to the document
  1631.         if($this->state==2)
  1632.                 $this->pages[$this->page].=$s."\n";
  1633.         else
  1634.                 $this->buffer.=$s."\n";
  1635. }
  1636. //End of class
  1637. }
  1638.  
  1639. //Handle special IE contype request
  1640. if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']=='contype')
  1641. {
  1642.         header('Content-Type: application/pdf');
  1643.         exit;
  1644. }
  1645.  
  1646. }
  1647. ?>
  1648.  
Credits
Sunday, Sep 18, 2005, 12:00 AM (Revision 11 - Thursday, Jul 14, 2011, 7:30 PM)
Open Source enables software developers to stand on the shoulders of giants instead of reinventing the wheel, so to speak. Kudos and many thanks to the folks who made their work freely available for reuse in MAJ.

read more
Bugs and Exploits
Friday, Aug 26, 2005, 12:00 AM (Revision 23 - Wednesday, May 29, 2013, 5:25 AM)
Although MAJ started as a family project, care has been taken to make it as "safe" as possible. With more people now working on MAJ, bugs and exploitable code may sometimes slip in. We invite you to poke around and see if you can find any. Generally, there are two things you can do when you find a MAJ or PHP-related bug or exploit:

1. Take advantage of it. But hey, what's so exciting about messing up someone's blog? Ho-hum, right?
2. Report it here so that we can work on a fix and make MAJ better.

read more
Search
Download
MAJ 2.0
75 files
35645 downloads
MAJ 1.0
26 files
14253 downloads
MAJ 0.14
45 files
36877 downloads