fhiiqm/tool/fpdf.php
changeset 33 f1a8785434e4
equal deleted inserted replaced
32:c2d325791e24 33:f1a8785434e4
       
     1 <?php
       
     2 /*******************************************************************************
       
     3 * FPDF                                                                         *
       
     4 *                                                                              *
       
     5 * Version: 1.7                                                                 *
       
     6 * Date:    2011-06-18                                                          *
       
     7 * Author:  Olivier PLATHEY                                                     *
       
     8 *******************************************************************************/
       
     9 
       
    10 define('FPDF_VERSION','1.7');
       
    11 define('FPDF_FONTPATH',$_SERVER['DOCUMENT_ROOT'].'/fhiiqm/css/fpdf_font/');
       
    12 
       
    13 class FPDF
       
    14 {
       
    15 var $page;               // current page number
       
    16 var $n;                  // current object number
       
    17 var $offsets;            // array of object offsets
       
    18 var $buffer;             // buffer holding in-memory PDF
       
    19 var $pages;              // array containing pages
       
    20 var $state;              // current document state
       
    21 var $compress;           // compression flag
       
    22 var $k;                  // scale factor (number of points in user unit)
       
    23 var $DefOrientation;     // default orientation
       
    24 var $CurOrientation;     // current orientation
       
    25 var $StdPageSizes;       // standard page sizes
       
    26 var $DefPageSize;        // default page size
       
    27 var $CurPageSize;        // current page size
       
    28 var $PageSizes;          // used for pages with non default sizes or orientations
       
    29 var $wPt, $hPt;          // dimensions of current page in points
       
    30 var $w, $h;              // dimensions of current page in user unit
       
    31 var $lMargin;            // left margin
       
    32 var $tMargin;            // top margin
       
    33 var $rMargin;            // right margin
       
    34 var $bMargin;            // page break margin
       
    35 var $cMargin;            // cell margin
       
    36 var $x, $y;              // current position in user unit
       
    37 var $lasth;              // height of last printed cell
       
    38 var $LineWidth;          // line width in user unit
       
    39 var $fontpath;           // path containing fonts
       
    40 var $CoreFonts;          // array of core font names
       
    41 var $fonts;              // array of used fonts
       
    42 var $FontFiles;          // array of font files
       
    43 var $diffs;              // array of encoding differences
       
    44 var $FontFamily;         // current font family
       
    45 var $FontStyle;          // current font style
       
    46 var $underline;          // underlining flag
       
    47 var $CurrentFont;        // current font info
       
    48 var $FontSizePt;         // current font size in points
       
    49 var $FontSize;           // current font size in user unit
       
    50 var $DrawColor;          // commands for drawing color
       
    51 var $FillColor;          // commands for filling color
       
    52 var $TextColor;          // commands for text color
       
    53 var $ColorFlag;          // indicates whether fill and text colors are different
       
    54 var $ws;                 // word spacing
       
    55 var $images;             // array of used images
       
    56 var $PageLinks;          // array of links in pages
       
    57 var $links;              // array of internal links
       
    58 var $AutoPageBreak;      // automatic page breaking
       
    59 var $PageBreakTrigger;   // threshold used to trigger page breaks
       
    60 var $InHeader;           // flag set when processing header
       
    61 var $InFooter;           // flag set when processing footer
       
    62 var $ZoomMode;           // zoom display mode
       
    63 var $LayoutMode;         // layout display mode
       
    64 var $title;              // title
       
    65 var $subject;            // subject
       
    66 var $author;             // author
       
    67 var $keywords;           // keywords
       
    68 var $creator;            // creator
       
    69 var $AliasNbPages;       // alias for total number of pages
       
    70 var $PDFVersion;         // PDF version number
       
    71 
       
    72 /*******************************************************************************
       
    73 *                                                                              *
       
    74 *                               Public methods                                 *
       
    75 *                                                                              *
       
    76 *******************************************************************************/
       
    77 function FPDF($orientation='P', $unit='mm', $size='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->PageSizes = 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->InHeader = false;
       
    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 	// Font path
       
   106 	if(defined('FPDF_FONTPATH'))
       
   107 	{
       
   108 		$this->fontpath = FPDF_FONTPATH;
       
   109 		if(substr($this->fontpath,-1)!='/' && substr($this->fontpath,-1)!='\\')
       
   110 			$this->fontpath .= '/';
       
   111 	}
       
   112 	elseif(is_dir(dirname(__FILE__).'/font'))
       
   113 		$this->fontpath = dirname(__FILE__).'/font/';
       
   114 	else
       
   115 		$this->fontpath = '';
       
   116 	// Core fonts
       
   117 	$this->CoreFonts = array('courier', 'helvetica', 'times', 'symbol', 'zapfdingbats');
       
   118 	// Scale factor
       
   119 	if($unit=='pt')
       
   120 		$this->k = 1;
       
   121 	elseif($unit=='mm')
       
   122 		$this->k = 72/25.4;
       
   123 	elseif($unit=='cm')
       
   124 		$this->k = 72/2.54;
       
   125 	elseif($unit=='in')
       
   126 		$this->k = 72;
       
   127 	else
       
   128 		$this->Error('Incorrect unit: '.$unit);
       
   129 	// Page sizes
       
   130 	$this->StdPageSizes = array('a3'=>array(841.89,1190.55), 'a4'=>array(595.28,841.89), 'a5'=>array(420.94,595.28),
       
   131 		'letter'=>array(612,792), 'legal'=>array(612,1008));
       
   132 	$size = $this->_getpagesize($size);
       
   133 	$this->DefPageSize = $size;
       
   134 	$this->CurPageSize = $size;
       
   135 	// Page orientation
       
   136 	$orientation = strtolower($orientation);
       
   137 	if($orientation=='p' || $orientation=='portrait')
       
   138 	{
       
   139 		$this->DefOrientation = 'P';
       
   140 		$this->w = $size[0];
       
   141 		$this->h = $size[1];
       
   142 	}
       
   143 	elseif($orientation=='l' || $orientation=='landscape')
       
   144 	{
       
   145 		$this->DefOrientation = 'L';
       
   146 		$this->w = $size[1];
       
   147 		$this->h = $size[0];
       
   148 	}
       
   149 	else
       
   150 		$this->Error('Incorrect orientation: '.$orientation);
       
   151 	$this->CurOrientation = $this->DefOrientation;
       
   152 	$this->wPt = $this->w*$this->k;
       
   153 	$this->hPt = $this->h*$this->k;
       
   154 	// Page margins (1 cm)
       
   155 	$margin = 28.35/$this->k;
       
   156 	$this->SetMargins($margin,$margin);
       
   157 	// Interior cell margin (1 mm)
       
   158 	$this->cMargin = $margin/10;
       
   159 	// Line width (0.2 mm)
       
   160 	$this->LineWidth = .567/$this->k;
       
   161 	// Automatic page break
       
   162 	$this->SetAutoPageBreak(true,2*$margin);
       
   163 	// Default display mode
       
   164 	$this->SetDisplayMode('default');
       
   165 	// Enable compression
       
   166 	$this->SetCompression(true);
       
   167 	// Set default PDF version number
       
   168 	$this->PDFVersion = '1.3';
       
   169 }
       
   170 
       
   171 function SetMargins($left, $top, $right=null)
       
   172 {
       
   173 	// Set left, top and right margins
       
   174 	$this->lMargin = $left;
       
   175 	$this->tMargin = $top;
       
   176 	if($right===null)
       
   177 		$right = $left;
       
   178 	$this->rMargin = $right;
       
   179 }
       
   180 
       
   181 function SetLeftMargin($margin)
       
   182 {
       
   183 	// Set left margin
       
   184 	$this->lMargin = $margin;
       
   185 	if($this->page>0 && $this->x<$margin)
       
   186 		$this->x = $margin;
       
   187 }
       
   188 
       
   189 function SetTopMargin($margin)
       
   190 {
       
   191 	// Set top margin
       
   192 	$this->tMargin = $margin;
       
   193 }
       
   194 
       
   195 function SetRightMargin($margin)
       
   196 {
       
   197 	// Set right margin
       
   198 	$this->rMargin = $margin;
       
   199 }
       
   200 
       
   201 function SetAutoPageBreak($auto, $margin=0)
       
   202 {
       
   203 	// Set auto page break mode and triggering margin
       
   204 	$this->AutoPageBreak = $auto;
       
   205 	$this->bMargin = $margin;
       
   206 	$this->PageBreakTrigger = $this->h-$margin;
       
   207 }
       
   208 
       
   209 function SetDisplayMode($zoom, $layout='default')
       
   210 {
       
   211 	// Set display mode in viewer
       
   212 	if($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom))
       
   213 		$this->ZoomMode = $zoom;
       
   214 	else
       
   215 		$this->Error('Incorrect zoom display mode: '.$zoom);
       
   216 	if($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default')
       
   217 		$this->LayoutMode = $layout;
       
   218 	else
       
   219 		$this->Error('Incorrect layout display mode: '.$layout);
       
   220 }
       
   221 
       
   222 function SetCompression($compress)
       
   223 {
       
   224 	// Set page compression
       
   225 	if(function_exists('gzcompress'))
       
   226 		$this->compress = $compress;
       
   227 	else
       
   228 		$this->compress = false;
       
   229 }
       
   230 
       
   231 function SetTitle($title, $isUTF8=false)
       
   232 {
       
   233 	// Title of document
       
   234 	if($isUTF8)
       
   235 		$title = $this->_UTF8toUTF16($title);
       
   236 	$this->title = $title;
       
   237 }
       
   238 
       
   239 function SetSubject($subject, $isUTF8=false)
       
   240 {
       
   241 	// Subject of document
       
   242 	if($isUTF8)
       
   243 		$subject = $this->_UTF8toUTF16($subject);
       
   244 	$this->subject = $subject;
       
   245 }
       
   246 
       
   247 function SetAuthor($author, $isUTF8=false)
       
   248 {
       
   249 	// Author of document
       
   250 	if($isUTF8)
       
   251 		$author = $this->_UTF8toUTF16($author);
       
   252 	$this->author = $author;
       
   253 }
       
   254 
       
   255 function SetKeywords($keywords, $isUTF8=false)
       
   256 {
       
   257 	// Keywords of document
       
   258 	if($isUTF8)
       
   259 		$keywords = $this->_UTF8toUTF16($keywords);
       
   260 	$this->keywords = $keywords;
       
   261 }
       
   262 
       
   263 function SetCreator($creator, $isUTF8=false)
       
   264 {
       
   265 	// Creator of document
       
   266 	if($isUTF8)
       
   267 		$creator = $this->_UTF8toUTF16($creator);
       
   268 	$this->creator = $creator;
       
   269 }
       
   270 
       
   271 function AliasNbPages($alias='{nb}')
       
   272 {
       
   273 	// Define an alias for total number of pages
       
   274 	$this->AliasNbPages = $alias;
       
   275 }
       
   276 
       
   277 function Error($msg)
       
   278 {
       
   279 	// Fatal error
       
   280 	die('<b>FPDF error:</b> '.$msg);
       
   281 }
       
   282 
       
   283 function Open()
       
   284 {
       
   285 	// Begin document
       
   286 	$this->state = 1;
       
   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='', $size='')
       
   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 	$fontsize = $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,$size);
       
   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,$fontsize);
       
   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->InHeader = true;
       
   349 	$this->Header();
       
   350 	$this->InHeader = false;
       
   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,$fontsize);
       
   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=null, $b=null)
       
   392 {
       
   393 	// Set color for all stroking operations
       
   394 	if(($r==0 && $g==0 && $b==0) || $g===null)
       
   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=null, $b=null)
       
   403 {
       
   404 	// Set color for all filling operations
       
   405 	if(($r==0 && $g==0 && $b==0) || $g===null)
       
   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=null, $b=null)
       
   415 {
       
   416 	// Set color for text
       
   417 	if(($r==0 && $g==0 && $b==0) || $g===null)
       
   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, OpenType or Type1 font
       
   465 	$family = strtolower($family);
       
   466 	if($file=='')
       
   467 		$file = str_replace(' ','',$family).strtolower($style).'.php';
       
   468 	$style = strtoupper($style);
       
   469 	if($style=='IB')
       
   470 		$style = 'BI';
       
   471 	$fontkey = $family.$style;
       
   472 	if(isset($this->fonts[$fontkey]))
       
   473 		return;
       
   474 	$info = $this->_loadfont($file);
       
   475 	$info['i'] = count($this->fonts)+1;
       
   476 	if(!empty($info['diff']))
       
   477 	{
       
   478 		// Search existing encodings
       
   479 		$n = array_search($info['diff'],$this->diffs);
       
   480 		if(!$n)
       
   481 		{
       
   482 			$n = count($this->diffs)+1;
       
   483 			$this->diffs[$n] = $info['diff'];
       
   484 		}
       
   485 		$info['diffn'] = $n;
       
   486 	}
       
   487 	if(!empty($info['file']))
       
   488 	{
       
   489 		// Embedded font
       
   490 		if($info['type']=='TrueType')
       
   491 			$this->FontFiles[$info['file']] = array('length1'=>$info['originalsize']);
       
   492 		else
       
   493 			$this->FontFiles[$info['file']] = array('length1'=>$info['size1'], 'length2'=>$info['size2']);
       
   494 	}
       
   495 	$this->fonts[$fontkey] = $info;
       
   496 }
       
   497 
       
   498 function SetFont($family, $style='', $size=0)
       
   499 {
       
   500 	// Select a font; size given in points
       
   501 	if($family=='')
       
   502 		$family = $this->FontFamily;
       
   503 	else
       
   504 		$family = strtolower($family);
       
   505 	$style = strtoupper($style);
       
   506 	if(strpos($style,'U')!==false)
       
   507 	{
       
   508 		$this->underline = true;
       
   509 		$style = str_replace('U','',$style);
       
   510 	}
       
   511 	else
       
   512 		$this->underline = false;
       
   513 	if($style=='IB')
       
   514 		$style = 'BI';
       
   515 	if($size==0)
       
   516 		$size = $this->FontSizePt;
       
   517 	// Test if font is already selected
       
   518 	if($this->FontFamily==$family && $this->FontStyle==$style && $this->FontSizePt==$size)
       
   519 		return;
       
   520 	// Test if font is already loaded
       
   521 	$fontkey = $family.$style;
       
   522 	if(!isset($this->fonts[$fontkey]))
       
   523 	{
       
   524 		// Test if one of the core fonts
       
   525 		if($family=='arial')
       
   526 			$family = 'helvetica';
       
   527 		if(in_array($family,$this->CoreFonts))
       
   528 		{
       
   529 			if($family=='symbol' || $family=='zapfdingbats')
       
   530 				$style = '';
       
   531 			$fontkey = $family.$style;
       
   532 			if(!isset($this->fonts[$fontkey]))
       
   533 				$this->AddFont($family,$style);
       
   534 		}
       
   535 		else
       
   536 			$this->Error('Undefined font: '.$family.' '.$style);
       
   537 	}
       
   538 	// Select it
       
   539 	$this->FontFamily = $family;
       
   540 	$this->FontStyle = $style;
       
   541 	$this->FontSizePt = $size;
       
   542 	$this->FontSize = $size/$this->k;
       
   543 	$this->CurrentFont = &$this->fonts[$fontkey];
       
   544 	if($this->page>0)
       
   545 		$this->_out(sprintf('BT /F%d %.2F Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
       
   546 }
       
   547 
       
   548 function SetFontSize($size)
       
   549 {
       
   550 	// Set font size in points
       
   551 	if($this->FontSizePt==$size)
       
   552 		return;
       
   553 	$this->FontSizePt = $size;
       
   554 	$this->FontSize = $size/$this->k;
       
   555 	if($this->page>0)
       
   556 		$this->_out(sprintf('BT /F%d %.2F Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
       
   557 }
       
   558 
       
   559 function AddLink()
       
   560 {
       
   561 	// Create a new internal link
       
   562 	$n = count($this->links)+1;
       
   563 	$this->links[$n] = array(0, 0);
       
   564 	return $n;
       
   565 }
       
   566 
       
   567 function SetLink($link, $y=0, $page=-1)
       
   568 {
       
   569 	// Set destination of internal link
       
   570 	if($y==-1)
       
   571 		$y = $this->y;
       
   572 	if($page==-1)
       
   573 		$page = $this->page;
       
   574 	$this->links[$link] = array($page, $y);
       
   575 }
       
   576 
       
   577 function Link($x, $y, $w, $h, $link)
       
   578 {
       
   579 	// Put a link on the page
       
   580 	$this->PageLinks[$this->page][] = array($x*$this->k, $this->hPt-$y*$this->k, $w*$this->k, $h*$this->k, $link);
       
   581 }
       
   582 
       
   583 function Text($x, $y, $txt)
       
   584 {
       
   585 	// Output a string
       
   586 	$s = sprintf('BT %.2F %.2F Td (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt));
       
   587 	if($this->underline && $txt!='')
       
   588 		$s .= ' '.$this->_dounderline($x,$y,$txt);
       
   589 	if($this->ColorFlag)
       
   590 		$s = 'q '.$this->TextColor.' '.$s.' Q';
       
   591 	$this->_out($s);
       
   592 }
       
   593 
       
   594 function AcceptPageBreak()
       
   595 {
       
   596 	// Accept automatic page break or not
       
   597 	return $this->AutoPageBreak;
       
   598 }
       
   599 
       
   600 function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='')
       
   601 {
       
   602 	// Output a cell
       
   603 	$k = $this->k;
       
   604 	if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak())
       
   605 	{
       
   606 		// Automatic page break
       
   607 		$x = $this->x;
       
   608 		$ws = $this->ws;
       
   609 		if($ws>0)
       
   610 		{
       
   611 			$this->ws = 0;
       
   612 			$this->_out('0 Tw');
       
   613 		}
       
   614 		$this->AddPage($this->CurOrientation,$this->CurPageSize);
       
   615 		$this->x = $x;
       
   616 		if($ws>0)
       
   617 		{
       
   618 			$this->ws = $ws;
       
   619 			$this->_out(sprintf('%.3F Tw',$ws*$k));
       
   620 		}
       
   621 	}
       
   622 	if($w==0)
       
   623 		$w = $this->w-$this->rMargin-$this->x;
       
   624 	$s = '';
       
   625 	if($fill || $border==1)
       
   626 	{
       
   627 		if($fill)
       
   628 			$op = ($border==1) ? 'B' : 'f';
       
   629 		else
       
   630 			$op = 'S';
       
   631 		$s = sprintf('%.2F %.2F %.2F %.2F re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op);
       
   632 	}
       
   633 	if(is_string($border))
       
   634 	{
       
   635 		$x = $this->x;
       
   636 		$y = $this->y;
       
   637 		if(strpos($border,'L')!==false)
       
   638 			$s .= sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k);
       
   639 		if(strpos($border,'T')!==false)
       
   640 			$s .= sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k);
       
   641 		if(strpos($border,'R')!==false)
       
   642 			$s .= sprintf('%.2F %.2F m %.2F %.2F l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
       
   643 		if(strpos($border,'B')!==false)
       
   644 			$s .= sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
       
   645 	}
       
   646 	if($txt!=='')
       
   647 	{
       
   648 		if($align=='R')
       
   649 			$dx = $w-$this->cMargin-$this->GetStringWidth($txt);
       
   650 		elseif($align=='C')
       
   651 			$dx = ($w-$this->GetStringWidth($txt))/2;
       
   652 		else
       
   653 			$dx = $this->cMargin;
       
   654 		if($this->ColorFlag)
       
   655 			$s .= 'q '.$this->TextColor.' ';
       
   656 		$txt2 = str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt)));
       
   657 		$s .= sprintf('BT %.2F %.2F Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2);
       
   658 		if($this->underline)
       
   659 			$s .= ' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt);
       
   660 		if($this->ColorFlag)
       
   661 			$s .= ' Q';
       
   662 		if($link)
       
   663 			$this->Link($this->x+$dx,$this->y+.5*$h-.5*$this->FontSize,$this->GetStringWidth($txt),$this->FontSize,$link);
       
   664 	}
       
   665 	if($s)
       
   666 		$this->_out($s);
       
   667 	$this->lasth = $h;
       
   668 	if($ln>0)
       
   669 	{
       
   670 		// Go to next line
       
   671 		$this->y += $h;
       
   672 		if($ln==1)
       
   673 			$this->x = $this->lMargin;
       
   674 	}
       
   675 	else
       
   676 		$this->x += $w;
       
   677 }
       
   678 
       
   679 function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false)
       
   680 {
       
   681 	// Output text with automatic or explicit line breaks
       
   682 	$cw = &$this->CurrentFont['cw'];
       
   683 	if($w==0)
       
   684 		$w = $this->w-$this->rMargin-$this->x;
       
   685 	$wmax = ($w-2*$this->cMargin)*1000/$this->FontSize;
       
   686 	$s = str_replace("\r",'',$txt);
       
   687 	$nb = strlen($s);
       
   688 	if($nb>0 && $s[$nb-1]=="\n")
       
   689 		$nb--;
       
   690 	$b = 0;
       
   691 	if($border)
       
   692 	{
       
   693 		if($border==1)
       
   694 		{
       
   695 			$border = 'LTRB';
       
   696 			$b = 'LRT';
       
   697 			$b2 = 'LR';
       
   698 		}
       
   699 		else
       
   700 		{
       
   701 			$b2 = '';
       
   702 			if(strpos($border,'L')!==false)
       
   703 				$b2 .= 'L';
       
   704 			if(strpos($border,'R')!==false)
       
   705 				$b2 .= 'R';
       
   706 			$b = (strpos($border,'T')!==false) ? $b2.'T' : $b2;
       
   707 		}
       
   708 	}
       
   709 	$sep = -1;
       
   710 	$i = 0;
       
   711 	$j = 0;
       
   712 	$l = 0;
       
   713 	$ns = 0;
       
   714 	$nl = 1;
       
   715 	while($i<$nb)
       
   716 	{
       
   717 		// Get next character
       
   718 		$c = $s[$i];
       
   719 		if($c=="\n")
       
   720 		{
       
   721 			// Explicit line break
       
   722 			if($this->ws>0)
       
   723 			{
       
   724 				$this->ws = 0;
       
   725 				$this->_out('0 Tw');
       
   726 			}
       
   727 			$this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
       
   728 			$i++;
       
   729 			$sep = -1;
       
   730 			$j = $i;
       
   731 			$l = 0;
       
   732 			$ns = 0;
       
   733 			$nl++;
       
   734 			if($border && $nl==2)
       
   735 				$b = $b2;
       
   736 			continue;
       
   737 		}
       
   738 		if($c==' ')
       
   739 		{
       
   740 			$sep = $i;
       
   741 			$ls = $l;
       
   742 			$ns++;
       
   743 		}
       
   744 		$l += $cw[$c];
       
   745 		if($l>$wmax)
       
   746 		{
       
   747 			// Automatic line break
       
   748 			if($sep==-1)
       
   749 			{
       
   750 				if($i==$j)
       
   751 					$i++;
       
   752 				if($this->ws>0)
       
   753 				{
       
   754 					$this->ws = 0;
       
   755 					$this->_out('0 Tw');
       
   756 				}
       
   757 				$this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
       
   758 			}
       
   759 			else
       
   760 			{
       
   761 				if($align=='J')
       
   762 				{
       
   763 					$this->ws = ($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
       
   764 					$this->_out(sprintf('%.3F Tw',$this->ws*$this->k));
       
   765 				}
       
   766 				$this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
       
   767 				$i = $sep+1;
       
   768 			}
       
   769 			$sep = -1;
       
   770 			$j = $i;
       
   771 			$l = 0;
       
   772 			$ns = 0;
       
   773 			$nl++;
       
   774 			if($border && $nl==2)
       
   775 				$b = $b2;
       
   776 		}
       
   777 		else
       
   778 			$i++;
       
   779 	}
       
   780 	// Last chunk
       
   781 	if($this->ws>0)
       
   782 	{
       
   783 		$this->ws = 0;
       
   784 		$this->_out('0 Tw');
       
   785 	}
       
   786 	if($border && strpos($border,'B')!==false)
       
   787 		$b .= 'B';
       
   788 	$this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
       
   789 	$this->x = $this->lMargin;
       
   790 }
       
   791 
       
   792 function Write($h, $txt, $link='')
       
   793 {
       
   794 	// Output text in flowing mode
       
   795 	$cw = &$this->CurrentFont['cw'];
       
   796 	$w = $this->w-$this->rMargin-$this->x;
       
   797 	$wmax = ($w-2*$this->cMargin)*1000/$this->FontSize;
       
   798 	$s = str_replace("\r",'',$txt);
       
   799 	$nb = strlen($s);
       
   800 	$sep = -1;
       
   801 	$i = 0;
       
   802 	$j = 0;
       
   803 	$l = 0;
       
   804 	$nl = 1;
       
   805 	while($i<$nb)
       
   806 	{
       
   807 		// Get next character
       
   808 		$c = $s[$i];
       
   809 		if($c=="\n")
       
   810 		{
       
   811 			// Explicit line break
       
   812 			$this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link);
       
   813 			$i++;
       
   814 			$sep = -1;
       
   815 			$j = $i;
       
   816 			$l = 0;
       
   817 			if($nl==1)
       
   818 			{
       
   819 				$this->x = $this->lMargin;
       
   820 				$w = $this->w-$this->rMargin-$this->x;
       
   821 				$wmax = ($w-2*$this->cMargin)*1000/$this->FontSize;
       
   822 			}
       
   823 			$nl++;
       
   824 			continue;
       
   825 		}
       
   826 		if($c==' ')
       
   827 			$sep = $i;
       
   828 		$l += $cw[$c];
       
   829 		if($l>$wmax)
       
   830 		{
       
   831 			// Automatic line break
       
   832 			if($sep==-1)
       
   833 			{
       
   834 				if($this->x>$this->lMargin)
       
   835 				{
       
   836 					// Move to next line
       
   837 					$this->x = $this->lMargin;
       
   838 					$this->y += $h;
       
   839 					$w = $this->w-$this->rMargin-$this->x;
       
   840 					$wmax = ($w-2*$this->cMargin)*1000/$this->FontSize;
       
   841 					$i++;
       
   842 					$nl++;
       
   843 					continue;
       
   844 				}
       
   845 				if($i==$j)
       
   846 					$i++;
       
   847 				$this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link);
       
   848 			}
       
   849 			else
       
   850 			{
       
   851 				$this->Cell($w,$h,substr($s,$j,$sep-$j),0,2,'',0,$link);
       
   852 				$i = $sep+1;
       
   853 			}
       
   854 			$sep = -1;
       
   855 			$j = $i;
       
   856 			$l = 0;
       
   857 			if($nl==1)
       
   858 			{
       
   859 				$this->x = $this->lMargin;
       
   860 				$w = $this->w-$this->rMargin-$this->x;
       
   861 				$wmax = ($w-2*$this->cMargin)*1000/$this->FontSize;
       
   862 			}
       
   863 			$nl++;
       
   864 		}
       
   865 		else
       
   866 			$i++;
       
   867 	}
       
   868 	// Last chunk
       
   869 	if($i!=$j)
       
   870 		$this->Cell($l/1000*$this->FontSize,$h,substr($s,$j),0,0,'',0,$link);
       
   871 }
       
   872 
       
   873 function Ln($h=null)
       
   874 {
       
   875 	// Line feed; default value is last cell height
       
   876 	$this->x = $this->lMargin;
       
   877 	if($h===null)
       
   878 		$this->y += $this->lasth;
       
   879 	else
       
   880 		$this->y += $h;
       
   881 }
       
   882 
       
   883 function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='')
       
   884 {
       
   885 	// Put an image on the page
       
   886 	if(!isset($this->images[$file]))
       
   887 	{
       
   888 		// First use of this image, get info
       
   889 		if($type=='')
       
   890 		{
       
   891 			$pos = strrpos($file,'.');
       
   892 			if(!$pos)
       
   893 				$this->Error('Image file has no extension and no type was specified: '.$file);
       
   894 			$type = substr($file,$pos+1);
       
   895 		}
       
   896 		$type = strtolower($type);
       
   897 		if($type=='jpeg')
       
   898 			$type = 'jpg';
       
   899 		$mtd = '_parse'.$type;
       
   900 		if(!method_exists($this,$mtd))
       
   901 			$this->Error('Unsupported image type: '.$type);
       
   902 		$info = $this->$mtd($file);
       
   903 		$info['i'] = count($this->images)+1;
       
   904 		$this->images[$file] = $info;
       
   905 	}
       
   906 	else
       
   907 		$info = $this->images[$file];
       
   908 
       
   909 	// Automatic width and height calculation if needed
       
   910 	if($w==0 && $h==0)
       
   911 	{
       
   912 		// Put image at 96 dpi
       
   913 		$w = -96;
       
   914 		$h = -96;
       
   915 	}
       
   916 	if($w<0)
       
   917 		$w = -$info['w']*72/$w/$this->k;
       
   918 	if($h<0)
       
   919 		$h = -$info['h']*72/$h/$this->k;
       
   920 	if($w==0)
       
   921 		$w = $h*$info['w']/$info['h'];
       
   922 	if($h==0)
       
   923 		$h = $w*$info['h']/$info['w'];
       
   924 
       
   925 	// Flowing mode
       
   926 	if($y===null)
       
   927 	{
       
   928 		if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak())
       
   929 		{
       
   930 			// Automatic page break
       
   931 			$x2 = $this->x;
       
   932 			$this->AddPage($this->CurOrientation,$this->CurPageSize);
       
   933 			$this->x = $x2;
       
   934 		}
       
   935 		$y = $this->y;
       
   936 		$this->y += $h;
       
   937 	}
       
   938 
       
   939 	if($x===null)
       
   940 		$x = $this->x;
       
   941 	$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']));
       
   942 	if($link)
       
   943 		$this->Link($x,$y,$w,$h,$link);
       
   944 }
       
   945 
       
   946 function GetX()
       
   947 {
       
   948 	// Get x position
       
   949 	return $this->x;
       
   950 }
       
   951 
       
   952 function SetX($x)
       
   953 {
       
   954 	// Set x position
       
   955 	if($x>=0)
       
   956 		$this->x = $x;
       
   957 	else
       
   958 		$this->x = $this->w+$x;
       
   959 }
       
   960 
       
   961 function GetY()
       
   962 {
       
   963 	// Get y position
       
   964 	return $this->y;
       
   965 }
       
   966 
       
   967 function SetY($y)
       
   968 {
       
   969 	// Set y position and reset x
       
   970 	$this->x = $this->lMargin;
       
   971 	if($y>=0)
       
   972 		$this->y = $y;
       
   973 	else
       
   974 		$this->y = $this->h+$y;
       
   975 }
       
   976 
       
   977 function SetXY($x, $y)
       
   978 {
       
   979 	// Set x and y positions
       
   980 	$this->SetY($y);
       
   981 	$this->SetX($x);
       
   982 }
       
   983 
       
   984 function Output($name='', $dest='')
       
   985 {
       
   986 	// Output PDF to some destination
       
   987 	if($this->state<3)
       
   988 		$this->Close();
       
   989 	$dest = strtoupper($dest);
       
   990 	if($dest=='')
       
   991 	{
       
   992 		if($name=='')
       
   993 		{
       
   994 			$name = 'doc.pdf';
       
   995 			$dest = 'I';
       
   996 		}
       
   997 		else
       
   998 			$dest = 'F';
       
   999 	}
       
  1000 	switch($dest)
       
  1001 	{
       
  1002 		case 'I':
       
  1003 			// Send to standard output
       
  1004 			$this->_checkoutput();
       
  1005 			if(PHP_SAPI!='cli')
       
  1006 			{
       
  1007 				// We send to a browser
       
  1008 				header('Content-Type: application/pdf');
       
  1009 				header('Content-Disposition: inline; filename="'.$name.'"');
       
  1010 				header('Cache-Control: private, max-age=0, must-revalidate');
       
  1011 				header('Pragma: public');
       
  1012 			}
       
  1013 			echo $this->buffer;
       
  1014 			break;
       
  1015 		case 'D':
       
  1016 			// Download file
       
  1017 			$this->_checkoutput();
       
  1018 			header('Content-Type: application/x-download');
       
  1019 			header('Content-Disposition: attachment; filename="'.$name.'"');
       
  1020 			header('Cache-Control: private, max-age=0, must-revalidate');
       
  1021 			header('Pragma: public');
       
  1022 			echo $this->buffer;
       
  1023 			break;
       
  1024 		case 'F':
       
  1025 			// Save to local file
       
  1026 			$f = fopen($name,'wb');
       
  1027 			if(!$f)
       
  1028 				$this->Error('Unable to create output file: '.$name);
       
  1029 			fwrite($f,$this->buffer,strlen($this->buffer));
       
  1030 			fclose($f);
       
  1031 			break;
       
  1032 		case 'S':
       
  1033 			// Return as a string
       
  1034 			return $this->buffer;
       
  1035 		default:
       
  1036 			$this->Error('Incorrect output destination: '.$dest);
       
  1037 	}
       
  1038 	return '';
       
  1039 }
       
  1040 
       
  1041 /*******************************************************************************
       
  1042 *                                                                              *
       
  1043 *                              Protected methods                               *
       
  1044 *                                                                              *
       
  1045 *******************************************************************************/
       
  1046 function _dochecks()
       
  1047 {
       
  1048 	// Check availability of %F
       
  1049 	if(sprintf('%.1F',1.0)!='1.0')
       
  1050 		$this->Error('This version of PHP is not supported');
       
  1051 	// Check mbstring overloading
       
  1052 	if(ini_get('mbstring.func_overload') & 2)
       
  1053 		$this->Error('mbstring overloading must be disabled');
       
  1054 	// Ensure runtime magic quotes are disabled
       
  1055 	if(get_magic_quotes_runtime())
       
  1056 		@set_magic_quotes_runtime(0);
       
  1057 }
       
  1058 
       
  1059 function _checkoutput()
       
  1060 {
       
  1061 	if(PHP_SAPI!='cli')
       
  1062 	{
       
  1063 		if(headers_sent($file,$line))
       
  1064 			$this->Error("Some data has already been output, can't send PDF file (output started at $file:$line)");
       
  1065 	}
       
  1066 	if(ob_get_length())
       
  1067 	{
       
  1068 		// The output buffer is not empty
       
  1069 		if(preg_match('/^(\xEF\xBB\xBF)?\s*$/',ob_get_contents()))
       
  1070 		{
       
  1071 			// It contains only a UTF-8 BOM and/or whitespace, let's clean it
       
  1072 			ob_clean();
       
  1073 		}
       
  1074 		else
       
  1075 			$this->Error("Some data has already been output, can't send PDF file");
       
  1076 	}
       
  1077 }
       
  1078 
       
  1079 function _getpagesize($size)
       
  1080 {
       
  1081 	if(is_string($size))
       
  1082 	{
       
  1083 		$size = strtolower($size);
       
  1084 		if(!isset($this->StdPageSizes[$size]))
       
  1085 			$this->Error('Unknown page size: '.$size);
       
  1086 		$a = $this->StdPageSizes[$size];
       
  1087 		return array($a[0]/$this->k, $a[1]/$this->k);
       
  1088 	}
       
  1089 	else
       
  1090 	{
       
  1091 		if($size[0]>$size[1])
       
  1092 			return array($size[1], $size[0]);
       
  1093 		else
       
  1094 			return $size;
       
  1095 	}
       
  1096 }
       
  1097 
       
  1098 function _beginpage($orientation, $size)
       
  1099 {
       
  1100 	$this->page++;
       
  1101 	$this->pages[$this->page] = '';
       
  1102 	$this->state = 2;
       
  1103 	$this->x = $this->lMargin;
       
  1104 	$this->y = $this->tMargin;
       
  1105 	$this->FontFamily = '';
       
  1106 	// Check page size and orientation
       
  1107 	if($orientation=='')
       
  1108 		$orientation = $this->DefOrientation;
       
  1109 	else
       
  1110 		$orientation = strtoupper($orientation[0]);
       
  1111 	if($size=='')
       
  1112 		$size = $this->DefPageSize;
       
  1113 	else
       
  1114 		$size = $this->_getpagesize($size);
       
  1115 	if($orientation!=$this->CurOrientation || $size[0]!=$this->CurPageSize[0] || $size[1]!=$this->CurPageSize[1])
       
  1116 	{
       
  1117 		// New size or orientation
       
  1118 		if($orientation=='P')
       
  1119 		{
       
  1120 			$this->w = $size[0];
       
  1121 			$this->h = $size[1];
       
  1122 		}
       
  1123 		else
       
  1124 		{
       
  1125 			$this->w = $size[1];
       
  1126 			$this->h = $size[0];
       
  1127 		}
       
  1128 		$this->wPt = $this->w*$this->k;
       
  1129 		$this->hPt = $this->h*$this->k;
       
  1130 		$this->PageBreakTrigger = $this->h-$this->bMargin;
       
  1131 		$this->CurOrientation = $orientation;
       
  1132 		$this->CurPageSize = $size;
       
  1133 	}
       
  1134 	if($orientation!=$this->DefOrientation || $size[0]!=$this->DefPageSize[0] || $size[1]!=$this->DefPageSize[1])
       
  1135 		$this->PageSizes[$this->page] = array($this->wPt, $this->hPt);
       
  1136 }
       
  1137 
       
  1138 function _endpage()
       
  1139 {
       
  1140 	$this->state = 1;
       
  1141 }
       
  1142 
       
  1143 function _loadfont($font)
       
  1144 {
       
  1145 	// Load a font definition file from the font directory
       
  1146 	include($this->fontpath.$font);
       
  1147 	$a = get_defined_vars();
       
  1148 	if(!isset($a['name']))
       
  1149 		$this->Error('Could not include font definition file');
       
  1150 	return $a;
       
  1151 }
       
  1152 
       
  1153 function _escape($s)
       
  1154 {
       
  1155 	// Escape special characters in strings
       
  1156 	$s = str_replace('\\','\\\\',$s);
       
  1157 	$s = str_replace('(','\\(',$s);
       
  1158 	$s = str_replace(')','\\)',$s);
       
  1159 	$s = str_replace("\r",'\\r',$s);
       
  1160 	return $s;
       
  1161 }
       
  1162 
       
  1163 function _textstring($s)
       
  1164 {
       
  1165 	// Format a text string
       
  1166 	return '('.$this->_escape($s).')';
       
  1167 }
       
  1168 
       
  1169 function _UTF8toUTF16($s)
       
  1170 {
       
  1171 	// Convert UTF-8 to UTF-16BE with BOM
       
  1172 	$res = "\xFE\xFF";
       
  1173 	$nb = strlen($s);
       
  1174 	$i = 0;
       
  1175 	while($i<$nb)
       
  1176 	{
       
  1177 		$c1 = ord($s[$i++]);
       
  1178 		if($c1>=224)
       
  1179 		{
       
  1180 			// 3-byte character
       
  1181 			$c2 = ord($s[$i++]);
       
  1182 			$c3 = ord($s[$i++]);
       
  1183 			$res .= chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2));
       
  1184 			$res .= chr((($c2 & 0x03)<<6) + ($c3 & 0x3F));
       
  1185 		}
       
  1186 		elseif($c1>=192)
       
  1187 		{
       
  1188 			// 2-byte character
       
  1189 			$c2 = ord($s[$i++]);
       
  1190 			$res .= chr(($c1 & 0x1C)>>2);
       
  1191 			$res .= chr((($c1 & 0x03)<<6) + ($c2 & 0x3F));
       
  1192 		}
       
  1193 		else
       
  1194 		{
       
  1195 			// Single-byte character
       
  1196 			$res .= "\0".chr($c1);
       
  1197 		}
       
  1198 	}
       
  1199 	return $res;
       
  1200 }
       
  1201 
       
  1202 function _dounderline($x, $y, $txt)
       
  1203 {
       
  1204 	// Underline text
       
  1205 	$up = $this->CurrentFont['up'];
       
  1206 	$ut = $this->CurrentFont['ut'];
       
  1207 	$w = $this->GetStringWidth($txt)+$this->ws*substr_count($txt,' ');
       
  1208 	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);
       
  1209 }
       
  1210 
       
  1211 function _parsejpg($file)
       
  1212 {
       
  1213 	// Extract info from a JPEG file
       
  1214 	$a = getimagesize($file);
       
  1215 	if(!$a)
       
  1216 		$this->Error('Missing or incorrect image file: '.$file);
       
  1217 	if($a[2]!=2)
       
  1218 		$this->Error('Not a JPEG file: '.$file);
       
  1219 	if(!isset($a['channels']) || $a['channels']==3)
       
  1220 		$colspace = 'DeviceRGB';
       
  1221 	elseif($a['channels']==4)
       
  1222 		$colspace = 'DeviceCMYK';
       
  1223 	else
       
  1224 		$colspace = 'DeviceGray';
       
  1225 	$bpc = isset($a['bits']) ? $a['bits'] : 8;
       
  1226 	$data = file_get_contents($file);
       
  1227 	return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data);
       
  1228 }
       
  1229 
       
  1230 function _parsepng($file)
       
  1231 {
       
  1232 	// Extract info from a PNG file
       
  1233 	$f = fopen($file,'rb');
       
  1234 	if(!$f)
       
  1235 		$this->Error('Can\'t open image file: '.$file);
       
  1236 	$info = $this->_parsepngstream($f,$file);
       
  1237 	fclose($f);
       
  1238 	return $info;
       
  1239 }
       
  1240 
       
  1241 function _parsepngstream($f, $file)
       
  1242 {
       
  1243 	// Check signature
       
  1244 	if($this->_readstream($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
       
  1245 		$this->Error('Not a PNG file: '.$file);
       
  1246 
       
  1247 	// Read header chunk
       
  1248 	$this->_readstream($f,4);
       
  1249 	if($this->_readstream($f,4)!='IHDR')
       
  1250 		$this->Error('Incorrect PNG file: '.$file);
       
  1251 	$w = $this->_readint($f);
       
  1252 	$h = $this->_readint($f);
       
  1253 	$bpc = ord($this->_readstream($f,1));
       
  1254 	if($bpc>8)
       
  1255 		$this->Error('16-bit depth not supported: '.$file);
       
  1256 	$ct = ord($this->_readstream($f,1));
       
  1257 	if($ct==0 || $ct==4)
       
  1258 		$colspace = 'DeviceGray';
       
  1259 	elseif($ct==2 || $ct==6)
       
  1260 		$colspace = 'DeviceRGB';
       
  1261 	elseif($ct==3)
       
  1262 		$colspace = 'Indexed';
       
  1263 	else
       
  1264 		$this->Error('Unknown color type: '.$file);
       
  1265 	if(ord($this->_readstream($f,1))!=0)
       
  1266 		$this->Error('Unknown compression method: '.$file);
       
  1267 	if(ord($this->_readstream($f,1))!=0)
       
  1268 		$this->Error('Unknown filter method: '.$file);
       
  1269 	if(ord($this->_readstream($f,1))!=0)
       
  1270 		$this->Error('Interlacing not supported: '.$file);
       
  1271 	$this->_readstream($f,4);
       
  1272 	$dp = '/Predictor 15 /Colors '.($colspace=='DeviceRGB' ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w;
       
  1273 
       
  1274 	// Scan chunks looking for palette, transparency and image data
       
  1275 	$pal = '';
       
  1276 	$trns = '';
       
  1277 	$data = '';
       
  1278 	do
       
  1279 	{
       
  1280 		$n = $this->_readint($f);
       
  1281 		$type = $this->_readstream($f,4);
       
  1282 		if($type=='PLTE')
       
  1283 		{
       
  1284 			// Read palette
       
  1285 			$pal = $this->_readstream($f,$n);
       
  1286 			$this->_readstream($f,4);
       
  1287 		}
       
  1288 		elseif($type=='tRNS')
       
  1289 		{
       
  1290 			// Read transparency info
       
  1291 			$t = $this->_readstream($f,$n);
       
  1292 			if($ct==0)
       
  1293 				$trns = array(ord(substr($t,1,1)));
       
  1294 			elseif($ct==2)
       
  1295 				$trns = array(ord(substr($t,1,1)), ord(substr($t,3,1)), ord(substr($t,5,1)));
       
  1296 			else
       
  1297 			{
       
  1298 				$pos = strpos($t,chr(0));
       
  1299 				if($pos!==false)
       
  1300 					$trns = array($pos);
       
  1301 			}
       
  1302 			$this->_readstream($f,4);
       
  1303 		}
       
  1304 		elseif($type=='IDAT')
       
  1305 		{
       
  1306 			// Read image data block
       
  1307 			$data .= $this->_readstream($f,$n);
       
  1308 			$this->_readstream($f,4);
       
  1309 		}
       
  1310 		elseif($type=='IEND')
       
  1311 			break;
       
  1312 		else
       
  1313 			$this->_readstream($f,$n+4);
       
  1314 	}
       
  1315 	while($n);
       
  1316 
       
  1317 	if($colspace=='Indexed' && empty($pal))
       
  1318 		$this->Error('Missing palette in '.$file);
       
  1319 	$info = array('w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'FlateDecode', 'dp'=>$dp, 'pal'=>$pal, 'trns'=>$trns);
       
  1320 	if($ct>=4)
       
  1321 	{
       
  1322 		// Extract alpha channel
       
  1323 		if(!function_exists('gzuncompress'))
       
  1324 			$this->Error('Zlib not available, can\'t handle alpha channel: '.$file);
       
  1325 		$data = gzuncompress($data);
       
  1326 		$color = '';
       
  1327 		$alpha = '';
       
  1328 		if($ct==4)
       
  1329 		{
       
  1330 			// Gray image
       
  1331 			$len = 2*$w;
       
  1332 			for($i=0;$i<$h;$i++)
       
  1333 			{
       
  1334 				$pos = (1+$len)*$i;
       
  1335 				$color .= $data[$pos];
       
  1336 				$alpha .= $data[$pos];
       
  1337 				$line = substr($data,$pos+1,$len);
       
  1338 				$color .= preg_replace('/(.)./s','$1',$line);
       
  1339 				$alpha .= preg_replace('/.(.)/s','$1',$line);
       
  1340 			}
       
  1341 		}
       
  1342 		else
       
  1343 		{
       
  1344 			// RGB image
       
  1345 			$len = 4*$w;
       
  1346 			for($i=0;$i<$h;$i++)
       
  1347 			{
       
  1348 				$pos = (1+$len)*$i;
       
  1349 				$color .= $data[$pos];
       
  1350 				$alpha .= $data[$pos];
       
  1351 				$line = substr($data,$pos+1,$len);
       
  1352 				$color .= preg_replace('/(.{3})./s','$1',$line);
       
  1353 				$alpha .= preg_replace('/.{3}(.)/s','$1',$line);
       
  1354 			}
       
  1355 		}
       
  1356 		unset($data);
       
  1357 		$data = gzcompress($color);
       
  1358 		$info['smask'] = gzcompress($alpha);
       
  1359 		if($this->PDFVersion<'1.4')
       
  1360 			$this->PDFVersion = '1.4';
       
  1361 	}
       
  1362 	$info['data'] = $data;
       
  1363 	return $info;
       
  1364 }
       
  1365 
       
  1366 function _readstream($f, $n)
       
  1367 {
       
  1368 	// Read n bytes from stream
       
  1369 	$res = '';
       
  1370 	while($n>0 && !feof($f))
       
  1371 	{
       
  1372 		$s = fread($f,$n);
       
  1373 		if($s===false)
       
  1374 			$this->Error('Error while reading stream');
       
  1375 		$n -= strlen($s);
       
  1376 		$res .= $s;
       
  1377 	}
       
  1378 	if($n>0)
       
  1379 		$this->Error('Unexpected end of stream');
       
  1380 	return $res;
       
  1381 }
       
  1382 
       
  1383 function _readint($f)
       
  1384 {
       
  1385 	// Read a 4-byte integer from stream
       
  1386 	$a = unpack('Ni',$this->_readstream($f,4));
       
  1387 	return $a['i'];
       
  1388 }
       
  1389 
       
  1390 function _parsegif($file)
       
  1391 {
       
  1392 	// Extract info from a GIF file (via PNG conversion)
       
  1393 	if(!function_exists('imagepng'))
       
  1394 		$this->Error('GD extension is required for GIF support');
       
  1395 	if(!function_exists('imagecreatefromgif'))
       
  1396 		$this->Error('GD has no GIF read support');
       
  1397 	$im = imagecreatefromgif($file);
       
  1398 	if(!$im)
       
  1399 		$this->Error('Missing or incorrect image file: '.$file);
       
  1400 	imageinterlace($im,0);
       
  1401 	$f = @fopen('php://temp','rb+');
       
  1402 	if($f)
       
  1403 	{
       
  1404 		// Perform conversion in memory
       
  1405 		ob_start();
       
  1406 		imagepng($im);
       
  1407 		$data = ob_get_clean();
       
  1408 		imagedestroy($im);
       
  1409 		fwrite($f,$data);
       
  1410 		rewind($f);
       
  1411 		$info = $this->_parsepngstream($f,$file);
       
  1412 		fclose($f);
       
  1413 	}
       
  1414 	else
       
  1415 	{
       
  1416 		// Use temporary file
       
  1417 		$tmp = tempnam('.','gif');
       
  1418 		if(!$tmp)
       
  1419 			$this->Error('Unable to create a temporary file');
       
  1420 		if(!imagepng($im,$tmp))
       
  1421 			$this->Error('Error while saving to temporary file');
       
  1422 		imagedestroy($im);
       
  1423 		$info = $this->_parsepng($tmp);
       
  1424 		unlink($tmp);
       
  1425 	}
       
  1426 	return $info;
       
  1427 }
       
  1428 
       
  1429 function _newobj()
       
  1430 {
       
  1431 	// Begin a new object
       
  1432 	$this->n++;
       
  1433 	$this->offsets[$this->n] = strlen($this->buffer);
       
  1434 	$this->_out($this->n.' 0 obj');
       
  1435 }
       
  1436 
       
  1437 function _putstream($s)
       
  1438 {
       
  1439 	$this->_out('stream');
       
  1440 	$this->_out($s);
       
  1441 	$this->_out('endstream');
       
  1442 }
       
  1443 
       
  1444 function _out($s)
       
  1445 {
       
  1446 	// Add a line to the document
       
  1447 	if($this->state==2)
       
  1448 		$this->pages[$this->page] .= $s."\n";
       
  1449 	else
       
  1450 		$this->buffer .= $s."\n";
       
  1451 }
       
  1452 
       
  1453 function _putpages()
       
  1454 {
       
  1455 	$nb = $this->page;
       
  1456 	if(!empty($this->AliasNbPages))
       
  1457 	{
       
  1458 		// Replace number of pages
       
  1459 		for($n=1;$n<=$nb;$n++)
       
  1460 			$this->pages[$n] = str_replace($this->AliasNbPages,$nb,$this->pages[$n]);
       
  1461 	}
       
  1462 	if($this->DefOrientation=='P')
       
  1463 	{
       
  1464 		$wPt = $this->DefPageSize[0]*$this->k;
       
  1465 		$hPt = $this->DefPageSize[1]*$this->k;
       
  1466 	}
       
  1467 	else
       
  1468 	{
       
  1469 		$wPt = $this->DefPageSize[1]*$this->k;
       
  1470 		$hPt = $this->DefPageSize[0]*$this->k;
       
  1471 	}
       
  1472 	$filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
       
  1473 	for($n=1;$n<=$nb;$n++)
       
  1474 	{
       
  1475 		// Page
       
  1476 		$this->_newobj();
       
  1477 		$this->_out('<</Type /Page');
       
  1478 		$this->_out('/Parent 1 0 R');
       
  1479 		if(isset($this->PageSizes[$n]))
       
  1480 			$this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$this->PageSizes[$n][0],$this->PageSizes[$n][1]));
       
  1481 		$this->_out('/Resources 2 0 R');
       
  1482 		if(isset($this->PageLinks[$n]))
       
  1483 		{
       
  1484 			// Links
       
  1485 			$annots = '/Annots [';
       
  1486 			foreach($this->PageLinks[$n] as $pl)
       
  1487 			{
       
  1488 				$rect = sprintf('%.2F %.2F %.2F %.2F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
       
  1489 				$annots .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
       
  1490 				if(is_string($pl[4]))
       
  1491 					$annots .= '/A <</S /URI /URI '.$this->_textstring($pl[4]).'>>>>';
       
  1492 				else
       
  1493 				{
       
  1494 					$l = $this->links[$pl[4]];
       
  1495 					$h = isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt;
       
  1496 					$annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>',1+2*$l[0],$h-$l[1]*$this->k);
       
  1497 				}
       
  1498 			}
       
  1499 			$this->_out($annots.']');
       
  1500 		}
       
  1501 		if($this->PDFVersion>'1.3')
       
  1502 			$this->_out('/Group <</Type /Group /S /Transparency /CS /DeviceRGB>>');
       
  1503 		$this->_out('/Contents '.($this->n+1).' 0 R>>');
       
  1504 		$this->_out('endobj');
       
  1505 		// Page content
       
  1506 		$p = ($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
       
  1507 		$this->_newobj();
       
  1508 		$this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
       
  1509 		$this->_putstream($p);
       
  1510 		$this->_out('endobj');
       
  1511 	}
       
  1512 	// Pages root
       
  1513 	$this->offsets[1] = strlen($this->buffer);
       
  1514 	$this->_out('1 0 obj');
       
  1515 	$this->_out('<</Type /Pages');
       
  1516 	$kids = '/Kids [';
       
  1517 	for($i=0;$i<$nb;$i++)
       
  1518 		$kids .= (3+2*$i).' 0 R ';
       
  1519 	$this->_out($kids.']');
       
  1520 	$this->_out('/Count '.$nb);
       
  1521 	$this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$wPt,$hPt));
       
  1522 	$this->_out('>>');
       
  1523 	$this->_out('endobj');
       
  1524 }
       
  1525 
       
  1526 function _putfonts()
       
  1527 {
       
  1528 	$nf = $this->n;
       
  1529 	foreach($this->diffs as $diff)
       
  1530 	{
       
  1531 		// Encodings
       
  1532 		$this->_newobj();
       
  1533 		$this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
       
  1534 		$this->_out('endobj');
       
  1535 	}
       
  1536 	foreach($this->FontFiles as $file=>$info)
       
  1537 	{
       
  1538 		// Font file embedding
       
  1539 		$this->_newobj();
       
  1540 		$this->FontFiles[$file]['n'] = $this->n;
       
  1541 		$font = file_get_contents($this->fontpath.$file,true);
       
  1542 		if(!$font)
       
  1543 			$this->Error('Font file not found: '.$file);
       
  1544 		$compressed = (substr($file,-2)=='.z');
       
  1545 		if(!$compressed && isset($info['length2']))
       
  1546 			$font = substr($font,6,$info['length1']).substr($font,6+$info['length1']+6,$info['length2']);
       
  1547 		$this->_out('<</Length '.strlen($font));
       
  1548 		if($compressed)
       
  1549 			$this->_out('/Filter /FlateDecode');
       
  1550 		$this->_out('/Length1 '.$info['length1']);
       
  1551 		if(isset($info['length2']))
       
  1552 			$this->_out('/Length2 '.$info['length2'].' /Length3 0');
       
  1553 		$this->_out('>>');
       
  1554 		$this->_putstream($font);
       
  1555 		$this->_out('endobj');
       
  1556 	}
       
  1557 	foreach($this->fonts as $k=>$font)
       
  1558 	{
       
  1559 		// Font objects
       
  1560 		$this->fonts[$k]['n'] = $this->n+1;
       
  1561 		$type = $font['type'];
       
  1562 		$name = $font['name'];
       
  1563 		if($type=='Core')
       
  1564 		{
       
  1565 			// Core font
       
  1566 			$this->_newobj();
       
  1567 			$this->_out('<</Type /Font');
       
  1568 			$this->_out('/BaseFont /'.$name);
       
  1569 			$this->_out('/Subtype /Type1');
       
  1570 			if($name!='Symbol' && $name!='ZapfDingbats')
       
  1571 				$this->_out('/Encoding /WinAnsiEncoding');
       
  1572 			$this->_out('>>');
       
  1573 			$this->_out('endobj');
       
  1574 		}
       
  1575 		elseif($type=='Type1' || $type=='TrueType')
       
  1576 		{
       
  1577 			// Additional Type1 or TrueType/OpenType font
       
  1578 			$this->_newobj();
       
  1579 			$this->_out('<</Type /Font');
       
  1580 			$this->_out('/BaseFont /'.$name);
       
  1581 			$this->_out('/Subtype /'.$type);
       
  1582 			$this->_out('/FirstChar 32 /LastChar 255');
       
  1583 			$this->_out('/Widths '.($this->n+1).' 0 R');
       
  1584 			$this->_out('/FontDescriptor '.($this->n+2).' 0 R');
       
  1585 			if(isset($font['diffn']))
       
  1586 				$this->_out('/Encoding '.($nf+$font['diffn']).' 0 R');
       
  1587 			else
       
  1588 				$this->_out('/Encoding /WinAnsiEncoding');
       
  1589 			$this->_out('>>');
       
  1590 			$this->_out('endobj');
       
  1591 			// Widths
       
  1592 			$this->_newobj();
       
  1593 			$cw = &$font['cw'];
       
  1594 			$s = '[';
       
  1595 			for($i=32;$i<=255;$i++)
       
  1596 				$s .= $cw[chr($i)].' ';
       
  1597 			$this->_out($s.']');
       
  1598 			$this->_out('endobj');
       
  1599 			// Descriptor
       
  1600 			$this->_newobj();
       
  1601 			$s = '<</Type /FontDescriptor /FontName /'.$name;
       
  1602 			foreach($font['desc'] as $k=>$v)
       
  1603 				$s .= ' /'.$k.' '.$v;
       
  1604 			if(!empty($font['file']))
       
  1605 				$s .= ' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->FontFiles[$font['file']]['n'].' 0 R';
       
  1606 			$this->_out($s.'>>');
       
  1607 			$this->_out('endobj');
       
  1608 		}
       
  1609 		else
       
  1610 		{
       
  1611 			// Allow for additional types
       
  1612 			$mtd = '_put'.strtolower($type);
       
  1613 			if(!method_exists($this,$mtd))
       
  1614 				$this->Error('Unsupported font type: '.$type);
       
  1615 			$this->$mtd($font);
       
  1616 		}
       
  1617 	}
       
  1618 }
       
  1619 
       
  1620 function _putimages()
       
  1621 {
       
  1622 	foreach(array_keys($this->images) as $file)
       
  1623 	{
       
  1624 		$this->_putimage($this->images[$file]);
       
  1625 		unset($this->images[$file]['data']);
       
  1626 		unset($this->images[$file]['smask']);
       
  1627 	}
       
  1628 }
       
  1629 
       
  1630 function _putimage(&$info)
       
  1631 {
       
  1632 	$this->_newobj();
       
  1633 	$info['n'] = $this->n;
       
  1634 	$this->_out('<</Type /XObject');
       
  1635 	$this->_out('/Subtype /Image');
       
  1636 	$this->_out('/Width '.$info['w']);
       
  1637 	$this->_out('/Height '.$info['h']);
       
  1638 	if($info['cs']=='Indexed')
       
  1639 		$this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
       
  1640 	else
       
  1641 	{
       
  1642 		$this->_out('/ColorSpace /'.$info['cs']);
       
  1643 		if($info['cs']=='DeviceCMYK')
       
  1644 			$this->_out('/Decode [1 0 1 0 1 0 1 0]');
       
  1645 	}
       
  1646 	$this->_out('/BitsPerComponent '.$info['bpc']);
       
  1647 	if(isset($info['f']))
       
  1648 		$this->_out('/Filter /'.$info['f']);
       
  1649 	if(isset($info['dp']))
       
  1650 		$this->_out('/DecodeParms <<'.$info['dp'].'>>');
       
  1651 	if(isset($info['trns']) && is_array($info['trns']))
       
  1652 	{
       
  1653 		$trns = '';
       
  1654 		for($i=0;$i<count($info['trns']);$i++)
       
  1655 			$trns .= $info['trns'][$i].' '.$info['trns'][$i].' ';
       
  1656 		$this->_out('/Mask ['.$trns.']');
       
  1657 	}
       
  1658 	if(isset($info['smask']))
       
  1659 		$this->_out('/SMask '.($this->n+1).' 0 R');
       
  1660 	$this->_out('/Length '.strlen($info['data']).'>>');
       
  1661 	$this->_putstream($info['data']);
       
  1662 	$this->_out('endobj');
       
  1663 	// Soft mask
       
  1664 	if(isset($info['smask']))
       
  1665 	{
       
  1666 		$dp = '/Predictor 15 /Colors 1 /BitsPerComponent 8 /Columns '.$info['w'];
       
  1667 		$smask = array('w'=>$info['w'], 'h'=>$info['h'], 'cs'=>'DeviceGray', 'bpc'=>8, 'f'=>$info['f'], 'dp'=>$dp, 'data'=>$info['smask']);
       
  1668 		$this->_putimage($smask);
       
  1669 	}
       
  1670 	// Palette
       
  1671 	if($info['cs']=='Indexed')
       
  1672 	{
       
  1673 		$filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
       
  1674 		$pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal'];
       
  1675 		$this->_newobj();
       
  1676 		$this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
       
  1677 		$this->_putstream($pal);
       
  1678 		$this->_out('endobj');
       
  1679 	}
       
  1680 }
       
  1681 
       
  1682 function _putxobjectdict()
       
  1683 {
       
  1684 	foreach($this->images as $image)
       
  1685 		$this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
       
  1686 }
       
  1687 
       
  1688 function _putresourcedict()
       
  1689 {
       
  1690 	$this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
       
  1691 	$this->_out('/Font <<');
       
  1692 	foreach($this->fonts as $font)
       
  1693 		$this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
       
  1694 	$this->_out('>>');
       
  1695 	$this->_out('/XObject <<');
       
  1696 	$this->_putxobjectdict();
       
  1697 	$this->_out('>>');
       
  1698 }
       
  1699 
       
  1700 function _putresources()
       
  1701 {
       
  1702 	$this->_putfonts();
       
  1703 	$this->_putimages();
       
  1704 	// Resource dictionary
       
  1705 	$this->offsets[2] = strlen($this->buffer);
       
  1706 	$this->_out('2 0 obj');
       
  1707 	$this->_out('<<');
       
  1708 	$this->_putresourcedict();
       
  1709 	$this->_out('>>');
       
  1710 	$this->_out('endobj');
       
  1711 }
       
  1712 
       
  1713 function _putinfo()
       
  1714 {
       
  1715 	$this->_out('/Producer '.$this->_textstring('FPDF '.FPDF_VERSION));
       
  1716 	if(!empty($this->title))
       
  1717 		$this->_out('/Title '.$this->_textstring($this->title));
       
  1718 	if(!empty($this->subject))
       
  1719 		$this->_out('/Subject '.$this->_textstring($this->subject));
       
  1720 	if(!empty($this->author))
       
  1721 		$this->_out('/Author '.$this->_textstring($this->author));
       
  1722 	if(!empty($this->keywords))
       
  1723 		$this->_out('/Keywords '.$this->_textstring($this->keywords));
       
  1724 	if(!empty($this->creator))
       
  1725 		$this->_out('/Creator '.$this->_textstring($this->creator));
       
  1726 	$this->_out('/CreationDate '.$this->_textstring('D:'.@date('YmdHis')));
       
  1727 }
       
  1728 
       
  1729 function _putcatalog()
       
  1730 {
       
  1731 	$this->_out('/Type /Catalog');
       
  1732 	$this->_out('/Pages 1 0 R');
       
  1733 	if($this->ZoomMode=='fullpage')
       
  1734 		$this->_out('/OpenAction [3 0 R /Fit]');
       
  1735 	elseif($this->ZoomMode=='fullwidth')
       
  1736 		$this->_out('/OpenAction [3 0 R /FitH null]');
       
  1737 	elseif($this->ZoomMode=='real')
       
  1738 		$this->_out('/OpenAction [3 0 R /XYZ null null 1]');
       
  1739 	elseif(!is_string($this->ZoomMode))
       
  1740 		$this->_out('/OpenAction [3 0 R /XYZ null null '.sprintf('%.2F',$this->ZoomMode/100).']');
       
  1741 	if($this->LayoutMode=='single')
       
  1742 		$this->_out('/PageLayout /SinglePage');
       
  1743 	elseif($this->LayoutMode=='continuous')
       
  1744 		$this->_out('/PageLayout /OneColumn');
       
  1745 	elseif($this->LayoutMode=='two')
       
  1746 		$this->_out('/PageLayout /TwoColumnLeft');
       
  1747 }
       
  1748 
       
  1749 function _putheader()
       
  1750 {
       
  1751 	$this->_out('%PDF-'.$this->PDFVersion);
       
  1752 }
       
  1753 
       
  1754 function _puttrailer()
       
  1755 {
       
  1756 	$this->_out('/Size '.($this->n+1));
       
  1757 	$this->_out('/Root '.$this->n.' 0 R');
       
  1758 	$this->_out('/Info '.($this->n-1).' 0 R');
       
  1759 }
       
  1760 
       
  1761 function _enddoc()
       
  1762 {
       
  1763 	$this->_putheader();
       
  1764 	$this->_putpages();
       
  1765 	$this->_putresources();
       
  1766 	// Info
       
  1767 	$this->_newobj();
       
  1768 	$this->_out('<<');
       
  1769 	$this->_putinfo();
       
  1770 	$this->_out('>>');
       
  1771 	$this->_out('endobj');
       
  1772 	// Catalog
       
  1773 	$this->_newobj();
       
  1774 	$this->_out('<<');
       
  1775 	$this->_putcatalog();
       
  1776 	$this->_out('>>');
       
  1777 	$this->_out('endobj');
       
  1778 	// Cross-ref
       
  1779 	$o = strlen($this->buffer);
       
  1780 	$this->_out('xref');
       
  1781 	$this->_out('0 '.($this->n+1));
       
  1782 	$this->_out('0000000000 65535 f ');
       
  1783 	for($i=1;$i<=$this->n;$i++)
       
  1784 		$this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
       
  1785 	// Trailer
       
  1786 	$this->_out('trailer');
       
  1787 	$this->_out('<<');
       
  1788 	$this->_puttrailer();
       
  1789 	$this->_out('>>');
       
  1790 	$this->_out('startxref');
       
  1791 	$this->_out($o);
       
  1792 	$this->_out('%%EOF');
       
  1793 	$this->state = 3;
       
  1794 }
       
  1795 // End of class
       
  1796 }
       
  1797 
       
  1798 // Handle special IE contype request
       
  1799 if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']=='contype')
       
  1800 {
       
  1801 	header('Content-Type: application/pdf');
       
  1802 	exit;
       
  1803 }
       
  1804 
       
  1805 ?>