[ PHPXref.com ] [ Generated: Sun Jul 20 20:33:16 2008 ] [ TCExam 3.0.008 ]
[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/shared/code/ -> tcpdf.php (source)

   1  <?php
   2  //============================================================+

   3  // File name   : fpdf.php

   4  // Begin       : 2002-08-03

   5  // Last Update : 2005-08-28

   6  // Authors     : Olivier PLATHEY,

   7  //               Nicola Asuni

   8  // Version     : 1.53.0.TC016

   9  // License     : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)

  10  //

  11  // Description : This is a PHP5 class for generating PDF files 

  12  //               on-the-fly without requiring external 

  13  //               extensions.

  14  //               This class is an extension and improvement of 

  15  //               the Public Domain FPDF class by Olivier Plathey 

  16  //               (http://www.fpdf.org).

  17  //

  18  // Main changes by Nicola Asuni:

  19  //    PHP5 porting;

  20  //    UTF-8 Unicode support;

  21  //    source code clean up;

  22  //    code style and formatting;

  23  //    source code documentation using phpDocumentor (www.phpdoc.org);

  24  //    All ISO page formats were included;

  25  //    image scale factor;

  26  //    includes methods to parse and print some XHTML code, supporting the following elements: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small;

  27  //    includes a method to print various barcode formats using an improved version of "Generic Barcode Render Class" by Karim Mribti (http://www.mribti.com/barcode/) (require GD library: http://www.boutell.com/gd/);

  28  //    defines standard Header() and Footer() methods.

  29  //============================================================+

  30  
  31  /**

  32   * This is a PHP5 class for generating PDF files on-the-fly without requiring external extensions.<br>

  33   * TCPDF project (http://tcpdf.sourceforge.net) is based on the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org).<br>

  34   * <h3>TCPDF main changes from FPDF are:</h3><ul>

  35   * <li>PHP5 porting</li>

  36   * <li>UTF-8 Unicode support</li>

  37   * <li>source code clean up</li>

  38   * <li>code style and formatting</li>

  39   * <li>source code documentation using phpDocumentor (www.phpdoc.org)</li>

  40   * <li>All ISO page formats were included</li>

  41   * <li>image scale factor</li>

  42   * <li>includes methods to parse and printsome XHTML code, supporting the following elements: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small;</li>

  43   * <li>includes a method to print various barcode formats using an improved version of "Generic Barcode Render Class" by Karim Mribti (http://www.mribti.com/barcode/) (require GD library: http://www.boutell.com/gd/)</li>

  44   * <li>defines standard Header() and Footer() methods.</li>

  45   * </ul>

  46   * Tools to encode your unicode fonts can be found at: http://www.acko.net/blog/ufpdf</p>

  47   * @name TCPDF

  48   * @package com.tecnick.tcpdf

  49   * @abstract Class for generating PDF files on-the-fly without requiring external extensions.

  50   * @author Nicola Asuni, Olivier PLATHEY

  51   * @copyright 2004-2005 Tecnick.com S.r.l (www.tecnick.com) Via Ugo Foscolo n.19 - 09045 Quartu Sant'Elena (CA) - ITALY - www.tecnick.com - info@tecnick.com

  52   * @link http://tcpdf.sourceforge.net

  53   * @license http://www.gnu.org/copyleft/lesser.html LGPL

  54   * @version 1.53.0.TC016

  55   */
  56  
  57  if(!class_exists('TCPDF')) {
  58      /**

  59       * define default PDF document producer

  60       */ 
  61      define('PDF_PRODUCER','TCPDF 1.53.0.TC016 (http://tcpdf.sourceforge.net)');
  62      
  63      /**

  64      * This is a PHP5 class for generating PDF files on-the-fly without requiring external extensions.<br>

  65      * This class is an extension and improvement of the FPDF class by Olivier Plathey (http://www.fpdf.org).<br>

  66      * This version contains some changes: [porting to PHP5, support for UTF-8 Unicode, code style and formatting, php documentation (www.phpdoc.org), ISO page formats, minor improvements, image scale factor]<br>

  67      * Tools to encode your unicode fonts can be found at: http://www.acko.net/blog/ufpdf

  68      * @name FPDF

  69      * @package com.tecnick.tcpdf

  70      * @version 1.53.0.TC016

  71      * @author Olivier PLATHEY, Nicola Asuni

  72      * @link http://tcpdf.sourceforge.net

  73      * @license http://www.gnu.org/copyleft/lesser.html LGPL

  74      */
  75      class TCPDF {
  76          //Private properties

  77  
  78          /**

  79          * @var current page number

  80          * @access protected

  81          */
  82          protected $page;
  83  
  84          /**

  85          * @var current object number

  86          * @access protected

  87          */
  88          protected $n;
  89  
  90          /**

  91          * @var array of object offsets

  92          * @access protected

  93          */
  94          protected $offsets;
  95  
  96          /**

  97          * @var buffer holding in-memory PDF

  98          * @access protected

  99          */
 100          protected $buffer;
 101  
 102          /**

 103          * @var array containing pages

 104          * @access protected

 105          */
 106          protected $pages;
 107  
 108          /**

 109          * @var current document state

 110          * @access protected

 111          */
 112          protected $state;
 113  
 114          /**

 115          * @var compression flag

 116          * @access protected

 117          */
 118          protected $compress;
 119  
 120          /**

 121          * @var default orientation

 122          * @access protected

 123          */
 124          protected $DefOrientation;
 125  
 126          /**

 127          * @var current orientation

 128          * @access protected

 129          */
 130          protected $CurOrientation;
 131  
 132          /**

 133          * @var array indicating orientation changes

 134          * @access protected

 135          */
 136          protected $OrientationChanges;
 137  
 138          /**

 139          * @var scale factor (number of points in user unit)

 140          * @access protected

 141          */
 142          protected $k;
 143  
 144          /**

 145          * @var width of page format in points

 146          * @access protected

 147          */
 148          protected $fwPt;
 149  
 150          /**

 151          * @var height of page format in points

 152          * @access protected

 153          */
 154          protected $fhPt;
 155  
 156          /**

 157          * @var width of page format in user unit

 158          * @access protected

 159          */
 160          protected $fw;
 161  
 162          /**

 163          * @var height of page format in user unit

 164          * @access protected

 165          */
 166          protected $fh;
 167  
 168          /**

 169          * @var current width of page in points

 170          * @access protected

 171          */
 172          protected $wPt;
 173  
 174          /**

 175          * @var current height of page in points

 176          * @access protected

 177          */
 178          protected $hPt;
 179  
 180          /**

 181          * @var current width of page in user unit

 182          * @access protected

 183          */
 184          protected $w;
 185  
 186          /**

 187          * @var current height of page in user unit

 188          * @access protected

 189          */
 190          protected $h;
 191  
 192          /**

 193          * @var left margin

 194          * @access protected

 195          */
 196          protected $lMargin;
 197  
 198          /**

 199          * @var top margin

 200          * @access protected

 201          */
 202          protected $tMargin;
 203  
 204          /**

 205          * @var right margin

 206          * @access protected

 207          */
 208          protected $rMargin;
 209  
 210          /**

 211          * @var page break margin

 212          * @access protected

 213          */
 214          protected $bMargin;
 215  
 216          /**

 217          * @var cell margin

 218          * @access protected

 219          */
 220          protected $cMargin;
 221  
 222          /**

 223          * @var current horizontal position in user unit for cell positioning

 224          * @access protected

 225          */
 226          protected $x;
 227  
 228          /**

 229          * @var current vertical position in user unit for cell positioning

 230          * @access protected

 231          */
 232          protected $y;
 233  
 234          /**

 235          * @var height of last cell printed

 236          * @access protected

 237          */
 238          protected $lasth;
 239  
 240          /**

 241          * @var line width in user unit

 242          * @access protected

 243          */
 244          protected $LineWidth;
 245  
 246          /**

 247          * @var array of standard font names

 248          * @access protected

 249          */
 250          protected $CoreFonts;
 251  
 252          /**

 253          * @var array of used fonts

 254          * @access protected

 255          */
 256          protected $fonts;
 257  
 258          /**

 259          * @var array of font files

 260          * @access protected

 261          */
 262          protected $FontFiles;
 263  
 264          /**

 265          * @var array of encoding differences

 266          * @access protected

 267          */
 268          protected $diffs;
 269  
 270          /**

 271          * @var array of used images

 272          * @access protected

 273          */
 274          protected $images;
 275  
 276          /**

 277          * @var array of links in pages

 278          * @access protected

 279          */
 280          protected $PageLinks;
 281  
 282          /**

 283          * @var array of internal links

 284          * @access protected

 285          */
 286          protected $links;
 287  
 288          /**

 289          * @var current font family

 290          * @access protected

 291          */
 292          protected $FontFamily;
 293  
 294          /**

 295          * @var current font style

 296          * @access protected

 297          */
 298          protected $FontStyle;
 299  
 300          /**

 301          * @var underlining flag

 302          * @access protected

 303          */
 304          protected $underline;
 305  
 306          /**

 307          * @var current font info

 308          * @access protected

 309          */
 310          protected $CurrentFont;
 311  
 312          /**

 313          * @var current font size in points

 314          * @access protected

 315          */
 316          protected $FontSizePt;
 317  
 318          /**

 319          * @var current font size in user unit

 320          * @access protected

 321          */
 322          protected $FontSize;
 323  
 324          /**

 325          * @var commands for drawing color

 326          * @access protected

 327          */
 328          protected $DrawColor;
 329  
 330          /**

 331          * @var commands for filling color

 332          * @access protected

 333          */
 334          protected $FillColor;
 335  
 336          /**

 337          * @var commands for text color

 338          * @access protected

 339          */
 340          protected $TextColor;
 341  
 342          /**

 343          * @var indicates whether fill and text colors are different

 344          * @access protected

 345          */
 346          protected $ColorFlag;
 347  
 348          /**

 349          * @var word spacing

 350          * @access protected

 351          */
 352          protected $ws;
 353  
 354          /**

 355          * @var automatic page breaking

 356          * @access protected

 357          */
 358          protected $AutoPageBreak;
 359  
 360          /**

 361          * @var threshold used to trigger page breaks

 362          * @access protected

 363          */
 364          protected $PageBreakTrigger;
 365  
 366          /**

 367          * @var flag set when processing footer

 368          * @access protected

 369          */
 370          protected $InFooter;
 371  
 372          /**

 373          * @var zoom display mode

 374          * @access protected

 375          */
 376          protected $ZoomMode;
 377  
 378          /**

 379          * @var layout display mode

 380          * @access protected

 381          */
 382          protected $LayoutMode;
 383  
 384          /**

 385          * @var title

 386          * @access protected

 387          */
 388          protected $title;
 389  
 390          /**

 391          * @var subject

 392          * @access protected

 393          */
 394          protected $subject;
 395  
 396          /**

 397          * @var author

 398          * @access protected

 399          */
 400          protected $author;
 401  
 402          /**

 403          * @var keywords

 404          * @access protected

 405          */
 406          protected $keywords;
 407  
 408          /**

 409          * @var creator

 410          * @access protected

 411          */
 412          protected $creator;
 413  
 414          /**

 415          * @var alias for total number of pages

 416          * @access protected

 417          */
 418          protected $AliasNbPages;
 419  
 420          /**

 421          * @var right-bottom corner X coordinate of inserted image

 422          * @since 2002-07-31

 423          * @author Nicola Asuni

 424          * @access protected

 425          */
 426          protected $img_rb_x;
 427  
 428          /**

 429          * @var right-bottom corner Y coordinate of inserted image

 430          * @since 2002-07-31

 431          * @author Nicola Asuni

 432          * @access protected

 433          */
 434          protected $img_rb_y;
 435  
 436          /**

 437          * @var image scale factor

 438          * @since 2004-06-14

 439          * @author Nicola Asuni

 440          * @access protected

 441          */
 442          protected $imgscale = 1;
 443  
 444          /**

 445          * @var boolean set to true when the input text is unicode (require unicode fonts)

 446          * @since 2005-01-02

 447          * @author Nicola Asuni

 448          * @access protected

 449          */
 450          protected $isunicode = false;
 451  
 452          /**

 453          * @var PDF version

 454          * @since 1.5.3

 455          * @access protected

 456          */
 457          protected $PDFVersion = "1.3";
 458          
 459          
 460          // ----------------------

 461          
 462          /**

 463           * @var Minimum distance between header and top page margin.

 464           * @access private

 465           */
 466          private $header_margin;
 467          
 468          /**

 469           * @var Minimum distance between footer and bottom page margin.

 470           * @access private

 471           */
 472          private $footer_margin;
 473          
 474          /**

 475           * @var original left margin value

 476           * @access private

 477           * @since 1.53.0.TC013

 478           */
 479          private $original_lMargin;
 480          
 481          /**

 482           * @var original right margin value

 483           * @access private

 484           * @since 1.53.0.TC013

 485           */
 486          private $original_rMargin;
 487              
 488          /**

 489           * @var Header font.

 490           * @access private

 491           */
 492          private $header_font;
 493          
 494          /**

 495           * @var Footer font.

 496           * @access private

 497           */
 498          private $footer_font;
 499          
 500          /**

 501           * @var Language templates.

 502           * @access private

 503           */
 504          private $l;
 505          
 506          /**

 507           * @var Barcode to print on page footer (only if set).

 508           * @access private

 509           */
 510          private $barcode = false;
 511          
 512          /**

 513           * @var If true prints header

 514           * @access private

 515           */
 516          private $print_header = true;
 517          
 518          /**

 519           * @var If true prints footer.

 520           * @access private

 521           */
 522          private $print_footer = true;
 523          
 524          /**

 525           * @var Header width (0 = full page width).

 526           * @access private

 527           */
 528          private $header_width = 0;
 529          
 530          /**

 531           * @var Header image logo.

 532           * @access private

 533           */
 534          private $header_logo = "";
 535          
 536          /**

 537           * @var Header image logo width in mm.

 538           * @access private

 539           */
 540          private $header_logo_width = 30;
 541          
 542          /**

 543           * @var String to print as title on document header.

 544           * @access private

 545           */
 546          private $header_title = "";
 547          
 548          /**

 549           * @var String to print on document header.

 550           * @access private

 551           */
 552          private $header_string = "";
 553          
 554          /**

 555           * @var Default number of columns for html table.

 556           * @access private

 557           */
 558          private $default_table_columns = 4;
 559          
 560          
 561          // variables for html parser

 562          
 563          /**

 564           * @var HTML PARSER: store current link.

 565           * @access private

 566           */
 567          private $HREF;
 568          
 569          /**

 570           * @var HTML PARSER: store font list.

 571           * @access private

 572           */
 573          private $fontList;
 574          
 575          /**

 576           * @var HTML PARSER: true when font attribute is set.

 577           * @access private

 578           */
 579          private $issetfont;
 580          
 581          /**

 582           * @var HTML PARSER: true when color attribute is set.

 583           * @access private

 584           */
 585          private $issetcolor;
 586          
 587          /**

 588           * @var HTML PARSER: true in case of ordered list (OL), false otherwise.

 589           * @access private

 590           */
 591          private $listordered = false;
 592          
 593          /**

 594           * @var HTML PARSER: count list items.

 595           * @access private

 596           */
 597          private $listcount = 0;
 598          
 599          /**

 600           * @var HTML PARSER: size of table border.

 601           * @access private

 602           */
 603          private $tableborder = 0;
 604          
 605          /**

 606           * @var HTML PARSER: true at the beginning of table.

 607           * @access private

 608           */
 609          private $tdbegin = false;
 610          
 611          /**

 612           * @var HTML PARSER: table width.

 613           * @access private

 614           */
 615          private $tdwidth = 0;
 616          
 617          /**

 618           * @var HTML PARSER: table height.

 619           * @access private

 620           */
 621          private $tdheight = 0;
 622          
 623          /**

 624           * @var HTML PARSER: table align.

 625           * @access private

 626           */
 627          private $tdalign = "L";
 628          
 629          /**

 630           * @var HTML PARSER: table background color.

 631           * @access private

 632           */
 633          private $tdbgcolor = false;
 634          
 635          /**

 636           * @var Store temporary font size in points.

 637           * @access private

 638           */
 639          private $tempfontsize = 10;
 640          
 641          /**

 642           * @var Bold font style status.

 643           * @access private

 644           */
 645          private $b;
 646          
 647          /**

 648           * @var Underlined font style status.

 649           * @access private

 650           */
 651          private $u;
 652          
 653          /**

 654           * @var Italic font style status.

 655           * @access private

 656           */
 657          private $i;
 658          
 659          /**

 660           * @var spacer for LI tags.

 661           * @access private

 662           */
 663          private $lispacer = "";
 664          
 665          /**

 666           * @var default encoding

 667           * @access private

 668           * @since 1.53.0.TC010

 669           */
 670          private $encoding = "UTF-8";
 671          
 672          /**

 673           * @var PHP internal encoding

 674           * @access private

 675           * @since 1.53.0.TC016

 676           */
 677          private $internal_encoding;
 678  
 679  
 680          //------------------------------------------------------------

 681          // Public methods

 682          //------------------------------------------------------------

 683  
 684          /**

 685           * This is the class constructor. 

 686           * It allows to set up the page format, the orientation and 

 687           * the measure unit used in all the methods (except for the font sizes).

 688           * @since 1.0

 689           * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or Portrait (default)</li><li>L or Landscape</li></ul>

 690           * @param string $unit User measure unit. Possible values are:<ul><li>pt: point</li><li>mm: millimeter (default)</li><li>cm: centimeter</li><li>in: inch</li></ul><br />A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit.

 691           * @param mixed $format The format used for pages. It can be either one of the following values (case insensitive) or a custom format in the form of a two-element array containing the width and the height (expressed in the unit given by unit).<ul><li>4A0</li><li>2A0</li><li>A0</li><li>A1</li><li>A2</li><li>A3</li><li>A4 (default)</li><li>A5</li><li>A6</li><li>A7</li><li>A8</li><li>A9</li><li>A10</li><li>B0</li><li>B1</li><li>B2</li><li>B3</li><li>B4</li><li>B5</li><li>B6</li><li>B7</li><li>B8</li><li>B9</li><li>B10</li><li>C0</li><li>C1</li><li>C2</li><li>C3</li><li>C4</li><li>C5</li><li>C6</li><li>C7</li><li>C8</li><li>C9</li><li>C10</li><li>RA0</li><li>RA1</li><li>RA2</li><li>RA3</li><li>RA4</li><li>SRA0</li><li>SRA1</li><li>SRA2</li><li>SRA3</li><li>SRA4</li><li>LETTER</li><li>LEGAL</li><li>EXECUTIVE</li><li>FOLIO</li></ul>

 692           * @param boolean $unicode TRUE means that the input text is unicode (default = true)

 693           * @param String $encoding charset encoding; default is UTF-8

 694           */
 695  		public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding="UTF-8") {
 696              
 697              /* Set internal character encoding to ASCII */

 698              if (function_exists("mb_internal_encoding") AND mb_internal_encoding()) {
 699                  $this->internal_encoding = mb_internal_encoding();
 700                  mb_internal_encoding("ASCII");
 701              }
 702                  
 703              //Some checks

 704              $this->_dochecks();
 705              //Initialization of properties

 706              $this->isunicode=$unicode;
 707              $this->page=0;
 708              $this->n=2;
 709              $this->buffer='';
 710              $this->pages=array();
 711              $this->OrientationChanges=array();
 712              $this->state=0;
 713              $this->fonts=array();
 714              $this->FontFiles=array();
 715              $this->diffs=array();
 716              $this->images=array();
 717              $this->links=array();
 718              $this->InFooter=false;
 719              $this->lasth=0;
 720              $this->FontFamily='';
 721              $this->FontStyle='';
 722              $this->FontSizePt=12;
 723              $this->underline=false;
 724              $this->DrawColor='0 G';
 725              $this->FillColor='0 g';
 726              $this->TextColor='0 g';
 727              $this->ColorFlag=false;
 728              $this->ws=0;
 729              //Standard Unicode fonts

 730              $this->CoreFonts=array(
 731              'courier'=>'Courier',
 732              'courierB'=>'Courier-Bold',
 733              'courierI'=>'Courier-Oblique',
 734              'courierBI'=>'Courier-BoldOblique',
 735              'helvetica'=>'Helvetica',
 736              'helveticaB'=>'Helvetica-Bold',
 737              'helveticaI'=>'Helvetica-Oblique',
 738              'helveticaBI'=>'Helvetica-BoldOblique',
 739              'times'=>'Times-Roman',
 740              'timesB'=>'Times-Bold',
 741              'timesI'=>'Times-Italic',
 742              'timesBI'=>'Times-BoldItalic',
 743              'symbol'=>'Symbol',
 744              'zapfdingbats'=>'ZapfDingbats'
 745              );
 746  
 747              //Scale factor

 748              // 2003-06-11 - Nicola Asuni : changed if/else with switch statement

 749              switch (strtolower($unit)){
 750                  case 'pt': {$this->k=1; break;}
 751                  case 'mm': {$this->k=72/25.4; break;}
 752                  case 'cm': {$this->k=72/2.54;; break;}
 753                  case 'in': {$this->k=72;; break;}
 754                  default : {$this->Error('Incorrect unit: '.$unit); break;}
 755              }
 756  
 757              //Page format

 758              if(is_string($format)) {
 759                  // 2002-07-24 - Nicola Asuni (info@tecnick.com)

 760                  // Added new page formats (45 standard ISO paper formats and 4 american common formats).

 761                  // Paper cordinates are calculated in this way: (inches * 72) where (1 inch = 2.54 cm)

 762                  switch (strtoupper($format)){
 763                      case '4A0': {$format = array(4767.87,6740.79); break;}
 764                      case '2A0': {$format = array(3370.39,4767.87); break;}
 765                      case 'A0': {$format = array(2383.94,3370.39); break;}
 766                      case 'A1': {$format = array(1683.78,2383.94); break;}
 767                      case 'A2': {$format = array(1190.55,1683.78); break;}
 768                      case 'A3': {$format = array(841.89,1190.55); break;}
 769                      case 'A4': default: {$format = array(595.28,841.89); break;}
 770                      case 'A5': {$format = array(419.53,595.28); break;}
 771                      case 'A6': {$format = array(297.64,419.53); break;}
 772                      case 'A7': {$format = array(209.76,297.64); break;}
 773                      case 'A8': {$format = array(147.40,209.76); break;}
 774                      case 'A9': {$format = array(104.88,147.40); break;}
 775                      case 'A10': {$format = array(73.70,104.88); break;}
 776                      case 'B0': {$format = array(2834.65,4008.19); break;}
 777                      case 'B1': {$format = array(2004.09,2834.65); break;}
 778                      case 'B2': {$format = array(1417.32,2004.09); break;}
 779                      case 'B3': {$format = array(1000.63,1417.32); break;}
 780                      case 'B4': {$format = array(708.66,1000.63); break;}
 781                      case 'B5': {$format = array(498.90,708.66); break;}
 782                      case 'B6': {$format = array(354.33,498.90); break;}
 783                      case 'B7': {$format = array(249.45,354.33); break;}
 784                      case 'B8': {$format = array(175.75,249.45); break;}
 785                      case 'B9': {$format = array(124.72,175.75); break;}
 786                      case 'B10': {$format = array(87.87,124.72); break;}
 787                      case 'C0': {$format = array(2599.37,3676.54); break;}
 788                      case 'C1': {$format = array(1836.85,2599.37); break;}
 789                      case 'C2': {$format = array(1298.27,1836.85); break;}
 790                      case 'C3': {$format = array(918.43,1298.27); break;}
 791                      case 'C4': {$format = array(649.13,918.43); break;}
 792                      case 'C5': {$format = array(459.21,649.13); break;}
 793                      case 'C6': {$format = array(323.15,459.21); break;}
 794                      case 'C7': {$format = array(229.61,323.15); break;}
 795                      case 'C8': {$format = array(161.57,229.61); break;}
 796                      case 'C9': {$format = array(113.39,161.57); break;}
 797                      case 'C10': {$format = array(79.37,113.39); break;}
 798                      case 'RA0': {$format = array(2437.80,3458.27); break;}
 799                      case 'RA1': {$format = array(1729.13,2437.80); break;}
 800                      case 'RA2': {$format = array(1218.90,1729.13); break;}
 801                      case 'RA3': {$format = array(864.57,1218.90); break;}
 802                      case 'RA4': {$format = array(609.45,864.57); break;}
 803                      case 'SRA0': {$format = array(2551.18,3628.35); break;}
 804                      case 'SRA1': {$format = array(1814.17,2551.18); break;}
 805                      case 'SRA2': {$format = array(1275.59,1814.17); break;}
 806                      case 'SRA3': {$format = array(907.09,1275.59); break;}
 807                      case 'SRA4': {$format = array(637.80,907.09); break;}
 808                      case 'LETTER': {$format = array(612.00,792.00); break;}
 809                      case 'LEGAL': {$format = array(612.00,1008.00); break;}
 810                      case 'EXECUTIVE': {$format = array(521.86,756.00); break;}
 811                      case 'FOLIO': {$format = array(612.00,936.00); break;}
 812                      // default: {$this->Error('Unknown page format: '.$format); break;}

 813                      // END CHANGES Nicola Asuni

 814                  }
 815                  $this->fwPt=$format[0];
 816                  $this->fhPt=$format[1];
 817              }
 818              else {
 819                  $this->fwPt=$format[0]*$this->k;
 820                  $this->fhPt=$format[1]*$this->k;
 821              }
 822  
 823              $this->fw=$this->fwPt/$this->k;
 824              $this->fh=$this->fhPt/$this->k;
 825  
 826              //Page orientation

 827              $orientation=strtolower($orientation);
 828              if($orientation=='p' or $orientation=='portrait') {
 829                  $this->DefOrientation='P';
 830                  $this->wPt=$this->fwPt;
 831                  $this->hPt=$this->fhPt;
 832              }
 833              elseif($orientation=='l' or $orientation=='landscape') {
 834                  $this->DefOrientation='L';
 835                  $this->wPt=$this->fhPt;
 836                  $this->hPt=$this->fwPt;
 837              }
 838              else {
 839                  $this->Error('Incorrect orientation: '.$orientation);
 840              }
 841  
 842              $this->CurOrientation=$this->DefOrientation;
 843              $this->w=$this->wPt/$this->k;
 844              $this->h=$this->hPt/$this->k;
 845              //Page margins (1 cm)

 846              $margin=28.35/$this->k;
 847              $this->SetMargins($margin,$margin);
 848              //Interior cell margin (1 mm)

 849              $this->cMargin=$margin/10;
 850              //Line width (0.2 mm)

 851              $this->LineWidth=.567/$this->k;
 852              //Automatic page break

 853              $this->SetAutoPageBreak(true,2*$margin);
 854              //Full width display mode

 855              $this->SetDisplayMode('fullwidth');
 856              //Compression

 857              $this->SetCompression(true);
 858              //Set default PDF version number

 859              $this->PDFVersion = "1.3";
 860              
 861              $this->encoding = $encoding;
 862              $this->b = 0;
 863              $this->i = 0;
 864              $this->u = 0;
 865              $this->HREF = '';
 866              $this->fontlist = array("arial", "times", "courier", "helvetica", "symbol");
 867              $this->issetfont = false;
 868              $this->issetcolor = false;
 869              $this->tableborder = 0;
 870              $this->tdbegin = false;
 871              $this->tdwidth=  0;
 872              $this->tdheight = 0;
 873              $this->tdalign = "L";
 874              $this->tdbgcolor = false;
 875          }
 876          
 877          /**

 878           * Default destructor.

 879           * @since 1.53.0.TC016

 880           */
 881  		public function __destruct() {
 882              // restore internal encoding

 883              if (isset($this->internal_encoding) AND !empty($this->internal_encoding)) {
 884                  mb_internal_encoding($this->internal_encoding);
 885              }
 886          }
 887  
 888          /**

 889          * Set the image scale.

 890          * @param float $scale image scale.

 891          * @author Nicola Asuni

 892          * @since 1.5.2

 893          */
 894  		public function setImageScale($scale) {
 895              $this->imgscale=$scale;
 896          }
 897  
 898          /**

 899          * Returns the image scale.

 900          * @return float image scale.

 901          * @author Nicola Asuni

 902          * @since 1.5.2

 903          */
 904  		public function getImageScale() {
 905              return $this->imgscale;
 906          }
 907  
 908          /**

 909          * Returns the page width in units.

 910          * @return int page width.

 911          * @author Nicola Asuni

 912          * @since 1.5.2

 913          */
 914  		public function getPageWidth() {
 915              return $this->w;
 916          }
 917  
 918          /**

 919          * Returns the page height in units.

 920          * @return int page height.

 921          * @author Nicola Asuni

 922          * @since 1.5.2

 923          */
 924  		public function getPageHeight() {
 925              return $this->fh;
 926          }
 927  
 928          /**

 929          * Returns the page break margin.

 930          * @return int page break margin.

 931          * @author Nicola Asuni

 932          * @since 1.5.2

 933          */
 934  		public function getBreakMargin() {
 935              return $this->bMargin;
 936          }
 937  
 938          /**

 939          * Returns the scale factor (number of points in user unit).

 940          * @return int scale factor.

 941          * @author Nicola Asuni

 942          * @since 1.5.2

 943          */
 944  		public function getScaleFactor() {
 945              return $this->k;
 946          }
 947  
 948          /**

 949          * Defines the left, top and right margins. By default, they equal 1 cm. Call this method to change them.

 950          * @param float $left Left margin.

 951          * @param float $top Top margin.

 952          * @param float $right Right margin. Default value is the left one.

 953          * @since 1.0

 954          * @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak()

 955          */
 956  		public function SetMargins($left, $top, $right=-1) {
 957              //Set left, top and right margins

 958              $this->lMargin=$left;
 959              $this->tMargin=$top;
 960              if($right==-1) {
 961                  $right=$left;
 962              }
 963              $this->rMargin=$right;
 964          }
 965  
 966          /**

 967          * Defines the left margin. The method can be called before creating the first page. If the current abscissa gets out of page, it is brought back to the margin.

 968          * @param float $margin The margin.

 969          * @since 1.4

 970          * @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()

 971          */
 972  		public function SetLeftMargin($margin) {
 973              //Set left margin

 974              $this->lMargin=$margin;
 975              if(($this->page>0) and ($this->x<$margin)) {
 976                  $this->x=$margin;
 977              }
 978          }
 979  
 980          /**

 981          * Defines the top margin. The method can be called before creating the first page.

 982          * @param float $margin The margin.

 983          * @since 1.5

 984          * @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()

 985          */
 986  		public function SetTopMargin($margin) {
 987              //Set top margin

 988              $this->tMargin=$margin;
 989          }
 990  
 991          /**

 992          * Defines the right margin. The method can be called before creating the first page.

 993          * @param float $margin The margin.

 994          * @since 1.5

 995          * @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()

 996          */
 997  		public function SetRightMargin($margin) {
 998              //Set right margin

 999              $this->rMargin=$margin;
1000          }
1001  
1002          /**

1003          * Enables or disables the automatic page breaking mode. When enabling, the second parameter is the distance from the bottom of the page that defines the triggering limit. By default, the mode is on and the margin is 2 cm.

1004          * @param boolean $auto Boolean indicating if mode should be on or off.

1005          * @param float $margin Distance from the bottom of the page.

1006          * @since 1.0

1007          * @see Cell(), MultiCell(), AcceptPageBreak()

1008          */
1009  		public function SetAutoPageBreak($auto, $margin=0) {
1010              //Set auto page break mode and triggering margin

1011              $this->AutoPageBreak=$auto;
1012              $this->bMargin=$margin;
1013              $this->PageBreakTrigger=$this->h-$margin;
1014          }
1015  
1016          /**

1017          * Defines the way the document is to be displayed by the viewer. The zoom level can be set: pages can be displayed entirely on screen, occupy the full width of the window, use real size, be scaled by a specific zooming factor or use viewer default (configured in the Preferences menu of Acrobat). The page layout can be specified too: single at once, continuous display, two columns or viewer default. By default, documents use the full width mode with continuous display.

1018          * @param mixed $zoom The zoom to use. It can be one of the following string values or a number indicating the zooming factor to use. <ul><li>fullpage: displays the entire page on screen </li><li>fullwidth: uses maximum width of window</li><li>real: uses real size (equivalent to 100% zoom)</li><li>default: uses viewer default mode</li></ul>

1019          * @param string $layout The page layout. Possible values are:<ul><li>single: displays one page at once</li><li>continuous: displays pages continuously (default)</li><li>two: displays two pages on two columns</li><li>default: uses viewer default mode</li></ul>

1020          * @since 1.2

1021          */
1022  		public function SetDisplayMode($zoom, $layout='continuous') {
1023              //Set display mode in viewer

1024              if($zoom=='fullpage' or $zoom=='fullwidth' or $zoom=='real' or $zoom=='default' or !is_string($zoom)) {
1025                  $this->ZoomMode=$zoom;
1026              }
1027              else {
1028                  $this->Error('Incorrect zoom display mode: '.$zoom);
1029              }
1030              if($layout=='single' or $layout=='continuous' or $layout=='two' or $layout=='default') {
1031                  $this->LayoutMode=$layout;
1032              }
1033              else {
1034                  $this->Error('Incorrect layout display mode: '.$layout);
1035              }
1036          }
1037  
1038          /**

1039          * Activates or deactivates page compression. When activated, the internal representation of each page is compressed, which leads to a compression ratio of about 2 for the resulting document. Compression is on by default.

1040          * Note: the Zlib extension is required for this feature. If not present, compression will be turned off.

1041          * @param boolean $compress Boolean indicating if compression must be enabled.

1042          * @since 1.4

1043          */
1044  		public function SetCompression($compress) {
1045              //Set page compression

1046              if(function_exists('gzcompress')) {
1047                  $this->compress=$compress;
1048              }
1049              else {
1050                  $this->compress=false;
1051              }
1052          }
1053  
1054          /**

1055          * Defines the title of the document.

1056          * @param string $title The title.

1057          * @since 1.2

1058          * @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject()

1059          */
1060  		public function SetTitle($title) {
1061              //Title of document

1062              $this->title=$title;
1063          }
1064  
1065          /**

1066          * Defines the subject of the document.

1067          * @param string $subject The subject.

1068          * @since 1.2

1069          * @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle()

1070          */
1071  		public function SetSubject($subject) {
1072              //Subject of document

1073              $this->subject=$subject;
1074          }
1075  
1076          /**

1077          * Defines the author of the document.

1078          * @param string $author The name of the author.

1079          * @since 1.2

1080          * @see SetCreator(), SetKeywords(), SetSubject(), SetTitle()

1081          */
1082  		public function SetAuthor($author) {
1083              //Author of document

1084              $this->author=$author;
1085          }
1086  
1087          /**

1088          * Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'.

1089          * @param string $keywords The list of keywords.

1090          * @since 1.2

1091          * @see SetAuthor(), SetCreator(), SetSubject(), SetTitle()

1092          */
1093  		public function SetKeywords($keywords) {
1094              //Keywords of document

1095              $this->keywords=$keywords;
1096          }
1097  
1098          /**

1099          * Defines the creator of the document. This is typically the name of the application that generates the PDF.

1100          * @param string $creator The name of the creator.

1101          * @since 1.2

1102          * @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle()

1103          */
1104  		public function SetCreator($creator) {
1105              //Creator of document

1106              $this->creator=$creator;
1107          }
1108  
1109          /**

1110          * Defines an alias for the total number of pages. It will be substituted as the document is closed.<br />

1111          * <b>Example:</b><br />

1112          * <pre>

1113          * class PDF extends FPDF {

1114          *     public function Footer() {

1115          *         //Go to 1.5 cm from bottom

1116          *         $this->SetY(-15);

1117          *         //Select Arial italic 8

1118          *         $this->SetFont('Arial','I',8);

1119          *         //Print current and total page numbers

1120          *         $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');

1121          *     }

1122          * }

1123          * $pdf=new PDF();

1124          * $pdf->AliasNbPages();

1125          * </pre>

1126          * @param string $alias The alias. Default value: {nb}.

1127          * @since 1.4

1128          * @see PageNo(), Footer()

1129          */
1130  		public function AliasNbPages($alias='{nb}') {
1131              //Define an alias for total number of pages

1132              $this->AliasNbPages = $this->_escapetext($alias);
1133          }
1134  
1135          /**

1136          * This method is automatically called in case of fatal error; it simply outputs the message and halts the execution. An inherited class may override it to customize the error handling but should always halt the script, or the resulting document would probably be invalid.

1137          * 2004-06-11 :: Nicola Asuni : changed bold tag with strong

1138          * @param string $msg The error message

1139          * @since 1.0

1140          */
1141  		public function Error($msg) {
1142              //Fatal error

1143              die('<strong>FPDF error: </strong>'.$msg);
1144          }
1145  
1146          /**

1147          * This method begins the generation of the PDF document. It is not necessary to call it explicitly because AddPage() does it automatically.

1148          * Note: no page is created by this method

1149          * @since 1.0

1150          * @see AddPage(), Close()

1151          */
1152  		public function Open() {
1153              //Begin document

1154              $this->state=1;
1155          }
1156  
1157          /**

1158          * Terminates the PDF document. It is not necessary to call this method explicitly because Output() does it automatically. If the document contains no page, AddPage() is called to prevent from getting an invalid document.

1159          * @since 1.0

1160          * @see Open(), Output()

1161          */
1162  		public function Close() {
1163              //Terminate document

1164              if($this->state==3) {
1165                  return;
1166              }
1167              if($this->page==0) {
1168                  $this->AddPage();
1169              }
1170              //Page footer

1171              $this->InFooter=true;
1172              $this->Footer();
1173              $this->InFooter=false;
1174              //Close page

1175              $this->_endpage();
1176              //Close document

1177              $this->_enddoc();
1178          }
1179  
1180          /**

1181          * Adds a new page to the document. If a page is already present, the Footer() method is called first to output the footer. Then the page is added, the current position set to the top-left corner according to the left and top margins, and Header() is called to display the header.

1182          * The font which was set before calling is automatically restored. There is no need to call SetFont() again if you want to continue with the same font. The same is true for colors and line width.

1183          * The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards.

1184          * @param string $orientation Page orientation. Possible values are (case insensitive):<ul><li>P or Portrait</li><li>L or Landscape</li></ul> The default value is the one passed to the constructor.

1185          * @since 1.0

1186          * @see FPDF(), Header(), Footer(), SetMargins()

1187          */
1188  		public function AddPage($orientation='') {
1189              //Start a new page

1190              if($this->state==0) {
1191                  $this->Open();
1192              }
1193              $family=$this->FontFamily;
1194              $style=$this->FontStyle.($this->underline ? 'U' : '');
1195              $size=$this->FontSizePt;
1196              $lw=$this->LineWidth;
1197              $dc=$this->DrawColor;
1198              $fc=$this->FillColor;
1199              $tc=$this->TextColor;
1200              $cf=$this->ColorFlag;
1201              if($this->page>0) {
1202                  //Page footer

1203                  $this->InFooter=true;
1204                  $this->Footer();
1205                  $this->InFooter=false;
1206                  //Close page

1207                  $this->_endpage();
1208              }
1209              //Start new page

1210              $this->_beginpage($orientation);
1211              //Set line cap style to square

1212              $this->_out('2 J');
1213              //Set line width

1214              $this->LineWidth=$lw;
1215              $this->_out(sprintf('%.2f w',$lw*$this->k));
1216              //Set font

1217              if($family) {
1218                  $this->SetFont($family,$style,$size);
1219              }
1220              //Set colors

1221              $this->DrawColor=$dc;
1222              if($dc!='0 G') {
1223                  $this->_out($dc);
1224              }
1225              $this->FillColor=$fc;
1226              if($fc!='0 g') {
1227                  $this->_out($fc);
1228              }
1229              $this->TextColor=$tc;
1230              $this->ColorFlag=$cf;
1231              //Page header

1232              $this->Header();
1233              //Restore line width

1234              if($this->LineWidth!=$lw) {
1235                  $this->LineWidth=$lw;
1236                  $this->_out(sprintf('%.2f w',$lw*$this->k));
1237              }
1238              //Restore font

1239              if($family) {
1240                  $this->SetFont($family,$style,$size);
1241              }
1242              //Restore colors

1243              if($this->DrawColor!=$dc) {
1244                  $this->DrawColor=$dc;
1245                  $this->_out($dc);
1246              }
1247              if($this->FillColor!=$fc) {
1248                  $this->FillColor=$fc;
1249                  $this->_out($fc);
1250              }
1251              $this->TextColor=$tc;
1252              $this->ColorFlag=$cf;
1253          }
1254          
1255          
1256          
1257          /**

1258            * Set header data.

1259           * @param string $ln header image logo

1260           * @param string $lw header image logo width in mm

1261           * @param string $ht string to print as title on document header

1262           * @param string $hs string to print on document header

1263          */
1264  		public function setHeaderData($ln="", $lw=0, $ht="", $hs="") {
1265              $this->header_logo = $ln;
1266              $this->header_logo_width = $lw;
1267              $this->header_title = $ht;
1268              $this->header_string = $hs;
1269          }
1270          
1271          /**

1272            * Set header margin.

1273           * (minimum distance between header and top page margin)

1274           * @param int $hm distance in millimeters

1275          */
1276  		public function setHeaderMargin($hm=10) {
1277              $this->header_margin = $hm;
1278          }
1279          
1280          /**

1281            * Set footer margin.

1282           * (minimum distance between footer and bottom page margin)

1283           * @param int $fm distance in millimeters

1284          */
1285  		public function setFooterMargin($fm=10) {
1286              $this->footer_margin = $fm;
1287          }
1288          
1289          /**

1290            * This method is used to render the page header.

1291            * It is automatically called by AddPage() and could be overwritten in your own inherited class.

1292           */
1293  		public function Header() {
1294              if ($this->print_header) {
1295                  
1296                  if (!isset($this->original_lMargin)) {
1297                      $this->original_lMargin = $this->lMargin;
1298                  }
1299                  if (!isset($this->original_rMargin)) {
1300                      $this->original_rMargin = $this->rMargin;
1301                  }
1302                  
1303                  //set current position

1304                  $this->SetXY($this->original_lMargin, $this->header_margin);
1305                  
1306                  if (($this->header_logo) AND ($this->header_logo != K_BLANK_IMAGE)) {
1307                      $this->Image(K_PATH_IMAGES.$this->header_logo, $this->original_lMargin, $this->header_margin, $this->header_logo_width);
1308                  }
1309                  else {
1310                      $this->img_rb_y = $this->GetY();
1311                  }
1312                  
1313                  $cell_height = round((K_CELL_HEIGHT_RATIO * $this->header_font[2]) / $this->k, 2);
1314                  
1315                  $header_x = $this->original_lMargin + ($this->header_logo_width * 1.05); //set left margin for text data cell

1316                  
1317                  // header title

1318                  $this->SetFont($this->header_font[0], 'B', $this->header_font[2] + 1);
1319                  $this->SetX($header_x);
1320                  $this->Cell($this->header_width, $cell_height, $this->header_title, 0, 1, 'L'); 
1321                  
1322                  // header string

1323                  $this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]);
1324                  $this->SetX($header_x);
1325                  $this->MultiCell($this->header_width, $cell_height, $this->header_string, 0, 'L', 0);
1326                  
1327                  // print an ending header line

1328                  if (empty($this->header_width)) {
1329                      //set style for cell border

1330                      $this->SetLineWidth(0.3);
1331                      $this->SetDrawColor(0, 0, 0);
1332                      $this->SetY(1 + max($this->img_rb_y, $this->GetY()));
1333                      $this->SetX($this->original_lMargin);
1334                      $this->Cell(0, 0, '', 'T', 0, 'C'); 
1335                  }
1336                  
1337                  //restore position

1338                  $this->SetXY($this->original_lMargin, $this->tMargin);
1339              }
1340          }
1341          
1342          /**

1343            * This method is used to render the page footer. 

1344            * It is automatically called by AddPage() and could be overwritten in your own inherited class.

1345           */
1346  		public function Footer() {
1347              if ($this->print_footer) {
1348                  
1349                  if (!isset($this->original_lMargin)) {
1350                      $this->original_lMargin = $this->lMargin;
1351                  }
1352                  if (!isset($this->original_rMargin)) {
1353                      $this->original_rMargin = $this->rMargin;
1354                  }
1355                  
1356                  //set font

1357                  $this->SetFont($this->footer_font[0], $this->footer_font[1] , $this->footer_font[2]);
1358                  //set style for cell border

1359                  $line_width = 0.3;
1360                  $this->SetLineWidth($line_width);
1361                  $this->SetDrawColor(0, 0, 0);
1362                  
1363                  $footer_height = round((K_CELL_HEIGHT_RATIO * $this->footer_font[2]) / $this->k, 2); //footer height

1364                  //get footer y position

1365                  $footer_y = $this->h - $this->footer_margin - $footer_height;
1366                  //set current position

1367                  $this->SetXY($this->original_lMargin, $footer_y); 
1368                  
1369                  //print document barcode

1370                  if ($this->barcode) {
1371                      $this->Ln();
1372                      $barcode_width = round(($this->w - $this->original_lMargin - $this->original_rMargin)); //max width

1373                      $this->writeBarcode($this->original_lMargin, $footer_y + $line_width, $barcode_width, $footer_height - $line_width, "C128B", false, false, 2, $this->barcode);
1374                  }
1375                  
1376                  $this->SetXY($this->original_lMargin, $footer_y); 
1377                  
1378                  //Print page number

1379                  $this->Cell(0, $footer_height, $this->l['w_page']." ".$this->PageNo().' / {nb}', 'T', 0, 'R'); 
1380              }
1381          }
1382          
1383          /**

1384          * Returns the current page number.

1385          * @return int page number

1386          * @since 1.0

1387          * @see AliasNbPages()

1388          */
1389  		public function PageNo() {
1390              //Get current page number

1391              return $this->page;
1392          }
1393  
1394          /**

1395          * Defines the color used for all drawing operations (lines, rectangles and cell borders). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

1396          * @param int $r If g et b are given, red component; if not, indicates the gray level. Value between 0 and 255

1397          * @param int $g Green component (between 0 and 255)

1398          * @param int $b Blue component (between 0 and 255)

1399          * @since 1.3

1400          * @see SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell()

1401          */
1402  		public function SetDrawColor($r, $g=-1, $b=-1) {
1403              //Set color for all stroking operations

1404              if(($r==0 and $g==0 and $b==0) or $g==-1) {
1405                  $this->DrawColor=sprintf('%.3f G',$r/255);
1406              }
1407              else {
1408                  $this->DrawColor=sprintf('%.3f %.3f %.3f RG',$r/255,$g/255,$b/255);
1409              }
1410              if($this->page>0) {
1411                  $this->_out($this->DrawColor);
1412              }
1413          }
1414  
1415          /**

1416          * Defines the color used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

1417          * @param int $r If g et b are given, red component; if not, indicates the gray level. Value between 0 and 255

1418          * @param int $g Green component (between 0 and 255)

1419          * @param int $b Blue component (between 0 and 255)

1420          * @since 1.3

1421          * @see SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell()

1422          */
1423  		public function SetFillColor($r, $g=-1, $b=-1) {
1424              //Set color for all filling operations

1425              if(($r==0 and $g==0 and $b==0) or $g==-1) {
1426                  $this->FillColor=sprintf('%.3f g',$r/255);
1427              }
1428              else {
1429                  $this->FillColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255);
1430              }
1431              $this->ColorFlag=($this->FillColor!=$this->TextColor);
1432              if($this->page>0) {
1433                  $this->_out($this->FillColor);
1434              }
1435          }
1436  
1437          /**

1438          * Defines the color used for text. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

1439          * @param int $r If g et b are given, red component; if not, indicates the gray level. Value between 0 and 255

1440          * @param int $g Green component (between 0 and 255)

1441          * @param int $b Blue component (between 0 and 255)

1442          * @since 1.3

1443          * @see SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell()

1444          */
1445  		public function SetTextColor($r, $g=-1, $b=-1) {
1446              //Set color for text

1447              if(($r==0 and $g==0 and $b==0) or $g==-1) {
1448                  $this->TextColor=sprintf('%.3f g',$r/255);
1449              }
1450              else {
1451                  $this->TextColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255);
1452              }
1453              $this->ColorFlag=($this->FillColor!=$this->TextColor);
1454          }
1455  
1456          /**

1457          * Returns the length of a string in user unit. A font must be selected.<br>

1458          * Support UTF-8 Unicode [Nicola Asuni, 2005-01-02]

1459          * @param string $s The string whose length is to be computed

1460          * @return int

1461          * @since 1.2

1462          */
1463  		public function GetStringWidth($s) {
1464              //Get width of a string in the current font

1465              $s = (string)$s;
1466              $cw = &$this->CurrentFont['cw'];
1467              $w = 0;
1468              if($this->isunicode) {
1469                  $unicode = $this->UTF8StringToArray($s);
1470                  foreach($unicode as $char) {
1471                      if (isset($cw[$char])) {
1472                          $w+=$cw[$char];
1473                      } elseif(isset($cw[ord($char)])) {
1474                          $w+=$cw[ord($char)];
1475                      } elseif(isset($cw[chr($char)])) {
1476                          $w+=$cw[chr($char)];
1477                      } elseif(isset($this->CurrentFont['desc']['MissingWidth'])) {
1478                          $w += $this->CurrentFont['desc']['MissingWidth']; // set default size

1479                      } else {
1480                          $w += 500;
1481                      }
1482                  }
1483              } else {
1484                  $l = strlen($s);
1485                  for($i=0; $i<$l; $i++) {
1486                      if (isset($cw[$s{$i}])) {
1487                          $w += $cw[$s{$i}];
1488                      } else if (isset($cw[ord($s{$i})])) {
1489                          $w += $cw[ord($s{$i})];
1490                      }
1491                  }
1492              }
1493              return ($w * $this->FontSize / 1000);
1494          }
1495  
1496          /**

1497          * Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page.

1498          * @param float $width The width.

1499          * @since 1.0

1500          * @see Line(), Rect(), Cell(), MultiCell()

1501          */
1502  		public function SetLineWidth($width) {
1503              //Set line width

1504              $this->LineWidth=$width;
1505              if($this->page>0) {
1506                  $this->_out(sprintf('%.2f w',$width*$this->k));
1507              }
1508          }
1509  
1510          /**

1511          * Draws a line between two points.

1512          * @param float $x1 Abscissa of first point

1513          * @param float $y1 Ordinate of first point

1514          * @param float $x2 Abscissa of second point

1515          * @param float $y2 Ordinate of second point

1516          * @since 1.0

1517          * @see SetLineWidth(), SetDrawColor()

1518          */
1519  		public function Line($x1, $y1, $x2, $y2) {
1520              //Draw a line

1521              $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));
1522          }
1523  
1524          /**

1525          * Outputs a rectangle. It can be drawn (border only), filled (with no border) or both.

1526          * @param float $x Abscissa of upper-left corner

1527          * @param float $y Ordinate of upper-left corner

1528          * @param float $w Width

1529          * @param float $h Height

1530          * @param string $style Style of rendering. Possible values are:<ul><li>D or empty string: draw (default)</li><li>F: fill</li><li>DF or FD: draw and fill</li></ul>

1531          * @since 1.0

1532          * @see SetLineWidth(), SetDrawColor(), SetFillColor()

1533          */
1534  		public function Rect($x, $y, $w, $h, $style='') {
1535              //Draw a rectangle

1536              if($style=='F') {
1537                  $op='f';
1538              }
1539              elseif($style=='FD' or $style=='DF') {
1540                  $op='B';
1541              }
1542              else {
1543                  $op='S';
1544              }
1545              $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));
1546          }
1547  
1548          /**

1549          * Imports a TrueType or Type1 font and makes it available. It is necessary to generate a font definition file first with the makefont.php utility. The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by FPDF_FONTPATH if the constant is defined. If it could not be found, the error "Could not include font definition file" is generated.

1550          * Support UTF-8 Unicode [Nicola Asuni, 2005-01-02].

1551          * <b>Example</b>:<br />

1552          * <pre>

1553          * $pdf->AddFont('Comic','I');

1554          * // is equivalent to:

1555          * $pdf->AddFont('Comic','I','comici.php');

1556          * </pre>

1557          * @param string $family Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font.

1558          * @param string $style Font style. Possible values are (case insensitive):<ul><li>empty string: regular (default)</li><li>B: bold</li><li>I: italic</li><li>BI or IB: bold italic</li></ul>

1559          * @param string $file The font definition file. By default, the name is built from the family and style, in lower case with no space.

1560          * @since 1.5

1561          * @see SetFont()

1562          */
1563  		public function AddFont($family, $style='', $file='') {
1564              if(empty($family)) {
1565                  return;
1566              }
1567  
1568              //Add a TrueType or Type1 font

1569              $family = strtolower($family);
1570              if((!$this->isunicode) AND ($family == 'arial')) {
1571                  $family = 'helvetica';
1572              }
1573  
1574              $style=strtoupper($style);
1575              $style=str_replace('U','',$style);
1576              if($style == 'IB') {
1577                  $style = 'BI';
1578              }
1579  
1580              $fontkey = $family.$style;
1581              // check if the font has been already added

1582              if(isset($this->fonts[$fontkey])) {
1583                  return;
1584              }
1585  
1586              if($file=='') {
1587                  $file = str_replace(' ', '', $family).strtolower($style).'.php';
1588              }
1589              if(!file_exists($this->_getfontpath().$file)) {
1590                  // try to load the basic file without styles

1591                  $file = str_replace(' ', '', $family).'.php';
1592              }
1593  
1594              include($this->_getfontpath().$file);
1595  
1596              if(!isset($name) AND !isset($fpdf_charwidths)) {
1597                  $this->Error('Could not include font definition file');
1598              }
1599  
1600              $i = count($this->fonts)+1;
1601  
1602              if($this->isunicode) {
1603                  $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'enc'=>$enc, 'file'=>$file, 'ctg'=>$ctg);
1604                  $fpdf_charwidths[$fontkey] = $cw;
1605              } else {
1606                  $this->fonts[$fontkey]=array('i'=>$i, 'type'=>'core', 'name'=>$this->CoreFonts[$fontkey], 'up'=>-100, 'ut'=>50, 'cw'=>$fpdf_charwidths[$fontkey]);
1607              }
1608  
1609              if(isset($diff) AND (!empty($diff))) {
1610                  //Search existing encodings

1611                  $d=0;
1612                  $nb=count($this->diffs);
1613                  for($i=1;$i<=$nb;$i++) {
1614                      if($this->diffs[$i]==$diff) {
1615                          $d=$i;
1616                          break;
1617                      }
1618                  }
1619                  if($d==0) {
1620                      $d=$nb+1;
1621                      $this->diffs[$d]=$diff;
1622                  }
1623                  $this->fonts[$fontkey]['diff']=$d;
1624              }
1625              if(!empty($file)) {
1626                  if((strcasecmp($type,"TrueType") == 0) OR (strcasecmp($type,"TrueTypeUnicode") == 0)) {
1627                      $this->FontFiles[$file]=array('length1'=>$originalsize);
1628                  }
1629                  else {
1630                      $this->FontFiles[$file]=array('length1'=>$size1,'length2'=>$size2);
1631                  }
1632              }
1633          }
1634  
1635          /**

1636          * Sets the font used to print character strings. It is mandatory to call this method at least once before printing text or the resulting document would not be valid.

1637          * The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe).

1638          * The method can be called before the first page is created and the font is retained from page to page.

1639          If you just wish to change the current font size, it is simpler to call SetFontSize().

1640          * Note: for the standard fonts, the font metric files must be accessible. There are three possibilities for this:<ul><li>They are in the current directory (the one where the running script lies)</li><li>They are in one of the directories defined by the include_path parameter</li><li>They are in the directory defined by the FPDF_FONTPATH constant</li></ul><br />

1641          * Example for the last case (note the trailing slash):<br />

1642          * <pre>

1643          * define('FPDF_FONTPATH','/home/www/font/');

1644          * require('fpdf.php');

1645          *

1646          * //Times regular 12

1647          * $pdf->SetFont('Times');

1648          * //Arial bold 14

1649          * $pdf->SetFont('Arial','B',14);

1650          * //Removes bold

1651          * $pdf->SetFont('');

1652          * //Times bold, italic and underlined 14

1653          * $pdf->SetFont('Times','BIU');

1654          * </pre><br />

1655          * If the file corresponding to the requested font is not found, the error "Could not include font metric file" is generated.

1656          * @param string $family Family font. It can be either a name defined by AddFont() or one of the standard families (case insensitive):<ul><li>Courier (fixed-width)</li><li>Helvetica or Arial (synonymous; sans serif)</li><li>Times (serif)</li><li>Symbol (symbolic)</li><li>ZapfDingbats (symbolic)</li></ul>It is also possible to pass an empty string. In that case, the current family is retained.

1657          * @param string $style Font style. Possible values are (case insensitive):<ul><li>empty string: regular</li><li>B: bold</li><li>I: italic</li><li>U: underline</li></ul>or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats

1658          * @param float $size Font size in points. The default value is the current size. If no size has been specified since the beginning of the document, the value taken is 12

1659          * @since 1.0

1660          * @see AddFont(), SetFontSize(), Cell(), MultiCell(), Write()

1661          */
1662  		public function SetFont($family, $style='', $size=0) {
1663  
1664              //Select a font; size given in points

1665              global $fpdf_charwidths;
1666  
1667              $family=strtolower($family);
1668              if($family=='') {
1669                  $family=$this->FontFamily;
1670              }
1671              if((!$this->isunicode) AND ($family == 'arial')) {
1672                  $family = 'helvetica';
1673              }
1674              elseif(($family=="symbol") OR ($family=="zapfdingbats")) {
1675                  $style='';
1676              }
1677              $style=strtoupper($style);
1678  
1679              if(strpos($style,'U')!==false) {
1680                  $this->underline=true;
1681                  $style=str_replace('U','',$style);
1682              }
1683              else {
1684                  $this->underline=false;
1685              }
1686              if($style=='IB') {
1687                  $style='BI';
1688              }
1689              if($size==0) {
1690                  $size=$this->FontSizePt;
1691              }
1692  
1693              // try to add font (if not already added)

1694              if($this->isunicode) {
1695                  $this->AddFont($family, $style);
1696              }
1697              
1698              //Test if font is already selected

1699              if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size)) {
1700                  return;
1701              }
1702              
1703              $fontkey = $family.$style;
1704              //if(!isset($this->fonts[$fontkey]) AND isset($this->fonts[$family])) {

