[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3master/var/www/se3/html2pdf/_tcpdf_5.0.002/ -> tcpdf.php (source)

   1  <?php
   2  //============================================================+
   3  // File name   : tcpdf.php
   4  // Begin       : 2002-08-03
   5  // Last Update : 2010-05-06
   6  // Author      : Nicola Asuni - info@tecnick.com - http://www.tcpdf.org
   7  // Version     : 5.0.002
   8  // License     : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
   9  //     ----------------------------------------------------------------------------
  10  //  Copyright (C) 2002-2010  Nicola Asuni - Tecnick.com S.r.l.
  11  //
  12  //     This program is free software: you can redistribute it and/or modify
  13  //     it under the terms of the GNU Lesser General Public License as published by
  14  //     the Free Software Foundation, either version 2.1 of the License, or
  15  //     (at your option) any later version.
  16  //
  17  //     This program is distributed in the hope that it will be useful,
  18  //     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19  //     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20  //     GNU Lesser General Public License for more details.
  21  //
  22  //     You should have received a copy of the GNU Lesser General Public License
  23  //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24  //
  25  //     See LICENSE.TXT file for more information.
  26  //  ----------------------------------------------------------------------------
  27  //
  28  // Description : This is a PHP class for generating PDF documents without
  29  //               requiring external extensions.
  30  //
  31  // NOTE:
  32  // This class was originally derived in 2002 from the Public
  33  // Domain FPDF class by Olivier Plathey (http://www.fpdf.org),
  34  // but now is almost entirely rewritten.
  35  //
  36  // Main features:
  37  //  * no external libraries are required for the basic functions;
  38  //  * all ISO page formats, custom page formats, custom margins and units of measure;
  39  //  * UTF-8 Unicode and Right-To-Left languages;
  40  //  * TrueTypeUnicode, OpenTypeUnicode, TrueType, OpenType, Type1 and CID-0 fonts;
  41  //  * methods to publish some XHTML code, Javascript and Forms;
  42  //  * images, graphic (geometric figures) and transformation methods;
  43  //  * supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http://www.imagemagick.org/www/formats.html)
  44  //  * 1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extention, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, QR-Code;
  45  //  * Grayscale, RGB, CMYK, Spot Colors and Transparencies;
  46  //  * automatic page header and footer management;
  47  //  * document encryption and digital signature certifications;
  48  //  * transactions to UNDO commands;
  49  //  * PDF annotations, including links, text and file attachments;
  50  //  * text rendering modes (fill, stroke and clipping);
  51  //  * multiple columns mode;
  52  //  * bookmarks and table of content;
  53  //  * text hyphenation;
  54  //  * automatic page break, line break and text alignments including justification;
  55  //  * automatic page numbering and page groups;
  56  //  * move and delete pages;
  57  //  * page compression (requires php-zlib extension);
  58  //
  59  // -----------------------------------------------------------
  60  // THANKS TO:
  61  //
  62  // Olivier Plathey (http://www.fpdf.org) for original FPDF.
  63  // Efthimios Mavrogeorgiadis (emavro@yahoo.com) for suggestions on RTL language support.
  64  // Klemen Vodopivec (http://www.fpdf.de/downloads/addons/37/) for Encryption algorithm.
  65  // Warren Sherliker (wsherliker@gmail.com) for better image handling.
  66  // dullus for text Justification.
  67  // Bob Vincent (pillarsdotnet@users.sourceforge.net) for <li> value attribute.
  68  // Patrick Benny for text stretch suggestion on Cell().
  69  // Johannes Güntert for JavaScript support.
  70  // Denis Van Nuffelen for Dynamic Form.
  71  // Jacek Czekaj for multibyte justification
  72  // Anthony Ferrara for the reintroduction of legacy image methods.
  73  // Sourceforge user 1707880 (hucste) for line-trough mode.
  74  // Larry Stanbery for page groups.
  75  // Martin Hall-May for transparency.
  76  // Aaron C. Spike for Polycurve method.
  77  // Mohamad Ali Golkar, Saleh AlMatrafe, Charles Abbott for Arabic and Persian support.
  78  // Moritz Wagner and Andreas Wurmser for graphic functions.
  79  // Andrew Whitehead for core fonts support.
  80  // Esteban Joël Marín for OpenType font conversion.
  81  // Teus Hagen for several suggestions and fixes.
  82  // Yukihiro Nakadaira for CID-0 CJK fonts fixes.
  83  // Kosmas Papachristos for some CSS improvements.
  84  // Marcel Partap for some fixes.
  85  // Won Kyu Park for several suggestions, fixes and patches.
  86  // Dominik Dzienia for QR-code support.
  87  // Laurent Minguet for some suggestions.
  88  // Anyone that has reported a bug or sent a suggestion.
  89  //============================================================+
  90  
  91  /**
  92   * This is a PHP class for generating PDF documents without requiring external extensions.<br>
  93   * TCPDF project (http://www.tcpdf.org) was originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.<br>
  94   * <h3>TCPDF main features are:</h3>
  95   * <ul>
  96   * <li>no external libraries are required for the basic functions;</li>
  97   * <li>all ISO page formats, custom page formats, custom margins and units of measure;</li>
  98   * <li>UTF-8 Unicode and Right-To-Left languages;</li>
  99   * <li>TrueTypeUnicode, OpenTypeUnicode, TrueType, OpenType, Type1 and CID-0 fonts;</li>
 100   * <li>methods to publish some XHTML code, Javascript and Forms;</li>
 101   * <li>images, graphic (geometric figures) and transformation methods;
 102   * <li>supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http://www.imagemagick.org/www/formats.html)</li>
 103   * <li>1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extention, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, QR-Code;</li>
 104   * <li>Grayscale, RGB, CMYK, Spot Colors and Transparencies;</li>
 105   * <li>automatic page header and footer management;</li>
 106   * <li>document encryption and digital signature certifications;</li>
 107   * <li>transactions to UNDO commands;</li>
 108   * <li>PDF annotations, including links, text and file attachments;</li>
 109   * <li>text rendering modes (fill, stroke and clipping);</li>
 110   * <li>multiple columns mode;</li>
 111   * <li>bookmarks and table of content;</li>
 112   * <li>text hyphenation;</li>
 113   * <li>automatic page break, line break and text alignments including justification;</li>
 114   * <li>automatic page numbering and page groups;</li>
 115   * <li>move and delete pages;</li>
 116   * <li>page compression (requires php-zlib extension);</li>
 117   * </ul>
 118   * Tools to encode your unicode fonts are on fonts/utils directory.</p>
 119   * @package com.tecnick.tcpdf
 120   * @abstract Class for generating PDF files on-the-fly without requiring external extensions.
 121   * @author Nicola Asuni
 122   * @copyright 2002-2010 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
 123   * @link http://www.tcpdf.org
 124   * @license http://www.gnu.org/copyleft/lesser.html LGPL
 125   * @version 5.0.002
 126   */
 127  
 128  /**
 129   * main configuration file
 130   */
 131  require_once(dirname(__FILE__).'/config/tcpdf_config.php');
 132  
 133  // includes some support files
 134  
 135  /**
 136   * unicode data
 137   */
 138  require_once(dirname(__FILE__).'/unicode_data.php');
 139  
 140  /**
 141   * html colors table
 142   */
 143  require_once(dirname(__FILE__).'/htmlcolors.php');
 144  
 145  if (!class_exists('TCPDF', false)) {
 146      /**
 147       * define default PDF document producer
 148       */
 149      define('PDF_PRODUCER', 'TCPDF 5.0.002 (http://www.tcpdf.org)');
 150  
 151      /**
 152      * This is a PHP class for generating PDF documents without requiring external extensions.<br>
 153      * TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.<br>
 154      * @name TCPDF
 155      * @package com.tecnick.tcpdf
 156      * @version 5.0.002
 157      * @author Nicola Asuni - info@tecnick.com
 158      * @link http://www.tcpdf.org
 159      * @license http://www.gnu.org/copyleft/lesser.html LGPL
 160      */
 161      class TCPDF {
 162  
 163          // protected or Protected properties
 164  
 165          /**
 166           * @var current page number
 167           * @access protected
 168           */
 169          protected $page;
 170  
 171          /**
 172           * @var current object number
 173           * @access protected
 174           */
 175          protected $n;
 176  
 177          /**
 178           * @var array of object offsets
 179           * @access protected
 180           */
 181          protected $offsets;
 182  
 183          /**
 184           * @var buffer holding in-memory PDF
 185           * @access protected
 186           */
 187          protected $buffer;
 188  
 189          /**
 190           * @var array containing pages
 191           * @access protected
 192           */
 193          protected $pages = array();
 194  
 195          /**
 196           * @var current document state
 197           * @access protected
 198           */
 199          protected $state;
 200  
 201          /**
 202           * @var compression flag
 203           * @access protected
 204           */
 205          protected $compress;
 206  
 207          /**
 208           * @var current page orientation (P = Portrait, L = Landscape)
 209           * @access protected
 210           */
 211          protected $CurOrientation;
 212  
 213          /**
 214           * @var array that stores page dimensions and graphic status.<ul><li>$this->pagedim[$this->page]['w'] => page_width_in_points</li><li>$this->pagedim[$this->page]['h'] => height in points</li><li>$this->pagedim[$this->page]['wk'] => page_width_in_points</li><li>$this->pagedim[$this->page]['hk'] => height</li><li>$this->pagedim[$this->page]['tm'] => top_margin</li><li>$this->pagedim[$this->page]['bm'] => bottom_margin</li><li>$this->pagedim[$this->page]['lm'] => left_margin</li><li>$this->pagedim[$this->page]['rm'] => right_margin</li><li>$this->pagedim[$this->page]['pb'] => auto_page_break</li><li>$this->pagedim[$this->page]['or'] => page_orientation</li><li>$this->pagedim[$this->page]['olm'] => original_left_margin</li><li>$this->pagedim[$this->page]['orm'] => original_right_margin</li></ul>
 215           * @access protected
 216           */
 217          protected $pagedim = array();
 218  
 219          /**
 220           * @var scale factor (number of points in user unit)
 221           * @access protected
 222           */
 223          protected $k;
 224  
 225          /**
 226           * @var width of page format in points
 227           * @access protected
 228           */
 229          protected $fwPt;
 230  
 231          /**
 232           * @var height of page format in points
 233           * @access protected
 234           */
 235          protected $fhPt;
 236  
 237          /**
 238           * @var current width of page in points
 239           * @access protected
 240           */
 241          protected $wPt;
 242  
 243          /**
 244           * @var current height of page in points
 245           * @access protected
 246           */
 247          protected $hPt;
 248  
 249          /**
 250           * @var current width of page in user unit
 251           * @access protected
 252           */
 253          protected $w;
 254  
 255          /**
 256           * @var current height of page in user unit
 257           * @access protected
 258           */
 259          protected $h;
 260  
 261          /**
 262           * @var left margin
 263           * @access protected
 264           */
 265          protected $lMargin;
 266  
 267          /**
 268           * @var top margin
 269           * @access protected
 270           */
 271          protected $tMargin;
 272  
 273          /**
 274           * @var right margin
 275           * @access protected
 276           */
 277          protected $rMargin;
 278  
 279          /**
 280           * @var page break margin
 281           * @access protected
 282           */
 283          protected $bMargin;
 284  
 285          /**
 286           * @var cell internal padding
 287           * @access protected
 288           */
 289          //protected
 290          public $cMargin;
 291  
 292          /**
 293           * @var cell internal padding (previous value)
 294           * @access protected
 295           */
 296          protected $oldcMargin;
 297  
 298          /**
 299           * @var current horizontal position in user unit for cell positioning
 300           * @access protected
 301           */
 302          protected $x;
 303  
 304          /**
 305           * @var current vertical position in user unit for cell positioning
 306           * @access protected
 307           */
 308          protected $y;
 309  
 310          /**
 311           * @var height of last cell printed
 312           * @access protected
 313           */
 314          protected $lasth;
 315  
 316          /**
 317           * @var line width in user unit
 318           * @access protected
 319           */
 320          protected $LineWidth;
 321  
 322          /**
 323           * @var array of standard font names
 324           * @access protected
 325           */
 326          protected $CoreFonts;
 327  
 328          /**
 329           * @var array of used fonts
 330           * @access protected
 331           */
 332          protected $fonts = array();
 333  
 334          /**
 335           * @var array of font files
 336           * @access protected
 337           */
 338          protected $FontFiles = array();
 339  
 340          /**
 341           * @var array of encoding differences
 342           * @access protected
 343           */
 344          protected $diffs = array();
 345  
 346          /**
 347           * @var array of used images
 348           * @access protected
 349           */
 350          protected $images = array();
 351  
 352          /**
 353           * @var array of Annotations in pages
 354           * @access protected
 355           */
 356          protected $PageAnnots = array();
 357  
 358          /**
 359           * @var array of internal links
 360           * @access protected
 361           */
 362          protected $links = array();
 363  
 364          /**
 365           * @var current font family
 366           * @access protected
 367           */
 368          protected $FontFamily;
 369  
 370          /**
 371           * @var current font style
 372           * @access protected
 373           */
 374          protected $FontStyle;
 375  
 376          /**
 377           * @var current font ascent (distance between font top and baseline)
 378           * @access protected
 379           * @since 2.8.000 (2007-03-29)
 380           */
 381          protected $FontAscent;
 382  
 383          /**
 384           * @var current font descent (distance between font bottom and baseline)
 385           * @access protected
 386           * @since 2.8.000 (2007-03-29)
 387           */
 388          protected $FontDescent;
 389  
 390          /**
 391           * @var underlining flag
 392           * @access protected
 393           */
 394          protected $underline;
 395  
 396          /**
 397           * @var overlining flag
 398           * @access protected
 399           */
 400          protected $overline;
 401  
 402          /**
 403           * @var current font info
 404           * @access protected
 405           */
 406          protected $CurrentFont;
 407  
 408          /**
 409           * @var current font size in points
 410           * @access protected
 411           */
 412          protected $FontSizePt;
 413  
 414          /**
 415           * @var current font size in user unit
 416           * @access protected
 417           */
 418          protected $FontSize;
 419  
 420          /**
 421           * @var commands for drawing color
 422           * @access protected
 423           */
 424          protected $DrawColor;
 425  
 426          /**
 427           * @var commands for filling color
 428           * @access protected
 429           */
 430          protected $FillColor;
 431  
 432          /**
 433           * @var commands for text color
 434           * @access protected
 435           */
 436          protected $TextColor;
 437  
 438          /**
 439           * @var indicates whether fill and text colors are different
 440           * @access protected
 441           */
 442          protected $ColorFlag;
 443  
 444          /**
 445           * @var automatic page breaking
 446           * @access protected
 447           */
 448          protected $AutoPageBreak;
 449  
 450          /**
 451           * @var threshold used to trigger page breaks
 452           * @access protected
 453           */
 454          protected $PageBreakTrigger;
 455  
 456          /**
 457           * @var flag set when processing footer
 458           * @access protected
 459           */
 460          protected $InFooter = false;
 461  
 462          /**
 463           * @var zoom display mode
 464           * @access protected
 465           */
 466          protected $ZoomMode;
 467  
 468          /**
 469           * @var layout display mode
 470           * @access protected
 471           */
 472          protected $LayoutMode;
 473  
 474          /**
 475           * @var title
 476           * @access protected
 477           */
 478          protected $title = '';
 479  
 480          /**
 481           * @var subject
 482           * @access protected
 483           */
 484          protected $subject = '';
 485  
 486          /**
 487           * @var author
 488           * @access protected
 489           */
 490          protected $author = '';
 491  
 492          /**
 493           * @var keywords
 494           * @access protected
 495           */
 496          protected $keywords = '';
 497  
 498          /**
 499           * @var creator
 500           * @access protected
 501           */
 502          protected $creator = '';
 503  
 504          /**
 505           * @var alias for total number of pages
 506           * @access protected
 507           */
 508          protected $AliasNbPages = '{nb}';
 509  
 510          /**
 511           * @var alias for page number
 512           * @access protected
 513           */
 514          protected $AliasNumPage = '{pnb}';
 515  
 516          /**
 517           * @var right-bottom corner X coordinate of inserted image
 518           * @since 2002-07-31
 519           * @author Nicola Asuni
 520           * @access protected
 521           */
 522          protected $img_rb_x;
 523  
 524          /**
 525           * @var right-bottom corner Y coordinate of inserted image
 526           * @since 2002-07-31
 527           * @author Nicola Asuni
 528           * @access protected
 529           */
 530          protected $img_rb_y;
 531  
 532          /**
 533           * @var adjusting factor to convert pixels to user units.
 534           * @since 2004-06-14
 535           * @author Nicola Asuni
 536           * @access protected
 537           */
 538          protected $imgscale = 1;
 539  
 540          /**
 541           * @var boolean set to true when the input text is unicode (require unicode fonts)
 542           * @since 2005-01-02
 543           * @author Nicola Asuni
 544           * @access protected
 545           */
 546          protected $isunicode = false;
 547  
 548          /**
 549           * @var PDF version
 550           * @since 1.5.3
 551           * @access protected
 552           */
 553          protected $PDFVersion = '1.7';
 554  
 555          /**
 556           * @var Minimum distance between header and top page margin.
 557           * @access protected
 558           */
 559          protected $header_margin;
 560  
 561          /**
 562           * @var Minimum distance between footer and bottom page margin.
 563           * @access protected
 564           */
 565          protected $footer_margin;
 566  
 567          /**
 568           * @var original left margin value
 569           * @access protected
 570           * @since 1.53.0.TC013
 571           */
 572          protected $original_lMargin;
 573  
 574          /**
 575           * @var original right margin value
 576           * @access protected
 577           * @since 1.53.0.TC013
 578           */
 579          protected $original_rMargin;
 580  
 581          /**
 582           * @var Header font.
 583           * @access protected
 584           */
 585          protected $header_font;
 586  
 587          /**
 588           * @var Footer font.
 589           * @access protected
 590           */
 591          protected $footer_font;
 592  
 593          /**
 594           * @var Language templates.
 595           * @access protected
 596           */
 597          protected $l;
 598  
 599          /**
 600           * @var Barcode to print on page footer (only if set).
 601           * @access protected
 602           */
 603          protected $barcode = false;
 604  
 605          /**
 606           * @var If true prints header
 607           * @access protected
 608           */
 609          protected $print_header = true;
 610  
 611          /**
 612           * @var If true prints footer.
 613           * @access protected
 614           */
 615          protected $print_footer = true;
 616  
 617          /**
 618           * @var Header image logo.
 619           * @access protected
 620           */
 621          protected $header_logo = '';
 622  
 623          /**
 624           * @var Header image logo width in mm.
 625           * @access protected
 626           */
 627          protected $header_logo_width = 30;
 628  
 629          /**
 630           * @var String to print as title on document header.
 631           * @access protected
 632           */
 633          protected $header_title = '';
 634  
 635          /**
 636           * @var String to print on document header.
 637           * @access protected
 638           */
 639          protected $header_string = '';
 640  
 641          /**
 642           * @var Default number of columns for html table.
 643           * @access protected
 644           */
 645          protected $default_table_columns = 4;
 646  
 647  
 648          // variables for html parser
 649  
 650          /**
 651           * @var HTML PARSER: array to store current link and rendering styles.
 652           * @access protected
 653           */
 654          protected $HREF = array();
 655  
 656          /**
 657           * @var store a list of available fonts on filesystem.
 658           * @access protected
 659           */
 660          protected $fontlist = array();
 661  
 662          /**
 663           * @var current foreground color
 664           * @access protected
 665           */
 666          protected $fgcolor;
 667  
 668          /**
 669           * @var HTML PARSER: array of boolean values, true in case of ordered list (OL), false otherwise.
 670           * @access protected
 671           */
 672          protected $listordered = array();
 673  
 674          /**
 675           * @var HTML PARSER: array count list items on nested lists.
 676           * @access protected
 677           */
 678          protected $listcount = array();
 679  
 680          /**
 681           * @var HTML PARSER: current list nesting level.
 682           * @access protected
 683           */
 684          protected $listnum = 0;
 685  
 686          /**
 687           * @var HTML PARSER: indent amount for lists.
 688           * @access protected
 689           */
 690          protected $listindent = 0;
 691  
 692          /**
 693           * @var HTML PARSER: current list indententation level.
 694           * @access protected
 695           */
 696          protected $listindentlevel = 0;
 697  
 698          /**
 699           * @var current background color
 700           * @access protected
 701           */
 702          protected $bgcolor;
 703  
 704          /**
 705           * @var Store temporary font size in points.
 706           * @access protected
 707           */
 708          protected $tempfontsize = 10;
 709  
 710          /**
 711           * @var spacer for LI tags.
 712           * @access protected
 713           */
 714          protected $lispacer = '';
 715  
 716          /**
 717           * @var default encoding
 718           * @access protected
 719           * @since 1.53.0.TC010
 720           */
 721          protected $encoding = 'UTF-8';
 722  
 723          /**
 724           * @var PHP internal encoding
 725           * @access protected
 726           * @since 1.53.0.TC016
 727           */
 728          protected $internal_encoding;
 729  
 730          /**
 731           * @var indicates if the document language is Right-To-Left
 732           * @access protected
 733           * @since 2.0.000
 734           */
 735          protected $rtl = false;
 736  
 737          /**
 738           * @var used to force RTL or LTR string inversion
 739           * @access protected
 740           * @since 2.0.000
 741           */
 742          protected $tmprtl = false;
 743  
 744          // --- Variables used for document encryption:
 745  
 746          /**
 747           * Indicates whether document is protected
 748           * @access protected
 749           * @since 2.0.000 (2008-01-02)
 750           */
 751          protected $encrypted;
 752  
 753          /**
 754           * U entry in pdf document
 755           * @access protected
 756           * @since 2.0.000 (2008-01-02)
 757           */
 758          protected $Uvalue;
 759  
 760          /**
 761           * O entry in pdf document
 762           * @access protected
 763           * @since 2.0.000 (2008-01-02)
 764           */
 765          protected $Ovalue;
 766  
 767          /**
 768           * P entry in pdf document
 769           * @access protected
 770           * @since 2.0.000 (2008-01-02)
 771           */
 772          protected $Pvalue;
 773  
 774          /**
 775           * encryption object id
 776           * @access protected
 777           * @since 2.0.000 (2008-01-02)
 778           */
 779          protected $enc_obj_id;
 780  
 781          /**
 782           * last RC4 key encrypted (cached for optimisation)
 783           * @access protected
 784           * @since 2.0.000 (2008-01-02)
 785           */
 786          protected $last_rc4_key;
 787  
 788          /**
 789           * last RC4 computed key
 790           * @access protected
 791           * @since 2.0.000 (2008-01-02)
 792           */
 793          protected $last_rc4_key_c;
 794  
 795          /**
 796           * RC4 padding
 797           * @access protected
 798           */
 799          protected $padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
 800  
 801          /**
 802           * RC4 encryption key
 803           * @access protected
 804           */
 805          protected $encryption_key;
 806  
 807          // --- bookmark ---
 808  
 809          /**
 810           * Outlines for bookmark
 811           * @access protected
 812           * @since 2.1.002 (2008-02-12)
 813           */
 814          protected $outlines = array();
 815  
 816          /**
 817           * Outline root for bookmark
 818           * @access protected
 819           * @since 2.1.002 (2008-02-12)
 820           */
 821          protected $OutlineRoot;
 822  
 823  
 824          // --- javascript and form ---
 825  
 826          /**
 827           * javascript code
 828           * @access protected
 829           * @since 2.1.002 (2008-02-12)
 830           */
 831          protected $javascript = '';
 832  
 833          /**
 834           * javascript counter
 835           * @access protected
 836           * @since 2.1.002 (2008-02-12)
 837           */
 838          protected $n_js;
 839  
 840          /**
 841           * line trough state
 842           * @access protected
 843           * @since 2.8.000 (2008-03-19)
 844           */
 845          protected $linethrough;
 846  
 847          // --- Variables used for User's Rights ---
 848          // See PDF reference chapter 8.7 Digital Signatures
 849  
 850          /**
 851           * If true enables user's rights on PDF reader
 852           * @access protected
 853           * @since 2.9.000 (2008-03-26)
 854           */
 855          protected $ur;
 856  
 857          /**
 858           * Names specifying additional document-wide usage rights for the document.
 859           * @access protected
 860           * @since 2.9.000 (2008-03-26)
 861           */
 862          protected $ur_document;
 863  
 864          /**
 865           * Names specifying additional annotation-related usage rights for the document.
 866           * @access protected
 867           * @since 2.9.000 (2008-03-26)
 868           */
 869          protected $ur_annots;
 870  
 871          /**
 872           * Names specifying additional form-field-related usage rights for the document.
 873           * @access protected
 874           * @since 2.9.000 (2008-03-26)
 875           */
 876          protected $ur_form;
 877  
 878          /**
 879           * Names specifying additional signature-related usage rights for the document.
 880           * @access protected
 881           * @since 2.9.000 (2008-03-26)
 882           */
 883          protected $ur_signature;
 884  
 885          /**
 886           * Dot Per Inch Document Resolution (do not change)
 887           * @access protected
 888           * @since 3.0.000 (2008-03-27)
 889           */
 890          protected $dpi = 72;
 891  
 892          /**
 893           * Array of page numbers were a new page group was started
 894           * @access protected
 895           * @since 3.0.000 (2008-03-27)
 896           */
 897          protected $newpagegroup = array();
 898  
 899          /**
 900           * Contains the number of pages of the groups
 901           * @access protected
 902           * @since 3.0.000 (2008-03-27)
 903           */
 904          protected $pagegroups;
 905  
 906          /**
 907           * Contains the alias of the current page group
 908           * @access protected
 909           * @since 3.0.000 (2008-03-27)
 910           */
 911          protected $currpagegroup;
 912  
 913          /**
 914           * Restrict the rendering of some elements to screen or printout.
 915           * @access protected
 916           * @since 3.0.000 (2008-03-27)
 917           */
 918          protected $visibility = 'all';
 919  
 920          /**
 921           * Print visibility.
 922           * @access protected
 923           * @since 3.0.000 (2008-03-27)
 924           */
 925          protected $n_ocg_print;
 926  
 927          /**
 928           * View visibility.
 929           * @access protected
 930           * @since 3.0.000 (2008-03-27)
 931           */
 932          protected $n_ocg_view;
 933  
 934          /**
 935           * Array of transparency objects and parameters.
 936           * @access protected
 937           * @since 3.0.000 (2008-03-27)
 938           */
 939          protected $extgstates;
 940  
 941          /**
 942           * Set the default JPEG compression quality (1-100)
 943           * @access protected
 944           * @since 3.0.000 (2008-03-27)
 945           */
 946          protected $jpeg_quality;
 947  
 948          /**
 949           * Default cell height ratio.
 950           * @access protected
 951           * @since 3.0.014 (2008-05-23)
 952           */
 953          protected $cell_height_ratio = K_CELL_HEIGHT_RATIO;
 954  
 955          /**
 956           * PDF viewer preferences.
 957           * @access protected
 958           * @since 3.1.000 (2008-06-09)
 959           */
 960          protected $viewer_preferences;
 961  
 962          /**
 963           * A name object specifying how the document should be displayed when opened.
 964           * @access protected
 965           * @since 3.1.000 (2008-06-09)
 966           */
 967          protected $PageMode;
 968  
 969          /**
 970           * Array for storing gradient information.
 971           * @access protected
 972           * @since 3.1.000 (2008-06-09)
 973           */
 974          protected $gradients = array();
 975  
 976          /**
 977           * Array used to store positions inside the pages buffer.
 978           * keys are the page numbers
 979           * @access protected
 980           * @since 3.2.000 (2008-06-26)
 981           */
 982          protected $intmrk = array();
 983  
 984          /**
 985           * Array used to store content positions inside the pages buffer.
 986           * keys are the page numbers
 987           * @access protected
 988           * @since 4.6.021 (2009-07-20)
 989           */
 990          protected $cntmrk = array();
 991  
 992          /**
 993           * Array used to store footer positions of each page.
 994           * @access protected
 995           * @since 3.2.000 (2008-07-01)
 996           */
 997          protected $footerpos = array();
 998  
 999  
1000          /**
1001           * Array used to store footer length of each page.
1002           * @access protected
1003           * @since 4.0.014 (2008-07-29)
1004           */
1005          protected $footerlen = array();
1006  
1007          /**
1008           * True if a newline is created.
1009           * @access protected
1010           * @since 3.2.000 (2008-07-01)
1011           */
1012          protected $newline = true;
1013  
1014          /**
1015           * End position of the latest inserted line
1016           * @access protected
1017           * @since 3.2.000 (2008-07-01)
1018           */
1019          protected $endlinex = 0;
1020  
1021          /**
1022           * PDF string for last line width
1023           * @access protected
1024           * @since 4.0.006 (2008-07-16)
1025           */
1026          protected $linestyleWidth = '';
1027  
1028          /**
1029           * PDF string for last line width
1030           * @access protected
1031           * @since 4.0.006 (2008-07-16)
1032           */
1033          protected $linestyleCap = '0 J';
1034  
1035          /**
1036           * PDF string for last line width
1037           * @access protected
1038           * @since 4.0.006 (2008-07-16)
1039           */
1040          protected $linestyleJoin = '0 j';
1041  
1042          /**
1043           * PDF string for last line width
1044           * @access protected
1045           * @since 4.0.006 (2008-07-16)
1046           */
1047          protected $linestyleDash = '[] 0 d';
1048  
1049          /**
1050           * True if marked-content sequence is open
1051           * @access protected
1052           * @since 4.0.013 (2008-07-28)
1053           */
1054          protected $openMarkedContent = false;
1055  
1056          /**
1057           * Count the latest inserted vertical spaces on HTML
1058           * @access protected
1059           * @since 4.0.021 (2008-08-24)
1060           */
1061          protected $htmlvspace = 0;
1062  
1063          /**
1064           * Array of Spot colors
1065           * @access protected
1066           * @since 4.0.024 (2008-09-12)
1067           */
1068          protected $spot_colors = array();
1069  
1070          /**
1071           * Symbol used for HTML unordered list items
1072           * @access protected
1073           * @since 4.0.028 (2008-09-26)
1074           */
1075          protected $lisymbol = '';
1076  
1077          /**
1078           * String used to mark the beginning and end of EPS image blocks
1079           * @access protected
1080           * @since 4.1.000 (2008-10-18)
1081           */
1082          protected $epsmarker = 'x#!#EPS#!#x';
1083  
1084          /**
1085           * Array of transformation matrix
1086           * @access protected
1087           * @since 4.2.000 (2008-10-29)
1088           */
1089          protected $transfmatrix = array();
1090  
1091          /**
1092           * Current key for transformation matrix
1093           * @access protected
1094           * @since 4.8.005 (2009-09-17)
1095           */
1096          protected $transfmatrix_key = 0;
1097  
1098          /**
1099           * Booklet mode for double-sided pages
1100           * @access protected
1101           * @since 4.2.000 (2008-10-29)
1102           */
1103          protected $booklet = false;
1104  
1105          /**
1106           * Epsilon value used for float calculations
1107           * @access protected
1108           * @since 4.2.000 (2008-10-29)
1109           */
1110          protected $feps = 0.005;
1111  
1112          /**
1113           * Array used for custom vertical spaces for HTML tags
1114           * @access protected
1115           * @since 4.2.001 (2008-10-30)
1116           */
1117          protected $tagvspaces = array();
1118  
1119          /**
1120           * @var HTML PARSER: custom indent amount for lists.
1121           * Negative value means disabled.
1122           * @access protected
1123           * @since 4.2.007 (2008-11-12)
1124           */
1125          protected $customlistindent = -1;
1126  
1127          /**
1128           * @var if true keeps the border open for the cell sides that cross the page.
1129           * @access protected
1130           * @since 4.2.010 (2008-11-14)
1131           */
1132          protected $opencell = true;
1133  
1134          /**
1135           * @var array of files to embedd
1136           * @access protected
1137           * @since 4.4.000 (2008-12-07)
1138           */
1139          protected $embeddedfiles = array();
1140  
1141          /**
1142           * @var boolean true when inside html pre tag
1143           * @access protected
1144           * @since 4.4.001 (2008-12-08)
1145           */
1146          protected $premode = false;
1147  
1148          /**
1149           * Array used to store positions of graphics transformation blocks inside the page buffer.
1150           * keys are the page numbers
1151           * @access protected
1152           * @since 4.4.002 (2008-12-09)
1153           */
1154          protected $transfmrk = array();
1155  
1156          /**
1157           * Default color for html links
1158           * @access protected
1159           * @since 4.4.003 (2008-12-09)
1160           */
1161          protected $htmlLinkColorArray = array(0, 0, 255);
1162  
1163          /**
1164           * Default font style to add to html links
1165           * @access protected
1166           * @since 4.4.003 (2008-12-09)
1167           */
1168          protected $htmlLinkFontStyle = 'U';
1169  
1170          /**
1171           * Counts the number of pages.
1172           * @access protected
1173           * @since 4.5.000 (2008-12-31)
1174           */
1175          protected $numpages = 0;
1176  
1177          /**
1178           * Array containing page lengths in bytes.
1179           * @access protected
1180           * @since 4.5.000 (2008-12-31)
1181           */
1182          protected $pagelen = array();
1183  
1184          /**
1185           * Counts the number of pages.
1186           * @access protected
1187           * @since 4.5.000 (2008-12-31)
1188           */
1189          protected $numimages = 0;
1190  
1191          /**
1192           * Store the image keys.
1193           * @access protected
1194           * @since 4.5.000 (2008-12-31)
1195           */
1196          protected $imagekeys = array();
1197  
1198          /**
1199           * Length of the buffer in bytes.
1200           * @access protected
1201           * @since 4.5.000 (2008-12-31)
1202           */
1203          protected $bufferlen = 0;
1204  
1205          /**
1206           * If true enables disk caching.
1207           * @access protected
1208           * @since 4.5.000 (2008-12-31)
1209           */
1210          protected $diskcache = false;
1211  
1212          /**
1213           * Counts the number of fonts.
1214           * @access protected
1215           * @since 4.5.000 (2009-01-02)
1216           */
1217          protected $numfonts = 0;
1218  
1219          /**
1220           * Store the font keys.
1221           * @access protected
1222           * @since 4.5.000 (2009-01-02)
1223           */
1224          protected $fontkeys = array();
1225  
1226          /**
1227           * Store the font object IDs.
1228           * @access protected
1229           * @since 4.8.001 (2009-09-09)
1230           */
1231          protected $font_obj_ids = array();
1232  
1233          /**
1234           * Store the fage status (true when opened, false when closed).
1235           * @access protected
1236           * @since 4.5.000 (2009-01-02)
1237           */
1238          protected $pageopen = array();
1239  
1240          /**
1241           * Default monospaced font
1242           * @access protected
1243           * @since 4.5.025 (2009-03-10)
1244           */
1245          protected $default_monospaced_font = 'courier';
1246  
1247          /**
1248           * Used to store a cloned copy of the current class object
1249           * @access protected
1250           * @since 4.5.029 (2009-03-19)
1251           */
1252          protected $objcopy;
1253  
1254          /**
1255           * Array used to store the lengths of cache files
1256           * @access protected
1257           * @since 4.5.029 (2009-03-19)
1258           */
1259          protected $cache_file_length = array();
1260  
1261          /**
1262           * Table header content to be repeated on each new page
1263           * @access protected
1264           * @since 4.5.030 (2009-03-20)
1265           */
1266          protected $thead = '';
1267  
1268          /**
1269           * Margins used for table header.
1270           * @access protected
1271           * @since 4.5.030 (2009-03-20)
1272           */
1273          protected $theadMargins = array();
1274  
1275          /**
1276           * Cache array for UTF8StringToArray() method.
1277           * @access protected
1278           * @since 4.5.037 (2009-04-07)
1279           */
1280          protected $cache_UTF8StringToArray = array();
1281  
1282          /**
1283           * Maximum size of cache array used for UTF8StringToArray() method.
1284           * @access protected
1285           * @since 4.5.037 (2009-04-07)
1286           */
1287          protected $cache_maxsize_UTF8StringToArray = 8;
1288  
1289          /**
1290           * Current size of cache array used for UTF8StringToArray() method.
1291           * @access protected
1292           * @since 4.5.037 (2009-04-07)
1293           */
1294          protected $cache_size_UTF8StringToArray = 0;
1295  
1296          /**
1297           * If true enables document signing
1298           * @access protected
1299           * @since 4.6.005 (2009-04-24)
1300           */
1301          protected $sign = false;
1302  
1303          /**
1304           * Signature data
1305           * @access protected
1306           * @since 4.6.005 (2009-04-24)
1307           */
1308          protected $signature_data = array();
1309  
1310          /**
1311           * Signature max length
1312           * @access protected
1313           * @since 4.6.005 (2009-04-24)
1314           */
1315          protected $signature_max_length = 11742;
1316  
1317          /**
1318           * Regular expression used to find blank characters used for word-wrapping.
1319           * @access protected
1320           * @since 4.6.006 (2009-04-28)
1321           */
1322          protected $re_spaces = '/[\s]/';
1323  
1324          /**
1325           * Signature object ID
1326           * @access protected
1327           * @since 4.6.022 (2009-06-23)
1328           */
1329          protected $sig_obj_id = 0;
1330  
1331          /**
1332           * ByteRange placemark used during signature process.
1333           * @access protected
1334           * @since 4.6.028 (2009-08-25)
1335           */
1336          protected $byterange_string = '/ByteRange[0 ********** ********** **********]';
1337  
1338          /**
1339           * Placemark used during signature process.
1340           * @access protected
1341           * @since 4.6.028 (2009-08-25)
1342           */
1343          protected $sig_annot_ref = '***SIGANNREF*** 0 R';
1344  
1345          /**
1346           * ID of page objects
1347           * @access protected
1348           * @since 4.7.000 (2009-08-29)
1349           */
1350          protected $page_obj_id = array();
1351  
1352          /**
1353           * Start ID for embedded file objects
1354           * @access protected
1355           * @since 4.7.000 (2009-08-29)
1356           */
1357          protected $embedded_start_obj_id = 100000;
1358  
1359          /**
1360           * Start ID for annotation objects
1361           * @access protected
1362           * @since 4.7.000 (2009-08-29)
1363           */
1364          protected $annots_start_obj_id = 200000;
1365  
1366          /**
1367           * Max ID of annotation object
1368           * @access protected
1369           * @since 4.7.000 (2009-08-29)
1370           */
1371          protected $annot_obj_id = 200000;
1372  
1373          /**
1374           * Current ID of annotation object
1375           * @access protected
1376           * @since 4.8.003 (2009-09-15)
1377           */
1378          protected $curr_annot_obj_id = 200000;
1379  
1380          /**
1381           * List of form annotations IDs
1382           * @access protected
1383           * @since 4.8.000 (2009-09-07)
1384           */
1385          protected $form_obj_id = array();
1386  
1387          /**
1388           * Deafult Javascript field properties. Possible values are described on official Javascript for Acrobat API reference. Annotation options can be directly specified using the 'aopt' entry.
1389           * @access protected
1390           * @since 4.8.000 (2009-09-07)
1391           */
1392          protected $default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
1393  
1394          /**
1395           * Javascript objects array
1396           * @access protected
1397           * @since 4.8.000 (2009-09-07)
1398           */
1399          protected $js_objects = array();
1400  
1401          /**
1402           * Start ID for javascript objects
1403           * @access protected
1404           * @since 4.8.000 (2009-09-07)
1405           */
1406          protected $js_start_obj_id = 300000;
1407  
1408          /**
1409           * Current ID of javascript object
1410           * @access protected
1411           * @since 4.8.000 (2009-09-07)
1412           */
1413          protected $js_obj_id = 300000;
1414  
1415          /**
1416           * Current form action (used during XHTML rendering)
1417           * @access protected
1418           * @since 4.8.000 (2009-09-07)
1419           */
1420          protected $form_action = '';
1421  
1422          /**
1423           * Current form encryption type (used during XHTML rendering)
1424           * @access protected
1425           * @since 4.8.000 (2009-09-07)
1426           */
1427          protected $form_enctype = 'application/x-www-form-urlencoded';
1428  
1429          /**
1430           * Current method to submit forms.
1431           * @access protected
1432           * @since 4.8.000 (2009-09-07)
1433           */
1434          protected $form_mode = 'post';
1435  
1436          /**
1437           * Start ID for appearance streams XObjects
1438           * @access protected
1439           * @since 4.8.001 (2009-09-09)
1440           */
1441          protected $apxo_start_obj_id = 400000;
1442  
1443          /**
1444           * Current ID of appearance streams XObjects
1445           * @access protected
1446           * @since 4.8.001 (2009-09-09)
1447           */
1448          protected $apxo_obj_id = 400000;
1449  
1450          /**
1451           * List of fonts used on form fields (fontname => fontkey).
1452           * @access protected
1453           * @since 4.8.001 (2009-09-09)
1454           */
1455          protected $annotation_fonts = array();
1456  
1457          /**
1458           * List of radio buttons parent objects.
1459           * @access protected
1460           * @since 4.8.001 (2009-09-09)
1461           */
1462          protected $radiobutton_groups = array();
1463  
1464          /**
1465           * List of radio group objects IDs
1466           * @access protected
1467           * @since 4.8.001 (2009-09-09)
1468           */
1469          protected $radio_groups = array();
1470  
1471          /**
1472           * Text indentation value (used for text-indent CSS attribute)
1473           * @access protected
1474           * @since 4.8.006 (2009-09-23)
1475           */
1476          protected $textindent = 0;
1477  
1478          /**
1479           * Store page number when startTransaction() is called.
1480           * @access protected
1481           * @since 4.8.006 (2009-09-23)
1482           */
1483          protected $start_transaction_page = 0;
1484  
1485          /**
1486           * Store Y position when startTransaction() is called.
1487           * @access protected
1488           * @since 4.9.001 (2010-03-28)
1489           */
1490          protected $start_transaction_y = 0;
1491  
1492          /**
1493           * True when we are printing the thead section on a new page
1494           * @access protected
1495           * @since 4.8.027 (2010-01-25)
1496           */
1497          protected $inthead = false;
1498  
1499          /**
1500           * Array of column measures (width, space, starting Y position)
1501           * @access protected
1502           * @since 4.9.001 (2010-03-28)
1503           */
1504          protected $columns = array();
1505  
1506          /**
1507           * Number of colums
1508           * @access protected
1509           * @since 4.9.001 (2010-03-28)
1510           */
1511          protected $num_columns = 0;
1512  
1513          /**
1514           * Current column number
1515           * @access protected
1516           * @since 4.9.001 (2010-03-28)
1517           */
1518          protected $current_column = 0;
1519  
1520          /**
1521           * Starting page for columns
1522           * @access protected
1523           * @since 4.9.001 (2010-03-28)
1524           */
1525          protected $column_start_page = 0;
1526  
1527          /**
1528           * Text rendering mode: 0 = Fill text; 1 = Stroke text; 2 = Fill, then stroke text; 3 = Neither fill nor stroke text (invisible); 4 = Fill text and add to path for clipping; 5 = Stroke text and add to path for clipping; 6 = Fill, then stroke text and add to path for clipping; 7 = Add text to path for clipping.
1529           * @access protected
1530           * @since 4.9.008 (2010-04-03)
1531           */
1532          protected $textrendermode = 0;
1533  
1534          /**
1535           * Text stroke width in doc units
1536           * @access protected
1537           * @since 4.9.008 (2010-04-03)
1538           */
1539          protected $textstrokewidth = 0;
1540  
1541          /**
1542           * @var current stroke color
1543           * @access protected
1544           * @since 4.9.008 (2010-04-03)
1545           */
1546          protected $strokecolor;
1547  
1548          /**
1549           * @var default unit of measure for document
1550           * @access protected
1551           * @since 5.0.000 (2010-04-22)
1552           */
1553          protected $pdfunit = 'mm';
1554  
1555          /**
1556           * @var true when we are on TOC (Table Of Content) page
1557           * @access protected
1558           */
1559          protected $tocpage = false;
1560  
1561          /**
1562           * @var If true convert vector images (SVG, EPS) to raster image using GD or ImageMagick library.
1563           * @access protected
1564           * @since 5.0.000 (2010-04-26)
1565           */
1566          protected $rasterize_vector_images = false;
1567  
1568          /**
1569           * @var directory used for the last SVG image
1570           * @access protected
1571           * @since 5.0.000 (2010-05-05)
1572           */
1573          protected $svgdir = '';
1574  
1575          /**
1576           * @var Deafult unit of measure for SVG
1577           * @access protected
1578           * @since 5.0.000 (2010-05-02)
1579           */
1580          protected $svgunit = 'px';
1581  
1582          /**
1583           * @var array of SVG gradients
1584           * @access protected
1585           * @since 5.0.000 (2010-05-02)
1586           */
1587          protected $svggradients = array();
1588  
1589          /**
1590           * @var ID of last SVG gradient
1591           * @access protected
1592           * @since 5.0.000 (2010-05-02)
1593           */
1594          protected $svggradientid = 0;
1595  
1596          /**
1597           * @var true when in SVG defs group
1598           * @access protected
1599           * @since 5.0.000 (2010-05-02)
1600           */
1601          protected $svgdefsmode = false;
1602  
1603          /**
1604           * @var array of SVG defs
1605           * @access protected
1606           * @since 5.0.000 (2010-05-02)
1607           */
1608          protected $svgdefs = array();
1609  
1610          /**
1611           * @var true when in SVG clipPath tag
1612           * @access protected
1613           * @since 5.0.000 (2010-04-26)
1614           */
1615          protected $svgclipmode = false;
1616  
1617          /**
1618           * @var array of SVG clipPath commands
1619           * @access protected
1620           * @since 5.0.000 (2010-05-02)
1621           */
1622          protected $svgclippaths = array();
1623  
1624          /**
1625           * @var ID of last SVG clipPath
1626           * @access protected
1627           * @since 5.0.000 (2010-05-02)
1628           */
1629          protected $svgclipid = 0;
1630  
1631          /**
1632           * @var svg text
1633           * @access protected
1634           * @since 5.0.000 (2010-05-02)
1635           */
1636          protected $svgtext = '';
1637  
1638          /**
1639           * @var array of hinheritable SVG properties
1640           * @access protected
1641           * @since 5.0.000 (2010-05-02)
1642           */
1643          protected $svginheritprop = array('clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'fill', 'fill-opacity', 'fill-rule', 'font', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'marker', 'marker-end', 'marker-mid', 'marker-start', 'pointer-events', 'shape-rendering', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-rendering', 'visibility', 'word-spacing', 'writing-mode');
1644  
1645          /**
1646           * @var array of SVG properties
1647           * @access protected
1648           * @since 5.0.000 (2010-05-02)
1649           */
1650          protected $svgstyles = array(array(
1651              'alignment-baseline' => 'auto',
1652              'baseline-shift' => 'baseline',
1653              'clip' => 'auto',
1654              'clip-path' => 'none',
1655              'clip-rule' => 'nonzero',
1656              'color' => 'black',
1657              'color-interpolation' => 'sRGB',
1658              'color-interpolation-filters' => 'linearRGB',
1659              'color-profile' => 'auto',
1660              'color-rendering' => 'auto',
1661              'cursor' => 'auto',
1662              'direction' => 'ltr',
1663              'display' => 'inline',
1664              'dominant-baseline' => 'auto',
1665              'enable-background' => 'accumulate',
1666              'fill' => 'black',
1667              'fill-opacity' => 1,
1668              'fill-rule' => 'nonzero',
1669              'filter' => 'none',
1670              'flood-color' => 'black',
1671              'flood-opacity' => 1,
1672              'font' => '',
1673              'font-family' => 'helvetica',
1674              'font-size' => 'medium',
1675              'font-size-adjust' => 'none',
1676              'font-stretch' => 'normal',
1677              'font-style' => 'normal',
1678              'font-variant' => 'normal',
1679              'font-weight' => 'normal',
1680              'glyph-orientation-horizontal' => '0deg',
1681              'glyph-orientation-vertical' => 'auto',
1682              'image-rendering' => 'auto',
1683              'kerning' => 'auto',
1684              'letter-spacing' => 'normal',
1685              'lighting-color' => 'white',
1686              'marker' => '',
1687              'marker-end' => 'none',
1688              'marker-mid' => 'none',
1689              'marker-start' => 'none',
1690              'mask' => 'none',
1691              'opacity' => 1,
1692              'overflow' => 'auto',
1693              'pointer-events' => 'visiblePainted',
1694              'shape-rendering' => 'auto',
1695              'stop-color' => 'black',
1696              'stop-opacity' => 1,
1697              'stroke' => 'none',
1698              'stroke-dasharray' => 'none',
1699              'stroke-dashoffset' => 0,
1700              'stroke-linecap' => 'butt',
1701              'stroke-linejoin' => 'miter',
1702              'stroke-miterlimit' => 4,
1703              'stroke-opacity' => 1,
1704              'stroke-width' => 1,
1705              'text-anchor' => 'start',
1706              'text-decoration' => 'none',
1707              'text-rendering' => 'auto',
1708              'unicode-bidi' => 'normal',
1709              'visibility' => 'visible',
1710              'word-spacing' => 'normal',
1711              'writing-mode' => 'lr-tb',
1712              'text-color' => 'black',
1713              'transfmatrix' => array(1, 0, 0, 1, 0, 0)
1714              ));
1715  
1716          //------------------------------------------------------------
1717          // METHODS
1718          //------------------------------------------------------------
1719  
1720          /**
1721           * This is the class constructor.
1722           * It allows to set up the page format, the orientation and
1723           * the measure unit used in all the methods (except for the font sizes).
1724           * @since 1.0
1725           * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or Portrait (default)</li><li>L or Landscape</li></ul>
1726           * @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.
1727           * @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>
1728           * @param boolean $unicode TRUE means that the input text is unicode (default = true)
1729           * @param boolean $diskcache if TRUE reduce the RAM memory usage by caching temporary data on filesystem (slower).
1730           * @param String $encoding charset encoding; default is UTF-8
1731           * @access public
1732           */
1733  		public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false) {
1734              /* Set internal character encoding to ASCII */
1735              if (function_exists('mb_internal_encoding') AND mb_internal_encoding()) {
1736                  $this->internal_encoding = mb_internal_encoding();
1737                  mb_internal_encoding('ASCII');
1738              }
1739              // set disk caching
1740              $this->diskcache = $diskcache ? true : false;
1741              // set language direction
1742              $this->rtl = false;
1743              $this->tmprtl = false;
1744              //Some checks
1745              $this->_dochecks();
1746              //Initialization of properties
1747              $this->isunicode = $unicode;
1748              $this->page = 0;
1749              $this->transfmrk[0] = array();
1750              $this->pagedim = array();
1751              $this->n = 2;
1752              $this->buffer = '';
1753              $this->pages = array();
1754              $this->state = 0;
1755              $this->fonts = array();
1756              $this->FontFiles = array();
1757              $this->diffs = array();
1758              $this->images = array();
1759              $this->links = array();
1760              $this->gradients = array();
1761              $this->InFooter = false;
1762              $this->lasth = 0;
1763              $this->FontFamily = 'helvetica';
1764              $this->FontStyle = '';
1765              $this->FontSizePt = 12;
1766              $this->underline = false;
1767              $this->overline = false;
1768              $this->linethrough = false;
1769              $this->DrawColor = '0 G';
1770              $this->FillColor = '0 g';
1771              $this->TextColor = '0 g';
1772              $this->ColorFlag = false;
1773              // encryption values
1774              $this->encrypted = false;
1775              $this->last_rc4_key = '';
1776              $this->padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
1777              //Standard Unicode fonts
1778              $this->CoreFonts = array(
1779                  'courier'=>'Courier',
1780                  'courierB'=>'Courier-Bold',
1781                  'courierI'=>'Courier-Oblique',
1782                  'courierBI'=>'Courier-BoldOblique',
1783                  'helvetica'=>'Helvetica',
1784                  'helveticaB'=>'Helvetica-Bold',
1785                  'helveticaI'=>'Helvetica-Oblique',
1786                  'helveticaBI'=>'Helvetica-BoldOblique',
1787                  'times'=>'Times-Roman',
1788                  'timesB'=>'Times-Bold',
1789                  'timesI'=>'Times-Italic',
1790                  'timesBI'=>'Times-BoldItalic',
1791                  'symbol'=>'Symbol',
1792                  'zapfdingbats'=>'ZapfDingbats'
1793              );
1794              //Set scale factor
1795              $this->setPageUnit($unit);
1796              // set page format and orientation
1797              $this->setPageFormat($format, $orientation);
1798              //Page margins (1 cm)
1799              $margin = 28.35 / $this->k;
1800              $this->SetMargins($margin, $margin);
1801              //Interior cell margin
1802              $this->cMargin = $margin / 10;
1803              //Line width (0.2 mm)
1804              $this->LineWidth = 0.57 / $this->k;
1805              $this->linestyleWidth = sprintf('%.2F w', ($this->LineWidth * $this->k));
1806              $this->linestyleCap = '0 J';
1807              $this->linestyleJoin = '0 j';
1808              $this->linestyleDash = '[] 0 d';
1809              //Automatic page break
1810              $this->SetAutoPageBreak(true, (2 * $margin));
1811              //Full width display mode
1812              $this->SetDisplayMode('fullwidth');
1813              //Compression
1814              $this->SetCompression(true);
1815              //Set default PDF version number
1816              $this->PDFVersion = '1.7';
1817              $this->encoding = $encoding;
1818              $this->HREF = array();
1819              $this->getFontsList();
1820              $this->fgcolor = array('R' => 0, 'G' => 0, 'B' => 0);
1821              $this->strokecolor = array('R' => 0, 'G' => 0, 'B' => 0);
1822              $this->bgcolor = array('R' => 255, 'G' => 255, 'B' => 255);
1823              $this->extgstates = array();
1824              // user's rights
1825              $this->sign = false;
1826              $this->ur = false;
1827              $this->ur_document = '/FullSave';
1828              $this->ur_annots = '/Create/Delete/Modify/Copy/Import/Export';
1829              $this->ur_form = '/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate';
1830              $this->ur_signature = '/Modify';
1831              // set default JPEG quality
1832              $this->jpeg_quality = 75;
1833              // initialize some settings
1834              $this->utf8Bidi(array(''), '');
1835              // set default font
1836              $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt);
1837              // check if PCRE Unicode support is enabled
1838              if ($this->isunicode AND (@preg_match('/\pL/u', 'a') == 1)) {
1839                  // PCRE unicode support is turned ON
1840                  // \p{Z} or \p{Separator}: any kind of Unicode whitespace or invisible separator.
1841                  // \p{Lo} or \p{Other_Letter}: a Unicode letter or ideograph that does not have lowercase and uppercase variants.
1842                  // \p{Lo} is needed because Chinese characters are packed next to each other without spaces in between.
1843                  //$this->re_spaces = '/[\s\p{Z}\p{Lo}]/u';
1844                  $this->re_spaces = '/[\s\p{Z}]/u';
1845              } else {
1846                  // PCRE unicode support is turned OFF
1847                  $this->re_spaces = '/[\s]/';
1848              }
1849              $this->annot_obj_id = $this->annots_start_obj_id;
1850              $this->curr_annot_obj_id = $this->annots_start_obj_id;
1851              $this->apxo_obj_id = $this->apxo_start_obj_id;
1852              $this->js_obj_id = $this->js_start_obj_id;
1853              $this->default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
1854          }
1855  
1856          /**
1857           * Default destructor.
1858           * @access public
1859           * @since 1.53.0.TC016
1860           */
1861  		public function __destruct() {
1862              // restore internal encoding
1863              if (isset($this->internal_encoding) AND !empty($this->internal_encoding)) {
1864                  mb_internal_encoding($this->internal_encoding);
1865              }
1866              // unset all class variables
1867              $this->_destroy(true);
1868          }
1869  
1870          /**
1871           * Set the units of measure for the document.
1872           * @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.
1873           * @access public
1874           * @since 3.0.015 (2008-06-06)
1875           */
1876  		public function setPageUnit($unit) {
1877              $unit = strtolower($unit);
1878              //Set scale factor
1879              switch ($unit) {
1880                  // points
1881                  case 'px':
1882                  case 'pt': {
1883                      $this->k = 1;
1884                      break;
1885                  }
1886                  // millimeters
1887                  case 'mm': {
1888                      $this->k = $this->dpi / 25.4;
1889                      break;
1890                  }
1891                  // centimeters
1892                  case 'cm': {
1893                      $this->k = $this->dpi / 2.54;
1894                      break;
1895                  }
1896                  // inches
1897                  case 'in': {
1898                      $this->k = $this->dpi;
1899                      break;
1900                  }
1901                  // unsupported unit
1902                  default : {
1903                      $this->Error('Incorrect unit: '.$unit);
1904                      break;
1905                  }
1906              }
1907              $this->pdfunit = $unit;
1908              if (isset($this->CurOrientation)) {
1909                      $this->setPageOrientation($this->CurOrientation);
1910              }
1911          }
1912  
1913          /**
1914           * Set the page format
1915           * @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>
1916           * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul>
1917           * @access public
1918           * @since 3.0.015 (2008-06-06)
1919           */
1920  		public function setPageFormat($format, $orientation='P') {
1921              //Page format
1922              if (is_string($format)) {
1923                  // Page formats (45 standard ISO paper formats and 4 american common formats).
1924                  // Paper cordinates are calculated in this way: (inches * 72) where (1 inch = 2.54 cm)
1925                  switch (strtoupper($format)) {
1926                      case '4A0': {$format = array(4767.87,6740.79); break;}
1927                      case '2A0': {$format = array(3370.39,4767.87); break;}
1928                      case 'A0': {$format = array(2383.94,3370.39); break;}
1929                      case 'A1': {$format = array(1683.78,2383.94); break;}
1930                      case 'A2': {$format = array(1190.55,1683.78); break;}
1931                      case 'A3': {$format = array(841.89,1190.55); break;}
1932                      case 'A4': default: {$format = array(595.28,841.89); break;}
1933                      case 'A5': {$format = array(419.53,595.28); break;}
1934                      case 'A6': {$format = array(297.64,419.53); break;}
1935                      case 'A7': {$format = array(209.76,297.64); break;}
1936                      case 'A8': {$format = array(147.40,209.76); break;}
1937                      case 'A9': {$format = array(104.88,147.40); break;}
1938                      case 'A10': {$format = array(73.70,104.88); break;}
1939                      case 'B0': {$format = array(2834.65,4008.19); break;}
1940                      case 'B1': {$format = array(2004.09,2834.65); break;}
1941                      case 'B2': {$format = array(1417.32,2004.09); break;}
1942                      case 'B3': {$format = array(1000.63,1417.32); break;}
1943                      case 'B4': {$format = array(708.66,1000.63); break;}
1944                      case 'B5': {$format = array(498.90,708.66); break;}
1945                      case 'B6': {$format = array(354.33,498.90); break;}
1946                      case 'B7': {$format = array(249.45,354.33); break;}
1947                      case 'B8': {$format = array(175.75,249.45); break;}
1948                      case 'B9': {$format = array(124.72,175.75); break;}
1949                      case 'B10': {$format = array(87.87,124.72); break;}
1950                      case 'C0': {$format = array(2599.37,3676.54); break;}
1951                      case 'C1': {$format = array(1836.85,2599.37); break;}
1952                      case 'C2': {$format = array(1298.27,1836.85); break;}
1953                      case 'C3': {$format = array(918.43,1298.27); break;}
1954                      case 'C4': {$format = array(649.13,918.43); break;}
1955                      case 'C5': {$format = array(459.21,649.13); break;}
1956                      case 'C6': {$format = array(323.15,459.21); break;}
1957                      case 'C7': {$format = array(229.61,323.15); break;}
1958                      case 'C8': {$format = array(161.57,229.61); break;}
1959                      case 'C9': {$format = array(113.39,161.57); break;}
1960                      case 'C10': {$format = array(79.37,113.39); break;}
1961                      case 'RA0': {$format = array(2437.80,3458.27); break;}
1962                      case 'RA1': {$format = array(1729.13,2437.80); break;}
1963                      case 'RA2': {$format = array(1218.90,1729.13); break;}
1964                      case 'RA3': {$format = array(864.57,1218.90); break;}
1965                      case 'RA4': {$format = array(609.45,864.57); break;}
1966                      case 'SRA0': {$format = array(2551.18,3628.35); break;}
1967                      case 'SRA1': {$format = array(1814.17,2551.18); break;}
1968                      case 'SRA2': {$format = array(1275.59,1814.17); break;}
1969                      case 'SRA3': {$format = array(907.09,1275.59); break;}
1970                      case 'SRA4': {$format = array(637.80,907.09); break;}
1971                      case 'LETTER': {$format = array(612.00,792.00); break;}
1972                      case 'LEGAL': {$format = array(612.00,1008.00); break;}
1973                      case 'EXECUTIVE': {$format = array(521.86,756.00); break;}
1974                      case 'FOLIO': {$format = array(612.00,936.00); break;}
1975                  }
1976                  $this->fwPt = $format[0];
1977                  $this->fhPt = $format[1];
1978              } else {
1979                  $this->fwPt = $format[0] * $this->k;
1980                  $this->fhPt = $format[1] * $this->k;
1981              }
1982              $this->setPageOrientation($orientation);
1983          }
1984  
1985          /**
1986           * Set page orientation.
1987           * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul>
1988           * @param boolean $autopagebreak Boolean indicating if auto-page-break mode should be on or off.
1989           * @param float $bottommargin bottom margin of the page.
1990           * @access public
1991           * @since 3.0.015 (2008-06-06)
1992           */
1993  		public function setPageOrientation($orientation, $autopagebreak='', $bottommargin='') {
1994              if ($this->fwPt > $this->fhPt) {
1995                  // landscape
1996                  $default_orientation = 'L';
1997              } else {
1998                  // portrait
1999                  $default_orientation = 'P';
2000              }
2001              $valid_orientations = array('P', 'L');
2002              if (empty($orientation)) {
2003                  $orientation = $default_orientation;
2004              } else {
2005                  $orientation = $orientation{0};
2006                  $orientation = strtoupper($orientation);
2007              }
2008              if (in_array($orientation, $valid_orientations) AND ($orientation != $default_orientation)) {
2009                  $this->CurOrientation = $orientation;
2010                  $this->wPt = $this->fhPt;
2011                  $this->hPt = $this->fwPt;
2012              } else {
2013                  $this->CurOrientation = $default_orientation;
2014                  $this->wPt = $this->fwPt;
2015                  $this->hPt = $this->fhPt;
2016              }
2017              $this->w = $this->wPt / $this->k;
2018              $this->h = $this->hPt / $this->k;
2019              if ($this->empty_string($autopagebreak)) {
2020                  if (isset($this->AutoPageBreak)) {
2021                      $autopagebreak = $this->AutoPageBreak;
2022                  } else {
2023                      $autopagebreak = true;
2024                  }
2025              }
2026              if ($this->empty_string($bottommargin)) {
2027                  if (isset($this->bMargin)) {
2028                      $bottommargin = $this->bMargin;
2029                  } else {
2030                      // default value = 2 cm
2031                      $bottommargin = 2 * 28.35 / $this->k;
2032                  }
2033              }
2034              $this->SetAutoPageBreak($autopagebreak, $bottommargin);
2035              // store page dimensions
2036              $this->pagedim[$this->page] = array('w' => $this->wPt, 'h' => $this->hPt, 'wk' => $this->w, 'hk' => $this->h, 'tm' => $this->tMargin, 'bm' => $bottommargin, 'lm' => $this->lMargin, 'rm' => $this->rMargin, 'pb' => $autopagebreak, 'or' => $this->CurOrientation, 'olm' => $this->original_lMargin, 'orm' => $this->original_rMargin);
2037          }
2038  
2039          /**
2040           * Set regular expression to detect withespaces or word separators.
2041           * @param string $re regular expression (leave empty for default).
2042           * @access public
2043           * @since 4.6.016 (2009-06-15)
2044           */
2045  		public function setSpacesRE($re='/[\s]/') {
2046              // if PCRE unicode support is turned ON:
2047              //     \p{Z} or \p{Separator}: any kind of Unicode whitespace or invisible separator.
2048              //     \p{Lo} or \p{Other_Letter}: a Unicode letter or ideograph that does not have lowercase and uppercase variants.
2049              //     \p{Lo} is needed because Chinese characters are packed next to each other without spaces in between.
2050              $this->re_spaces = $re;
2051          }
2052  
2053          /**
2054           * Enable or disable Right-To-Left language mode
2055           * @param Boolean $enable if true enable Right-To-Left language mode.
2056           * @param Boolean $resetx if true reset the X position on direction change.
2057           * @access public
2058           * @since 2.0.000 (2008-01-03)
2059           */
2060  		public function setRTL($enable, $resetx=true) {
2061              $enable = $enable ? true : false;
2062              $resetx = ($resetx AND ($enable != $this->rtl));
2063              $this->rtl = $enable;
2064              $this->tmprtl = false;
2065              if ($resetx) {
2066                  $this->Ln(0);
2067              }
2068          }
2069  
2070          /**
2071           * Return the RTL status
2072           * @return boolean
2073           * @access public
2074           * @since 4.0.012 (2008-07-24)
2075           */
2076  		public function getRTL() {
2077              return $this->rtl;
2078          }
2079  
2080          /**
2081           * Force temporary RTL language direction
2082           * @param mixed $mode can be false, 'L' for LTR or 'R' for RTL
2083           * @access public
2084           * @since 2.1.000 (2008-01-09)
2085           */
2086  		public function setTempRTL($mode) {
2087              $newmode = false;
2088              switch ($mode) {
2089                  case 'ltr':
2090                  case 'LTR':
2091                  case 'L': {
2092                      if ($this->rtl) {
2093                          $newmode = 'L';
2094                      }
2095                      break;
2096                  }
2097                  case 'rtl':
2098                  case 'RTL':
2099                  case 'R': {
2100                      if (!$this->rtl) {
2101                          $newmode = 'R';
2102                      }
2103                      break;
2104                  }
2105                  case false:
2106                  default: {
2107                      $newmode = false;
2108                      break;
2109                  }
2110              }
2111              $this->tmprtl = $newmode;
2112          }
2113  
2114          /**
2115           * Return the current temporary RTL status
2116           * @return boolean
2117           * @access public
2118           * @since 4.8.014 (2009-11-04)
2119           */
2120  		public function isRTLTextDir() {
2121              return ($this->rtl OR ($this->tmprtl == 'R'));
2122          }
2123  
2124          /**
2125           * Set the last cell height.
2126           * @param float $h cell height.
2127           * @author Nicola Asuni
2128           * @access public
2129           * @since 1.53.0.TC034
2130           */
2131  		public function setLastH($h) {
2132              $this->lasth = $h;
2133          }
2134  
2135          /**
2136           * Get the last cell height.
2137           * @return last cell height
2138           * @access public
2139           * @since 4.0.017 (2008-08-05)
2140           */
2141  		public function getLastH() {
2142              return $this->lasth;
2143          }
2144  
2145          /**
2146           * Set the adjusting factor to convert pixels to user units.
2147           * @param float $scale adjusting factor to convert pixels to user units.
2148           * @author Nicola Asuni
2149           * @access public
2150           * @since 1.5.2
2151           */
2152  		public function setImageScale($scale) {
2153              $this->imgscale = $scale;
2154          }
2155  
2156          /**
2157           * Returns the adjusting factor to convert pixels to user units.
2158           * @return float adjusting factor to convert pixels to user units.
2159           * @author Nicola Asuni
2160           * @access public
2161           * @since 1.5.2
2162           */
2163  		public function getImageScale() {
2164              return $this->imgscale;
2165          }
2166  
2167          /**
2168           * Returns an array of page dimensions:
2169           * <ul><li>$this->pagedim[$this->page]['w'] => page_width_in_points</li><li>$this->pagedim[$this->page]['h'] => height in points</li><li>$this->pagedim[$this->page]['wk'] => page_width_in_points</li><li>$this->pagedim[$this->page]['hk'] => height</li><li>$this->pagedim[$this->page]['tm'] => top_margin</li><li>$this->pagedim[$this->page]['bm'] => bottom_margin</li><li>$this->pagedim[$this->page]['lm'] => left_margin</li><li>$this->pagedim[$this->page]['rm'] => right_margin</li><li>$this->pagedim[$this->page]['pb'] => auto_page_break</li><li>$this->pagedim[$this->page]['or'] => page_orientation</li><li>$this->pagedim[$this->page]['olm'] => original_left_margin</li><li>$this->pagedim[$this->page]['orm'] => original_right_margin</li></ul>
2170           * @param int $pagenum page number (empty = current page)
2171           * @return array of page dimensions.
2172           * @author Nicola Asuni
2173           * @access public
2174           * @since 4.5.027 (2009-03-16)
2175           */
2176  		public function getPageDimensions($pagenum='') {
2177              if (empty($pagenum)) {
2178                  $pagenum = $this->page;
2179              }
2180              return $this->pagedim[$pagenum];
2181          }
2182  
2183          /**
2184           * Returns the page width in units.
2185           * @param int $pagenum page number (empty = current page)
2186           * @return int page width.
2187           * @author Nicola Asuni
2188           * @access public
2189           * @since 1.5.2
2190           * @see getPageDimensions()
2191           */
2192  		public function getPageWidth($pagenum='') {
2193              if (empty($pagenum)) {
2194                  return $this->w;
2195              }
2196              return $this->pagedim[$pagenum]['w'];
2197          }
2198  
2199          /**
2200           * Returns the page height in units.
2201           * @param int $pagenum page number (empty = current page)
2202           * @return int page height.
2203           * @author Nicola Asuni
2204           * @access public
2205           * @since 1.5.2
2206           * @see getPageDimensions()
2207           */
2208  		public function getPageHeight($pagenum='') {
2209              if (empty($pagenum)) {
2210                  return $this->h;
2211              }
2212              return $this->pagedim[$pagenum]['h'];
2213          }
2214  
2215          /**
2216           * Returns the page break margin.
2217           * @param int $pagenum page number (empty = current page)
2218           * @return int page break margin.
2219           * @author Nicola Asuni
2220           * @access public
2221           * @since 1.5.2
2222           * @see getPageDimensions()
2223           */
2224  		public function getBreakMargin($pagenum='') {
2225              if (empty($pagenum)) {
2226                  return $this->bMargin;
2227              }
2228              return $this->pagedim[$pagenum]['bm'];
2229          }
2230  
2231          /**
2232           * Returns the scale factor (number of points in user unit).
2233           * @return int scale factor.
2234           * @author Nicola Asuni
2235           * @access public
2236           * @since 1.5.2
2237           */
2238  		public function getScaleFactor() {
2239              return $this->k;
2240          }
2241  
2242          /**
2243           * Defines the left, top and right margins.
2244           * @param float $left Left margin.
2245           * @param float $top Top margin.
2246           * @param float $right Right margin. Default value is the left one.
2247           * @param boolean $keepmargins if true overwrites the default page margins
2248           * @access public
2249           * @since 1.0
2250           * @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak()
2251           */
2252  		public function SetMargins($left, $top, $right=-1, $keepmargins=false) {
2253              //Set left, top and right margins
2254              $this->lMargin = $left;
2255              $this->tMargin = $top;
2256              if ($right == -1) {
2257                  $right = $left;
2258              }
2259              $this->rMargin = $right;
2260              if ($keepmargins) {
2261                  // overwrite original values
2262                  $this->original_lMargin = $this->lMargin;
2263                  $this->original_rMargin = $this->rMargin;
2264              }
2265          }
2266  
2267          /**
2268           * 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.
2269           * @param float $margin The margin.
2270           * @access public
2271           * @since 1.4
2272           * @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
2273           */
2274  		public function SetLeftMargin($margin) {
2275              //Set left margin
2276              $this->lMargin=$margin;
2277              if (($this->page > 0) AND ($this->x < $margin)) {
2278                  $this->x = $margin;
2279              }
2280          }
2281  
2282          /**
2283           * Defines the top margin. The method can be called before creating the first page.
2284           * @param float $margin The margin.
2285           * @access public
2286           * @since 1.5
2287           * @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
2288           */
2289  		public function SetTopMargin($margin) {
2290              //Set top margin
2291              $this->tMargin=$margin;
2292              if (($this->page > 0) AND ($this->y < $margin)) {
2293                  $this->y = $margin;
2294              }
2295          }
2296  
2297          /**
2298           * Defines the right margin. The method can be called before creating the first page.
2299           * @param float $margin The margin.
2300           * @access public
2301           * @since 1.5
2302           * @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()
2303           */
2304  		public function SetRightMargin($margin) {
2305              $this->rMargin=$margin;
2306              if (($this->page > 0) AND ($this->x > ($this->w - $margin))) {
2307                  $this->x = $this->w - $margin;
2308              }
2309          }
2310  
2311          /**
2312           * Set the internal Cell padding.
2313           * @param float $pad internal padding.
2314           * @access public
2315           * @since 2.1.000 (2008-01-09)
2316           * @see Cell(), SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()
2317           */
2318  		public function SetCellPadding($pad) {
2319              $this->cMargin = $pad;
2320          }
2321  
2322          /**
2323           * 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.
2324           * @param boolean $auto Boolean indicating if mode should be on or off.
2325           * @param float $margin Distance from the bottom of the page.
2326           * @access public
2327           * @since 1.0
2328           * @see Cell(), MultiCell(), AcceptPageBreak()
2329           */
2330  		public function SetAutoPageBreak($auto, $margin=0) {
2331              //Set auto page break mode and triggering margin
2332              $this->AutoPageBreak = $auto;
2333              $this->bMargin = $margin;
2334              $this->PageBreakTrigger = $this->h - $margin;
2335          }
2336  
2337          /**
2338           * Defines the way the document is to be displayed by the viewer.
2339           * @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>
2340           * @param string $layout The page layout. Possible values are:<ul><li>SinglePage Display one page at a time</li><li>OneColumn Display the pages in one column</li><li>TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left</li><li>TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right</li><li>TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left</li><li>TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right</li></ul>
2341           * @param string $mode A name object specifying how the document should be displayed when opened:<ul><li>UseNone Neither document outline nor thumbnail images visible</li><li>UseOutlines Document outline visible</li><li>UseThumbs Thumbnail images visible</li><li>FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible</li><li>UseOC (PDF 1.5) Optional content group panel visible</li><li>UseAttachments (PDF 1.6) Attachments panel visible</li></ul>
2342           * @access public
2343           * @since 1.2
2344           */
2345  		public function SetDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') {
2346              //Set display mode in viewer
2347              if (($zoom == 'fullpage') OR ($zoom == 'fullwidth') OR ($zoom == 'real') OR ($zoom == 'default') OR (!is_string($zoom))) {
2348                  $this->ZoomMode = $zoom;
2349              } else {
2350                  $this->Error('Incorrect zoom display mode: '.$zoom);
2351              }
2352              switch ($layout) {
2353                  case 'default':
2354                  case 'single':
2355                  case 'SinglePage': {
2356                      $this->LayoutMode = 'SinglePage';
2357                      break;
2358                  }
2359                  case 'continuous':
2360                  case 'OneColumn': {
2361                      $this->LayoutMode = 'OneColumn';
2362                      break;
2363                  }
2364                  case 'two':
2365                  case 'TwoColumnLeft': {
2366                      $this->LayoutMode = 'TwoColumnLeft';
2367                      break;
2368                  }
2369                  case 'TwoColumnRight': {
2370                      $this->LayoutMode = 'TwoColumnRight';
2371                      break;
2372                  }
2373                  case 'TwoPageLeft': {
2374                      $this->LayoutMode = 'TwoPageLeft';
2375                      break;
2376                  }
2377                  case 'TwoPageRight': {
2378                      $this->LayoutMode = 'TwoPageRight';
2379                      break;
2380                  }
2381                  default: {
2382                      $this->LayoutMode = 'SinglePage';
2383                  }
2384              }
2385              switch ($mode) {
2386                  case 'UseNone': {
2387                      $this->PageMode = 'UseNone';
2388                      break;
2389                  }
2390                  case 'UseOutlines': {
2391                      $this->PageMode = 'UseOutlines';
2392                      break;
2393                  }
2394                  case 'UseThumbs': {
2395                      $this->PageMode = 'UseThumbs';
2396                      break;
2397                  }
2398                  case 'FullScreen': {
2399                      $this->PageMode = 'FullScreen';
2400                      break;
2401                  }
2402                  case 'UseOC': {
2403                      $this->PageMode = 'UseOC';
2404                      break;
2405                  }
2406                  case '': {
2407                      $this->PageMode = 'UseAttachments';
2408                      break;
2409                  }
2410                  default: {
2411                      $this->PageMode = 'UseNone';
2412                  }
2413              }
2414          }
2415  
2416          /**
2417           * 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.
2418           * Note: the Zlib extension is required for this feature. If not present, compression will be turned off.
2419           * @param boolean $compress Boolean indicating if compression must be enabled.
2420           * @access public
2421           * @since 1.4
2422           */
2423  		public function SetCompression($compress) {
2424              //Set page compression
2425              if (function_exists('gzcompress')) {
2426                  $this->compress = $compress;
2427              } else {
2428                  $this->compress = false;
2429              }
2430          }
2431  
2432          /**
2433           * Defines the title of the document.
2434           * @param string $title The title.
2435           * @access public
2436           * @since 1.2
2437           * @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject()
2438           */
2439  		public function SetTitle($title) {
2440              //Title of document
2441              $this->title = $title;
2442          }
2443  
2444          /**
2445           * Defines the subject of the document.
2446           * @param string $subject The subject.
2447           * @access public
2448           * @since 1.2
2449           * @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle()
2450           */
2451  		public function SetSubject($subject) {
2452              //Subject of document
2453              $this->subject = $subject;
2454          }
2455  
2456          /**
2457           * Defines the author of the document.
2458           * @param string $author The name of the author.
2459           * @access public
2460           * @since 1.2
2461           * @see SetCreator(), SetKeywords(), SetSubject(), SetTitle()
2462           */
2463  		public function SetAuthor($author) {
2464              //Author of document
2465              $this->author = $author;
2466          }
2467  
2468          /**
2469           * Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'.
2470           * @param string $keywords The list of keywords.
2471           * @access public
2472           * @since 1.2
2473           * @see SetAuthor(), SetCreator(), SetSubject(), SetTitle()
2474           */
2475  		public function SetKeywords($keywords) {
2476              //Keywords of document
2477              $this->keywords = $keywords;
2478          }
2479  
2480          /**
2481           * Defines the creator of the document. This is typically the name of the application that generates the PDF.
2482           * @param string $creator The name of the creator.
2483           * @access public
2484           * @since 1.2
2485           * @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle()
2486           */
2487  		public function SetCreator($creator) {
2488              //Creator of document
2489              $this->creator = $creator;
2490          }
2491  
2492          /**
2493           * 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.
2494           * 2004-06-11 :: Nicola Asuni : changed bold tag with strong
2495           * @param string $msg The error message
2496           * @access public
2497           * @since 1.0
2498           */
2499  		public function Error($msg) {
2500              // unset all class variables
2501              $this->_destroy(true);
2502              // exit program and print error
2503              die('<strong>TCPDF ERROR: </strong>'.$msg);
2504          }
2505  
2506          /**
2507           * This method begins the generation of the PDF document.
2508           * It is not necessary to call it explicitly because AddPage() does it automatically.
2509           * Note: no page is created by this method
2510           * @access public
2511           * @since 1.0
2512           * @see AddPage(), Close()
2513           */
2514  		public function Open() {
2515              //Begin document
2516              $this->state = 1;
2517          }
2518  
2519          /**
2520           * Terminates the PDF document.
2521           * It is not necessary to call this method explicitly because Output() does it automatically.
2522           * If the document contains no page, AddPage() is called to prevent from getting an invalid document.
2523           * @access public
2524           * @since 1.0
2525           * @see Open(), Output()
2526           */
2527  		public function Close() {
2528              if ($this->state == 3) {
2529                  return;
2530              }
2531              if ($this->page == 0) {
2532                  $this->AddPage();
2533              }
2534              // close page
2535              $this->endPage();
2536              // close document
2537              $this->_enddoc();
2538              // unset all class variables (except critical ones)
2539              $this->_destroy(false);
2540          }
2541  
2542          /**
2543           * Move pointer at the specified document page and update page dimensions.
2544           * @param int $pnum page number (1 ... numpages)
2545           * @param boolean $resetmargins if true reset left, right, top margins and Y position.
2546           * @access public
2547           * @since 2.1.000 (2008-01-07)
2548           * @see getPage(), lastpage(), getNumPages()
2549           */
2550  		public function setPage($pnum, $resetmargins=false) {
2551              if ($pnum == $this->page) {
2552                  return;
2553              }
2554              if (($pnum > 0) AND ($pnum <= $this->numpages)) {
2555                  $this->state = 2;
2556                  // save current graphic settings
2557                  //$gvars = $this->getGraphicVars();
2558                  $oldpage = $this->page;
2559                  $this->page = $pnum;
2560                  $this->wPt = $this->pagedim[$this->page]['w'];
2561                  $this->hPt = $this->pagedim[$this->page]['h'];
2562                  $this->w = $this->wPt / $this->k;
2563                  $this->h = $this->hPt / $this->k;
2564                  $this->tMargin = $this->pagedim[$this->page]['tm'];
2565                  $this->bMargin = $this->pagedim[$this->page]['bm'];
2566                  $this->original_lMargin = $this->pagedim[$this->page]['olm'];
2567                  $this->original_rMargin = $this->pagedim[$this->page]['orm'];
2568                  $this->AutoPageBreak = $this->pagedim[$this->page]['pb'];
2569                  $this->CurOrientation = $this->pagedim[$this->page]['or'];
2570                  $this->SetAutoPageBreak($this->AutoPageBreak, $this->bMargin);
2571                  // restore graphic settings
2572                  //$this->setGraphicVars($gvars);
2573                  if ($resetmargins) {
2574                      $this->lMargin = $this->pagedim[$this->page]['olm'];
2575                      $this->rMargin = $this->pagedim[$this->page]['orm'];
2576                      $this->SetY($this->tMargin);
2577                  } else {
2578                      // account for booklet mode
2579                      if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
2580                          $deltam = $this->pagedim[$this->page]['olm'] - $this->pagedim[$this->page]['orm'];
2581                          $this->lMargin += $deltam;
2582                          $this->rMargin -= $deltam;
2583                      }
2584                  }
2585              } else {
2586                  $this->Error('Wrong page number on setPage() function.');
2587              }
2588          }
2589  
2590          /**
2591           * Reset pointer to the last document page.
2592           * @param boolean $resetmargins if true reset left, right, top margins and Y position.
2593           * @access public
2594           * @since 2.0.000 (2008-01-04)
2595           * @see setPage(), getPage(), getNumPages()
2596           */
2597  		public function lastPage($resetmargins=false) {
2598              $this->setPage($this->getNumPages(), $resetmargins);
2599          }
2600  
2601          /**
2602           * Get current document page number.
2603           * @return int page number
2604           * @access public
2605           * @since 2.1.000 (2008-01-07)
2606           * @see setPage(), lastpage(), getNumPages()
2607           */
2608  		public function getPage() {
2609              return $this->page;
2610          }
2611  
2612  
2613          /**
2614           * Get the total number of insered pages.
2615           * @return int number of pages
2616           * @access public
2617           * @since 2.1.000 (2008-01-07)
2618           * @see setPage(), getPage(), lastpage()
2619           */
2620  		public function getNumPages() {
2621              return $this->numpages;
2622          }
2623  
2624          /**
2625           * Adds a new TOC (Table Of Content) page to the document.
2626           * @param string $orientation page orientation.
2627           * @param boolean $keepmargins if true overwrites the default page margins with the current margins
2628           * @access public
2629           * @since 5.0.001 (2010-05-06)
2630           * @see AddPage(), startPage(), endPage(), endTOCPage()
2631           */
2632  		public function addTOCPage($orientation='', $format='', $keepmargins=false) {
2633              $this->AddPage($orientation, $format, $keepmargins, true);
2634          }
2635  
2636          /**
2637           * Terminate the current TOC (Table Of Content) page
2638           * @access public
2639           * @since 5.0.001 (2010-05-06)
2640           * @see AddPage(), startPage(), endPage(), addTOCPage()
2641           */
2642  		public function endTOCPage() {
2643              $this->endPage(true);
2644          }
2645  
2646          /**
2647           * Adds a new page to the document. If a page is already present, the Footer() method is called first to output the footer (if enabled). Then the page is added, the current position set to the top-left corner according to the left and top margins (or top-right if in RTL mode), and Header() is called to display the header (if enabled).
2648           * The origin of the coordinate system is at the top-left corner (or top-right for RTL) and increasing ordinates go downwards.
2649           * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul>
2650           * @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>
2651           * @param boolean $keepmargins if true overwrites the default page margins with the current margins
2652           * @param boolean $tocpage if true set the tocpage state to true (the added page will be used to display Table Of Content).
2653           * @access public
2654           * @since 1.0
2655           * @see startPage(), endPage(), addTOCPage(), endTOCPage()
2656           */
2657  		public function AddPage($orientation='', $format='', $keepmargins=false, $tocpage=false) {
2658              if (!isset($this->original_lMargin) OR $keepmargins) {
2659                  $this->original_lMargin = $this->lMargin;
2660              }
2661              if (!isset($this->original_rMargin) OR $keepmargins) {
2662                  $this->original_rMargin = $this->rMargin;
2663              }
2664              // terminate previous page
2665              $this->endPage();
2666              // start new page
2667              $this->startPage($orientation, $format, $tocpage);
2668          }
2669  
2670          /**
2671           * Terminate the current page
2672           * @param boolean $tocpage if true set the tocpage state to false (end the page used to display Table Of Content).
2673           * @access public
2674           * @since 4.2.010 (2008-11-14)
2675           * @see AddPage(), startPage(), addTOCPage(), endTOCPage()
2676           */
2677  		public function endPage($tocpage=false) {
2678              // check if page is already closed
2679              if (($this->page == 0) OR ($this->numpages > $this->page) OR (!$this->pageopen[$this->page])) {
2680                  return;
2681              }
2682              $this->InFooter = true;
2683              // print page footer
2684              $this->setFooter();
2685              // close page
2686              $this->_endpage();
2687              // mark page as closed
2688              $this->pageopen[$this->page] = false;
2689              $this->InFooter = false;
2690              if ($tocpage) {
2691                  $this->tocpage = false;
2692              }
2693          }
2694  
2695          /**
2696           * Starts a new page to the document. The page must be closed using the endPage() function.
2697           * The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards.
2698           * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul>
2699           * @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>
2700           * @param boolean $tocpage if true set the tocpage state to true (the added page will be used to display Table of Content).
2701           * @access public
2702           * @since 4.2.010 (2008-11-14)
2703           * @see AddPage(), endPage(), addTOCPage(), endTOCPage()
2704           */
2705  		public function startPage($orientation='', $format='', $tocpage=false) {
2706              if ($tocpage) {
2707                  $this->tocpage = true;
2708              }
2709              if ($this->numpages > $this->page) {
2710                  // this page has been already added
2711                  $this->setPage($this->page + 1);
2712                  $this->SetY($this->tMargin);
2713                  return;
2714              }
2715              // start a new page
2716              if ($this->state == 0) {
2717                  $this->Open();
2718              }
2719              ++$this->numpages;
2720              $this->swapMargins($this->booklet);
2721              // save current graphic settings
2722              $gvars = $this->getGraphicVars();
2723              // start new page
2724              $this->_beginpage($orientation, $format);
2725              // mark page as open
2726              $this->pageopen[$this->page] = true;
2727              // restore graphic settings
2728              $this->setGraphicVars($gvars);
2729              // mark this point
2730              $this->setPageMark();
2731              // print page header
2732              $this->setHeader();
2733              // restore graphic settings
2734              $this->setGraphicVars($gvars);
2735              // mark this point
2736              $this->setPageMark();
2737              // print table header (if any)
2738              $this->setTableHeader();
2739          }
2740  
2741          /**
2742            * Set start-writing mark on current page stream used to put borders and fills.
2743            * Borders and fills are always created after content and inserted on the position marked by this method.
2744            * This function must be called after calling Image() function for a background image.
2745            * Background images must be always inserted before calling Multicell() or WriteHTMLCell() or WriteHTML() functions.
2746            * @access public
2747            * @since 4.0.016 (2008-07-30)
2748           */
2749  		public function setPageMark() {
2750              $this->intmrk[$this->page] = $this->pagelen[$this->page];
2751              $this->setContentMark();
2752          }
2753  
2754          /**
2755            * Set start-writing mark on selected page.
2756            * Borders and fills are always created after content and inserted on the position marked by this method.
2757            * @param int $page page number (default is the current page)
2758            * @access protected
2759            * @since 4.6.021 (2009-07-20)
2760           */
2761  		protected function setContentMark($page=0) {
2762              if ($page <= 0) {
2763                  $page = $this->page;
2764              }
2765              if (isset($this->footerlen[$page])) {
2766                  $this->cntmrk[$page] = $this->pagelen[$page] - $this->footerlen[$page];
2767              } else {
2768                  $this->cntmrk[$page] = $this->pagelen[$page];
2769              }
2770          }
2771  
2772          /**
2773            * Set header data.
2774           * @param string $ln header image logo
2775           * @param string $lw header image logo width in mm
2776           * @param string $ht string to print as title on document header
2777           * @param string $hs string to print on document header
2778           * @access public
2779           */
2780  		public function setHeaderData($ln='', $lw=0, $ht='', $hs='') {
2781              $this->header_logo = $ln;
2782              $this->header_logo_width = $lw;
2783              $this->header_title = $ht;
2784              $this->header_string = $hs;
2785          }
2786  
2787          /**
2788            * Returns header data:
2789            * <ul><li>$ret['logo'] = logo image</li><li>$ret['logo_width'] = width of the image logo in user units</li><li>$ret['title'] = header title</li><li>$ret['string'] = header description string</li></ul>
2790           * @return array()
2791           * @access public
2792           * @since 4.0.012 (2008-07-24)
2793           */
2794  		public function getHeaderData() {
2795              $ret = array();
2796              $ret['logo'] = $this->header_logo;
2797              $ret['logo_width'] = $this->header_logo_width;
2798              $ret['title'] = $this->header_title;
2799              $ret['string'] = $this->header_string;
2800              return $ret;
2801          }
2802  
2803          /**
2804            * Set header margin.
2805           * (minimum distance between header and top page margin)
2806           * @param int $hm distance in user units
2807           * @access public
2808           */
2809  		public function setHeaderMargin($hm=10) {
2810              $this->header_margin = $hm;
2811          }
2812  
2813          /**
2814            * Returns header margin in user units.
2815           * @return float
2816           * @since 4.0.012 (2008-07-24)
2817           * @access public
2818           */
2819  		public function getHeaderMargin() {
2820              return $this->header_margin;
2821          }
2822  
2823          /**
2824            * Set footer margin.
2825           * (minimum distance between footer and bottom page margin)
2826           * @param int $fm distance in user units
2827           * @access public
2828           */
2829  		public function setFooterMargin($fm=10) {
2830              $this->footer_margin = $fm;
2831          }
2832  
2833          /**
2834            * Returns footer margin in user units.
2835           * @return float
2836           * @since 4.0.012 (2008-07-24)
2837           * @access public
2838           */
2839  		public function getFooterMargin() {
2840              return $this->footer_margin;
2841          }
2842          /**
2843            * Set a flag to print page header.
2844           * @param boolean $val set to true to print the page header (default), false otherwise.
2845           * @access public
2846           */
2847  		public function setPrintHeader($val=true) {
2848              $this->print_header = $val;
2849          }
2850  
2851          /**
2852            * Set a flag to print page footer.
2853           * @param boolean $value set to true to print the page footer (default), false otherwise.
2854           * @access public
2855           */
2856  		public function setPrintFooter($val=true) {
2857              $this->print_footer = $val;
2858          }
2859  
2860          /**
2861            * Return the right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image
2862           * @return float
2863           * @access public
2864           */
2865  		public function getImageRBX() {
2866              return $this->img_rb_x;
2867          }
2868  
2869          /**
2870            * Return the right-bottom (or left-bottom for RTL) corner Y coordinate of last inserted image
2871           * @return float
2872           * @access public
2873           */
2874  		public function getImageRBY() {
2875              return $this->img_rb_y;
2876          }
2877  
2878          /**
2879            * This method is used to render the page header.
2880            * It is automatically called by AddPage() and could be overwritten in your own inherited class.
2881           * @access public
2882           */
2883  		public function Header() {
2884              $ormargins = $this->getOriginalMargins();
2885              $headerfont = $this->getHeaderFont();
2886              $headerdata = $this->getHeaderData();
2887              if (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) {
2888                  $this->Image(K_PATH_IMAGES.$headerdata['logo'], $this->GetX(), $this->getHeaderMargin(), $headerdata['logo_width']);
2889                  $imgy = $this->getImageRBY();
2890              } else {
2891                  $imgy = $this->GetY();
2892              }
2893              $cell_height = round(($this->getCellHeightRatio() * $headerfont[2]) / $this->getScaleFactor(), 2);
2894              // set starting margin for text data cell
2895              if ($this->getRTL()) {
2896                  $header_x = $ormargins['right'] + ($headerdata['logo_width'] * 1.1);
2897              } else {
2898                  $header_x = $ormargins['left'] + ($headerdata['logo_width'] * 1.1);
2899              }
2900              $this->SetTextColor(0, 0, 0);
2901              // header title
2902              $this->SetFont($headerfont[0], 'B', $headerfont[2] + 1);
2903              $this->SetX($header_x);
2904              $this->Cell(0, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0);
2905              // header string
2906              $this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]);
2907              $this->SetX($header_x);
2908              $this->MultiCell(0, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false);
2909              // print an ending header line
2910              $this->SetLineStyle(array('width' => 0.85 / $this->getScaleFactor(), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)));
2911              $this->SetY((2.835 / $this->getScaleFactor()) + max($imgy, $this->GetY()));
2912              if ($this->getRTL()) {
2913                  $this->SetX($ormargins['right']);
2914              } else {
2915                  $this->SetX($ormargins['left']);
2916              }
2917              $this->Cell(0, 0, '', 'T', 0, 'C');
2918          }
2919  
2920          /**
2921            * This method is used to render the page footer.
2922            * It is automatically called by AddPage() and could be overwritten in your own inherited class.
2923           * @access public
2924           */
2925  		public function Footer() {
2926              $cur_y = $this->GetY();
2927              $ormargins = $this->getOriginalMargins();
2928              $this->SetTextColor(0, 0, 0);
2929              //set style for cell border
2930              $line_width = 0.85 / $this->getScaleFactor();
2931              $this->SetLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)));
2932              //print document barcode
2933              $barcode = $this->getBarcode();
2934              if (!empty($barcode)) {
2935                  $this->Ln($line_width);
2936                  $barcode_width = round(($this->getPageWidth() - $ormargins['left'] - $ormargins['right'])/3);
2937                  $this->write1DBarcode($barcode, 'C128B', $this->GetX(), $cur_y + $line_width, $barcode_width, (($this->getFooterMargin() / 3) - $line_width), 0.3, '', '');
2938              }
2939              if (empty($this->pagegroups)) {
2940                  $pagenumtxt = $this->l['w_page'].' '.$this->getAliasNumPage().' / '.$this->getAliasNbPages();
2941              } else {
2942                  $pagenumtxt = $this->l['w_page'].' '.$this->getPageNumGroupAlias().' / '.$this->getPageGroupAlias();
2943              }
2944              $this->SetY($cur_y);
2945              //Print page number
2946              if ($this->getRTL()) {
2947                  $this->SetX($ormargins['right']);
2948                  $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'L');
2949              } else {
2950                  $this->SetX($ormargins['left']);
2951                  $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'R');
2952              }
2953          }
2954  
2955          /**
2956            * This method is used to render the page header.
2957            * @access protected
2958            * @since 4.0.012 (2008-07-24)
2959           */
2960  		protected function setHeader() {
2961              if ($this->print_header) {
2962                  $temp_thead = $this->thead;
2963                  $temp_theadMargins = $this->theadMargins;
2964                  $lasth = $this->lasth;
2965                  $this->_out('q');
2966                  $this->rMargin = $this->original_rMargin;
2967                  $this->lMargin = $this->original_lMargin;
2968                  $this->cMargin = 0;
2969                  //set current position
2970                  if ($this->rtl) {
2971                      $this->SetXY($this->original_rMargin, $this->header_margin);
2972                  } else {
2973                      $this->SetXY($this->original_lMargin, $this->header_margin);
2974                  }
2975                  $this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]);
2976                  $this->Header();
2977                  //restore position
2978                  if ($this->rtl) {
2979                      $this->SetXY($this->original_rMargin, $this->tMargin);
2980                  } else {
2981                      $this->SetXY($this->original_lMargin, $this->tMargin);
2982                  }
2983                  $this->_out('Q');
2984                  $this->lasth = $lasth;
2985                  $this->thead = $temp_thead;
2986                  $this->theadMargins = $temp_theadMargins;
2987                  $this->newline = false;
2988              }
2989          }
2990  
2991          /**
2992            * This method is used to render the page footer.
2993            * @access protected
2994            * @since 4.0.012 (2008-07-24)
2995           */
2996  		protected function setFooter() {
2997              //Page footer
2998              // save current graphic settings
2999              $gvars = $this->getGraphicVars();
3000              // mark this point
3001              $this->footerpos[$this->page] = $this->pagelen[$this->page];
3002              $this->_out("\n");
3003              if ($this->print_footer) {
3004                  $temp_thead = $this->thead;
3005                  $temp_theadMargins = $this->theadMargins;
3006                  $lasth = $this->lasth;
3007                  $this->_out('q');
3008                  $this->rMargin = $this->original_rMargin;
3009                  $this->lMargin = $this->original_lMargin;
3010                  $this->cMargin = 0;
3011                  //set current position
3012                  $footer_y = $this->h - $this->footer_margin;
3013                  if ($this->rtl) {
3014                      $this->SetXY($this->original_rMargin, $footer_y);
3015                  } else {
3016                      $this->SetXY($this->original_lMargin, $footer_y);
3017                  }
3018                  $this->SetFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]);
3019                  $this->Footer();
3020                  //restore position
3021                  if ($this->rtl) {
3022                      $this->SetXY($this->original_rMargin, $this->tMargin);
3023                  } else {
3024                      $this->SetXY($this->original_lMargin, $this->tMargin);
3025                  }
3026                  $this->_out('Q');
3027                  $this->lasth = $lasth;
3028                  $this->thead = $temp_thead;
3029                  $this->theadMargins = $temp_theadMargins;
3030              }
3031              // restore graphic settings
3032              $this->setGraphicVars($gvars);
3033              // calculate footer length
3034              $this->footerlen[$this->page] = $this->pagelen[$this->page] - $this->footerpos[$this->page] + 1;
3035          }
3036  
3037          /**
3038            * This method is used to render the table header on new page (if any).
3039            * @access protected
3040            * @since 4.5.030 (2009-03-25)
3041           */
3042  		protected function setTableHeader() {
3043              if ($this->num_columns > 1) {
3044                  // multi column mode
3045                  return;
3046              }
3047              if (isset($this->theadMargins['top'])) {
3048                  // restore the original top-margin
3049                  $this->tMargin = $this->theadMargins['top'];
3050                  $this->pagedim[$this->page]['tm'] = $this->tMargin;
3051                  $this->y = $this->tMargin;
3052              }
3053              if (!$this->empty_string($this->thead) AND (!$this->inthead)) {
3054                  // set margins
3055                  $prev_lMargin = $this->lMargin;
3056                  $prev_rMargin = $this->rMargin;
3057                  $this->lMargin = $this->pagedim[$this->page]['olm'];
3058                  $this->rMargin = $this->pagedim[$this->page]['orm'];
3059                  $this->cMargin = $this->theadMargins['cmargin'];
3060                  if ($this->rtl) {
3061                      $this->x = $this->w - $this->rMargin;
3062                  } else {
3063                      $this->x = $this->lMargin;
3064                  }
3065                  // print table header
3066                  $this->writeHTML($this->thead, false, false, false, false, '');
3067                  // set new top margin to skip the table headers
3068                  if (!isset($this->theadMargins['top'])) {
3069                      $this->theadMargins['top'] = $this->tMargin;
3070                  }
3071                  $this->tMargin = $this->y;
3072                  $this->pagedim[$this->page]['tm'] = $this->tMargin;
3073                  $this->lasth = 0;
3074                  $this->lMargin = $prev_lMargin;
3075                  $this->rMargin = $prev_rMargin;
3076              }
3077          }
3078  
3079          /**
3080           * Returns the current page number.
3081           * @return int page number
3082           * @access public
3083           * @since 1.0
3084           * @see AliasNbPages(), getAliasNbPages()
3085           */
3086  		public function PageNo() {
3087              return $this->page;
3088          }
3089  
3090          /**
3091           * Defines a new spot color.
3092           * It can be expressed in RGB components or gray scale.
3093           * The method can be called before the first page is created and the value is retained from page to page.
3094           * @param int $c Cyan color for CMYK. Value between 0 and 255
3095           * @param int $m Magenta color for CMYK. Value between 0 and 255
3096           * @param int $y Yellow color for CMYK. Value between 0 and 255
3097           * @param int $k Key (Black) color for CMYK. Value between 0 and 255
3098           * @access public
3099           * @since 4.0.024 (2008-09-12)
3100           * @see SetDrawSpotColor(), SetFillSpotColor(), SetTextSpotColor()
3101           */
3102  		public function AddSpotColor($name, $c, $m, $y, $k) {
3103              if (!isset($this->spot_colors[$name])) {
3104                  $i = 1 + count($this->spot_colors);
3105                  $this->spot_colors[$name] = array('i' => $i, 'c' => $c, 'm' => $m, 'y' => $y, 'k' => $k);
3106              }
3107          }
3108  
3109          /**
3110           * Defines the color used for all drawing operations (lines, rectangles and cell borders).
3111           * It can be expressed in RGB components or gray scale.
3112           * The method can be called before the first page is created and the value is retained from page to page.
3113           * @param array $color array of colors
3114           * @access public
3115           * @since 3.1.000 (2008-06-11)
3116           * @see SetDrawColor()
3117           */
3118  		public function SetDrawColorArray($color) {
3119              if (isset($color)) {
3120                  $color = array_values($color);
3121                  $r = isset($color[0]) ? $color[0] : -1;
3122                  $g = isset($color[1]) ? $color[1] : -1;
3123                  $b = isset($color[2]) ? $color[2] : -1;
3124                  $k = isset($color[3]) ? $color[3] : -1;
3125                  if ($r >= 0) {
3126                      $this->SetDrawColor($r, $g, $b, $k);
3127                  }
3128              }
3129          }
3130  
3131          /**
3132           * 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.
3133           * @param int $col1 Gray level for single color, or Red color for RGB, or Cyan color for CMYK. Value between 0 and 255
3134           * @param int $col2 Green color for RGB, or Magenta color for CMYK. Value between 0 and 255
3135           * @param int $col3 Blue color for RGB, or Yellow color for CMYK. Value between 0 and 255
3136           * @param int $col4 Key (Black) color for CMYK. Value between 0 and 255
3137           * @access public
3138           * @since 1.3
3139           * @see SetDrawColorArray(), SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell()
3140           */
3141  		public function SetDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1) {
3142              // set default values
3143              if (!is_numeric($col1)) {
3144                  $col1 = 0;
3145              }
3146              if (!is_numeric($col2)) {
3147                  $col2 = -1;
3148              }
3149              if (!is_numeric($col3)) {
3150                  $col3 = -1;
3151              }
3152              if (!is_numeric($col4)) {
3153                  $col4 = -1;
3154              }
3155              //Set color for all stroking operations
3156              if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
3157                  // Grey scale
3158                  $this->DrawColor = sprintf('%.3F G', $col1/255);
3159                  $this->strokecolor = array('G' => $col1);
3160              } elseif ($col4 == -1) {
3161                  // RGB
3162                  $this->DrawColor = sprintf('%.3F %.3F %.3F RG', $col1/255, $col2/255, $col3/255);
3163                  $this->strokecolor = array('R' => $col1, 'G' => $col2, 'B' => $col3);
3164              } else {
3165                  // CMYK
3166                  $this->DrawColor = sprintf('%.3F %.3F %.3F %.3F K', $col1/100, $col2/100, $col3/100, $col4/100);
3167                  $this->strokecolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4);
3168              }
3169              if ($this->page > 0) {
3170                  $this->_out($this->DrawColor);
3171              }
3172          }
3173  
3174          /**
3175           * Defines the spot color used for all drawing operations (lines, rectangles and cell borders).
3176           * @param string $name name of the spot color
3177           * @param int $tint the intensity of the color (from 0 to 100 ; 100 = full intensity by default).
3178           * @access public
3179           * @since 4.0.024 (2008-09-12)
3180           * @see AddSpotColor(), SetFillSpotColor(), SetTextSpotColor()
3181           */
3182  		public function SetDrawSpotColor($name, $tint=100) {
3183              if (!isset($this->spot_colors[$name])) {
3184                  $this->Error('Undefined spot color: '.$name);
3185              }
3186              $this->DrawColor = sprintf('/CS%d CS %.3F SCN', $this->spot_colors[$name]['i'], $tint/100);
3187              if ($this->page > 0) {
3188                  $this->_out($this->DrawColor);
3189              }
3190          }
3191  
3192          /**
3193           * Defines the color used for all filling operations (filled rectangles and cell backgrounds).
3194           * It can be expressed in RGB components or gray scale.
3195           * The method can be called before the first page is created and the value is retained from page to page.
3196           * @param array $color array of colors
3197           * @access public
3198           * @since 3.1.000 (2008-6-11)
3199           * @see SetFillColor()
3200           */
3201  		public function SetFillColorArray($color) {
3202              if (isset($color)) {
3203                  $color = array_values($color);
3204                  $r = isset($color[0]) ? $color[0] : -1;
3205                  $g = isset($color[1]) ? $color[1] : -1;
3206                  $b = isset($color[2]) ? $color[2] : -1;
3207                  $k = isset($color[3]) ? $color[3] : -1;
3208                  if ($r >= 0) {
3209                      $this->SetFillColor($r, $g, $b, $k);
3210                  }
3211              }
3212          }
3213  
3214          /**
3215           * 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.
3216           * @param int $col1 Gray level for single color, or Red color for RGB, or Cyan color for CMYK. Value between 0 and 255
3217           * @param int $col2 Green color for RGB, or Magenta color for CMYK. Value between 0 and 255
3218           * @param int $col3 Blue color for RGB, or Yellow color for CMYK. Value between 0 and 255
3219           * @param int $col4 Key (Black) color for CMYK. Value between 0 and 255
3220           * @access public
3221           * @since 1.3
3222           * @see SetFillColorArray(), SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell()
3223           */
3224  		public function SetFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1) {
3225              // set default values
3226              if (!is_numeric($col1)) {
3227                  $col1 = 0;
3228              }
3229              if (!is_numeric($col2)) {
3230                  $col2 = -1;
3231              }
3232              if (!is_numeric($col3)) {
3233                  $col3 = -1;
3234              }
3235              if (!is_numeric($col4)) {
3236                  $col4 = -1;
3237              }
3238              //Set color for all filling operations
3239              if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
3240                  // Grey scale
3241                  $this->FillColor = sprintf('%.3F g', $col1/255);
3242                  $this->bgcolor = array('G' => $col1);
3243              } elseif ($col4 == -1) {
3244                  // RGB
3245                  $this->FillColor = sprintf('%.3F %.3F %.3F rg', $col1/255, $col2/255, $col3/255);
3246                  $this->bgcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3);
3247              } else {
3248                  // CMYK
3249                  $this->FillColor = sprintf('%.3F %.3F %.3F %.3F k', $col1/100, $col2/100, $col3/100, $col4/100);
3250                  $this->bgcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4);
3251              }
3252              $this->ColorFlag = ($this->FillColor != $this->TextColor);
3253              if ($this->page > 0) {
3254                  $this->_out($this->FillColor);
3255              }
3256          }
3257  
3258          /**
3259           * Defines the spot color used for all filling operations (filled rectangles and cell backgrounds).
3260           * @param string $name name of the spot color
3261           * @param int $tint the intensity of the color (from 0 to 100 ; 100 = full intensity by default).
3262           * @access public
3263           * @since 4.0.024 (2008-09-12)
3264           * @see AddSpotColor(), SetDrawSpotColor(), SetTextSpotColor()
3265           */
3266  		public function SetFillSpotColor($name, $tint=100) {
3267              if (!isset($this->spot_colors[$name])) {
3268                  $this->Error('Undefined spot color: '.$name);
3269              }
3270              $this->FillColor = sprintf('/CS%d cs %.3F scn', $this->spot_colors[$name]['i'], $tint/100);
3271              $this->ColorFlag = ($this->FillColor != $this->TextColor);
3272              if ($this->page > 0) {
3273                  $this->_out($this->FillColor);
3274              }
3275          }
3276  
3277          /**
3278           * Defines the color used for text. It can be expressed in RGB components or gray scale.
3279           * The method can be called before the first page is created and the value is retained from page to page.
3280           * @param array $color array of colors
3281           * @access public
3282           * @since 3.1.000 (2008-6-11)
3283           * @see SetFillColor()
3284           */
3285  		public function SetTextColorArray($color) {
3286              if (isset($color)) {
3287                  $color = array_values($color);
3288                  $r = isset($color[0]) ? $color[0] : -1;
3289                  $g = isset($color[1]) ? $color[1] : -1;
3290                  $b = isset($color[2]) ? $color[2] : -1;
3291                  $k = isset($color[3]) ? $color[3] : -1;
3292                  if ($r >= 0) {
3293                      $this->SetTextColor($r, $g, $b, $k);
3294                  }
3295              }
3296          }
3297  
3298          /**
3299           * 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.
3300           * @param int $col1 Gray level for single color, or Red color for RGB, or Cyan color for CMYK. Value between 0 and 255
3301           * @param int $col2 Green color for RGB, or Magenta color for CMYK. Value between 0 and 255
3302           * @param int $col3 Blue color for RGB, or Yellow color for CMYK. Value between 0 and 255
3303           * @param int $col4 Key (Black) color for CMYK. Value between 0 and 255
3304           * @access public
3305           * @since 1.3
3306           * @see SetTextColorArray(), SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell()
3307           */
3308  		public function SetTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1) {
3309              // set default values
3310              if (!is_numeric($col1)) {
3311                  $col1 = 0;
3312              }
3313              if (!is_numeric($col2)) {
3314                  $col2 = -1;
3315              }
3316              if (!is_numeric($col3)) {
3317                  $col3 = -1;
3318              }
3319              if (!is_numeric($col4)) {
3320                  $col4 = -1;
3321              }
3322              //Set color for text
3323              if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
3324                  // Grey scale
3325                  $this->TextColor = sprintf('%.3F g', $col1/255);
3326                  $this->fgcolor = array('G' => $col1);
3327              } elseif ($col4 == -1) {
3328                  // RGB
3329                  $this->TextColor = sprintf('%.3F %.3F %.3F rg', $col1/255, $col2/255, $col3/255);
3330                  $this->fgcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3);
3331              } else {
3332                  // CMYK
3333                  $this->TextColor = sprintf('%.3F %.3F %.3F %.3F k', $col1/100, $col2/100, $col3/100, $col4/100);
3334                  $this->fgcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4);
3335              }
3336              $this->ColorFlag = ($this->FillColor != $this->TextColor);
3337          }
3338  
3339          /**
3340           * Defines the spot color used for text.
3341           * @param string $name name of the spot color
3342           * @param int $tint the intensity of the color (from 0 to 100 ; 100 = full intensity by default).
3343           * @access public
3344           * @since 4.0.024 (2008-09-12)
3345           * @see AddSpotColor(), SetDrawSpotColor(), SetFillSpotColor()
3346           */
3347  		public function SetTextSpotColor($name, $tint=100) {
3348              if (!isset($this->spot_colors[$name])) {
3349                  $this->Error('Undefined spot color: '.$name);
3350              }
3351              $this->TextColor = sprintf('/CS%d cs %.3F scn', $this->spot_colors[$name]['i'], $tint/100);
3352              $this->ColorFlag = ($this->FillColor != $this->TextColor);
3353              if ($this->page > 0) {
3354                  $this->_out($this->TextColor);
3355              }
3356          }
3357  
3358          /**
3359           * Returns the length of a string in user unit. A font must be selected.<br>
3360           * @param string $s The string whose length is to be computed
3361           * @param string $fontname Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained.
3362           * @param string $fontstyle 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><li>D: line-trough</li><li>O: overline</li></ul> or any combination. The default value is regular.
3363           * @param float $fontsize Font size in points. The default value is the current size.
3364           * @param boolean $getarray if true returns an array of characters widths, if false returns the total length.
3365           * @return mixed int total string length or array of characted widths
3366           * @author Nicola Asuni
3367           * @access public
3368           * @since 1.2
3369           */
3370  		public function GetStringWidth($s, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) {
3371              return $this->GetArrStringWidth($this->utf8Bidi($this->UTF8StringToArray($s), $s, $this->tmprtl), $fontname, $fontstyle, $fontsize, $getarray);
3372          }
3373  
3374          /**
3375           * Returns the string length of an array of chars in user unit or an array of characters widths. A font must be selected.<br>
3376           * @param string $sa The array of chars whose total length is to be computed
3377           * @param string $fontname Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained.
3378           * @param string $fontstyle 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><li>D: line trough</li><li>O: overline</li></ul> or any combination. The default value is regular.
3379           * @param float $fontsize Font size in points. The default value is the current size.
3380           * @param boolean $getarray if true returns an array of characters widths, if false returns the total length.
3381           * @return mixed int total string length or array of characted widths
3382           * @author Nicola Asuni
3383           * @access public
3384           * @since 2.4.000 (2008-03-06)
3385           */
3386  		public function GetArrStringWidth($sa, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) {
3387              // store current values
3388              if (!$this->empty_string($fontname)) {
3389                  $prev_FontFamily = $this->FontFamily;
3390                  $prev_FontStyle = $this->FontStyle;
3391                  $prev_FontSizePt = $this->FontSizePt;
3392                  $this->SetFont($fontname, $fontstyle, $fontsize);
3393              }
3394              // convert UTF-8 array to Latin1 if required
3395              $sa = $this->UTF8ArrToLatin1($sa);
3396              $w = 0; // total width
3397              $wa = array(); // array of characters widths
3398              foreach ($sa as $char) {
3399                  // character width
3400                  $cw = $this->GetCharWidth($char);
3401                  $wa[] = $cw;
3402                  $w += $cw;
3403              }
3404              // restore previous values
3405              if (!$this->empty_string($fontname)) {
3406                  $this->SetFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt);
3407              }
3408              if ($getarray) {
3409                  return $wa;
3410              }
3411              return $w;
3412          }
3413  
3414          /**
3415           * Returns the length of the char in user unit for the current font.
3416           * @param int $char The char code whose length is to be returned
3417           * @return int char width
3418           * @author Nicola Asuni
3419           * @access public
3420           * @since 2.4.000 (2008-03-06)
3421           */
3422  		public function GetCharWidth($char) {
3423              if ($char == 173) {
3424                  // SHY character will not be printed
3425                  return (0);
3426              }
3427              $cw = &$this->CurrentFont['cw'];
3428              if (isset($cw[$char])) {
3429                  $w = $cw[$char];
3430              } elseif (isset($this->CurrentFont['dw'])) {
3431                  // default width
3432                  $w = $this->CurrentFont['dw'];
3433              } elseif (isset($cw[32])) {
3434                  // default width
3435                  $w = $cw[32];
3436              } else {
3437                  $w = 600;
3438              }
3439              return ($w * $this->FontSize / 1000);
3440          }
3441  
3442          /**
3443           * Returns the numbero of characters in a string.
3444           * @param string $s The input string.
3445           * @return int number of characters
3446           * @access public
3447           * @since 2.0.0001 (2008-01-07)
3448           */
3449  		public function GetNumChars($s) {
3450              if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
3451                  return count($this->UTF8StringToArray($s));
3452              }
3453              return strlen($s);
3454          }
3455  
3456          /**
3457           * Fill the list of available fonts ($this->fontlist).
3458           * @access protected
3459           * @since 4.0.013 (2008-07-28)
3460           */
3461  		protected function getFontsList() {
3462              $fontsdir = opendir($this->_getfontpath());
3463              while (($file = readdir($fontsdir)) !== false) {
3464                  if (substr($file, -4) == '.php') {
3465                      array_push($this->fontlist, strtolower(basename($file, '.php')));
3466                  }
3467              }
3468              closedir($fontsdir);
3469          }
3470  
3471          /**
3472           * Imports a TrueType, Type1, core, or CID0 font and makes it available.
3473           * It is necessary to generate a font definition file first (read /fonts/utils/README.TXT).
3474           * The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by K_PATH_FONTS if the constant is defined. If it could not be found, the error "Could not include font definition file" is generated.
3475           * @param string $family Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font.
3476           * @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>
3477           * @param string $fontfile The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
3478           * @return array containing the font data, or false in case of error.
3479           * @access public
3480           * @since 1.5
3481           * @see SetFont()
3482           */
3483  		public function AddFont($family, $style='', $fontfile='') {
3484              if ($this->empty_string($family)) {
3485                  if (!$this->empty_string($this->FontFamily)) {
3486                      $family = $this->FontFamily;
3487                  } else {
3488                      $this->Error('Empty font family');
3489                  }
3490              }
3491              $family = strtolower($family);
3492              if ((!$this->isunicode) AND ($family == 'arial')) {
3493                  $family = 'helvetica';
3494              }
3495              if (($family == 'symbol') OR ($family == 'zapfdingbats')) {
3496                  $style = '';
3497              }
3498              $tempstyle = strtoupper($style);
3499              $style = '';
3500              // underline
3501              if (strpos($tempstyle, 'U') !== false) {
3502                  $this->underline = true;
3503              } else {
3504                  $this->underline = false;
3505              }
3506              // line-through (deleted)
3507              if (strpos($tempstyle, 'D') !== false) {
3508                  $this->linethrough = true;
3509              } else {
3510                  $this->linethrough = false;
3511              }
3512              // overline
3513              if (strpos($tempstyle, 'O') !== false) {
3514                  $this->overline = true;
3515              } else {
3516                  $this->overline = false;
3517              }
3518              // bold
3519              if (strpos($tempstyle, 'B') !== false) {
3520                  $style .= 'B';
3521              }
3522              // oblique
3523              if (strpos($tempstyle, 'I') !== false) {
3524                  $style .= 'I';
3525              }
3526              $bistyle = $style;
3527              $fontkey = $family.$style;
3528              $font_style = $style.($this->underline ? 'U' : '').($this->linethrough ? 'D' : '').($this->overline ? 'O' : '');
3529              $fontdata = array('fontkey' => $fontkey, 'family' => $family, 'style' => $font_style);
3530              // check if the font has been already added
3531              if ($this->getFontBuffer($fontkey) !== false) {
3532                  return $fontdata;
3533              }
3534              if (isset($type)) {
3535                  unset($type);
3536              }
3537              if (isset($cw)) {
3538                  unset($cw);
3539              }
3540              // get specified font directory (if any)
3541              $fontdir = false;
3542              if (!$this->empty_string($fontfile)) {
3543                  $fontdir = dirname($fontfile);
3544                  if ($this->empty_string($fontdir) OR ($fontdir == '.')) {
3545                      $fontdir = '';
3546                  } else {
3547                      $fontdir .= '/';
3548                  }
3549              }
3550              // search and include font file
3551              if ($this->empty_string($fontfile) OR (!file_exists($fontfile))) {
3552                  // build a standard filenames for specified font
3553                  $fontfile1 = str_replace(' ', '', $family).strtolower($style).'.php';
3554                  $fontfile2 = str_replace(' ', '', $family).'.php';
3555                  // search files on various directories
3556                  if (($fontdir !== false) AND file_exists($fontdir.$fontfile1)) {
3557                      $fontfile = $fontdir.$fontfile1;
3558                  } elseif (file_exists($this->_getfontpath().$fontfile1)) {
3559                      $fontfile = $this->_getfontpath().$fontfile1;
3560                  } elseif (file_exists($fontfile1)) {
3561                      $fontfile = $fontfile1;
3562                  } elseif (($fontdir !== false) AND file_exists($fontdir.$fontfile2)) {
3563                      $fontfile = $fontdir.$fontfile2;
3564                  } elseif (file_exists($this->_getfontpath().$fontfile2)) {
3565                      $fontfile = $this->_getfontpath().$fontfile2;
3566                  } else {
3567                      $fontfile = $fontfile2;
3568                  }
3569              }
3570              // include font file
3571              if (file_exists($fontfile)) {
3572                  include($fontfile);
3573              } else {
3574                  $this->Error('Could not include font definition file: '.$family.'');
3575              }
3576              // check font parameters
3577              if ((!isset($type)) OR (!isset($cw))) {
3578                  $this->Error('The font definition file has a bad format: '.$fontfile.'');
3579              }
3580              // SET default parameters
3581              if (!isset($file) OR $this->empty_string($file)) {
3582                  $file = '';
3583              }
3584              if (!isset($enc) OR $this->empty_string($enc)) {
3585                  $enc = '';
3586              }
3587              if (!isset($cidinfo) OR $this->empty_string($cidinfo)) {
3588                  $cidinfo = array('Registry'=>'Adobe','Ordering'=>'Identity','Supplement'=>0);
3589                  $cidinfo['uni2cid'] = array();
3590              }
3591              if (!isset($ctg) OR $this->empty_string($ctg)) {
3592                  $ctg = '';
3593              }
3594              if (!isset($desc) OR $this->empty_string($desc)) {
3595                  $desc = array();
3596              }
3597              if (!isset($up) OR $this->empty_string($up)) {
3598                  $up = -100;
3599              }
3600              if (!isset($ut) OR $this->empty_string($ut)) {
3601                  $ut = 50;
3602              }
3603              if (!isset($cw) OR $this->empty_string($cw)) {
3604                  $cw = array();
3605              }
3606              if (!isset($dw) OR $this->empty_string($dw)) {
3607                  // set default width
3608                  if (isset($desc['MissingWidth']) AND ($desc['MissingWidth'] > 0)) {
3609                      $dw = $desc['MissingWidth'];
3610                  } elseif (isset($cw[32])) {
3611                      $dw = $cw[32];
3612                  } else {
3613                      $dw = 600;
3614                  }
3615              }
3616              ++$this->numfonts;
3617              if ($type == 'cidfont0') {
3618                  // register CID font (all styles at once)
3619                  $styles = array('' => '', 'B' => ',Bold', 'I' => ',Italic', 'BI' => ',BoldItalic');
3620                  $sname = $name.$styles[$bistyle];
3621                  // artificial bold
3622                  if (strpos($bistyle, 'B') !== false) {
3623                      if (isset($desc['StemV'])) {
3624                          $desc['StemV'] *= 2;
3625                      } else {
3626                          $desc['StemV'] = 120;
3627                      }
3628                  }
3629                  // artificial italic
3630                  if (strpos($bistyle, 'I') !== false) {
3631                      if (isset($desc['ItalicAngle'])) {
3632                          $desc['ItalicAngle'] -= 11;
3633                      } else {
3634                          $desc['ItalicAngle'] = -11;
3635                      }
3636                  }
3637              } elseif ($type == 'core') {
3638                  $name = $this->CoreFonts[$fontkey];
3639              } elseif (($type == 'TrueType') OR ($type == 'Type1')) {
3640                  // ...
3641              } elseif ($type == 'TrueTypeUnicode') {
3642                  $enc = 'Identity-H';
3643              } else {
3644                  $this->Error('Unknow font type: '.$type.'');
3645              }
3646              $this->setFontBuffer($fontkey, array('i' => $this->numfonts, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'dw' => $dw, 'enc' => $enc, 'cidinfo' => $cidinfo, 'file' => $file, 'ctg' => $ctg));
3647              if (isset($diff) AND (!empty($diff))) {
3648                  //Search existing encodings
3649                  $d = 0;
3650                  $nb = count($this->diffs);
3651                  for ($i=1; $i <= $nb; ++$i) {
3652                      if ($this->diffs[$i] == $diff) {
3653                          $d = $i;
3654                          break;
3655                      }
3656                  }
3657                  if ($d == 0) {
3658                      $d = $nb + 1;
3659                      $this->diffs[$d] = $diff;
3660                  }
3661                  $this->setFontSubBuffer($fontkey, 'diff', $d);
3662              }
3663              if (!$this->empty_string($file)) {
3664                  if ((strcasecmp($type,'TrueType') == 0) OR (strcasecmp($type, 'TrueTypeUnicode') == 0)) {
3665                      $this->FontFiles[$file] = array('length1' => $originalsize, 'fontdir' => $fontdir);
3666                  } elseif ($type != 'core') {
3667                      $this->FontFiles[$file] = array('length1' => $size1, 'length2' => $size2, 'fontdir' => $fontdir);
3668                  }
3669              }
3670              return $fontdata;
3671          }
3672  
3673          /**
3674           * Sets the font used to print character strings.
3675           * The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe).
3676           * The method can be called before the first page is created and the font is retained from page to page.
3677           * If you just wish to change the current font size, it is simpler to call SetFontSize().
3678           * 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 K_PATH_FONTS constant</li></ul><br />
3679           * @param string $family Family font. It can be either a name defined by AddFont() or one of the standard Type1 families (case insensitive):<ul><li>times (Times-Roman)</li><li>timesb (Times-Bold)</li><li>timesi (Times-Italic)</li><li>timesbi (Times-BoldItalic)</li><li>helvetica (Helvetica)</li><li>helveticab (Helvetica-Bold)</li><li>helveticai (Helvetica-Oblique)</li><li>helveticabi (Helvetica-BoldOblique)</li><li>courier (Courier)</li><li>courierb (Courier-Bold)</li><li>courieri (Courier-Oblique)</li><li>courierbi (Courier-BoldOblique)</li><li>symbol (Symbol)</li><li>zapfdingbats (ZapfDingbats)</li></ul> It is also possible to pass an empty string. In that case, the current family is retained.
3680           * @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><li>D: line trough</li><li>O: overline</li></ul> or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats basic fonts or other fonts when not defined.
3681           * @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
3682           * @param string $fontfile The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
3683           * @access public
3684           * @since 1.0
3685           * @see AddFont(), SetFontSize()
3686           */
3687  		public function SetFont($family, $style='', $size=0, $fontfile='') {
3688              //Select a font; size given in points
3689              if ($size == 0) {
3690                  $size = $this->FontSizePt;
3691              }
3692              // try to add font (if not already added)
3693              $fontdata = $this->AddFont($family, $style, $fontfile);
3694              $this->FontFamily = $fontdata['family'];
3695              $this->FontStyle = $fontdata['style'];
3696              $this->CurrentFont = $this->getFontBuffer($fontdata['fontkey']);
3697              $this->SetFontSize($size);
3698          }
3699  
3700          /**
3701           * Defines the size of the current font.
3702           * @param float $size The size (in points)
3703           * @access public
3704           * @since 1.0
3705           * @see SetFont()
3706           */
3707  		public function SetFontSize($size) {
3708              //Set font size in points
3709              $this->FontSizePt = $size;
3710              $this->FontSize = $size / $this->k;
3711              if (isset($this->CurrentFont['desc']['Ascent']) AND ($this->CurrentFont['desc']['Ascent'] > 0)) {
3712                  $this->FontAscent = $this->CurrentFont['desc']['Ascent'] * $this->FontSize / 1000;
3713              } else {
3714                  $this->FontAscent = 0.85 * $this->FontSize;
3715              }
3716              if (isset($this->CurrentFont['desc']['Descent']) AND ($this->CurrentFont['desc']['Descent'] <= 0)) {
3717                  $this->FontDescent = - $this->CurrentFont['desc']['Descent'] * $this->FontSize / 1000;
3718              } else {
3719                  $this->FontDescent = 0.15 * $this->FontSize;
3720              }
3721              if (($this->page > 0) AND (isset($this->CurrentFont['i']))) {
3722                  $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3723              }
3724          }
3725  
3726          /**
3727           * Return the font descent value
3728           * @param string $font font name
3729           * @param string $style font style
3730           * @param float $size The size (in points)
3731           * @return int font descent
3732           * @access public
3733           * @since 4.9.003 (2010-03-30)
3734           */
3735  		public function getFontDescent($font, $style='', $size=0) {
3736              //Set font size in points
3737              $sizek = $size / $this->k;
3738              $fontdata = $this->AddFont($font, $style);
3739              if (isset($fontdata['desc']['Descent']) AND ($fontdata['desc']['Descent'] <= 0)) {
3740                  $descent = - $fontdata['desc']['Descent'] * $sizek / 1000;
3741              } else {
3742                  $descent = 0.15 * $sizek;
3743              }
3744              return $descent;
3745          }
3746  
3747          /**
3748           * Return the font ascent value
3749           * @param string $font font name
3750           * @param string $style font style
3751           * @param float $size The size (in points)
3752           * @return int font ascent
3753           * @access public
3754           * @since 4.9.003 (2010-03-30)
3755           */
3756  		public function getFontAscent($font, $style='', $size=0) {
3757              //Set font size in points
3758              $sizek = $size / $this->k;
3759              $fontdata = $this->AddFont($font, $style);
3760              if (isset($fontdata['desc']['Ascent']) AND ($fontdata['desc']['Ascent'] > 0)) {
3761                  $ascent = $fontdata['desc']['Ascent'] * $sizek / 1000;
3762              } else {
3763                  $ascent = 0.85 * $sizek;
3764              }
3765              return $ascent;
3766          }
3767  
3768          /**
3769           * Defines the default monospaced font.
3770           * @param string $font Font name.
3771           * @access public
3772           * @since 4.5.025
3773           */
3774  		public function SetDefaultMonospacedFont($font) {
3775              $this->default_monospaced_font = $font;
3776          }
3777  
3778          /**
3779           * 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 />
3780           * The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is defined with SetLink().
3781           * @access public
3782           * @since 1.5
3783           * @see Cell(), Write(), Image(), Link(), SetLink()
3784           */
3785  		public function AddLink() {
3786              //Create a new internal link
3787              $n = count($this->links) + 1;
3788              $this->links[$n] = array(0, 0);
3789              return $n;
3790          }
3791  
3792          /**
3793           * Defines the page and position a link points to.
3794           * @param int $link The link identifier returned by AddLink()
3795           * @param float $y Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page)
3796           * @param int $page Number of target page; -1 indicates the current page. This is the default value
3797           * @access public
3798           * @since 1.5
3799           * @see AddLink()
3800           */
3801  		public function SetLink($link, $y=0, $page=-1) {
3802              if ($y == -1) {
3803                  $y = $this->y;
3804              }
3805              if ($page == -1) {
3806                  $page = $this->page;
3807              }
3808              $this->links[$link] = array($page, $y);
3809          }
3810  
3811          /**
3812           * Puts a link on a rectangular area of the page.
3813           * 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.
3814           * @param float $x Abscissa of the upper-left corner of the rectangle
3815           * @param float $y Ordinate of the upper-left corner of the rectangle
3816           * @param float $w Width of the rectangle
3817           * @param float $h Height of the rectangle
3818           * @param mixed $link URL or identifier returned by AddLink()
3819           * @param int $spaces number of spaces on the text to link
3820           * @access public
3821           * @since 1.5
3822           * @see AddLink(), Annotation(), Cell(), Write(), Image()
3823           */
3824  		public function Link($x, $y, $w, $h, $link, $spaces=0) {
3825              $this->Annotation($x, $y, $w, $h, $link, array('Subtype'=>'Link'), $spaces);
3826          }
3827  
3828          /**
3829           * Puts a markup annotation on a rectangular area of the page.
3830           * !!!!THE ANNOTATION SUPPORT IS NOT YET FULLY IMPLEMENTED !!!!
3831           * @param float $x Abscissa of the upper-left corner of the rectangle
3832           * @param float $y Ordinate of the upper-left corner of the rectangle
3833           * @param float $w Width of the rectangle
3834           * @param float $h Height of the rectangle
3835           * @param string $text annotation text or alternate content
3836           * @param array $opt array of options (see section 8.4 of PDF reference 1.7).
3837           * @param int $spaces number of spaces on the text to link
3838           * @access public
3839           * @since 4.0.018 (2008-08-06)
3840           */
3841  		public function Annotation($x, $y, $w, $h, $text, $opt=array('Subtype'=>'Text'), $spaces=0) {
3842              if ($x === '') {
3843                  $x = $this->x;
3844              }
3845              if ($y === '') {
3846                  $y = $this->y;
3847              }
3848              // recalculate coordinates to account for graphic transformations
3849              if (isset($this->transfmatrix)) {
3850                  for ($i=$this->transfmatrix_key; $i > 0; --$i) {
3851                      $maxid = count($this->transfmatrix[$i]) - 1;
3852                      for ($j=$maxid; $j >= 0; --$j) {
3853                          $ctm = $this->transfmatrix[$i][$j];
3854                          if (isset($ctm['a'])) {
3855                              $x = $x * $this->k;
3856                              $y = ($this->h - $y) * $this->k;
3857                              $w = $w * $this->k;
3858                              $h = $h * $this->k;
3859                              // top left
3860                              $xt = $x;
3861                              $yt = $y;
3862                              $x1 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
3863                              $y1 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
3864                              // top right
3865                              $xt = $x + $w;
3866                              $yt = $y;
3867                              $x2 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
3868                              $y2 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
3869                              // bottom left
3870                              $xt = $x;
3871                              $yt = $y - $h;
3872                              $x3 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
3873                              $y3 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
3874                              // bottom right
3875                              $xt = $x + $w;
3876                              $yt = $y - $h;
3877                              $x4 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
3878                              $y4 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
3879                              // new coordinates (rectangle area)
3880                              $x = min($x1, $x2, $x3, $x4);
3881                              $y = max($y1, $y2, $y3, $y4);
3882                              $w = (max($x1, $x2, $x3, $x4) - $x) / $this->k;
3883                              $h = ($y - min($y1, $y2, $y3, $y4)) / $this->k;
3884                              $x = $x / $this->k;
3885                              $y = $this->h - ($y / $this->k);
3886                          }
3887                      }
3888                  }
3889              }
3890              if ($this->page <= 0) {
3891                  $page = 1;
3892              } else {
3893                  $page = $this->page;
3894              }
3895              if (!isset($this->PageAnnots[$page])) {
3896                  $this->PageAnnots[$page] = array();
3897              }
3898              $this->PageAnnots[$page][] = array('x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'txt' => $text, 'opt' => $opt, 'numspaces' => $spaces);
3899              if ((($opt['Subtype'] == 'FileAttachment') OR ($opt['Subtype'] == 'Sound')) AND (!$this->empty_string($opt['FS'])) AND file_exists($opt['FS']) AND (!isset($this->embeddedfiles[basename($opt['FS'])]))) {
3900                  $this->embeddedfiles[basename($opt['FS'])] = array('file' => $opt['FS'], 'n' => (count($this->embeddedfiles) + $this->embedded_start_obj_id));
3901              }
3902              // Add widgets annotation's icons
3903              if (isset($opt['mk']['i']) AND file_exists($opt['mk']['i'])) {
3904                  $this->Image($opt['mk']['i'], '', '', 10, 10, '', '', '', false, 300, '', false, false, 0, false, true);
3905              }
3906              if (isset($opt['mk']['ri']) AND file_exists($opt['mk']['ri'])) {
3907                  $this->Image($opt['mk']['ri'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true);
3908              }
3909              if (isset($opt['mk']['ix']) AND file_exists($opt['mk']['ix'])) {
3910                  $this->Image($opt['mk']['ix'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true);
3911              }
3912              ++$this->annot_obj_id;
3913          }
3914  
3915          /**
3916           * Embedd the attached files.
3917           * @since 4.4.000 (2008-12-07)
3918           * @access protected
3919           * @see Annotation()
3920           */
3921  		protected function _putEmbeddedFiles() {
3922              reset($this->embeddedfiles);
3923              foreach ($this->embeddedfiles as $filename => $filedata) {
3924                  $data = file_get_contents($filedata['file']);
3925                  $filter = '';
3926                  if ($this->compress) {
3927                      $data = gzcompress($data);
3928                      $filter = ' /Filter /FlateDecode';
3929                  }
3930                  $this->offsets[$filedata['n']] = $this->bufferlen;
3931                  $out = $filedata['n'].' 0 obj';
3932                  $out .= ' <</Type /EmbeddedFile'.$filter.' /Length '.strlen($data).' >>';
3933                  $out .= ' '.$this->_getstream($data, $filedata['n']);
3934                  $out .= ' endobj';
3935                  $this->_out($out);
3936              }
3937          }
3938  
3939          /**
3940           * Prints a text cell at the specified position.
3941           * The origin is on the left of the first charcter, on the baseline.
3942           * This method allows to place a string precisely on the page.
3943           * @param float $x Abscissa of the cell origin
3944           * @param float $y Ordinate of the cell origin
3945           * @param string $txt String to print
3946           * @param int $fstroke outline size in user units (false = disable)
3947           * @param boolean $fclip if true activate clipping mode (you must call StartTransform() before this function and StopTransform() to stop the clipping tranformation).
3948           * @param boolean $ffill if true fills the text
3949           * @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>
3950           * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
3951           * @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><li>J: justify</li></ul>
3952           * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
3953           * @param mixed $link URL or identifier returned by AddLink().
3954           * @param int $stretch stretch carachter mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if necessary</li><li>2 = forced horizontal scaling</li><li>3 = character spacing only if necessary</li><li>4 = forced character spacing</li></ul>
3955           * @param boolean $ignore_min_height if true ignore automatic minimum height value.
3956           * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li><li>B : cell bottom</li></ul>
3957           * @param string $valign text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>C : center</li><li>B : bottom</li></ul>
3958           * @param boolean $rtloff if true uses the page top-left corner as origin of axis for $x and $y initial position.
3959           * @access public
3960           * @since 1.0
3961           * @see Cell(), Write(), MultiCell(), WriteHTML(), WriteHTMLCell()
3962           */
3963  		public function Text($x, $y, $txt, $fstroke=false, $fclip=false, $ffill=true, $border=0, $ln=0, $align='', $fill=0, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M', $rtloff=false) {
3964              $textrendermode = $this->textrendermode;
3965              $textstrokewidth = $this->textstrokewidth;
3966              $this->setTextRenderingMode($fstroke, $ffill, $fclip);
3967              $this->SetXY($x, $y, $rtloff);
3968              $this->Cell(0, 0, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height, $calign, $valign);
3969              // restore previous rendering mode
3970              $this->textrendermode = $textrendermode;
3971              $this->textstrokewidth = $textstrokewidth;
3972          }
3973  
3974          /**
3975           * Whenever a page break condition is met, the method is called, and the break is issued or not depending on the returned value.
3976           * The default implementation returns a value according to the mode selected by SetAutoPageBreak().<br />
3977           * This method is called automatically and should not be called directly by the application.
3978           * @return boolean
3979           * @access public
3980           * @since 1.4
3981           * @see SetAutoPageBreak()
3982           */
3983  		public function AcceptPageBreak() {
3984              if ($this->num_columns > 1) {
3985                  // multi column mode
3986                  if($this->current_column < ($this->num_columns - 1)) {
3987                      // go to next column
3988                      $this->selectColumn($this->current_column + 1);
3989                  } else {
3990                      // add a new page
3991                      $this->AddPage();
3992                      // set first column
3993                      $this->selectColumn(0);
3994                  }
3995                  // avoid page breaking from checkPageBreak()
3996                  return false;
3997              }
3998              return $this->AutoPageBreak;
3999          }
4000  
4001          /**
4002           * Add page if needed.
4003           * @param float $h Cell height. Default value: 0.
4004           * @param mixed $y starting y position, leave empty for current position.
4005           * @param boolean $addpage if true add a page, otherwise only return the true/false state
4006           * @return boolean true in case of page break, false otherwise.
4007           * @since 3.2.000 (2008-07-01)
4008           * @access protected
4009           */
4010  		protected function checkPageBreak($h=0, $y='', $addpage=true) {
4011              if ($this->empty_string($y)) {
4012                  $y = $this->y;
4013              }
4014              if ((($y + $h) > $this->PageBreakTrigger) AND (!$this->InFooter) AND ($this->AcceptPageBreak())) {
4015                  if ($addpage) {
4016                      //Automatic page break
4017                      $x = $this->x;
4018                      $this->AddPage($this->CurOrientation);
4019                      $this->y = $this->tMargin;
4020                      $oldpage = $this->page - 1;
4021                      if ($this->rtl) {
4022                          if ($this->pagedim[$this->page]['orm'] != $this->pagedim[$oldpage]['orm']) {
4023                              $this->x = $x - ($this->pagedim[$this->page]['orm'] - $this->pagedim[$oldpage]['orm']);
4024                          } else {
4025                              $this->x = $x;
4026                          }
4027                      } else {
4028                          if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
4029                              $this->x = $x + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$oldpage]['olm']);
4030                          } else {
4031                              $this->x = $x;
4032                          }
4033                      }
4034                  }
4035                  return true;
4036              }
4037              return false;
4038          }
4039  
4040          /**
4041           * 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 />
4042           * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.
4043           * @param float $w Cell width. If 0, the cell extends up to the right margin.
4044           * @param float $h Cell height. Default value: 0.
4045           * @param string $txt String to print. Default value: empty string.
4046           * @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>
4047           * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
4048          Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
4049           * @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><li>J: justify</li></ul>
4050           * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
4051           * @param mixed $link URL or identifier returned by AddLink().
4052           * @param int $stretch stretch carachter mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if necessary</li><li>2 = forced horizontal scaling</li><li>3 = character spacing only if necessary</li><li>4 = forced character spacing</li></ul>
4053           * @param boolean $ignore_min_height if true ignore automatic minimum height value.
4054           * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>C : center</li><li>B : cell bottom</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li></ul>
4055           * @param string $valign text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>C : center</li><li>B : bottom</li></ul>
4056           * @access public
4057           * @since 1.0
4058           * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak()
4059           */
4060  		public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=0, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') {
4061              if (!$ignore_min_height) {
4062                  $min_cell_height = $this->FontSize * $this->cell_height_ratio;
4063                  if ($h < $min_cell_height) {
4064                      $h = $min_cell_height;
4065                  }
4066              }
4067              $this->checkPageBreak($h);
4068              $this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height, $calign, $valign));
4069          }
4070  
4071          /**
4072           * Removes SHY characters from text.
4073           * @param string $txt input string
4074           * @return string without SHY characters.
4075           * @access public
4076           * @since (4.5.019) 2009-02-28
4077           */
4078  		public function removeSHY($txt='') {
4079              /*
4080              * Unicode Data
4081              * Name : SOFT HYPHEN, commonly abbreviated as SHY
4082              * HTML Entity (decimal): &#173;
4083              * HTML Entity (hex): &#xad;
4084              * HTML Entity (named): &shy;
4085              * How to type in Microsoft Windows: [Alt +00AD] or [Alt 0173]
4086              * UTF-8 (hex): 0xC2 0xAD (c2ad)
4087              * UTF-8 character: chr(194).chr(173)
4088              */
4089              $txt = preg_replace('/([\\xc2]{1}[\\xad]{1})/', '', $txt);
4090              if (!$this->isunicode) {
4091                  $txt = preg_replace('/([\\xad]{1})/', '', $txt);
4092              }
4093              return $txt;
4094          }
4095  
4096          /**
4097           * Returns the PDF string code to print 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 />
4098           * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.
4099           * @param float $w Cell width. If 0, the cell extends up to the right margin.
4100           * @param float $h Cell height. Default value: 0.
4101           * @param string $txt String to print. Default value: empty string.
4102           * @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>
4103           * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
4104           * @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><li>J: justify</li></ul>
4105           * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.
4106           * @param mixed $link URL or identifier returned by AddLink().
4107           * @param int $stretch stretch carachter mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if necessary</li><li>2 = forced horizontal scaling</li><li>3 = character spacing only if necessary</li><li>4 = forced character spacing</li></ul>
4108           * @param boolean $ignore_min_height if true ignore automatic minimum height value.
4109           * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>C : center</li><li>B : cell bottom</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li></ul>
4110           * @param string $valign text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>C : center</li><li>B : bottom</li></ul>
4111           * @access protected
4112           * @since 1.0
4113           * @see Cell()
4114           */
4115  		protected function getCellCode($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=0, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') {
4116              $txt = $this->removeSHY($txt);
4117              $rs = ''; //string to be returned
4118              if (!$ignore_min_height) {
4119                  $min_cell_height = $this->FontSize * $this->cell_height_ratio;
4120                  if ($h < $min_cell_height) {
4121                      $h = $min_cell_height;
4122                  }
4123              }
4124              $k = $this->k;
4125              $x = $this->x;
4126              $y = $this->y;
4127              // cell vertical alignment
4128              switch ($calign) {
4129                  case 'A': {
4130                      // font top
4131                      switch ($valign) {
4132                          case 'T': {
4133                              // top
4134                              $y -= ($this->LineWidth / 2);
4135                              break;
4136                          }
4137                          case 'B': {
4138                              // bottom
4139                              $y -= ($h - $this->FontAscent - $this->FontDescent - ($this->LineWidth / 2));
4140                              break;
4141                          }
4142                          default:
4143                          case 'M': {
4144                              // center
4145                              $y -= (($h - $this->FontAscent - $this->FontDescent) / 2);
4146                              break;
4147                          }
4148                      }
4149                      break;
4150                  }
4151                  case 'L': {
4152                      // font baseline
4153                      switch ($valign) {
4154                          case 'T': {
4155                              // top
4156                              $y -= ($this->FontAscent + ($this->LineWidth / 2));
4157                              break;
4158                          }
4159                          case 'B': {
4160                              // bottom
4161                              $y -= ($h - $this->FontDescent - ($this->LineWidth / 2));
4162                              break;
4163                          }
4164                          default:
4165                          case 'M': {
4166                              // center
4167                              $y -= (($h + $this->FontAscent - $this->FontDescent) / 2);
4168                              break;
4169                          }
4170                      }
4171                      break;
4172                  }
4173                  case 'D': {
4174                      // font bottom
4175                      switch ($valign) {
4176                          case 'T': {
4177                              // top
4178                              $y -= ($this->FontAscent + $this->FontDescent + ($this->LineWidth / 2));
4179                              break;
4180                          }
4181                          case 'B': {
4182                              // bottom
4183                              $y -= ($h - ($this->LineWidth / 2));
4184                              break;
4185                          }
4186                          default:
4187                          case 'M': {
4188                              // center
4189                              $y -= (($h + $this->FontAscent + $this->FontDescent) / 2);
4190                              break;
4191                          }
4192                      }
4193                      break;
4194                  }
4195                  case 'B': {
4196                      // cell bottom
4197                      $y -= $h;
4198                      break;
4199                  }
4200                  case 'C': {
4201                      // cell center
4202                      $y -= ($h / 2);
4203                      break;
4204                  }
4205                  default:
4206                  case 'T': {
4207                      // cell top
4208                      break;
4209                  }
4210              }
4211              // text vertical alignment
4212              switch ($valign) {
4213                  case 'T': {
4214                      // top
4215                      $basefonty = $y + $this->FontAscent + ($this->LineWidth / 2);
4216                      break;
4217                  }
4218                  case 'B': {
4219                      // bottom
4220                      $basefonty = $y + $h - $this->FontDescent - ($this->LineWidth / 2);
4221                      break;
4222                  }
4223                  default:
4224                  case 'M': {
4225                      // center
4226                      $basefonty = $y + (($h + $this->FontAscent - $this->FontDescent) / 2);
4227                      break;
4228                  }
4229              }
4230              if ($this->empty_string($w) OR ($w <= 0)) {
4231                  if ($this->rtl) {
4232                      $w = $x - $this->lMargin;
4233                  } else {
4234                      $w = $this->w - $this->rMargin - $x;
4235                  }
4236              }
4237              $s = '';
4238              // fill and borders
4239              if (($fill == 1) OR ($border == 1)) {
4240                  if ($fill == 1) {
4241                      $op = ($border == 1) ? 'B' : 'f';
4242                  } else {
4243                      $op = 'S';
4244                  }
4245                  if ($this->rtl) {
4246                      $xk = (($this->x  - $w) * $k);
4247                  } else {
4248                      $xk = ($this->x * $k);
4249                  }
4250                  $s .= sprintf('%.2F %.2F %.2F %.2F re %s ', $xk, (($this->h - $y) * $k), ($w * $k), (-$h * $k), $op);
4251              }
4252              if (is_string($border)) {
4253                  $lm = ($this->LineWidth / 2);
4254                  if (strpos($border,'L') !== false) {
4255                      if ($this->rtl) {
4256                          $xk = ($x - $w) * $k;
4257                      } else {
4258                          $xk = $x * $k;
4259                      }
4260                      $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $xk, (($this->h - $y + $lm) * $k), $xk, (($this->h - ($y + $h + $lm)) * $k));
4261                  }
4262                  if (strpos($border,'T') !== false) {
4263                      if ($this->rtl) {
4264                          $xk = ($x - $w + $lm) * $k;
4265                          $xwk = ($x - $lm) * $k;
4266                      } else {
4267                          $xk = ($x - $lm) * $k;
4268                          $xwk = ($x + $w + $lm) * $k;
4269                      }
4270                      $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $xk, (($this->h - $y) * $k), $xwk, (($this->h - $y) * $k));
4271                  }
4272                  if (strpos($border,'R') !== false) {
4273                      if ($this->rtl) {
4274                          $xk = $x * $k;
4275                      } else {
4276                          $xk = ($x + $w) * $k;
4277                      }
4278                      $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $xk, (($this->h - $y + $lm) * $k), $xk, (($this->h - ($y + $h + $lm))* $k));
4279                  }
4280                  if (strpos($border,'B') !== false) {
4281                      if ($this->rtl) {
4282                          $xk = ($x - $w + $lm) * $k;
4283                          $xwk = ($x - $lm) * $k;
4284                      } else {
4285                          $xk = ($x - $lm) * $k;
4286                          $xwk = ($x + $w + $lm) * $k;
4287                      }
4288                      $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $xk, (($this->h - ($y + $h)) * $k), $xwk, (($this->h - ($y + $h)) * $k));
4289                  }
4290              }
4291              if ($txt != '') {
4292                  $txt2 = $txt;
4293                  if ($this->isunicode) {
4294                      if (($this->CurrentFont['type'] == 'core') OR ($this->CurrentFont['type'] == 'TrueType') OR ($this->CurrentFont['type'] == 'Type1')) {
4295                          $txt2 = $this->UTF8ToLatin1($txt2);
4296                      } else {
4297                          $unicode = $this->UTF8StringToArray($txt); // array of UTF-8 unicode values
4298                          $unicode = $this->utf8Bidi($unicode, '', $this->tmprtl);
4299                          if (defined('K_THAI_TOPCHARS') AND (K_THAI_TOPCHARS == true)) {
4300                              // ---- Fix for bug #2977340 "Incorrect Thai characters position arrangement" ----
4301                              // NOTE: this doesn't work with HTML justification
4302                              // Symbols that could overlap on the font top (only works in LTR)
4303                              $topchar = array(3611, 3613, 3615, 3650, 3651, 3652); // chars that extends on top
4304                              $topsym = array(3633, 3636, 3637, 3638, 3639, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662); // symbols with top position
4305                              $numchars = count($unicode); // number of chars
4306                              $unik = 0;
4307                              $uniblock = array();
4308                              $uniblock[$unik] = array();
4309                              $uniblock[$unik][] = $unicode[0];
4310                              // resolve overlapping conflicts by splitting the string in several parts
4311                              for ($i = 1; $i < $numchars; ++$i) {
4312                                  // check if symbols overlaps at top
4313                                  if (in_array($unicode[$i], $topsym) AND (in_array($unicode[($i - 1)], $topsym) OR in_array($unicode[($i - 1)], $topchar))) {
4314                                      // move symbols to another array
4315                                      ++$unik;
4316                                      $uniblock[$unik] = array();
4317                                      $uniblock[$unik][] =