1705              //    $style='';

1706              //}

1707  
1708              //Test if used for the first time

1709              if(!isset($this->fonts[$fontkey])) {
1710                  //Check if one of the standard fonts

1711                  if(isset($this->CoreFonts[$fontkey])) {
1712                      if(!isset($fpdf_charwidths[$fontkey])) {
1713                          //Load metric file

1714                          $file = $family;
1715                          if(($family!='symbol') AND ($family!='zapfdingbats')) {
1716                              $file .= strtolower($style);
1717                          }
1718                          if(!file_exists($this->_getfontpath().$file.'.php')) {
1719                              // try to load the basic file without styles

1720                              $file = $family;
1721                              $fontkey = $family;
1722                          }
1723                          include($this->_getfontpath().$file.'.php');
1724                          if (($this->isunicode AND !isset($ctg)) OR ((!$this->isunicode) AND (!isset($fpdf_charwidths[$fontkey]))) ) {
1725                              $this->Error("Could not include font metric file [".$fontkey."]: ".$this->_getfontpath().$file.".php");
1726                          }
1727                      }
1728                      $i = count($this->fonts) + 1;
1729  
1730                      if($this->isunicode) {
1731                          $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'enc'=>$enc, 'file'=>$file, 'ctg'=>$ctg);
1732                          $fpdf_charwidths[$fontkey] = $cw;
1733                      } else {
1734                          $this->fonts[$fontkey]=array('i'=>$i, 'type'=>'core', 'name'=>$this->CoreFonts[$fontkey], 'up'=>-100, 'ut'=>50, 'cw'=>$fpdf_charwidths[$fontkey]);
1735                      }
1736                  }
1737                  else {
1738                      $this->Error('Undefined font: '.$family.' '.$style);
1739                  }
1740              }
1741              //Select it

1742              $this->FontFamily = $family;
1743              $this->FontStyle = $style;
1744              $this->FontSizePt = $size;
1745              $this->FontSize = $size / $this->k;
1746              $this->CurrentFont = &$this->fonts[$fontkey];
1747              if($this->page>0) {
1748                  $this->_out(sprintf('BT /F%d %.2f Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
1749              }
1750          }
1751  
1752          /**

1753          * Defines the size of the current font.

1754          * @param float $size The size (in points)

1755          * @since 1.0

1756          * @see SetFont()

1757          */
1758  		public function SetFontSize($size) {
1759              //Set font size in points

1760              if($this->FontSizePt==$size) {
1761                  return;
1762              }
1763              $this->FontSizePt = $size;
1764              $this->FontSize = $size / $this->k;
1765              if($this->page > 0) {
1766                  $this->_out(sprintf('BT /F%d %.2f Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
1767              }
1768          }
1769  
1770          /**

1771          * Creates a new internal link and returns its identifier. An internal link is a clickable area which directs to another place within the document.<br />

1772          * The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is defined with SetLink().

1773          * @since 1.5

1774          * @see Cell(), Write(), Image(), Link(), SetLink()

1775          */
1776  		public function AddLink() {
1777              //Create a new internal link

1778              $n=count($this->links)+1;
1779              $this->links[$n]=array(0,0);
1780              return $n;
1781          }
1782  
1783          /**

1784          * Defines the page and position a link points to

1785          * @param int $link The link identifier returned by AddLink()

1786          * @param float $y Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page)

1787          * @param int $page Number of target page; -1 indicates the current page. This is the default value

1788          * @since 1.5

1789          * @see AddLink()

1790          */
1791  		public function SetLink($link, $y=0, $page=-1) {
1792              //Set destination of internal link

1793              if($y==-1) {
1794                  $y=$this->y;
1795              }
1796              if($page==-1) {
1797                  $page=$this->page;
1798              }
1799              $this->links[$link]=array($page,$y);
1800          }
1801  
1802          /**

1803          * Puts a link on a rectangular area of the page. Text or image links are generally put via Cell(), Write() or Image(), but this method can be useful for instance to define a clickable area inside an image.

1804          * @param float $x Abscissa of the upper-left corner of the rectangle

1805          * @param float $y Ordinate of the upper-left corner of the rectangle

1806          * @param float $w Width of the rectangle

1807          * @param float $h Height of the rectangle

1808          * @param mixed $link URL or identifier returned by AddLink()

1809          * @since 1.5

1810          * @see AddLink(), Cell(), Write(), Image()

1811          */
1812  		public function Link($x, $y, $w, $h, $link) {
1813              //Put a link on the page

1814              $this->PageLinks[$this->page][] = array($x * $this->k, $this->hPt - $y * $this->k, $w * $this->k, $h*$this->k, $link);
1815          }
1816  
1817          /**

1818          * Prints a character string. The origin is on the left of the first charcter, on the baseline. This method allows to place a string precisely on the page, but it is usually easier to use Cell(), MultiCell() or Write() which are the standard methods to print text.

1819          * @param float $x Abscissa of the origin

1820          * @param float $y Ordinate of the origin

1821          * @param string $txt String to print

1822          * @since 1.0

1823          * @see SetFont(), SetTextColor(), Cell(), MultiCell(), Write()

1824          */
1825  		public function Text($x, $y, $txt) {
1826              //Output a string

1827              $s=sprintf('BT %.2f %.2f Td (%s) Tj ET', $x * $this->k, ($this->h-$y) * $this->k, $this->_escapetext($txt));
1828              if($this->underline AND ($txt!='')) {
1829                  $s .= ' '.$this->_dounderline($x,$y,$txt);
1830              }
1831              if($this->ColorFlag) {
1832                  $s='q '.$this->TextColor.' '.$s.' Q';
1833              }
1834              $this->_out($s);
1835          }
1836  
1837          /**

1838          * Whenever a page break condition is met, the method is called, and the break is issued or not depending on the returned value. The default implementation returns a value according to the mode selected by SetAutoPageBreak().<br />

1839          * This method is called automatically and should not be called directly by the application.<br />

1840          * <b>Example:</b><br />

1841          * The method is overriden in an inherited class in order to obtain a 3 column layout:<br />

1842          * <pre>

1843          * class PDF extends FPDF {

1844          *     var $col=0;

1845          *

1846          *     public function SetCol($col) {

1847          *         //Move position to a column

1848          *         $this->col=$col;

1849          *         $x=10+$col*65;

1850          *         $this->SetLeftMargin($x);

1851          *         $this->SetX($x);

1852          *     }

1853          *

1854          *     public function AcceptPageBreak() {

1855          *         if($this->col<2) {

1856          *             //Go to next column

1857          *             $this->SetCol($this->col+1);

1858          *             $this->SetY(10);

1859          *             return false;

1860          *         }

1861          *         else {

1862          *             //Go back to first column and issue page break

1863          *             $this->SetCol(0);

1864          *             return true;

1865          *         }

1866          *     }

1867          * }

1868          *

1869          * $pdf=new PDF();

1870          * $pdf->Open();

1871          * $pdf->AddPage();

1872          * $pdf->SetFont('Arial','',12);

1873          * for($i=1;$i<=300;$i++) {

1874          *     $pdf->Cell(0,5,"Line $i",0,1);

1875          * }

1876          * $pdf->Output();

1877          * </pre>

1878          * @return boolean

1879          * @since 1.4

1880          * @see SetAutoPageBreak()

1881          */
1882  		public function AcceptPageBreak() {
1883              //Accept automatic page break or not

1884              return $this->AutoPageBreak;
1885          }
1886  
1887          /**

1888          * Prints a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.<br />

1889          * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.

1890          * @param float $w Cell width. If 0, the cell extends up to the right margin.

1891          * @param float $h Cell height. Default value: 0.

1892          * @param string $txt String to print. Default value: empty string.

1893          * @param mixed $border Indicates if borders must be drawn around the cell. The value can be either a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul>or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul>

1894          * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>

1895          Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.

1896          * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li></ul>

1897          * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.

1898          * @param mixed $link URL or identifier returned by AddLink().

1899          * @since 1.0

1900          * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak()

1901          */
1902  		public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=0, $link='') {
1903              //Output a cell

1904              $k=$this->k;
1905              if(($this->y + $h) > $this->PageBreakTrigger AND empty($this->InFooter) AND $this->AcceptPageBreak()) {
1906                  //Automatic page break

1907                  $x = $this->x;
1908                  $ws = $this->ws;
1909                  if($ws > 0) {
1910                      $this->ws = 0;
1911                      $this->_out('0 Tw');
1912                  }
1913                  $this->AddPage($this->CurOrientation);
1914                  $this->x = $x;
1915                  if($ws > 0) {
1916                      $this->ws = $ws;
1917                      $this->_out(sprintf('%.3f Tw',$ws * $k));
1918                  }
1919              }
1920              if($w == 0) {
1921                  $w = $this->w - $this->rMargin - $this->x;
1922              }
1923              $s = '';
1924              if(($fill == 1) OR ($border == 1)) {
1925                  if($fill == 1) {
1926                      $op = ($border == 1) ? 'B' : 'f';
1927                  }
1928                  else {
1929                      $op = 'S';
1930                  }
1931                  $s = sprintf('%.2f %.2f %.2f %.2f re %s ', $this->x * $k, ($this->h - $this->y) * $k, $w * $k, -$h * $k, $op);
1932              }
1933              if(is_string($border)) {
1934                  $x=$this->x;
1935                  $y=$this->y;
1936                  if(strpos($border,'L')!==false) {
1937                      $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k);
1938                  }
1939                  if(strpos($border,'T')!==false) {
1940                      $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k);
1941                  }
1942                  if(strpos($border,'R')!==false) {
1943                      $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
1944                  }
1945                  if(strpos($border,'B')!==false) {
1946                      $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
1947                  }
1948              }
1949              if($txt != '') {
1950                  $width = $this->GetStringWidth($txt);
1951                  if($align == 'R') {
1952                      $dx = $w - $this->cMargin - $width;
1953                  }
1954                  elseif($align=='C') {
1955                      $dx = ($w - $width)/2;
1956                  }
1957                  else {
1958                      $dx = $this->cMargin;
1959                  }
1960                  if($this->ColorFlag) {
1961                      $s .= 'q '.$this->TextColor.' ';
1962                  }
1963                  $txt2 = $this->_escapetext($txt);
1964                  $s.=sprintf('BT %.2f %.2f Td (%s) Tj ET', ($this->x + $dx) * $k, ($this->h - ($this->y + 0.5 * $h + 0.3 * $this->FontSize)) * $k, $txt2);
1965                  if($this->underline) {
1966                      $s.=' '.$this->_dounderline($this->x + $dx, $this->y + 0.5 * $h + 0.3 * $this->FontSize, $txt);
1967                  }
1968                  if($this->ColorFlag) {
1969                      $s.=' Q';
1970                  }
1971                  if($link) {
1972                      $this->Link($this->x + $dx, $this->y + 0.5 * $h - 0.5 * $this->FontSize, $width, $this->FontSize, $link);
1973                  }
1974              }
1975              if($s) {
1976                  $this->_out($s);
1977              }
1978              $this->lasth = $h;
1979              if($ln>0) {
1980                  //Go to next line

1981                  $this->y += $h;
1982                  if($ln == 1) {
1983                      $this->x = $this->lMargin;
1984                  }
1985              }
1986              else {
1987                  $this->x += $w;
1988              }
1989          }
1990  
1991          /**

1992          * This method allows printing text with line breaks. They can be automatic (as soon as the text reaches the right border of the cell) or explicit (via the \n character). As many cells as necessary are output, one below the other.<br />

1993          * Text can be aligned, centered or justified. The cell block can be framed and the background painted.

1994          * @param float $w Width of cells. If 0, they extend up to the right margin of the page.

1995          * @param float $h Height of cells.

1996          * @param string $txt String to print

1997          * @param mixed $border Indicates if borders must be drawn around the cell block. The value can be either a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul>or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul>

1998          * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>

1999          Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.

2000          * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align</li><li>C: center</li><li>R: right align</li><li>J: justification (default value)</li></ul>

2001          * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.

2002          * @since 1.3

2003          * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), Cell(), Write(), SetAutoPageBreak()

2004          */
2005  		public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=0) {
2006              //Output text with automatic or explicit line breaks

2007              $cw = &$this->CurrentFont['cw'];
2008  
2009              if($w == 0) {
2010                  $w = $this->w - $this->rMargin - $this->x;
2011              }
2012  
2013              $wmax = ($w - 2 * $this->cMargin);
2014  
2015              $s = str_replace("\r", '', $txt); // remove carriage returns

2016              $nb = strlen($s);
2017  
2018              $b=0;
2019              if($border) {
2020                  if($border==1) {
2021                      $border='LTRB';
2022                      $b='LRT';
2023                      $b2='LR';
2024                  }
2025                  else {
2026                      $b2='';
2027                      if(strpos($border,'L')!==false) {
2028                          $b2.='L';
2029                      }
2030                      if(strpos($border,'R')!==false) {
2031                          $b2.='R';
2032                      }
2033                      $b=(strpos($border,'T')!==false) ? $b2.'T' : $b2;
2034                  }
2035              }
2036              $sep=-1;
2037              $i=0;
2038              $j=0;
2039              $l=0;
2040              $ns=0;
2041              $nl=1;
2042              while($i<$nb) {
2043                  //Get next character

2044                  $c = $s{$i};
2045                  if(preg_match("/[\n]/u", $c)) {
2046                      //Explicit line break

2047                      if($this->ws > 0) {
2048                          $this->ws = 0;
2049                          $this->_out('0 Tw');
2050                      }
2051                      $this->Cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
2052                      $i++;
2053                      $sep=-1;
2054                      $j=$i;
2055                      $l=0;
2056                      $ns=0;
2057                      $nl++;
2058                      if($border and $nl==2) {
2059                          $b = $b2;
2060                      }
2061                      continue;
2062                  }
2063                  if(preg_match("/[ ]/u", $c)) {
2064                      $sep = $i;
2065                      $ls = $l;
2066                      $ns++;
2067                  }
2068  
2069                  $l = $this->GetStringWidth(substr($s, $j, $i-$j));
2070  
2071                  if($l > $wmax) {
2072                      //Automatic line break

2073                      if($sep == -1) {
2074                          if($i == $j) {
2075                              $i++;
2076                          }
2077                          if($this->ws > 0) {
2078                              $this->ws = 0;
2079                              $this->_out('0 Tw');
2080                          }
2081                          $this->Cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
2082                      }
2083                      else {
2084                          if($align=='J') {
2085                              $this->ws = ($ns>1) ? ($wmax-$ls)/($ns-1) : 0;
2086                              $this->_out(sprintf('%.3f Tw', $this->ws * $this->k));
2087                          }
2088                          $this->Cell($w, $h, substr($s, $j, $sep-$j), $b, 2, $align, $fill);
2089                          $i = $sep + 1;
2090                      }
2091                      $sep=-1;
2092                      $j=$i;
2093                      $l=0;
2094                      $ns=0;
2095                      $nl++;
2096                      if($border AND ($nl==2)) {
2097                          $b=$b2;
2098                      }
2099                  }
2100                  else {
2101                      $i++;
2102                  }
2103              }
2104              //Last chunk

2105              if($this->ws>0) {
2106                  $this->ws=0;
2107                  $this->_out('0 Tw');
2108              }
2109              if($border and is_int(strpos($border,'B'))) {
2110                  $b.='B';
2111              }
2112              $this->Cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
2113              $this->x=$this->lMargin;
2114          }
2115  
2116          /**

2117          * This method prints text from the current position. When the right margin is reached (or the \n character is met) a line break occurs and text continues from the left margin. Upon method exit, the current position is left just at the end of the text. It is possible to put a link on the text.<br />

2118          * <b>Example:</b><br />

2119          * <pre>

2120          * //Begin with regular font

2121          * $pdf->SetFont('Arial','',14);

2122          * $pdf->Write(5,'Visit ');

2123          * //Then put a blue underlined link

2124          * $pdf->SetTextColor(0,0,255);

2125          * $pdf->SetFont('','U');

2126          * $pdf->Write(5,'www.fpdf.org','http://www.fpdf.org');

2127          * </pre>

2128          * @param float $h Line height

2129          * @param string $txt String to print

2130          * @param mixed $link URL or identifier returned by AddLink()

2131          * @since 1.5

2132          * @see SetFont(), SetTextColor(), AddLink(), MultiCell(), SetAutoPageBreak()

2133          */
2134  		public function Write($h, $txt, $link='') {
2135  
2136              //Output text in flowing mode

2137              $cw = &$this->CurrentFont['cw'];
2138              $w = $this->w - $this->rMargin - $this->x;
2139              $wmax = ($w - 2 * $this->cMargin);
2140  
2141              $s = str_replace("\r", '', $txt);
2142              $nb = strlen($s);
2143  
2144              // handle single space character

2145              if(($nb==1) AND preg_match("/[ ]/u", $s)) {
2146                  $this->x += $this->GetStringWidth($s);
2147                  return;
2148              }
2149  
2150              $sep=-1;
2151              $i=0;
2152              $j=0;
2153              $l=0;
2154              $nl=1;
2155              while($i<$nb) {
2156                  //Get next character

2157                  $c=$s{$i};
2158                  if(preg_match("/[\n]/u", $c)) {
2159                      //Explicit line break

2160                      $this->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, '', 0, $link);
2161                      $i++;
2162                      $sep = -1;
2163                      $j = $i;
2164                      $l = 0;
2165                      if($nl == 1) {
2166                          $this->x = $this->lMargin;
2167                          $w = $this->w - $this->rMargin - $this->x;
2168                          $wmax = ($w - 2 * $this->cMargin);
2169                      }
2170                      $nl++;
2171                      continue;
2172                  }
2173                  if(preg_match("/[ ]/u", $c)) {
2174                      $sep= $i;
2175                  }
2176  
2177                  $l = $this->GetStringWidth(substr($s, $j, $i-$j));
2178  
2179                  if($l > $wmax) {
2180                      //Automatic line break

2181                      if($sep == -1) {
2182                          if($this->x > $this->lMargin) {
2183                              //Move to next line

2184                              $this->x = $this->lMargin;
2185                              $this->y += $h;
2186                              $w=$this->w - $this->rMargin - $this->x;
2187                              $wmax=($w - 2 * $this->cMargin);
2188                              $i++;
2189                              $nl++;
2190                              continue;
2191                          }
2192                          if($i==$j) {
2193                              $i++;
2194                          }
2195                          $this->Cell($w, $h, substr($s, $j, $i-$j), 0, 2, '', 0, $link);
2196                      }
2197                      else {
2198                          $this->Cell($w, $h, substr($s, $j, $sep-$j), 0, 2, '', 0, $link);
2199                          $i=$sep+1;
2200                      }
2201                      $sep = -1;
2202                      $j = $i;
2203                      $l = 0;
2204                      if($nl==1) {
2205                          $this->x = $this->lMargin;
2206                          $w = $this->w - $this->rMargin - $this->x;
2207                          $wmax = ($w - 2 * $this->cMargin);
2208                      }
2209                      $nl++;
2210                  }
2211                  else {
2212                      $i++;
2213                  }
2214              }
2215              //Last chunk

2216              if($i!=$j) {
2217                  $this->Cell($l / 1000 * $this->FontSize, $h, substr($s, $j), 0, 0, '', 0, $link);
2218              }
2219  
2220              $this->x += $this->GetStringWidth(substr($s, $j, $i-$j));
2221          }
2222  
2223          /**

2224          * Puts an image in the page. The upper-left corner must be given. The dimensions can be specified in different ways:<ul><li>explicit width and height (expressed in user unit)</li><li>one explicit dimension, the other being calculated automatically in order to keep the original proportions</li><li>no explicit dimension, in which case the image is put at 72 dpi</li></ul>

2225          * Supported formats are JPEG and PNG.

2226          * For JPEG, all flavors are allowed:<ul><li>gray scales</li><li>true colors (24 bits)</li><li>CMYK (32 bits)</li></ul>

2227          * For PNG, are allowed:<ul><li>gray scales on at most 8 bits (256 levels)</li><li>indexed colors</li><li>true colors (24 bits)</li></ul>

2228          * but are not supported:<ul><li>Interlacing</li><li>Alpha channel</li></ul>

2229          * If a transparent color is defined, it will be taken into account (but will be only interpreted by Acrobat 4 and above).<br />

2230          * The format can be specified explicitly or inferred from the file extension.<br />

2231          * It is possible to put a link on the image.<br />

2232          * Remark: if an image is used several times, only one copy will be embedded in the file.<br />

2233          * @param string $file Name of the file containing the image.

2234          * @param float $x Abscissa of the upper-left corner.

2235          * @param float $y Ordinate of the upper-left corner.

2236          * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated.

2237          * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated.

2238          * @param string $type Image format. Possible values are (case insensitive): JPG, JPEG, PNG. If not specified, the type is inferred from the file extension.

2239          * @param mixed $link URL or identifier returned by AddLink().

2240          * @since 1.1

2241          * @see AddLink()

2242          */
2243  		public function Image($file, $x, $y, $w=0, $h=0, $type='', $link='') {
2244              //Put an image on the page

2245              if(!isset($this->images[$file])) {
2246                  //First use of image, get info

2247                  if($type == '') {
2248                      $pos = strrpos($file,'.');
2249                      if(empty($pos)) {
2250                          $this->Error('Image file has no extension and no type was specified: '.$file);
2251                      }
2252                      $type = substr($file, $pos+1);
2253                  }
2254                  $type = strtolower($type);
2255                  $mqr = get_magic_quotes_runtime();
2256                  set_magic_quotes_runtime(0);
2257                  if($type == 'jpg' or $type == 'jpeg') {
2258                      $info=$this->_parsejpg($file);
2259                  }
2260                  elseif($type == 'png') {
2261                      $info=$this->_parsepng($file);
2262                  }
2263                  else {
2264                      //Allow for additional formats

2265                      $mtd='_parse'.$type;
2266                      if(!method_exists($this,$mtd)) {
2267                          $this->Error('Unsupported image type: '.$type);
2268                      }
2269                      $info=$this->$mtd($file);
2270                  }
2271                  set_magic_quotes_runtime($mqr);
2272                  $info['i']=count($this->images)+1;
2273                  $this->images[$file]=$info;
2274              }
2275              else {
2276                  $info=$this->images[$file];
2277              }
2278              //Automatic width and height calculation if needed

2279              if(($w == 0) and ($h == 0)) {
2280                  //Put image at 72 dpi

2281                  // 2004-06-14 :: Nicola Asuni, scale factor where added

2282                  $w = $info['w'] / ($this->imgscale * $this->k);
2283                  $h = $info['h'] / ($this->imgscale * $this->k);
2284              }
2285              if($w == 0) {
2286                  $w = $h * $info['w'] / $info['h'];
2287              }
2288              if($h == 0) {
2289                  $h = $w * $info['h'] / $info['w'];
2290              }
2291              $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']));
2292              if($link) {
2293                  $this->Link($x, $y, $w, $h, $link);
2294              }
2295  
2296              //2002-07-31 - Nicola Asuni

2297              // set right-bottom corner coordinates

2298              $this->img_rb_x = $x + $w;
2299              $this->img_rb_y = $y + $h;
2300          }
2301  
2302          /**

2303          * Performs a line break. The current abscissa goes back to the left margin and the ordinate increases by the amount passed in parameter.

2304          * @param float $h The height of the break. By default, the value equals the height of the last printed cell.

2305          * @since 1.0

2306          * @see Cell()

2307          */
2308          public function Ln($h='') {
2309              //Line feed; default value is last cell height

2310              $this->x=$this->lMargin;
2311              if(is_string($h)) {
2312                  $this->y+=$this->lasth;
2313              }
2314              else {
2315                  $this->y+=$h;
2316              }
2317          }
2318  
2319          /**

2320          * Returns the abscissa of the current position.

2321          * @return float

2322          * @since 1.2

2323          * @see SetX(), GetY(), SetY()

2324          */
2325  		public function GetX() {
2326              //Get x position

2327              return $this->x;
2328          }
2329  
2330          /**

2331          * Defines the abscissa of the current position. If the passed value is negative, it is relative to the right of the page.

2332          * @param float $x The value of the abscissa.

2333          * @since 1.2

2334          * @see GetX(), GetY(), SetY(), SetXY()

2335          */
2336  		public function SetX($x) {
2337              //Set x position

2338              if($x>=0) {
2339                  $this->x=$x;
2340              }
2341              else {
2342                  $this->x=$this->w+$x;
2343              }
2344          }
2345  
2346          /**

2347          * Returns the ordinate of the current position.

2348          * @return float

2349          * @since 1.0

2350          * @see SetY(), GetX(), SetX()

2351          */
2352  		public function GetY() {
2353              //Get y position

2354              return $this->y;
2355          }
2356  
2357          /**

2358          * Moves the current abscissa back to the left margin and sets the ordinate. If the passed value is negative, it is relative to the bottom of the page.

2359          * @param float $y The value of the ordinate.

2360          * @since 1.0

2361          * @see GetX(), GetY(), SetY(), SetXY()

2362          */
2363  		public function SetY($y) {
2364              //Set y position and reset x

2365              $this->x=$this->lMargin;
2366              if($y>=0) {
2367                  $this->y=$y;
2368              }
2369              else {
2370                  $this->y=$this->h+$y;
2371              }
2372          }
2373  
2374          /**

2375          * Defines the abscissa and ordinate of the current position. If the passed values are negative, they are relative respectively to the right and bottom of the page.

2376          * @param float $x The value of the abscissa

2377          * @param float $y The value of the ordinate

2378          * @since 1.2

2379          * @see SetX(), SetY()

2380          */
2381  		public function SetXY($x, $y) {
2382              //Set x and y positions

2383              $this->SetY($y);
2384              $this->SetX($x);
2385          }
2386  
2387          /**

2388          * Send the document to a given destination: string, local file or browser. In the last case, the plug-in may be used (if present) or a download ("Save as" dialog box) may be forced.<br />

2389          * The method first calls Close() if necessary to terminate the document.

2390          * @param string $name The name of the file. If not given, the document will be sent to the browser (destination I) with the name doc.pdf.

2391          * @param string $dest Destination where to send the document. It can take one of the following values:<ul><li>I: send the file inline to the browser. The plug-in is used if available. The name given by name is used when one selects the "Save as" option on the link generating the PDF.</li><li>D: send to the browser and force a file download with the name given by name.</li><li>F: save to a local file with the name given by name.</li><li>S: return the document as a string. name is ignored.</li></ul>If the parameter is not specified but a name is given, destination is F. If no parameter is specified at all, destination is I.<br />Note: for compatibility with previous versions, a boolean value is also accepted (false for F and true for D).

2392          * @since 1.0

2393          * @see Close()

2394          */
2395  		public function Output($name='',$dest='') {
2396              //Output PDF to some destination

2397              //Finish document if necessary

2398              if($this->state < 3) {
2399                  $this->Close();
2400              }
2401              //Normalize parameters

2402              if(is_bool($dest)) {
2403                  $dest=$dest ? 'D' : 'F';
2404              }
2405              $dest=strtoupper($dest);
2406              if($dest=='') {
2407                  if($name=='') {
2408                      $name='doc.pdf';
2409                      $dest='I';
2410                  } else {
2411                      $dest='F';
2412                  }
2413              }
2414              switch($dest) {
2415                  case 'I': {
2416                      //Send to standard output

2417                      if(ob_get_contents()) {
2418                          $this->Error('Some data has already been output, can\'t send PDF file');
2419                      }
2420                      if(php_sapi_name()!='cli') {
2421                          //We send to a browser

2422                          header('Content-Type: application/pdf');
2423                          if(headers_sent()) {
2424                              $this->Error('Some data has already been output to browser, can\'t send PDF file');
2425                          }
2426                          header('Content-Length: '.strlen($this->buffer));
2427                          header('Content-disposition: inline; filename="'.$name.'"');
2428                      }
2429                      echo $this->buffer;
2430                      break;
2431                  }
2432                  case 'D': {
2433                      //Download file

2434                      if(ob_get_contents()) {
2435                          $this->Error('Some data has already been output, can\'t send PDF file');
2436                      }
2437                      if(isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) {
2438                          header('Content-Type: application/force-download');
2439                      } else {
2440                          header('Content-Type: application/octet-stream');
2441                      }
2442                      if(headers_sent()) {
2443                          $this->Error('Some data has already been output to browser, can\'t send PDF file');
2444                      }
2445                      header('Content-Length: '.strlen($this->buffer));
2446                      header('Content-disposition: attachment; filename="'.$name.'"');
2447                      echo $this->buffer;
2448                      break;
2449                  }
2450                  case 'F': {
2451                      //Save to local file

2452                      $f=fopen($name,'wb');
2453                      if(!$f) {
2454                          $this->Error('Unable to create output file: '.$name);
2455                      }
2456                      fwrite($f,$this->buffer,strlen($this->buffer));
2457                      fclose($f);
2458                      break;
2459                  }
2460                  case 'S': {
2461                      //Return as a string

2462                      return $this->buffer;
2463                  }
2464                  default: {
2465                      $this->Error('Incorrect output destination: '.$dest);
2466                  }
2467              }
2468              return '';
2469          }
2470  
2471          // Protected methods

2472  
2473          /**

2474          * Check for locale-related bug

2475          * @access protected

2476          */
2477  		protected function _dochecks() {
2478              //Check for locale-related bug

2479              if(1.1==1) {
2480                  $this->Error('Don\'t alter the locale before including class file');
2481              }
2482              //Check for decimal separator

2483              if(sprintf('%.1f',1.0)!='1.0') {
2484                  setlocale(LC_NUMERIC,'C');
2485              }
2486          }
2487  
2488          /**

2489          * Return fonts path

2490          * @access protected

2491          */
2492  		protected function _getfontpath() {
2493              if(!defined('FPDF_FONTPATH') AND is_dir(dirname(__FILE__).'/font')) {
2494                  define('FPDF_FONTPATH', dirname(__FILE__).'/font/');
2495              }
2496              return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
2497          }
2498  
2499          /**

2500          * Start document

2501          * @access protected

2502          */
2503  		protected function _begindoc() {
2504              //Start document

2505              $this->state=1;
2506              $this->_out('%PDF-1.3');
2507          }
2508  
2509          /**

2510          * _putpages

2511          * @access protected

2512          */
2513  		protected function _putpages() {
2514              $nb = $this->page;
2515              if(!empty($this->AliasNbPages)) {
2516                  $nbstr = $this->UTF8ToUTF16BE($nb, false);
2517                  //Replace number of pages

2518                  for($n=1;$n<=$nb;$n++) {
2519                      $this->pages[$n]=str_replace($this->AliasNbPages, $nbstr, $this->pages[$n]);
2520                  }
2521              }
2522              if($this->DefOrientation=='P') {
2523                  $wPt=$this->fwPt;
2524                  $hPt=$this->fhPt;
2525              }
2526              else {
2527                  $wPt=$this->fhPt;
2528                  $hPt=$this->fwPt;
2529              }
2530              $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
2531              for($n=1;$n<=$nb;$n++) {
2532                  //Page

2533                  $this->_newobj();
2534                  $this->_out('<</Type /Page');
2535                  $this->_out('/Parent 1 0 R');
2536                  if(isset($this->OrientationChanges[$n])) {
2537                      $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$hPt,$wPt));
2538                  }
2539                  $this->_out('/Resources 2 0 R');
2540                  if(isset($this->PageLinks[$n])) {
2541                      //Links

2542                      $annots='/Annots [';
2543                      foreach($this->PageLinks[$n] as $pl) {
2544                          $rect=sprintf('%.2f %.2f %.2f %.2f',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
2545                          $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
2546                          if(is_string($pl[4])) {
2547                              $annots.='/A <</S /URI /URI ('.$this->_escape($pl[4]).')>>>>';
2548                          }
2549                          else {
2550                              $l=$this->links[$pl[4]];
2551                              $h=isset($this->OrientationChanges[$l[0]]) ? $wPt : $hPt;
2552                              $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>',1+2*$l[0],$h-$l[1]*$this->k);
2553                          }
2554                      }
2555                      $this->_out($annots.']');
2556                  }
2557                  $this->_out('/Contents '.($this->n+1).' 0 R>>');
2558                  $this->_out('endobj');
2559                  //Page content

2560                  $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
2561                  $this->_newobj();
2562                  $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
2563                  $this->_putstream($p);
2564                  $this->_out('endobj');
2565              }
2566              //Pages root

2567              $this->offsets[1]=strlen($this->buffer);
2568              $this->_out('1 0 obj');
2569              $this->_out('<</Type /Pages');
2570              $kids='/Kids [';
2571              for($i=0;$i<$nb;$i++) {
2572                  $kids.=(3+2*$i).' 0 R ';
2573              }
2574              $this->_out($kids.']');
2575              $this->_out('/Count '.$nb);
2576              $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$wPt,$hPt));
2577              $this->_out('>>');
2578              $this->_out('endobj');
2579          }
2580  
2581          /**

2582          * Adds fonts

2583          * _putfonts

2584          * @access protected

2585          */
2586  		protected function _putfonts() {
2587              $nf=$this->n;
2588              foreach($this->diffs as $diff) {
2589                  //Encodings

2590                  $this->_newobj();
2591                  $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
2592                  $this->_out('endobj');
2593              }
2594              $mqr=get_magic_quotes_runtime();
2595              set_magic_quotes_runtime(0);
2596              foreach($this->FontFiles as $file=>$info) {
2597                  //Font file embedding

2598                  $this->_newobj();
2599                  $this->FontFiles[$file]['n']=$this->n;
2600                  $font='';
2601                  $f=fopen($this->_getfontpath().$file,'rb',1);
2602                  if(!$f) {
2603                      $this->Error('Font file not found');
2604                  }
2605                  while(!feof($f)) {
2606                      $font .= fread($f, 8192);
2607                  }
2608                  fclose($f);
2609                  $compressed=(substr($file,-2)=='.z');
2610                  if(!$compressed && isset($info['length2'])) {
2611                      $header=(ord($font{0})==128);
2612                      if($header) {
2613                          //Strip first binary header

2614                          $font=substr($font,6);
2615                      }
2616                      if($header && ord($font{$info['length1']})==128) {
2617                          //Strip second binary header

2618                          $font=substr($font,0,$info['length1']).substr($font,$info['length1']+6);
2619                      }
2620                  }
2621                  $this->_out('<</Length '.strlen($font));
2622                  if($compressed) {
2623                      $this->_out('/Filter /FlateDecode');
2624                  }
2625                  $this->_out('/Length1 '.$info['length1']);
2626                  if(isset($info['length2'])) {
2627                      $this->_out('/Length2 '.$info['length2'].' /Length3 0');
2628                  }
2629                  $this->_out('>>');
2630                  $this->_putstream($font);
2631                  $this->_out('endobj');
2632              }
2633              set_magic_quotes_runtime($mqr);
2634              foreach($this->fonts as $k=>$font) {
2635                  //Font objects

2636                  $this->fonts[$k]['n']=$this->n+1;
2637                  $type=$font['type'];
2638                  $name=$font['name'];
2639                  if($type=='core') {
2640                      //Standard font

2641                      $this->_newobj();
2642                      $this->_out('<</Type /Font');
2643                      $this->_out('/BaseFont /'.$name);
2644                      $this->_out('/Subtype /Type1');
2645                      if($name!='Symbol' && $name!='ZapfDingbats') {
2646                          $this->_out('/Encoding /WinAnsiEncoding');
2647                      }
2648                      $this->_out('>>');
2649                      $this->_out('endobj');
2650                  } elseif($type=='Type1' || $type=='TrueType') {
2651                      //Additional Type1 or TrueType font

2652                      $this->_newobj();
2653                      $this->_out('<</Type /Font');
2654                      $this->_out('/BaseFont /'.$name);
2655                      $this->_out('/Subtype /'.$type);
2656                      $this->_out('/FirstChar 32 /LastChar 255');
2657                      $this->_out('/Widths '.($this->n+1).' 0 R');
2658                      $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
2659                      if($font['enc']) {
2660                          if(isset($font['diff'])) {
2661                              $this->_out('/Encoding '.($nf+$font['diff']).' 0 R');
2662                          } else {
2663                              $this->_out('/Encoding /WinAnsiEncoding');
2664                          }
2665                      }
2666                      $this->_out('>>');
2667                      $this->_out('endobj');
2668                      //Widths

2669                      $this->_newobj();
2670                      $cw=&$font['cw'];
2671                      $s='[';
2672                      for($i=32;$i<=255;$i++) {
2673                          $s.=$cw[chr($i)].' ';
2674                      }
2675                      $this->_out($s.']');
2676                      $this->_out('endobj');
2677                      //Descriptor

2678                      $this->_newobj();
2679                      $s='<</Type /FontDescriptor /FontName /'.$name;
2680                      foreach($font['desc'] as $k=>$v) {
2681                          $s.=' /'.$k.' '.$v;
2682                      }
2683                      $file = $font['file'];
2684                      if($file) {
2685                          $s.=' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->FontFiles[$file]['n'].' 0 R';
2686                      }
2687                      $this->_out($s.'>>');
2688                      $this->_out('endobj');
2689                  } else {
2690                      //Allow for additional types

2691                      $mtd='_put'.strtolower($type);
2692                      if(!method_exists($this, $mtd)) {
2693                          $this->Error('Unsupported font type: '.$type);
2694                      }
2695                      $this->$mtd($font);
2696                  }
2697              }
2698          }
2699  
2700          /**

2701          * _putimages

2702          * @access protected

2703          */
2704  		protected function _putimages() {
2705              $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
2706              reset($this->images);
2707              while(list($file,$info)=each($this->images)) {
2708                  $this->_newobj();
2709                  $this->images[$file]['n']=$this->n;
2710                  $this->_out('<</Type /XObject');
2711                  $this->_out('/Subtype /Image');
2712                  $this->_out('/Width '.$info['w']);
2713                  $this->_out('/Height '.$info['h']);
2714                  if($info['cs']=='Indexed') {
2715                      $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
2716                  }
2717                  else {
2718                      $this->_out('/ColorSpace /'.$info['cs']);
2719                      if($info['cs']=='DeviceCMYK') {
2720                          $this->_out('/Decode [1 0 1 0 1 0 1 0]');
2721                      }
2722                  }
2723                  $this->_out('/BitsPerComponent '.$info['bpc']);
2724                  if(isset($info['f'])) {
2725                      $this->_out('/Filter /'.$info['f']);
2726                  }
2727                  if(isset($info['parms'])) {
2728                      $this->_out($info['parms']);
2729                  }
2730                  if(isset($info['trns']) and is_array($info['trns'])) {
2731                      $trns='';
2732                      for($i=0;$i<count($info['trns']);$i++) {
2733                          $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
2734                      }
2735                      $this->_out('/Mask ['.$trns.']');
2736                  }
2737                  $this->_out('/Length '.strlen($info['data']).'>>');
2738                  $this->_putstream($info['data']);
2739                  unset($this->images[$file]['data']);
2740                  $this->_out('endobj');
2741                  //Palette

2742                  if($info['cs']=='Indexed') {
2743                      $this->_newobj();
2744                      $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
2745                      $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
2746                      $this->_putstream($pal);
2747                      $this->_out('endobj');
2748                  }
2749              }
2750          }
2751  
2752          /**

2753          * _putxobjectdict

2754          * @access protected

2755          */
2756  		function _putxobjectdict() {
2757              foreach($this->images as $image) {
2758                  $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
2759              }
2760          }
2761  
2762          /**

2763          * _putresourcedict

2764          * @access protected

2765          */
2766  		function _putresourcedict(){
2767              $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
2768              $this->_out('/Font <<');
2769              foreach($this->fonts as $font) {
2770                  $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
2771              }
2772              $this->_out('>>');
2773              $this->_out('/XObject <<');
2774              $this->_putxobjectdict();
2775              $this->_out('>>');
2776          }
2777  
2778          /**

2779          * _putresources

2780          * @access protected

2781          */
2782  		function _putresources() {
2783              $this->_putfonts();
2784              $this->_putimages();
2785              //Resource dictionary

2786              $this->offsets[2]=strlen($this->buffer);
2787              $this->_out('2 0 obj');
2788              $this->_out('<<');
2789              $this->_putresourcedict();
2790              $this->_out('>>');
2791              $this->_out('endobj');
2792          }
2793          
2794          /**

2795          * _putinfo

2796          * @access protected

2797          */
2798  		protected function _putinfo() {
2799              $this->_out('/Producer '.$this->_textstring(PDF_PRODUCER));
2800              if(!empty($this->title)) {
2801                  $this->_out('/Title '.$this->_textstring($this->title));
2802              }
2803              if(!empty($this->subject)) {
2804                  $this->_out('/Subject '.$this->_textstring($this->subject));
2805              }
2806              if(!empty($this->author)) {
2807                  $this->_out('/Author '.$this->_textstring($this->author));
2808              }
2809              if(!empty($this->keywords)) {
2810                  $this->_out('/Keywords '.$this->_textstring($this->keywords));
2811              }
2812              if(!empty($this->creator)) {
2813                  $this->_out('/Creator '.$this->_textstring($this->creator));
2814              }
2815              $this->_out('/CreationDate '.$this->_textstring('D:'.date('YmdHis')));
2816          }
2817  
2818          /**

2819          * _putcatalog

2820          * @access protected

2821          */
2822  		protected function _putcatalog() {
2823              $this->_out('/Type /Catalog');
2824              $this->_out('/Pages 1 0 R');
2825              if($this->ZoomMode=='fullpage') {
2826                  $this->_out('/OpenAction [3 0 R /Fit]');
2827              }
2828              elseif($this->ZoomMode=='fullwidth') {
2829                  $this->_out('/OpenAction [3 0 R /FitH null]');
2830              }
2831              elseif($this->ZoomMode=='real') {
2832                  $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
2833              }
2834              elseif(!is_string($this->ZoomMode)) {
2835                  $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
2836              }
2837              if($this->LayoutMode=='single') {
2838                  $this->_out('/PageLayout /SinglePage');
2839              }
2840              elseif($this->LayoutMode=='continuous') {
2841                  $this->_out('/PageLayout /OneColumn');
2842              }
2843              elseif($this->LayoutMode=='two') {
2844                  $this->_out('/PageLayout /TwoColumnLeft');
2845              }
2846          }
2847  
2848          /**

2849          * _puttrailer

2850          * @access protected

2851          */
2852  		protected function _puttrailer() {
2853              $this->_out('/Size '.($this->n+1));
2854              $this->_out('/Root '.$this->n.' 0 R');
2855              $this->_out('/Info '.($this->n-1).' 0 R');
2856          }
2857  
2858          /**

2859          * _putheader

2860          * @access protected

2861          */
2862  		function _putheader() {
2863              $this->_out('%PDF-'.$this->PDFVersion);
2864          }
2865  
2866          /**

2867          * _enddoc

2868          * @access protected

2869          */
2870  		protected function _enddoc() {
2871              $this->_putheader();
2872              $this->_putpages();
2873              $this->_putresources();
2874              //Info

2875              $this->_newobj();
2876              $this->_out('<<');
2877              $this->_putinfo();
2878              $this->_out('>>');
2879              $this->_out('endobj');
2880              //Catalog

2881              $this->_newobj();
2882              $this->_out('<<');
2883              $this->_putcatalog();
2884              $this->_out('>>');
2885              $this->_out('endobj');
2886              //Cross-ref

2887              $o=strlen($this->buffer);
2888              $this->_out('xref');
2889              $this->_out('0 '.($this->n+1));
2890              $this->_out('0000000000 65535 f ');
2891              for($i=1;$i<=$this->n;$i++) {
2892                  $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
2893              }
2894              //Trailer

2895              $this->_out('trailer');
2896              $this->_out('<<');
2897              $this->_puttrailer();
2898              $this->_out('>>');
2899              $this->_out('startxref');
2900              $this->_out($o);
2901              $this->_out('%%EOF');
2902              $this->state=3;
2903          }
2904  
2905          /**

2906          * _beginpage

2907          * @access protected

2908          */
2909  		protected function _beginpage($orientation) {
2910              $this->page++;
2911              $this->pages[$this->page]='';
2912              $this->state=2;
2913              $this->x=$this->lMargin;
2914              $this->y=$this->tMargin;
2915              $this->FontFamily='';
2916              //Page orientation

2917              if(empty($orientation)) {
2918                  $orientation=$this->DefOrientation;
2919              }
2920              else {
2921                  $orientation=strtoupper($orientation{0});
2922                  if($orientation!=$this->DefOrientation) {
2923                      $this->OrientationChanges[$this->page]=true;
2924                  }
2925              }
2926              if($orientation!=$this->CurOrientation) {
2927                  //Change orientation

2928                  if($orientation=='P') {
2929                      $this->wPt=$this->fwPt;
2930                      $this->hPt=$this->fhPt;
2931                      $this->w=$this->fw;
2932                      $this->h=$this->fh;
2933                  }
2934                  else {
2935                      $this->wPt=$this->fhPt;
2936                      $this->hPt=$this->fwPt;
2937                      $this->w=$this->fh;
2938                      $this->h=$this->fw;
2939                  }
2940                  $this->PageBreakTrigger=$this->h-$this->bMargin;
2941                  $this->CurOrientation=$orientation;
2942              }
2943          }
2944  
2945          /**

2946          * End of page contents

2947          * @access protected

2948          */
2949  		protected function _endpage() {
2950              $this->state=1;
2951          }
2952  
2953          /**

2954          * Begin a new object

2955          * @access protected

2956          */
2957  		protected function _newobj() {
2958              $this->n++;
2959              $this->offsets[$this->n]=strlen($this->buffer);
2960              $this->_out($this->n.' 0 obj');
2961          }
2962  
2963          /**

2964          * Underline text

2965          * @access protected

2966          */
2967  		protected function _dounderline($x,$y,$txt) {
2968              $up = $this->CurrentFont['up'];
2969              $ut = $this->CurrentFont['ut'];
2970              $w = $this->GetStringWidth($txt) + $this->ws * substr_count($txt,' ');
2971              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);
2972          }
2973  
2974          /**

2975          * Extract info from a JPEG file

2976          * @access protected

2977          */
2978  		protected function _parsejpg($file) {
2979              $a=GetImageSize($file);
2980              if(empty($a)) {
2981                  $this->Error('Missing or incorrect image file: '.$file);
2982              }
2983              if($a[2]!=2) {
2984                  $this->Error('Not a JPEG file: '.$file);
2985              }
2986              if(!isset($a['channels']) or $a['channels']==3) {
2987                  $colspace='DeviceRGB';
2988              }
2989              elseif($a['channels']==4) {
2990                  $colspace='DeviceCMYK';
2991              }
2992              else {
2993                  $colspace='DeviceGray';
2994              }
2995              $bpc=isset($a['bits']) ? $a['bits'] : 8;
2996              //Read whole file

2997              $f=fopen($file,'rb');
2998              $data='';
2999              while(!feof($f)) {
3000                  $data.=fread($f,4096);
3001              }
3002              fclose($f);
3003              return array('w'=>$a[0],'h'=>$a[1],'cs'=>$colspace,'bpc'=>$bpc,'f'=>'DCTDecode','data'=>$data);
3004          }
3005  
3006          /**

3007          * Extract info from a PNG file

3008          * @access protected

3009          */
3010  		protected function _parsepng($file) {
3011              $f=fopen($file,'rb');
3012              if(empty($f)) {
3013                  $this->Error('Can\'t open image file: '.$file);
3014              }
3015              //Check signature

3016              if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
3017                  $this->Error('Not a PNG file: '.$file);
3018              }
3019              //Read header chunk

3020              fread($f,4);
3021              if(fread($f,4)!='IHDR') {
3022                  $this->Error('Incorrect PNG file: '.$file);
3023              }
3024              $w=$this->_freadint($f);
3025              $h=$this->_freadint($f);
3026              $bpc=ord(fread($f,1));
3027              if($bpc>8) {
3028                  $this->Error('16-bit depth not supported: '.$file);
3029              }
3030              $ct=ord(fread($f,1));
3031              if($ct==0) {
3032                  $colspace='DeviceGray';
3033              }
3034              elseif($ct==2) {
3035                  $colspace='DeviceRGB';
3036              }
3037              elseif($ct==3) {
3038                  $colspace='Indexed';
3039              }
3040              else {
3041                  $this->Error('Alpha channel not supported: '.$file);
3042              }
3043              if(ord(fread($f,1))!=0) {
3044                  $this->Error('Unknown compression method: '.$file);
3045              }
3046              if(ord(fread($f,1))!=0) {
3047                  $this->Error('Unknown filter method: '.$file);
3048              }
3049              if(ord(fread($f,1))!=0) {
3050                  $this->Error('Interlacing not supported: '.$file);
3051              }
3052              fread($f,4);
3053              $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
3054              //Scan chunks looking for palette, transparency and image data

3055              $pal='';
3056              $trns='';
3057              $data='';
3058              do {
3059                  $n=$this->_freadint($f);
3060                  $type=fread($f,4);
3061                  if($type=='PLTE') {
3062                      //Read palette

3063                      $pal=fread($f,$n);
3064                      fread($f,4);
3065                  }
3066                  elseif($type=='tRNS') {
3067                      //Read transparency info

3068                      $t=fread($f,$n);
3069                      if($ct==0) {
3070                          $trns=array(ord(substr($t,1,1)));
3071                      }
3072                      elseif($ct==2) {
3073                          $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
3074                      }
3075                      else {
3076                          $pos=strpos($t,chr(0));
3077                          if($pos!==false) {
3078                              $trns=array($pos);
3079                          }
3080                      }
3081                      fread($f,4);
3082                  }
3083                  elseif($type=='IDAT') {
3084                      //Read image data block

3085                      $data.=fread($f,$n);
3086                      fread($f,4);
3087                  }
3088                  elseif($type=='IEND') {
3089                      break;
3090                  }
3091                  else {
3092                      fread($f,$n+4);
3093                  }
3094              }
3095              while($n);
3096              if($colspace=='Indexed' and empty($pal)) {
3097                  $this->Error('Missing palette in '.$file);
3098              }
3099              fclose($f);
3100              return array('w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'FlateDecode', 'parms'=>$parms, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$data);
3101          }
3102  
3103          /**

3104          * Read a 4-byte integer from file

3105          * @access protected

3106          */
3107  		protected function _freadint($f) {
3108              //Read a 4-byte integer from file

3109              $a=unpack('Ni',fread($f,4));
3110              return $a['i'];
3111          }
3112  
3113          /**

3114          * Format a text string

3115          * @access protected

3116          */
3117  		protected function _textstring($s) {
3118              if($this->isunicode) {
3119                  //Convert string to UTF-16BE

3120                  $s = $this->UTF8ToUTF16BE($s, true);
3121              }
3122              return '('. $this->_escape($s).')';
3123          }
3124  
3125          /**

3126          * Format a text string

3127          * @access protected

3128          */
3129  		function _escapetext($s) {
3130              if($this->isunicode) {
3131                  //Convert string to UTF-16BE

3132                  $s = $this->UTF8ToUTF16BE($s, false);
3133              }
3134              return $this->_escape($s);
3135          }
3136  
3137          /**

3138          * Add \ before \, ( and )

3139          * @access protected

3140          */
3141  		protected function _escape($s) {
3142              return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\'));
3143          }
3144  
3145          /**

3146          *

3147          * @access protected

3148          */
3149  		protected function _putstream($s) {
3150              $this->_out('stream');
3151              $this->_out($s);
3152              $this->_out('endstream');
3153          }
3154  
3155          /**

3156          * Add a line to the document

3157          * @access protected

3158          */
3159  		protected function _out($s) {
3160              if($this->state==2) {
3161                  $this->pages[$this->page] .= $s."\n";
3162              }
3163              else {
3164                  $this->buffer .= $s."\n";
3165              }
3166          }
3167  
3168          /**

3169          * Adds unicode fonts.<br>

3170          * Based on PDF Reference 1.3 (section 5)

3171          * @access protected

3172          * @author Nicola Asuni

3173          * @since 1.52.0.TC005 (2005-01-05)

3174          */
3175  		protected function _puttruetypeunicode($font) {
3176              // Type0 Font

3177              // A composite font—a font composed of other fonts, organized hierarchically

3178              $this->_newobj();
3179              $this->_out('<</Type /Font');
3180              $this->_out('/Subtype /Type0');
3181              $this->_out('/BaseFont /'.$font['name'].'');
3182              $this->_out('/Encoding /Identity-H'); //The horizontal identity mapping for 2-byte CIDs; may be used with CIDFonts using any Registry, Ordering, and Supplement values.

3183              $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
3184              $this->_out('>>');
3185              $this->_out('endobj');
3186              
3187              // CIDFontType2

3188              // A CIDFont whose glyph descriptions are based on TrueType font technology

3189              $this->_newobj();
3190              $this->_out('<</Type /Font');
3191              $this->_out('/Subtype /CIDFontType2');
3192              $this->_out('/BaseFont /'.$font['name'].'');
3193              $this->_out('/CIDSystemInfo '.($this->n + 1).' 0 R'); 
3194              $this->_out('/FontDescriptor '.($this->n + 2).' 0 R');
3195              if (isset($font['desc']['MissingWidth'])){
3196                  $this->_out('/DW '.$font['desc']['MissingWidth'].''); // The default width for glyphs in the CIDFont MissingWidth

3197              }
3198              $w = "";
3199              foreach ($font['cw'] as $cid => $width) {
3200                  $w .= ''.$cid.' ['.$width.'] '; // define a specific width for each individual CID

3201              }
3202              $this->_out('/W ['.$w.']'); // A description of the widths for the glyphs in the CIDFont

3203              $this->_out('/CIDToGIDMap '.($this->n + 3).' 0 R');
3204              $this->_out('>>');
3205              $this->_out('endobj');
3206              
3207              // CIDSystemInfo dictionary

3208              // A dictionary containing entries that define the character collectionof the CIDFont.

3209              $this->_newobj();
3210              $this->_out('<</Registry (Adobe)'); // A string identifying an issuer of character collections

3211              $this->_out('/Ordering (UCS)'); // A string that uniquely names a character collection issued by a specific registry

3212              $this->_out('/Supplement 0'); // The supplement number of the character collection.

3213              $this->_out('>>');
3214              $this->_out('endobj');
3215              
3216              // Font descriptor

3217              // A font descriptor describing the CIDFont’s default metrics other than its glyph widths

3218              $this->_newobj();
3219              $this->_out('<</Type /FontDescriptor');
3220              $this->_out('/FontName /'.$font['name']);
3221              foreach ($font['desc'] as $key => $value) {
3222                  $this->_out('/'.$key.' '.$value);
3223              }
3224              if ($font['file']) {
3225                  // A stream containing a TrueType font program

3226                  $this->_out('/FontFile2 '.$this->FontFiles[$font['file']]['n'].' 0 R');
3227              }
3228              $this->_out('>>');
3229              $this->_out('endobj');
3230  
3231              // Embed CIDToGIDMap

3232              // A specification of the mapping from CIDs to glyph indices

3233              $this->_newobj();
3234              $ctgfile = $this->_getfontpath().$font['ctg'];
3235              if(!file_exists($ctgfile)) {
3236                  $this->Error('Font file not found: '.$ctgfile);
3237              }
3238              $size = filesize($ctgfile);
3239              $this->_out('<</Length '.$size.'');
3240              if(substr($ctgfile, -2) == '.z') { // check file extension
3241                  /* Decompresses data encoded using the public-domain 

3242                  zlib/deflate compression method, reproducing the 

3243                  original text or binary data */
3244                  $this->_out('/Filter /FlateDecode');
3245              }
3246              $this->_out('>>');
3247              $this->_putstream(file_get_contents($ctgfile));
3248              $this->_out('endobj');
3249          }
3250  
3251           /**

3252           * Converts UTF-8 strings to codepoints array.<br>

3253           * Invalid byte sequences will be replaced with 0xFFFD (replacement character)<br>

3254           * Based on: http://www.faqs.org/rfcs/rfc3629.html

3255           * <pre>

3256           *       Char. number range  |        UTF-8 octet sequence

3257           *       (hexadecimal)    |              (binary)

3258           *    --------------------+-----------------------------------------------

3259           *    0000 0000-0000 007F | 0xxxxxxx

3260           *    0000 0080-0000 07FF | 110xxxxx 10xxxxxx

3261           *    0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx

3262           *    0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

3263           *    ---------------------------------------------------------------------

3264           *

3265           *   ABFN notation:

3266           *   ---------------------------------------------------------------------

3267           *   UTF8-octets = *( UTF8-char )

3268           *   UTF8-char   = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4

3269           *   UTF8-1      = %x00-7F

3270           *   UTF8-2      = %xC2-DF UTF8-tail

3271           *

3272           *   UTF8-3      = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /

3273           *                 %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )

3274           *   UTF8-4      = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /

3275           *                 %xF4 %x80-8F 2( UTF8-tail )

3276           *   UTF8-tail   = %x80-BF

3277           *   ---------------------------------------------------------------------

3278           * </pre>

3279           * @param string $str string to process.

3280           * @return array containing codepoints (UTF-8 characters values)

3281           * @access protected

3282           * @author Nicola Asuni

3283           * @since 1.53.0.TC005 (2005-01-05)

3284           */
3285  		protected function UTF8StringToArray($str) {
3286              if(!$this->isunicode) {
3287                  return $str; // string is not in unicode

3288              }
3289              $unicode = array(); // array containing unicode values

3290              $bytes  = array(); // array containing single character byte sequences

3291              $numbytes  = 1; // number of octetc needed to represent the UTF-8 character

3292              
3293              $str .= ""; // force $str to be a string

3294              $length = strlen($str);
3295              
3296              for($i = 0; $i < $length; $i++) {
3297                  $char = ord($str{$i}); // get one string character at time

3298                  if(count($bytes) == 0) { // get starting octect
3299                      if ($char <= 0x7F) {
3300                          $unicode[] = $char; // use the character "as is" because is ASCII

3301                      } elseif (($char >> 0x05) == 0x06) { // 2 bytes character (0x06 = 110 BIN)
3302                          $bytes[] = ($char - 0xC0) << 0x06; 
3303                          $numbytes = 2;
3304                      } elseif (($char >> 0x04) == 0x0E) { // 3 bytes character (0x0E = 1110 BIN)
3305                          $bytes[] = ($char - 0xE0) << 0x0C; 
3306                          $numbytes = 3;
3307                      } elseif (($char >> 0x03) == 0x1E) { // 4 bytes character (0x1E = 11110 BIN)
3308                          $bytes[] = ($char - 0xF0) << 0x12; 
3309                          $numbytes = 4;
3310                      } else {
3311                          // use replacement character for other invalid sequences

3312                          $unicode[] = 0xFFFD;
3313                          $bytes = array();
3314                          $numbytes = 1;
3315                      }
3316                  } elseif (($char >> 0x06) == 0x02) { // bytes 2, 3 and 4 must start with 0x02 = 10 BIN
3317                      $bytes[] = $char - 0x80;
3318                      if (count($bytes) == $numbytes) {
3319                          // compose UTF-8 bytes to a single unicode value

3320                          $char = $bytes[0];
3321                          for($j = 1; $j < $numbytes; $j++) {
3322                              $char += ($bytes[$j] << (($numbytes - $j - 1) * 0x06));
3323                          }
3324                          if ((($char >= 0xD800) AND ($char <= 0xDFFF)) OR ($char >= 0x10FFFF)) {
3325                              /* The definition of UTF-8 prohibits encoding character numbers between

3326                              U+D800 and U+DFFF, which are reserved for use with the UTF-16

3327                              encoding form (as surrogate pairs) and do not directly represent

3328                              characters. */
3329                              $unicode[] = 0xFFFD; // use replacement character

3330                          }
3331                          else {
3332                              $unicode[] = $char; // add char to array

3333                          }
3334                          // reset data for next char

3335                          $bytes = array(); 
3336                          $numbytes = 1;
3337                      }
3338                  } else {
3339                      // use replacement character for other invalid sequences

3340                      $unicode[] = 0xFFFD;
3341                      $bytes = array();
3342                      $numbytes = 1;
3343                  }
3344              }
3345              return $unicode;
3346          }
3347          
3348          /**

3349           * Converts UTF-8 strings to UTF16-BE.<br>

3350           * Based on: http://www.faqs.org/rfcs/rfc2781.html

3351            * <pre>

3352           *   Encoding UTF-16:

3353           * 

3354            *   Encoding of a single character from an ISO 10646 character value to

3355           *    UTF-16 proceeds as follows. Let U be the character number, no greater

3356           *    than 0x10FFFF.

3357           * 

3358           *    1) If U < 0x10000, encode U as a 16-bit unsigned integer and

3359           *       terminate.

3360           * 

3361           *    2) Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,

3362           *       U' must be less than or equal to 0xFFFFF. That is, U' can be

3363           *       represented in 20 bits.

3364           * 

3365           *    3) Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and

3366           *       0xDC00, respectively. These integers each have 10 bits free to

3367           *       encode the character value, for a total of 20 bits.

3368           * 

3369           *    4) Assign the 10 high-order bits of the 20-bit U' to the 10 low-order

3370           *       bits of W1 and the 10 low-order bits of U' to the 10 low-order

3371           *       bits of W2. Terminate.

3372           * 

3373           *    Graphically, steps 2 through 4 look like:

3374           *    U' = yyyyyyyyyyxxxxxxxxxx

3375           *    W1 = 110110yyyyyyyyyy

3376           *    W2 = 110111xxxxxxxxxx

3377           * </pre>

3378           * @param string $str string to process.

3379           * @param boolean $setbom if true set the Byte Order Mark (BOM = 0xFEFF)

3380           * @return string

3381           * @access protected

3382           * @author Nicola Asuni

3383           * @since 1.53.0.TC005 (2005-01-05)

3384           * @uses UTF8StringToArray

3385           */
3386  		protected function UTF8ToUTF16BE($str, $setbom=true) {
3387              if(!$this->isunicode) {
3388                  return $str; // string is not in unicode

3389              }
3390              $outstr = ""; // string to be returned

3391              $unicode = $this->UTF8StringToArray($str); // array containing UTF-8 unicode values

3392              $numitems = count($unicode);
3393              
3394              if ($setbom) {
3395                  $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)

3396              }
3397              foreach($unicode as $char) {
3398                  if($char == 0xFFFD) {
3399                      $outstr .= "\xFF\xFD"; // replacement character

3400                  } elseif ($char < 0x10000) {
3401                      $outstr .= chr($char >> 0x08);
3402                      $outstr .= chr($char & 0xFF);
3403                  } else {
3404                      $char -= 0x10000;
3405                      $w1 = 0xD800 | ($char >> 0x10);
3406                      $w2 = 0xDC00 | ($char & 0x3FF);    
3407                      $outstr .= chr($w1 >> 0x08);
3408                      $outstr .= chr($w1 & 0xFF);
3409                      $outstr .= chr($w2 >> 0x08);
3410                      $outstr .= chr($w2 & 0xFF);
3411                  }
3412              }
3413              return $outstr;
3414          }
3415          
3416          // ====================================================

3417          
3418          /**

3419            * Set header font.

3420           * @param array $font font

3421           * @since 1.1

3422           */
3423  		public function setHeaderFont($font) {
3424              $this->header_font = $font;
3425          }
3426          
3427          /**

3428            * Set footer font.

3429           * @param array $font font

3430           * @since 1.1

3431           */
3432  		public function setFooterFont($font) {
3433              $this->footer_font = $font;
3434          }
3435          
3436          /**

3437            * Set language array.

3438           * @param array $language

3439           * @since 1.1

3440           */
3441  		public function setLanguageArray($language) {
3442              $this->l = $language;
3443          }
3444          
3445          /**

3446            * Set document barcode.

3447           * @param string $bc barcode

3448           */
3449  		public function setBarcode($bc="") {
3450              $this->barcode = $bc;
3451          }
3452          
3453          /**

3454            * Print Barcode.

3455           * @param int $x x position in user units

3456           * @param int $y y position in user units

3457           * @param int $w width in user units

3458           * @param int $h height position in user units

3459           * @param string $type type of barcode (I25, C128A, C128B, C128C, C39)

3460           * @param string $style barcode style

3461           * @param string $font font for text

3462           * @param int $xres x resolution

3463           * @param string $code code to print

3464           */
3465  		public function writeBarcode($x, $y, $w, $h, $type, $style, $font, $xres, $code) {
3466              require_once ("../../shared/barcode/barcode.php");
3467              require_once ("../../shared/barcode/i25object.php");
3468              require_once ("../../shared/barcode/c39object.php");
3469              require_once ("../../shared/barcode/c128aobject.php");
3470              require_once ("../../shared/barcode/c128bobject.php");
3471              require_once ("../../shared/barcode/c128cobject.php");
3472              
3473              if (empty($code)) {
3474                  return;
3475              }
3476              
3477              if (empty($style)) {
3478                  $style  = BCS_ALIGN_LEFT;
3479                  $style |= BCS_IMAGE_PNG;
3480                  $style |= BCS_TRANSPARENT;
3481                  //$style |= BCS_BORDER;

3482                  //$style |= BCS_DRAW_TEXT;

3483                  //$style |= BCS_STRETCH_TEXT;

3484                  //$style |= BCS_REVERSE_COLOR;

3485              }
3486              if (empty($font)) {$font = BCD_DEFAULT_FONT;}
3487              if (empty($xres)) {$xres = BCD_DEFAULT_XRES;}
3488              
3489              $scale_factor = 1.5 * $xres * $this->k;
3490              $bc_w = round($w * $scale_factor); //width in points

3491              $bc_h = round($h * $scale_factor); //height in points

3492              
3493              switch (strtoupper($type)) {
3494                  case "I25": {
3495                      $obj = new I25Object($bc_w, $bc_h, $style, $code);
3496                      break;
3497                  }
3498                  case "C128A": {
3499                      $obj = new C128AObject($bc_w, $bc_h, $style, $code);
3500                      break;
3501                  }
3502                  default:
3503                  case "C128B": {
3504                      $obj = new C128BObject($bc_w, $bc_h, $style, $code);
3505                      break;
3506                  }
3507                  case "C128C": {
3508                      $obj = new C128CObject($bc_w, $bc_h, $style, $code);
3509                      break;
3510                  }
3511                  case "C39": {
3512                      $obj = new C39Object($bc_w, $bc_h, $style, $code);
3513                      break;
3514                  }
3515              }
3516              
3517              $obj->SetFont($font);   
3518              $obj->DrawObject($xres);
3519              
3520              //use a temporary file....

3521              $tmpName = tempnam(K_PATH_CACHE,'img');
3522              imagepng($obj->getImage(), $tmpName);
3523              $this->Image($tmpName, $x, $y, $w, $h, 'png');
3524              $obj->DestroyObject();
3525              unset($obj);
3526              unlink($tmpName);
3527          }
3528          
3529          /**

3530            * Returns the PDF data.

3531           */
3532  		public function getPDFData() {
3533              if($this->state < 3) {
3534                  $this->Close();
3535              }
3536              return $this->buffer;
3537          }
3538          
3539          // --- HTML PARSER FUNCTIONS ---

3540          
3541          /**

3542           * Allows to preserve some HTML formatting.<br />

3543           * Supports: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small

3544           * @param string $html text to display

3545           * @param boolean $ln if true add a new line after text (default = true)

3546           */
3547  		public function writeHTML($html, $ln=true) {
3548              $html=strip_tags($html,"<h1><h2><h3><h4><h5><h6><b><u><i><a><img><p><br><strong><em><font><blockquote><li><ul><ol><hr><td><th><tr><table><sup><sub><small>"); //remove all unsupported tags

3549              //replace carriage returns, newlines and tabs

3550              $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " "); 
3551              $html = strtr($html, $repTable);
3552              $pattern = '/(<[^>]+>)/Uu';
3553              $a = preg_split($pattern, $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); //explodes the string

3554              
3555              if (empty($this->lasth)) {
3556                  //set row height

3557                  $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; 
3558              }
3559              
3560              foreach($a as $key=>$element) {
3561                  if (!preg_match($pattern, $element)) {
3562                      //Text

3563                      if($this->HREF) {
3564                          $this->addHtmlLink($this->HREF, $element);
3565                      }
3566                      elseif($this->tdbegin) {
3567                          if((strlen(trim($element)) > 0) AND ($element != "&nbsp;")) {
3568                              $this->Cell($this->tdwidth, $this->tdheight, $this->unhtmlentities($element), $this->tableborder, '', $this->tdalign, $this->tdbgcolor);
3569                          }
3570                          elseif($element == "&nbsp;") {
3571                              $this->Cell($this->tdwidth, $this->tdheight, '', $this->tableborder, '', $this->tdalign, $this->tdbgcolor);
3572                          }
3573                      }
3574                      else {
3575                          $this->Write($this->lasth, stripslashes($this->unhtmlentities($element)));
3576                      }
3577                  }
3578                  else {
3579                      $element = substr($element, 1, -1);
3580                      //Tag

3581                      if($element{0}=='/') {
3582                          $this->closedHTMLTagHandler(strtolower(substr($element, 1)));
3583                      }
3584                      else {
3585                          //Extract attributes

3586                          $a2 = explode(' ',$element);
3587                          $tag = strtolower(array_shift($a2));
3588                          $attr = array();
3589                          foreach($a2 as $v) {
3590                              if (ereg('^([^=]*)=["\']?([^"\']*)["\']?$', $v, $a3)) {
3591                                  $attr[strtolower($a3[1])] = $a3[2];
3592                              }
3593                          }
3594                          $this->openHTMLTagHandler($tag, $attr);
3595                      }
3596                  }
3597              }
3598              if ($ln) {
3599                  $this->Ln($this->lasth);
3600              }
3601          }
3602          
3603          /**

3604           * Prints a cell (rectangular area) with optional borders, background color and html text string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.<br />

3605           * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.

3606           * @param float $w Cell width. If 0, the cell extends up to the right margin.

3607           * @param float $h Cell minimum height. The cell extends automatically if needed.

3608           * @param float $x upper-left corner X coordinate

3609           * @param float $y upper-left corner Y coordinate

3610           * @param string $html html text to print. Default value: empty string.

3611           * @param mixed $border Indicates if borders must be drawn around the cell. The value can be either a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul>or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul>

3612           * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>

3613      Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.

3614           * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0. NOTE: this parameter has not been implemented.

3615           * @see Cell()

3616           */
3617  		public function writeHTMLCell($w, $h, $x, $y, $html='', $border=0, $ln=0, $fill=0) {
3618              
3619              $fill = 0; // disable fill function

3620              
3621              if (empty($this->lasth)) {
3622                  //set row height

3623                  $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; 
3624              }
3625              
3626              if (empty($x)) {
3627                  $x = $this->GetX();
3628              }
3629              if (empty($y)) {
3630                  $y = $this->GetY();
3631              }
3632              
3633              // get current page number

3634              $pagenum = $this->page;
3635              
3636              $this->SetX($x);
3637              $this->SetY($y);
3638                      
3639              if(empty($w)) {
3640                  $w = $this->fw - $x - $this->rMargin;
3641              }
3642              
3643              // store original margin values

3644              $lMargin = $this->lMargin;
3645              $rMargin = $this->rMargin;
3646              
3647              // set new margin values

3648              $this->SetLeftMargin($x);
3649              $this->SetRightMargin($this->fw - $x - $w);
3650                      
3651              // calculate remaining vertical space on page

3652              $restspace = $this->getPageHeight() - $this->GetY() - $this->getBreakMargin();
3653              
3654              $this->writeHTML($html); // write html text

3655              
3656              // check if a new page has been created

3657              if ($this->page > $pagenum) {
3658                  $currentY =  $this->GetY();
3659                  
3660                  // design a cell around the text on first page

3661                  $currentpage = $this->page;
3662                  $this->page = $pagenum;
3663                  $this->SetY($this->getPageHeight() - $restspace - $this->getBreakMargin());
3664                  $h = $restspace - 1;
3665                  $this->Cell($w, $h, "", $border, $ln, 'L', $fill);
3666                  
3667                  // design a cell around the text on last page

3668                  $this->page = $currentpage;
3669                  $h = $currentY - $this->tMargin;
3670                  $this->SetY($this->tMargin); // put cursor at the beginning of text

3671                  $this->Cell($w, $h, "", $border, $ln, 'L', $fill);
3672              } else {
3673                  $h = max($h, ($this->GetY() - $y));
3674                  $this->SetY($y); // put cursor at the beginning of text

3675                  // design a cell around the text

3676                  $this->Cell($w, $h, "", $border, $ln, 'L', $fill);
3677              }
3678              
3679              // restore original margin values

3680              $this->SetLeftMargin($lMargin);
3681              $this->SetRightMargin($rMargin);
3682              
3683              if ($ln) {
3684                  $this->Ln(0);
3685              }
3686          }
3687          
3688          /**

3689           * Process opening tags.

3690           * @param string $tag tag name (in uppercase)

3691           * @param string $attr tag attribute (in uppercase)

3692           * @access private

3693           */
3694  		private function openHTMLTagHandler($tag, $attr) {
3695              //Opening tag

3696              switch($tag) {
3697                  case 'table': {
3698                      if ((isset($attr['border'])) AND ($attr['border'] != '')) {
3699                          $this->tableborder = $attr['border'];
3700                      }
3701                      else {
3702                          $this->tableborder = 0;
3703                      }
3704                      break;
3705                  }
3706                  case 'tr': {
3707                      break;
3708                  }
3709                  case 'td':
3710                  case 'th': {
3711                      if ((isset($attr['width'])) AND ($attr['width'] != '')) {
3712                          $this->tdwidth = ($attr['width']/4);
3713                      }
3714                      else {
3715                          $this->tdwidth = (($this->w - $this->lMargin - $this->rMargin) / $this->default_table_columns);
3716                      }
3717                      if ((isset($attr['height'])) AND ($attr['height'] != '')) {
3718                          $this->tdheight=($attr['height'] / $this->k);
3719                      }
3720                      else {
3721                          $this->tdheight = $this->lasth;
3722                      }
3723                      if ((isset($attr['align'])) AND ($attr['align'] != '')) {
3724                          switch ($attr['align']) {
3725                              case 'center': {
3726                                  $this->tdalign = "C";
3727                                  break;
3728                              }
3729                              case 'right': {
3730                                  $this->tdalign = "R";
3731                                  break;
3732                              }
3733                              default:
3734                              case 'left': {
3735                                  $this->tdalign = "L";
3736                                  break;
3737                              }
3738                          }
3739                      }
3740                      if ((isset($attr['bgcolor'])) AND ($attr['bgcolor'] != '')) {
3741                          $coul = $this->convertColorHexToDec($attr['bgcolor']);
3742                          $this->SetFillColor($coul['R'], $coul['G'], $coul['B']);
3743                          $this->tdbgcolor=true;
3744                      }
3745                      $this->tdbegin=true;
3746                      break;
3747                  }
3748                  case 'hr': {
3749                      $this->Ln();
3750                      if ((isset($attr['width'])) AND ($attr['width'] != '')) {
3751                          $hrWidth = $attr['width'];
3752                      }
3753                      else {
3754                          $hrWidth = $this->w - $this->lMargin - $this->rMargin;
3755                      }
3756                      $x = $this->GetX();
3757                      $y = $this->GetY();
3758                      $this->SetLineWidth(0.2);
3759                      $this->Line($x, $y, $x + $hrWidth, $y);
3760                      $this->SetLineWidth(0.2);
3761                      $this->Ln();
3762                      break;
3763                  }
3764                  case 'strong': {
3765                      $this->setStyle('b', true);
3766                      break;
3767                  }
3768                  case 'em': {
3769                      $this->setStyle('i', true);
3770                      break;
3771                  }
3772                  case 'b':
3773                  case 'i':
3774                  case 'u': {
3775                      $this->setStyle($tag, true);
3776                      break;
3777                  }
3778                  case 'a': {
3779                      $this->HREF = $attr['href'];
3780                      break;
3781                  }
3782                  case 'img': {
3783                      if(isset($attr['src'])) {
3784                          // replace relative path with real server path

3785                          $attr['src'] = str_replace(K_PATH_URL_CACHE, K_PATH_CACHE, $attr['src']);
3786                          if(!isset($attr['width'])) {
3787                              $attr['width'] = 0;
3788                          }
3789                          if(!isset($attr['height'])) {
3790                              $attr['height'] = 0;
3791                          }
3792                          
3793                          $this->Image($attr['src'], $this->GetX(),$this->GetY(), $this->pixelsToMillimeters($attr['width']), $this->pixelsToMillimeters($attr['height']));
3794                          //$this->SetX($this->img_rb_x);

3795                          $this->SetY($this->img_rb_y);
3796                          
3797                      }
3798                      break;
3799                  }
3800                  case 'ul': {
3801                      $this->listordered = false;
3802                      $this->listcount = 0;
3803                      break;
3804                  }
3805                  case 'ol': {
3806                      $this->listordered = true;
3807                      $this->listcount = 0;
3808                      break;
3809                  }
3810                  case 'li': {
3811                      $this->Ln();
3812                      if ($this->listordered) {
3813                          $this->lispacer = "    ".(++$this->listcount).". ";
3814                      }
3815                      else {
3816                          //unordered list simbol

3817                          $this->lispacer = "    -  ";
3818                      }
3819                      $this->Write($this->lasth, $this->lispacer);
3820                      break;
3821                  }
3822                  case 'tr':
3823                  case 'blockquote':
3824                  case 'br': {
3825                      $this->Ln();
3826                      if(strlen($this->lispacer) > 0) {
3827                          $this->x += $this->GetStringWidth($this->lispacer);
3828                      }
3829                      break;
3830                  }
3831                  case 'p': {
3832                      $this->Ln();
3833                      $this->Ln();
3834                      break;
3835                  }
3836                  case 'sup': {
3837                      $currentFontSize = $this->FontSize;
3838                      $this->tempfontsize = $this->FontSizePt;
3839                      $this->SetFontSize($this->FontSizePt * K_SMALL_RATIO);
3840                      $this->SetXY($this->GetX(), $this->GetY() - (($currentFontSize - $this->FontSize)*(K_SMALL_RATIO)));
3841                      break;
3842                  }
3843                  case 'sub': {
3844                      $currentFontSize = $this->FontSize;
3845                      $this->tempfontsize = $this->FontSizePt;
3846                      $this->SetFontSize($this->FontSizePt * K_SMALL_RATIO);
3847                      $this->SetXY($this->GetX(), $this->GetY() + (($currentFontSize - $this->FontSize)*(K_SMALL_RATIO)));
3848                      break;
3849                  }
3850                  case 'small': {
3851                      $currentFontSize = $this->FontSize;
3852                      $this->tempfontsize = $this->FontSizePt;
3853                      $this->SetFontSize($this->FontSizePt * K_SMALL_RATIO);
3854                      $this->SetXY($this->GetX(), $this->GetY() + (($currentFontSize - $this->FontSize)/3));
3855                      break;
3856                  }
3857                  case 'font': {
3858                      if (isset($attr['color']) AND $attr['color']!='') {
3859                          $coul = $this->convertColorHexToDec($attr['color']);
3860                          $this->SetTextColor($coul['R'],$coul['G'],$coul['B']);
3861                          $this->issetcolor=true;
3862                      }
3863                      if (isset($attr['face']) and in_array(strtolower($attr['face']), $this->fontlist)) {
3864                          $this->SetFont(strtolower($attr['FACE']));
3865                          $this->issetfont=true;
3866                      }
3867                      if (isset($attr['size'])) {
3868                          $headsize = intval($attr['size']);
3869                      } else {
3870                          $headsize = 0;
3871                      }
3872                      $currentFontSize = $this->FontSize;
3873                      $this->tempfontsize = $this->FontSizePt;
3874                      $this->SetFontSize($this->FontSizePt + $headsize);
3875                      $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO;
3876                      break;
3877                  }
3878                  case 'h1': 
3879                  case 'h2': 
3880                  case 'h3': 
3881                  case 'h4': 
3882                  case 'h5': 
3883                  case 'h6': {
3884                      $headsize = (4 - substr($tag, 1)) * 2;
3885                      $currentFontSize = $this->FontSize;
3886                      $this->tempfontsize = $this->FontSizePt;
3887                      $this->SetFontSize($this->FontSizePt + $headsize);
3888                      $this->setStyle('b', true);
3889                      $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO;
3890                      break;
3891                  }
3892              }
3893          }
3894          
3895          /**

3896           * Process closing tags.

3897           * @param string $tag tag name (in uppercase)

3898           * @access private

3899           */
3900  		private function closedHTMLTagHandler($tag) {
3901              //Closing tag

3902              switch($tag) {
3903                  case 'td':
3904                  case 'th': {
3905                      $this->tdbegin = false;
3906                      $this->tdwidth = 0;
3907                      $this->tdheight = 0;
3908                      $this->tdalign = "L";
3909                      $this->tdbgcolor = false;
3910                      break;
3911                  }
3912                  case 'tr': {
3913                      $this->Ln();
3914                      break;
3915                  }
3916                  case 'table': {
3917                      $this->tableborder=0;
3918                      break;
3919                  }
3920                  case 'strong': {
3921                      $tag = 'b';
3922                      $this->setStyle($tag, false);
3923                      break;
3924                  }
3925                  case 'em': {
3926                      $tag = 'i';
3927                      break;
3928                  }
3929                  case 'strong':
3930                  case 'b':
3931                  case 'i':
3932                  case 'u': {
3933                      $this->setStyle($tag, false);
3934                      break;
3935                  }
3936                  case 'a': {
3937                      $this->HREF = '';
3938                      break;
3939                  }
3940                  case 'sup': {
3941                      $currentFontSize = $this->FontSize;
3942                      $this->SetFontSize($this->tempfontsize);
3943                      $this->tempfontsize = $this->FontSizePt;
3944                      $this->SetXY($this->GetX(), $this->GetY() - (($currentFontSize - $this->FontSize)*(K_SMALL_RATIO)));
3945                      break;
3946                  }
3947                  case 'sub': {
3948                      $currentFontSize = $this->FontSize;
3949                      $this->SetFontSize($this->tempfontsize);
3950                      $this->tempfontsize = $this->FontSizePt;
3951                      $this->SetXY($this->GetX(), $this->GetY() + (($currentFontSize - $this->FontSize)*(K_SMALL_RATIO)));
3952                      break;
3953                  }
3954                  case 'small': {
3955                      $currentFontSize = $this->FontSize;
3956                      $this->SetFontSize($this->tempfontsize);
3957                      $this->tempfontsize = $this->FontSizePt;
3958                      $this->SetXY($this->GetX(), $this->GetY() - (($this->FontSize - $currentFontSize)/3));
3959                      break;
3960                  }
3961                  case 'font': {
3962                      if ($this->issetcolor == true) {
3963                          $this->SetTextColor(0);
3964                      }
3965                      if ($this->issetfont) {
3966                          $this->SetFont('arial');
3967                          $this->issetfont = false;
3968                      }
3969                      $currentFontSize = $this->