"Fossies" - the Fresh Open Source Software Archive

Member "4.6.1/composer/tecnickcom/tcpdf/tcpdf.php" (8 Apr 2021, 901091 Bytes) of package /linux/www/studip-4.6.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tcpdf.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 //============================================================+
    3 // File name   : tcpdf.php
    4 // Version     : 6.3.2
    5 // Begin       : 2002-08-03
    6 // Last Update : 2019-09-20
    7 // Author      : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
    8 // License     : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
    9 // -------------------------------------------------------------------
   10 // Copyright (C) 2002-2019 Nicola Asuni - Tecnick.com LTD
   11 //
   12 // This file is part of TCPDF software library.
   13 //
   14 // TCPDF is free software: you can redistribute it and/or modify it
   15 // under the terms of the GNU Lesser General Public License as
   16 // published by the Free Software Foundation, either version 3 of the
   17 // License, or (at your option) any later version.
   18 //
   19 // TCPDF is distributed in the hope that it will be useful, but
   20 // WITHOUT ANY WARRANTY; without even the implied warranty of
   21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   22 // See the GNU Lesser General Public License for more details.
   23 //
   24 // You should have received a copy of the License
   25 // along with TCPDF. If not, see
   26 // <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>.
   27 //
   28 // See LICENSE.TXT file for more information.
   29 // -------------------------------------------------------------------
   30 //
   31 // Description :
   32 //   This is a PHP class for generating PDF documents without requiring external extensions.
   33 //
   34 // NOTE:
   35 //   This class was originally derived in 2002 from the Public
   36 //   Domain FPDF class by Olivier Plathey (http://www.fpdf.org),
   37 //   but now is almost entirely rewritten and contains thousands of
   38 //   new lines of code and hundreds new features.
   39 //
   40 // Main features:
   41 //  * no external libraries are required for the basic functions;
   42 //  * all standard page formats, custom page formats, custom margins and units of measure;
   43 //  * UTF-8 Unicode and Right-To-Left languages;
   44 //  * TrueTypeUnicode, TrueType, Type1 and CID-0 fonts;
   45 //  * font subsetting;
   46 //  * methods to publish some XHTML + CSS code, Javascript and Forms;
   47 //  * images, graphic (geometric figures) and transformation methods;
   48 //  * 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 ImageMagick (http://www.imagemagick.org/www/formats.html)
   49 //  * 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 Extension, 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, Datamatrix, QR-Code, PDF417;
   50 //  * JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies;
   51 //  * automatic page header and footer management;
   52 //  * document encryption up to 256 bit and digital signature certifications;
   53 //  * transactions to UNDO commands;
   54 //  * PDF annotations, including links, text and file attachments;
   55 //  * text rendering modes (fill, stroke and clipping);
   56 //  * multiple columns mode;
   57 //  * no-write page regions;
   58 //  * bookmarks, named destinations and table of content;
   59 //  * text hyphenation;
   60 //  * text stretching and spacing (tracking);
   61 //  * automatic page break, line break and text alignments including justification;
   62 //  * automatic page numbering and page groups;
   63 //  * move and delete pages;
   64 //  * page compression (requires php-zlib extension);
   65 //  * XOBject Templates;
   66 //  * Layers and object visibility.
   67 //  * PDF/A-1b support
   68 //============================================================+
   69 
   70 /**
   71  * @file
   72  * This is a PHP class for generating PDF documents without requiring external extensions.<br>
   73  * 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>
   74  * <h3>TCPDF main features are:</h3>
   75  * <ul>
   76  * <li>no external libraries are required for the basic functions;</li>
   77  * <li>all standard page formats, custom page formats, custom margins and units of measure;</li>
   78  * <li>UTF-8 Unicode and Right-To-Left languages;</li>
   79  * <li>TrueTypeUnicode, TrueType, Type1 and CID-0 fonts;</li>
   80  * <li>font subsetting;</li>
   81  * <li>methods to publish some XHTML + CSS code, Javascript and Forms;</li>
   82  * <li>images, graphic (geometric figures) and transformation methods;
   83  * <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 ImageMagick (http://www.imagemagick.org/www/formats.html)</li>
   84  * <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 Extension, 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, Datamatrix, QR-Code, PDF417;</li>
   85  * <li>JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies;</li>
   86  * <li>automatic page header and footer management;</li>
   87  * <li>document encryption up to 256 bit and digital signature certifications;</li>
   88  * <li>transactions to UNDO commands;</li>
   89  * <li>PDF annotations, including links, text and file attachments;</li>
   90  * <li>text rendering modes (fill, stroke and clipping);</li>
   91  * <li>multiple columns mode;</li>
   92  * <li>no-write page regions;</li>
   93  * <li>bookmarks, named destinations and table of content;</li>
   94  * <li>text hyphenation;</li>
   95  * <li>text stretching and spacing (tracking);</li>
   96  * <li>automatic page break, line break and text alignments including justification;</li>
   97  * <li>automatic page numbering and page groups;</li>
   98  * <li>move and delete pages;</li>
   99  * <li>page compression (requires php-zlib extension);</li>
  100  * <li>XOBject Templates;</li>
  101  * <li>Layers and object visibility;</li>
  102  * <li>PDF/A-1b support.</li>
  103  * </ul>
  104  * Tools to encode your unicode fonts are on fonts/utils directory.</p>
  105  * @package com.tecnick.tcpdf
  106  * @author Nicola Asuni
  107  * @version 6.3.2
  108  */
  109 
  110 // TCPDF configuration
  111 require_once(dirname(__FILE__).'/tcpdf_autoconfig.php');
  112 // TCPDF static font methods and data
  113 require_once(dirname(__FILE__).'/include/tcpdf_font_data.php');
  114 // TCPDF static font methods and data
  115 require_once(dirname(__FILE__).'/include/tcpdf_fonts.php');
  116 // TCPDF static color methods and data
  117 require_once(dirname(__FILE__).'/include/tcpdf_colors.php');
  118 // TCPDF static image methods and data
  119 require_once(dirname(__FILE__).'/include/tcpdf_images.php');
  120 // TCPDF static methods and data
  121 require_once(dirname(__FILE__).'/include/tcpdf_static.php');
  122 
  123 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  124 
  125 /**
  126  * @class TCPDF
  127  * PHP class for generating PDF documents without requiring external extensions.
  128  * 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>
  129  * @package com.tecnick.tcpdf
  130  * @brief PHP class for generating PDF documents without requiring external extensions.
  131  * @version 6.3.2
  132  * @author Nicola Asuni - info@tecnick.com
  133  * @IgnoreAnnotation("protected")
  134  * @IgnoreAnnotation("public")
  135  * @IgnoreAnnotation("pre")
  136  */
  137 class TCPDF {
  138 
  139     // Protected properties
  140 
  141     /**
  142      * Current page number.
  143      * @protected
  144      */
  145     protected $page;
  146 
  147     /**
  148      * Current object number.
  149      * @protected
  150      */
  151     protected $n;
  152 
  153     /**
  154      * Array of object offsets.
  155      * @protected
  156      */
  157     protected $offsets = array();
  158 
  159     /**
  160      * Array of object IDs for each page.
  161      * @protected
  162      */
  163     protected $pageobjects = array();
  164 
  165     /**
  166      * Buffer holding in-memory PDF.
  167      * @protected
  168      */
  169     protected $buffer;
  170 
  171     /**
  172      * Array containing pages.
  173      * @protected
  174      */
  175     protected $pages = array();
  176 
  177     /**
  178      * Current document state.
  179      * @protected
  180      */
  181     protected $state;
  182 
  183     /**
  184      * Compression flag.
  185      * @protected
  186      */
  187     protected $compress;
  188 
  189     /**
  190      * Current page orientation (P = Portrait, L = Landscape).
  191      * @protected
  192      */
  193     protected $CurOrientation;
  194 
  195     /**
  196      * Page dimensions.
  197      * @protected
  198      */
  199     protected $pagedim = array();
  200 
  201     /**
  202      * Scale factor (number of points in user unit).
  203      * @protected
  204      */
  205     protected $k;
  206 
  207     /**
  208      * Width of page format in points.
  209      * @protected
  210      */
  211     protected $fwPt;
  212 
  213     /**
  214      * Height of page format in points.
  215      * @protected
  216      */
  217     protected $fhPt;
  218 
  219     /**
  220      * Current width of page in points.
  221      * @protected
  222      */
  223     protected $wPt;
  224 
  225     /**
  226      * Current height of page in points.
  227      * @protected
  228      */
  229     protected $hPt;
  230 
  231     /**
  232      * Current width of page in user unit.
  233      * @protected
  234      */
  235     protected $w;
  236 
  237     /**
  238      * Current height of page in user unit.
  239      * @protected
  240      */
  241     protected $h;
  242 
  243     /**
  244      * Left margin.
  245      * @protected
  246      */
  247     protected $lMargin;
  248 
  249     /**
  250      * Right margin.
  251      * @protected
  252      */
  253     protected $rMargin;
  254 
  255     /**
  256      * Cell left margin (used by regions).
  257      * @protected
  258      */
  259     protected $clMargin;
  260 
  261     /**
  262      * Cell right margin (used by regions).
  263      * @protected
  264      */
  265     protected $crMargin;
  266 
  267     /**
  268      * Top margin.
  269      * @protected
  270      */
  271     protected $tMargin;
  272 
  273     /**
  274      * Page break margin.
  275      * @protected
  276      */
  277     protected $bMargin;
  278 
  279     /**
  280      * Array of cell internal paddings ('T' => top, 'R' => right, 'B' => bottom, 'L' => left).
  281      * @since 5.9.000 (2010-10-03)
  282      * @protected
  283      */
  284     protected $cell_padding = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0);
  285 
  286     /**
  287      * Array of cell margins ('T' => top, 'R' => right, 'B' => bottom, 'L' => left).
  288      * @since 5.9.000 (2010-10-04)
  289      * @protected
  290      */
  291     protected $cell_margin = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0);
  292 
  293     /**
  294      * Current horizontal position in user unit for cell positioning.
  295      * @protected
  296      */
  297     protected $x;
  298 
  299     /**
  300      * Current vertical position in user unit for cell positioning.
  301      * @protected
  302      */
  303     protected $y;
  304 
  305     /**
  306      * Height of last cell printed.
  307      * @protected
  308      */
  309     protected $lasth;
  310 
  311     /**
  312      * Line width in user unit.
  313      * @protected
  314      */
  315     protected $LineWidth;
  316 
  317     /**
  318      * Array of standard font names.
  319      * @protected
  320      */
  321     protected $CoreFonts;
  322 
  323     /**
  324      * Array of used fonts.
  325      * @protected
  326      */
  327     protected $fonts = array();
  328 
  329     /**
  330      * Array of font files.
  331      * @protected
  332      */
  333     protected $FontFiles = array();
  334 
  335     /**
  336      * Array of encoding differences.
  337      * @protected
  338      */
  339     protected $diffs = array();
  340 
  341     /**
  342      * Array of used images.
  343      * @protected
  344      */
  345     protected $images = array();
  346 
  347     /**
  348      * Depth of the svg tag, to keep track if the svg tag is a subtag or the root tag.
  349      * @protected
  350      */
  351     protected $svg_tag_depth = 0;
  352 
  353     /**
  354      * Array of Annotations in pages.
  355      * @protected
  356      */
  357     protected $PageAnnots = array();
  358 
  359     /**
  360      * Array of internal links.
  361      * @protected
  362      */
  363     protected $links = array();
  364 
  365     /**
  366      * Current font family.
  367      * @protected
  368      */
  369     protected $FontFamily;
  370 
  371     /**
  372      * Current font style.
  373      * @protected
  374      */
  375     protected $FontStyle;
  376 
  377     /**
  378      * Current font ascent (distance between font top and baseline).
  379      * @protected
  380      * @since 2.8.000 (2007-03-29)
  381      */
  382     protected $FontAscent;
  383 
  384     /**
  385      * Current font descent (distance between font bottom and baseline).
  386      * @protected
  387      * @since 2.8.000 (2007-03-29)
  388      */
  389     protected $FontDescent;
  390 
  391     /**
  392      * Underlining flag.
  393      * @protected
  394      */
  395     protected $underline;
  396 
  397     /**
  398      * Overlining flag.
  399      * @protected
  400      */
  401     protected $overline;
  402 
  403     /**
  404      * Current font info.
  405      * @protected
  406      */
  407     protected $CurrentFont;
  408 
  409     /**
  410      * Current font size in points.
  411      * @protected
  412      */
  413     protected $FontSizePt;
  414 
  415     /**
  416      * Current font size in user unit.
  417      * @protected
  418      */
  419     protected $FontSize;
  420 
  421     /**
  422      * Commands for drawing color.
  423      * @protected
  424      */
  425     protected $DrawColor;
  426 
  427     /**
  428      * Commands for filling color.
  429      * @protected
  430      */
  431     protected $FillColor;
  432 
  433     /**
  434      * Commands for text color.
  435      * @protected
  436      */
  437     protected $TextColor;
  438 
  439     /**
  440      * Indicates whether fill and text colors are different.
  441      * @protected
  442      */
  443     protected $ColorFlag;
  444 
  445     /**
  446      * Automatic page breaking.
  447      * @protected
  448      */
  449     protected $AutoPageBreak;
  450 
  451     /**
  452      * Threshold used to trigger page breaks.
  453      * @protected
  454      */
  455     protected $PageBreakTrigger;
  456 
  457     /**
  458      * Flag set when processing page header.
  459      * @protected
  460      */
  461     protected $InHeader = false;
  462 
  463     /**
  464      * Flag set when processing page footer.
  465      * @protected
  466      */
  467     protected $InFooter = false;
  468 
  469     /**
  470      * Zoom display mode.
  471      * @protected
  472      */
  473     protected $ZoomMode;
  474 
  475     /**
  476      * Layout display mode.
  477      * @protected
  478      */
  479     protected $LayoutMode;
  480 
  481     /**
  482      * If true set the document information dictionary in Unicode.
  483      * @protected
  484      */
  485     protected $docinfounicode = true;
  486 
  487     /**
  488      * Document title.
  489      * @protected
  490      */
  491     protected $title = '';
  492 
  493     /**
  494      * Document subject.
  495      * @protected
  496      */
  497     protected $subject = '';
  498 
  499     /**
  500      * Document author.
  501      * @protected
  502      */
  503     protected $author = '';
  504 
  505     /**
  506      * Document keywords.
  507      * @protected
  508      */
  509     protected $keywords = '';
  510 
  511     /**
  512      * Document creator.
  513      * @protected
  514      */
  515     protected $creator = '';
  516 
  517     /**
  518      * Starting page number.
  519      * @protected
  520      */
  521     protected $starting_page_number = 1;
  522 
  523     /**
  524      * The right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image.
  525      * @since 2002-07-31
  526      * @author Nicola Asuni
  527      * @protected
  528      */
  529     protected $img_rb_x;
  530 
  531     /**
  532      * The right-bottom corner Y coordinate of last inserted image.
  533      * @since 2002-07-31
  534      * @author Nicola Asuni
  535      * @protected
  536      */
  537     protected $img_rb_y;
  538 
  539     /**
  540      * Adjusting factor to convert pixels to user units.
  541      * @since 2004-06-14
  542      * @author Nicola Asuni
  543      * @protected
  544      */
  545     protected $imgscale = 1;
  546 
  547     /**
  548      * Boolean flag set to true when the input text is unicode (require unicode fonts).
  549      * @since 2005-01-02
  550      * @author Nicola Asuni
  551      * @protected
  552      */
  553     protected $isunicode = false;
  554 
  555     /**
  556      * PDF version.
  557      * @since 1.5.3
  558      * @protected
  559      */
  560     protected $PDFVersion = '1.7';
  561 
  562     /**
  563      * ID of the stored default header template (-1 = not set).
  564      * @protected
  565      */
  566     protected $header_xobjid = false;
  567 
  568     /**
  569      * If true reset the Header Xobject template at each page
  570      * @protected
  571      */
  572     protected $header_xobj_autoreset = false;
  573 
  574     /**
  575      * Minimum distance between header and top page margin.
  576      * @protected
  577      */
  578     protected $header_margin;
  579 
  580     /**
  581      * Minimum distance between footer and bottom page margin.
  582      * @protected
  583      */
  584     protected $footer_margin;
  585 
  586     /**
  587      * Original left margin value.
  588      * @protected
  589      * @since 1.53.0.TC013
  590      */
  591     protected $original_lMargin;
  592 
  593     /**
  594      * Original right margin value.
  595      * @protected
  596      * @since 1.53.0.TC013
  597      */
  598     protected $original_rMargin;
  599 
  600     /**
  601      * Default font used on page header.
  602      * @protected
  603      */
  604     protected $header_font;
  605 
  606     /**
  607      * Default font used on page footer.
  608      * @protected
  609      */
  610     protected $footer_font;
  611 
  612     /**
  613      * Language templates.
  614      * @protected
  615      */
  616     protected $l;
  617 
  618     /**
  619      * Barcode to print on page footer (only if set).
  620      * @protected
  621      */
  622     protected $barcode = false;
  623 
  624     /**
  625      * Boolean flag to print/hide page header.
  626      * @protected
  627      */
  628     protected $print_header = true;
  629 
  630     /**
  631      * Boolean flag to print/hide page footer.
  632      * @protected
  633      */
  634     protected $print_footer = true;
  635 
  636     /**
  637      * Header image logo.
  638      * @protected
  639      */
  640     protected $header_logo = '';
  641 
  642     /**
  643      * Width of header image logo in user units.
  644      * @protected
  645      */
  646     protected $header_logo_width = 30;
  647 
  648     /**
  649      * Title to be printed on default page header.
  650      * @protected
  651      */
  652     protected $header_title = '';
  653 
  654     /**
  655      * String to pring on page header after title.
  656      * @protected
  657      */
  658     protected $header_string = '';
  659 
  660     /**
  661      * Color for header text (RGB array).
  662      * @since 5.9.174 (2012-07-25)
  663      * @protected
  664      */
  665     protected $header_text_color = array(0,0,0);
  666 
  667     /**
  668      * Color for header line (RGB array).
  669      * @since 5.9.174 (2012-07-25)
  670      * @protected
  671      */
  672     protected $header_line_color = array(0,0,0);
  673 
  674     /**
  675      * Color for footer text (RGB array).
  676      * @since 5.9.174 (2012-07-25)
  677      * @protected
  678      */
  679     protected $footer_text_color = array(0,0,0);
  680 
  681     /**
  682      * Color for footer line (RGB array).
  683      * @since 5.9.174 (2012-07-25)
  684      * @protected
  685      */
  686     protected $footer_line_color = array(0,0,0);
  687 
  688     /**
  689      * Text shadow data array.
  690      * @since 5.9.174 (2012-07-25)
  691      * @protected
  692      */
  693     protected $txtshadow = array('enabled'=>false, 'depth_w'=>0, 'depth_h'=>0, 'color'=>false, 'opacity'=>1, 'blend_mode'=>'Normal');
  694 
  695     /**
  696      * Default number of columns for html table.
  697      * @protected
  698      */
  699     protected $default_table_columns = 4;
  700 
  701     // variables for html parser
  702 
  703     /**
  704      * HTML PARSER: array to store current link and rendering styles.
  705      * @protected
  706      */
  707     protected $HREF = array();
  708 
  709     /**
  710      * List of available fonts on filesystem.
  711      * @protected
  712      */
  713     protected $fontlist = array();
  714 
  715     /**
  716      * Current foreground color.
  717      * @protected
  718      */
  719     protected $fgcolor;
  720 
  721     /**
  722      * HTML PARSER: array of boolean values, true in case of ordered list (OL), false otherwise.
  723      * @protected
  724      */
  725     protected $listordered = array();
  726 
  727     /**
  728      * HTML PARSER: array count list items on nested lists.
  729      * @protected
  730      */
  731     protected $listcount = array();
  732 
  733     /**
  734      * HTML PARSER: current list nesting level.
  735      * @protected
  736      */
  737     protected $listnum = 0;
  738 
  739     /**
  740      * HTML PARSER: indent amount for lists.
  741      * @protected
  742      */
  743     protected $listindent = 0;
  744 
  745     /**
  746      * HTML PARSER: current list indententation level.
  747      * @protected
  748      */
  749     protected $listindentlevel = 0;
  750 
  751     /**
  752      * Current background color.
  753      * @protected
  754      */
  755     protected $bgcolor;
  756 
  757     /**
  758      * Temporary font size in points.
  759      * @protected
  760      */
  761     protected $tempfontsize = 10;
  762 
  763     /**
  764      * Spacer string for LI tags.
  765      * @protected
  766      */
  767     protected $lispacer = '';
  768 
  769     /**
  770      * Default encoding.
  771      * @protected
  772      * @since 1.53.0.TC010
  773      */
  774     protected $encoding = 'UTF-8';
  775 
  776     /**
  777      * PHP internal encoding.
  778      * @protected
  779      * @since 1.53.0.TC016
  780      */
  781     protected $internal_encoding;
  782 
  783     /**
  784      * Boolean flag to indicate if the document language is Right-To-Left.
  785      * @protected
  786      * @since 2.0.000
  787      */
  788     protected $rtl = false;
  789 
  790     /**
  791      * Boolean flag used to force RTL or LTR string direction.
  792      * @protected
  793      * @since 2.0.000
  794      */
  795     protected $tmprtl = false;
  796 
  797     // --- Variables used for document encryption:
  798 
  799     /**
  800      * IBoolean flag indicating whether document is protected.
  801      * @protected
  802      * @since 2.0.000 (2008-01-02)
  803      */
  804     protected $encrypted;
  805 
  806     /**
  807      * Array containing encryption settings.
  808      * @protected
  809      * @since 5.0.005 (2010-05-11)
  810      */
  811     protected $encryptdata = array();
  812 
  813     /**
  814      * Last RC4 key encrypted (cached for optimisation).
  815      * @protected
  816      * @since 2.0.000 (2008-01-02)
  817      */
  818     protected $last_enc_key;
  819 
  820     /**
  821      * Last RC4 computed key.
  822      * @protected
  823      * @since 2.0.000 (2008-01-02)
  824      */
  825     protected $last_enc_key_c;
  826 
  827     /**
  828      * File ID (used on document trailer).
  829      * @protected
  830      * @since 5.0.005 (2010-05-12)
  831      */
  832     protected $file_id;
  833 
  834     // --- bookmark ---
  835 
  836     /**
  837      * Outlines for bookmark.
  838      * @protected
  839      * @since 2.1.002 (2008-02-12)
  840      */
  841     protected $outlines = array();
  842 
  843     /**
  844      * Outline root for bookmark.
  845      * @protected
  846      * @since 2.1.002 (2008-02-12)
  847      */
  848     protected $OutlineRoot;
  849 
  850     // --- javascript and form ---
  851 
  852     /**
  853      * Javascript code.
  854      * @protected
  855      * @since 2.1.002 (2008-02-12)
  856      */
  857     protected $javascript = '';
  858 
  859     /**
  860      * Javascript counter.
  861      * @protected
  862      * @since 2.1.002 (2008-02-12)
  863      */
  864     protected $n_js;
  865 
  866     /**
  867      * line through state
  868      * @protected
  869      * @since 2.8.000 (2008-03-19)
  870      */
  871     protected $linethrough;
  872 
  873     /**
  874      * Array with additional document-wide usage rights for the document.
  875      * @protected
  876      * @since 5.8.014 (2010-08-23)
  877      */
  878     protected $ur = array();
  879 
  880     /**
  881      * DPI (Dot Per Inch) Document Resolution (do not change).
  882      * @protected
  883      * @since 3.0.000 (2008-03-27)
  884      */
  885     protected $dpi = 72;
  886 
  887     /**
  888      * Array of page numbers were a new page group was started (the page numbers are the keys of the array).
  889      * @protected
  890      * @since 3.0.000 (2008-03-27)
  891      */
  892     protected $newpagegroup = array();
  893 
  894     /**
  895      * Array that contains the number of pages in each page group.
  896      * @protected
  897      * @since 3.0.000 (2008-03-27)
  898      */
  899     protected $pagegroups = array();
  900 
  901     /**
  902      * Current page group number.
  903      * @protected
  904      * @since 3.0.000 (2008-03-27)
  905      */
  906     protected $currpagegroup = 0;
  907 
  908     /**
  909      * Array of transparency objects and parameters.
  910      * @protected
  911      * @since 3.0.000 (2008-03-27)
  912      */
  913     protected $extgstates;
  914 
  915     /**
  916      * Set the default JPEG compression quality (1-100).
  917      * @protected
  918      * @since 3.0.000 (2008-03-27)
  919      */
  920     protected $jpeg_quality;
  921 
  922     /**
  923      * Default cell height ratio.
  924      * @protected
  925      * @since 3.0.014 (2008-05-23)
  926      */
  927     protected $cell_height_ratio = K_CELL_HEIGHT_RATIO;
  928 
  929     /**
  930      * PDF viewer preferences.
  931      * @protected
  932      * @since 3.1.000 (2008-06-09)
  933      */
  934     protected $viewer_preferences;
  935 
  936     /**
  937      * A name object specifying how the document should be displayed when opened.
  938      * @protected
  939      * @since 3.1.000 (2008-06-09)
  940      */
  941     protected $PageMode;
  942 
  943     /**
  944      * Array for storing gradient information.
  945      * @protected
  946      * @since 3.1.000 (2008-06-09)
  947      */
  948     protected $gradients = array();
  949 
  950     /**
  951      * Array used to store positions inside the pages buffer (keys are the page numbers).
  952      * @protected
  953      * @since 3.2.000 (2008-06-26)
  954      */
  955     protected $intmrk = array();
  956 
  957     /**
  958      * Array used to store positions inside the pages buffer (keys are the page numbers).
  959      * @protected
  960      * @since 5.7.000 (2010-08-03)
  961      */
  962     protected $bordermrk = array();
  963 
  964     /**
  965      * Array used to store page positions to track empty pages (keys are the page numbers).
  966      * @protected
  967      * @since 5.8.007 (2010-08-18)
  968      */
  969     protected $emptypagemrk = array();
  970 
  971     /**
  972      * Array used to store content positions inside the pages buffer (keys are the page numbers).
  973      * @protected
  974      * @since 4.6.021 (2009-07-20)
  975      */
  976     protected $cntmrk = array();
  977 
  978     /**
  979      * Array used to store footer positions of each page.
  980      * @protected
  981      * @since 3.2.000 (2008-07-01)
  982      */
  983     protected $footerpos = array();
  984 
  985     /**
  986      * Array used to store footer length of each page.
  987      * @protected
  988      * @since 4.0.014 (2008-07-29)
  989      */
  990     protected $footerlen = array();
  991 
  992     /**
  993      * Boolean flag to indicate if a new line is created.
  994      * @protected
  995      * @since 3.2.000 (2008-07-01)
  996      */
  997     protected $newline = true;
  998 
  999     /**
 1000      * End position of the latest inserted line.
 1001      * @protected
 1002      * @since 3.2.000 (2008-07-01)
 1003      */
 1004     protected $endlinex = 0;
 1005 
 1006     /**
 1007      * PDF string for width value of the last line.
 1008      * @protected
 1009      * @since 4.0.006 (2008-07-16)
 1010      */
 1011     protected $linestyleWidth = '';
 1012 
 1013     /**
 1014      * PDF string for CAP value of the last line.
 1015      * @protected
 1016      * @since 4.0.006 (2008-07-16)
 1017      */
 1018     protected $linestyleCap = '0 J';
 1019 
 1020     /**
 1021      * PDF string for join value of the last line.
 1022      * @protected
 1023      * @since 4.0.006 (2008-07-16)
 1024      */
 1025     protected $linestyleJoin = '0 j';
 1026 
 1027     /**
 1028      * PDF string for dash value of the last line.
 1029      * @protected
 1030      * @since 4.0.006 (2008-07-16)
 1031      */
 1032     protected $linestyleDash = '[] 0 d';
 1033 
 1034     /**
 1035      * Boolean flag to indicate if marked-content sequence is open.
 1036      * @protected
 1037      * @since 4.0.013 (2008-07-28)
 1038      */
 1039     protected $openMarkedContent = false;
 1040 
 1041     /**
 1042      * Count the latest inserted vertical spaces on HTML.
 1043      * @protected
 1044      * @since 4.0.021 (2008-08-24)
 1045      */
 1046     protected $htmlvspace = 0;
 1047 
 1048     /**
 1049      * Array of Spot colors.
 1050      * @protected
 1051      * @since 4.0.024 (2008-09-12)
 1052      */
 1053     protected $spot_colors = array();
 1054 
 1055     /**
 1056      * Symbol used for HTML unordered list items.
 1057      * @protected
 1058      * @since 4.0.028 (2008-09-26)
 1059      */
 1060     protected $lisymbol = '';
 1061 
 1062     /**
 1063      * String used to mark the beginning and end of EPS image blocks.
 1064      * @protected
 1065      * @since 4.1.000 (2008-10-18)
 1066      */
 1067     protected $epsmarker = 'x#!#EPS#!#x';
 1068 
 1069     /**
 1070      * Array of transformation matrix.
 1071      * @protected
 1072      * @since 4.2.000 (2008-10-29)
 1073      */
 1074     protected $transfmatrix = array();
 1075 
 1076     /**
 1077      * Current key for transformation matrix.
 1078      * @protected
 1079      * @since 4.8.005 (2009-09-17)
 1080      */
 1081     protected $transfmatrix_key = 0;
 1082 
 1083     /**
 1084      * Booklet mode for double-sided pages.
 1085      * @protected
 1086      * @since 4.2.000 (2008-10-29)
 1087      */
 1088     protected $booklet = false;
 1089 
 1090     /**
 1091      * Epsilon value used for float calculations.
 1092      * @protected
 1093      * @since 4.2.000 (2008-10-29)
 1094      */
 1095     protected $feps = 0.005;
 1096 
 1097     /**
 1098      * Array used for custom vertical spaces for HTML tags.
 1099      * @protected
 1100      * @since 4.2.001 (2008-10-30)
 1101      */
 1102     protected $tagvspaces = array();
 1103 
 1104     /**
 1105      * HTML PARSER: custom indent amount for lists. Negative value means disabled.
 1106      * @protected
 1107      * @since 4.2.007 (2008-11-12)
 1108      */
 1109     protected $customlistindent = -1;
 1110 
 1111     /**
 1112      * Boolean flag to indicate if the border of the cell sides that cross the page should be removed.
 1113      * @protected
 1114      * @since 4.2.010 (2008-11-14)
 1115      */
 1116     protected $opencell = true;
 1117 
 1118     /**
 1119      * Array of files to embedd.
 1120      * @protected
 1121      * @since 4.4.000 (2008-12-07)
 1122      */
 1123     protected $embeddedfiles = array();
 1124 
 1125     /**
 1126      * Boolean flag to indicate if we are inside a PRE tag.
 1127      * @protected
 1128      * @since 4.4.001 (2008-12-08)
 1129      */
 1130     protected $premode = false;
 1131 
 1132     /**
 1133      * Array used to store positions of graphics transformation blocks inside the page buffer.
 1134      * keys are the page numbers
 1135      * @protected
 1136      * @since 4.4.002 (2008-12-09)
 1137      */
 1138     protected $transfmrk = array();
 1139 
 1140     /**
 1141      * Default color for html links.
 1142      * @protected
 1143      * @since 4.4.003 (2008-12-09)
 1144      */
 1145     protected $htmlLinkColorArray = array(0, 0, 255);
 1146 
 1147     /**
 1148      * Default font style to add to html links.
 1149      * @protected
 1150      * @since 4.4.003 (2008-12-09)
 1151      */
 1152     protected $htmlLinkFontStyle = 'U';
 1153 
 1154     /**
 1155      * Counts the number of pages.
 1156      * @protected
 1157      * @since 4.5.000 (2008-12-31)
 1158      */
 1159     protected $numpages = 0;
 1160 
 1161     /**
 1162      * Array containing page lengths in bytes.
 1163      * @protected
 1164      * @since 4.5.000 (2008-12-31)
 1165      */
 1166     protected $pagelen = array();
 1167 
 1168     /**
 1169      * Counts the number of pages.
 1170      * @protected
 1171      * @since 4.5.000 (2008-12-31)
 1172      */
 1173     protected $numimages = 0;
 1174 
 1175     /**
 1176      * Store the image keys.
 1177      * @protected
 1178      * @since 4.5.000 (2008-12-31)
 1179      */
 1180     protected $imagekeys = array();
 1181 
 1182     /**
 1183      * Length of the buffer in bytes.
 1184      * @protected
 1185      * @since 4.5.000 (2008-12-31)
 1186      */
 1187     protected $bufferlen = 0;
 1188 
 1189     /**
 1190      * Counts the number of fonts.
 1191      * @protected
 1192      * @since 4.5.000 (2009-01-02)
 1193      */
 1194     protected $numfonts = 0;
 1195 
 1196     /**
 1197      * Store the font keys.
 1198      * @protected
 1199      * @since 4.5.000 (2009-01-02)
 1200      */
 1201     protected $fontkeys = array();
 1202 
 1203     /**
 1204      * Store the font object IDs.
 1205      * @protected
 1206      * @since 4.8.001 (2009-09-09)
 1207      */
 1208     protected $font_obj_ids = array();
 1209 
 1210     /**
 1211      * Store the fage status (true when opened, false when closed).
 1212      * @protected
 1213      * @since 4.5.000 (2009-01-02)
 1214      */
 1215     protected $pageopen = array();
 1216 
 1217     /**
 1218      * Default monospace font.
 1219      * @protected
 1220      * @since 4.5.025 (2009-03-10)
 1221      */
 1222     protected $default_monospaced_font = 'courier';
 1223 
 1224     /**
 1225      * Cloned copy of the current class object.
 1226      * @protected
 1227      * @since 4.5.029 (2009-03-19)
 1228      */
 1229     protected $objcopy;
 1230 
 1231     /**
 1232      * Array used to store the lengths of cache files.
 1233      * @protected
 1234      * @since 4.5.029 (2009-03-19)
 1235      */
 1236     protected $cache_file_length = array();
 1237 
 1238     /**
 1239      * Table header content to be repeated on each new page.
 1240      * @protected
 1241      * @since 4.5.030 (2009-03-20)
 1242      */
 1243     protected $thead = '';
 1244 
 1245     /**
 1246      * Margins used for table header.
 1247      * @protected
 1248      * @since 4.5.030 (2009-03-20)
 1249      */
 1250     protected $theadMargins = array();
 1251 
 1252     /**
 1253      * Boolean flag to enable document digital signature.
 1254      * @protected
 1255      * @since 4.6.005 (2009-04-24)
 1256      */
 1257     protected $sign = false;
 1258 
 1259     /**
 1260      * Digital signature data.
 1261      * @protected
 1262      * @since 4.6.005 (2009-04-24)
 1263      */
 1264     protected $signature_data = array();
 1265 
 1266     /**
 1267      * Digital signature max length.
 1268      * @protected
 1269      * @since 4.6.005 (2009-04-24)
 1270      */
 1271     protected $signature_max_length = 11742;
 1272 
 1273     /**
 1274      * Data for digital signature appearance.
 1275      * @protected
 1276      * @since 5.3.011 (2010-06-16)
 1277      */
 1278     protected $signature_appearance = array('page' => 1, 'rect' => '0 0 0 0');
 1279 
 1280     /**
 1281      * Array of empty digital signature appearances.
 1282      * @protected
 1283      * @since 5.9.101 (2011-07-06)
 1284      */
 1285     protected $empty_signature_appearance = array();
 1286 
 1287     /**
 1288      * Boolean flag to enable document timestamping with TSA.
 1289      * @protected
 1290      * @since 6.0.085 (2014-06-19)
 1291      */
 1292     protected $tsa_timestamp = false;
 1293 
 1294     /**
 1295      * Timestamping data.
 1296      * @protected
 1297      * @since 6.0.085 (2014-06-19)
 1298      */
 1299     protected $tsa_data = array();
 1300 
 1301     /**
 1302      * Regular expression used to find blank characters (required for word-wrapping).
 1303      * @protected
 1304      * @since 4.6.006 (2009-04-28)
 1305      */
 1306     protected $re_spaces = '/[^\S\xa0]/';
 1307 
 1308     /**
 1309      * Array of $re_spaces parts.
 1310      * @protected
 1311      * @since 5.5.011 (2010-07-09)
 1312      */
 1313     protected $re_space = array('p' => '[^\S\xa0]', 'm' => '');
 1314 
 1315     /**
 1316      * Digital signature object ID.
 1317      * @protected
 1318      * @since 4.6.022 (2009-06-23)
 1319      */
 1320     protected $sig_obj_id = 0;
 1321 
 1322     /**
 1323      * ID of page objects.
 1324      * @protected
 1325      * @since 4.7.000 (2009-08-29)
 1326      */
 1327     protected $page_obj_id = array();
 1328 
 1329     /**
 1330      * List of form annotations IDs.
 1331      * @protected
 1332      * @since 4.8.000 (2009-09-07)
 1333      */
 1334     protected $form_obj_id = array();
 1335 
 1336     /**
 1337      * 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.
 1338      * @protected
 1339      * @since 4.8.000 (2009-09-07)
 1340      */
 1341     protected $default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
 1342 
 1343     /**
 1344      * Javascript objects array.
 1345      * @protected
 1346      * @since 4.8.000 (2009-09-07)
 1347      */
 1348     protected $js_objects = array();
 1349 
 1350     /**
 1351      * Current form action (used during XHTML rendering).
 1352      * @protected
 1353      * @since 4.8.000 (2009-09-07)
 1354      */
 1355     protected $form_action = '';
 1356 
 1357     /**
 1358      * Current form encryption type (used during XHTML rendering).
 1359      * @protected
 1360      * @since 4.8.000 (2009-09-07)
 1361      */
 1362     protected $form_enctype = 'application/x-www-form-urlencoded';
 1363 
 1364     /**
 1365      * Current method to submit forms.
 1366      * @protected
 1367      * @since 4.8.000 (2009-09-07)
 1368      */
 1369     protected $form_mode = 'post';
 1370 
 1371     /**
 1372      * List of fonts used on form fields (fontname => fontkey).
 1373      * @protected
 1374      * @since 4.8.001 (2009-09-09)
 1375      */
 1376     protected $annotation_fonts = array();
 1377 
 1378     /**
 1379      * List of radio buttons parent objects.
 1380      * @protected
 1381      * @since 4.8.001 (2009-09-09)
 1382      */
 1383     protected $radiobutton_groups = array();
 1384 
 1385     /**
 1386      * List of radio group objects IDs.
 1387      * @protected
 1388      * @since 4.8.001 (2009-09-09)
 1389      */
 1390     protected $radio_groups = array();
 1391 
 1392     /**
 1393      * Text indentation value (used for text-indent CSS attribute).
 1394      * @protected
 1395      * @since 4.8.006 (2009-09-23)
 1396      */
 1397     protected $textindent = 0;
 1398 
 1399     /**
 1400      * Store page number when startTransaction() is called.
 1401      * @protected
 1402      * @since 4.8.006 (2009-09-23)
 1403      */
 1404     protected $start_transaction_page = 0;
 1405 
 1406     /**
 1407      * Store Y position when startTransaction() is called.
 1408      * @protected
 1409      * @since 4.9.001 (2010-03-28)
 1410      */
 1411     protected $start_transaction_y = 0;
 1412 
 1413     /**
 1414      * True when we are printing the thead section on a new page.
 1415      * @protected
 1416      * @since 4.8.027 (2010-01-25)
 1417      */
 1418     protected $inthead = false;
 1419 
 1420     /**
 1421      * Array of column measures (width, space, starting Y position).
 1422      * @protected
 1423      * @since 4.9.001 (2010-03-28)
 1424      */
 1425     protected $columns = array();
 1426 
 1427     /**
 1428      * Number of colums.
 1429      * @protected
 1430      * @since 4.9.001 (2010-03-28)
 1431      */
 1432     protected $num_columns = 1;
 1433 
 1434     /**
 1435      * Current column number.
 1436      * @protected
 1437      * @since 4.9.001 (2010-03-28)
 1438      */
 1439     protected $current_column = 0;
 1440 
 1441     /**
 1442      * Starting page for columns.
 1443      * @protected
 1444      * @since 4.9.001 (2010-03-28)
 1445      */
 1446     protected $column_start_page = 0;
 1447 
 1448     /**
 1449      * Maximum page and column selected.
 1450      * @protected
 1451      * @since 5.8.000 (2010-08-11)
 1452      */
 1453     protected $maxselcol = array('page' => 0, 'column' => 0);
 1454 
 1455     /**
 1456      * Array of: X difference between table cell x start and starting page margin, cellspacing, cellpadding.
 1457      * @protected
 1458      * @since 5.8.000 (2010-08-11)
 1459      */
 1460     protected $colxshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0));
 1461 
 1462     /**
 1463      * 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.
 1464      * @protected
 1465      * @since 4.9.008 (2010-04-03)
 1466      */
 1467     protected $textrendermode = 0;
 1468 
 1469     /**
 1470      * Text stroke width in doc units.
 1471      * @protected
 1472      * @since 4.9.008 (2010-04-03)
 1473      */
 1474     protected $textstrokewidth = 0;
 1475 
 1476     /**
 1477      * Current stroke color.
 1478      * @protected
 1479      * @since 4.9.008 (2010-04-03)
 1480      */
 1481     protected $strokecolor;
 1482 
 1483     /**
 1484      * Default unit of measure for document.
 1485      * @protected
 1486      * @since 5.0.000 (2010-04-22)
 1487      */
 1488     protected $pdfunit = 'mm';
 1489 
 1490     /**
 1491      * Boolean flag true when we are on TOC (Table Of Content) page.
 1492      * @protected
 1493      */
 1494     protected $tocpage = false;
 1495 
 1496     /**
 1497      * Boolean flag: if true convert vector images (SVG, EPS) to raster image using GD or ImageMagick library.
 1498      * @protected
 1499      * @since 5.0.000 (2010-04-26)
 1500      */
 1501     protected $rasterize_vector_images = false;
 1502 
 1503     /**
 1504      * Boolean flag: if true enables font subsetting by default.
 1505      * @protected
 1506      * @since 5.3.002 (2010-06-07)
 1507      */
 1508     protected $font_subsetting = true;
 1509 
 1510     /**
 1511      * Array of default graphic settings.
 1512      * @protected
 1513      * @since 5.5.008 (2010-07-02)
 1514      */
 1515     protected $default_graphic_vars = array();
 1516 
 1517     /**
 1518      * Array of XObjects.
 1519      * @protected
 1520      * @since 5.8.014 (2010-08-23)
 1521      */
 1522     protected $xobjects = array();
 1523 
 1524     /**
 1525      * Boolean value true when we are inside an XObject.
 1526      * @protected
 1527      * @since 5.8.017 (2010-08-24)
 1528      */
 1529     protected $inxobj = false;
 1530 
 1531     /**
 1532      * Current XObject ID.
 1533      * @protected
 1534      * @since 5.8.017 (2010-08-24)
 1535      */
 1536     protected $xobjid = '';
 1537 
 1538     /**
 1539      * Percentage of character stretching.
 1540      * @protected
 1541      * @since 5.9.000 (2010-09-29)
 1542      */
 1543     protected $font_stretching = 100;
 1544 
 1545     /**
 1546      * Increases or decreases the space between characters in a text by the specified amount (tracking).
 1547      * @protected
 1548      * @since 5.9.000 (2010-09-29)
 1549      */
 1550     protected $font_spacing = 0;
 1551 
 1552     /**
 1553      * Array of no-write regions.
 1554      * ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right)
 1555      * @protected
 1556      * @since 5.9.003 (2010-10-14)
 1557      */
 1558     protected $page_regions = array();
 1559 
 1560     /**
 1561      * Boolean value true when page region check is active.
 1562      * @protected
 1563      */
 1564     protected $check_page_regions = true;
 1565 
 1566     /**
 1567      * Array of PDF layers data.
 1568      * @protected
 1569      * @since 5.9.102 (2011-07-13)
 1570      */
 1571     protected $pdflayers = array();
 1572 
 1573     /**
 1574      * A dictionary of names and corresponding destinations (Dests key on document Catalog).
 1575      * @protected
 1576      * @since 5.9.097 (2011-06-23)
 1577      */
 1578     protected $dests = array();
 1579 
 1580     /**
 1581      * Object ID for Named Destinations
 1582      * @protected
 1583      * @since 5.9.097 (2011-06-23)
 1584      */
 1585     protected $n_dests;
 1586 
 1587     /**
 1588      * Embedded Files Names
 1589      * @protected
 1590      * @since 5.9.204 (2013-01-23)
 1591      */
 1592     protected $efnames = array();
 1593 
 1594     /**
 1595      * Directory used for the last SVG image.
 1596      * @protected
 1597      * @since 5.0.000 (2010-05-05)
 1598      */
 1599     protected $svgdir = '';
 1600 
 1601     /**
 1602      *  Deafult unit of measure for SVG.
 1603      * @protected
 1604      * @since 5.0.000 (2010-05-02)
 1605      */
 1606     protected $svgunit = 'px';
 1607 
 1608     /**
 1609      * Array of SVG gradients.
 1610      * @protected
 1611      * @since 5.0.000 (2010-05-02)
 1612      */
 1613     protected $svggradients = array();
 1614 
 1615     /**
 1616      * ID of last SVG gradient.
 1617      * @protected
 1618      * @since 5.0.000 (2010-05-02)
 1619      */
 1620     protected $svggradientid = 0;
 1621 
 1622     /**
 1623      * Boolean value true when in SVG defs group.
 1624      * @protected
 1625      * @since 5.0.000 (2010-05-02)
 1626      */
 1627     protected $svgdefsmode = false;
 1628 
 1629     /**
 1630      * Array of SVG defs.
 1631      * @protected
 1632      * @since 5.0.000 (2010-05-02)
 1633      */
 1634     protected $svgdefs = array();
 1635 
 1636     /**
 1637      * Boolean value true when in SVG clipPath tag.
 1638      * @protected
 1639      * @since 5.0.000 (2010-04-26)
 1640      */
 1641     protected $svgclipmode = false;
 1642 
 1643     /**
 1644      * Array of SVG clipPath commands.
 1645      * @protected
 1646      * @since 5.0.000 (2010-05-02)
 1647      */
 1648     protected $svgclippaths = array();
 1649 
 1650     /**
 1651      * Array of SVG clipPath tranformation matrix.
 1652      * @protected
 1653      * @since 5.8.022 (2010-08-31)
 1654      */
 1655     protected $svgcliptm = array();
 1656 
 1657     /**
 1658      * ID of last SVG clipPath.
 1659      * @protected
 1660      * @since 5.0.000 (2010-05-02)
 1661      */
 1662     protected $svgclipid = 0;
 1663 
 1664     /**
 1665      * SVG text.
 1666      * @protected
 1667      * @since 5.0.000 (2010-05-02)
 1668      */
 1669     protected $svgtext = '';
 1670 
 1671     /**
 1672      * SVG text properties.
 1673      * @protected
 1674      * @since 5.8.013 (2010-08-23)
 1675      */
 1676     protected $svgtextmode = array();
 1677 
 1678     /**
 1679      * Array of SVG properties.
 1680      * @protected
 1681      * @since 5.0.000 (2010-05-02)
 1682      */
 1683     protected $svgstyles = array(array(
 1684         'alignment-baseline' => 'auto',
 1685         'baseline-shift' => 'baseline',
 1686         'clip' => 'auto',
 1687         'clip-path' => 'none',
 1688         'clip-rule' => 'nonzero',
 1689         'color' => 'black',
 1690         'color-interpolation' => 'sRGB',
 1691         'color-interpolation-filters' => 'linearRGB',
 1692         'color-profile' => 'auto',
 1693         'color-rendering' => 'auto',
 1694         'cursor' => 'auto',
 1695         'direction' => 'ltr',
 1696         'display' => 'inline',
 1697         'dominant-baseline' => 'auto',
 1698         'enable-background' => 'accumulate',
 1699         'fill' => 'black',
 1700         'fill-opacity' => 1,
 1701         'fill-rule' => 'nonzero',
 1702         'filter' => 'none',
 1703         'flood-color' => 'black',
 1704         'flood-opacity' => 1,
 1705         'font' => '',
 1706         'font-family' => 'helvetica',
 1707         'font-size' => 'medium',
 1708         'font-size-adjust' => 'none',
 1709         'font-stretch' => 'normal',
 1710         'font-style' => 'normal',
 1711         'font-variant' => 'normal',
 1712         'font-weight' => 'normal',
 1713         'glyph-orientation-horizontal' => '0deg',
 1714         'glyph-orientation-vertical' => 'auto',
 1715         'image-rendering' => 'auto',
 1716         'kerning' => 'auto',
 1717         'letter-spacing' => 'normal',
 1718         'lighting-color' => 'white',
 1719         'marker' => '',
 1720         'marker-end' => 'none',
 1721         'marker-mid' => 'none',
 1722         'marker-start' => 'none',
 1723         'mask' => 'none',
 1724         'opacity' => 1,
 1725         'overflow' => 'auto',
 1726         'pointer-events' => 'visiblePainted',
 1727         'shape-rendering' => 'auto',
 1728         'stop-color' => 'black',
 1729         'stop-opacity' => 1,
 1730         'stroke' => 'none',
 1731         'stroke-dasharray' => 'none',
 1732         'stroke-dashoffset' => 0,
 1733         'stroke-linecap' => 'butt',
 1734         'stroke-linejoin' => 'miter',
 1735         'stroke-miterlimit' => 4,
 1736         'stroke-opacity' => 1,
 1737         'stroke-width' => 1,
 1738         'text-anchor' => 'start',
 1739         'text-decoration' => 'none',
 1740         'text-rendering' => 'auto',
 1741         'unicode-bidi' => 'normal',
 1742         'visibility' => 'visible',
 1743         'word-spacing' => 'normal',
 1744         'writing-mode' => 'lr-tb',
 1745         'text-color' => 'black',
 1746         'transfmatrix' => array(1, 0, 0, 1, 0, 0)
 1747         ));
 1748 
 1749     /**
 1750      * If true force sRGB color profile for all document.
 1751      * @protected
 1752      * @since 5.9.121 (2011-09-28)
 1753      */
 1754     protected $force_srgb = false;
 1755 
 1756     /**
 1757      * If true set the document to PDF/A mode.
 1758      * @protected
 1759      * @since 5.9.121 (2011-09-27)
 1760      */
 1761     protected $pdfa_mode = false;
 1762 
 1763     /**
 1764      * version of PDF/A mode (1 - 3).
 1765      * @protected
 1766      * @since 6.2.26 (2019-03-12)
 1767      */
 1768     protected $pdfa_version = 1;
 1769 
 1770     /**
 1771      * Document creation date-time
 1772      * @protected
 1773      * @since 5.9.152 (2012-03-22)
 1774      */
 1775     protected $doc_creation_timestamp;
 1776 
 1777     /**
 1778      * Document modification date-time
 1779      * @protected
 1780      * @since 5.9.152 (2012-03-22)
 1781      */
 1782     protected $doc_modification_timestamp;
 1783 
 1784     /**
 1785      * Custom XMP data.
 1786      * @protected
 1787      * @since 5.9.128 (2011-10-06)
 1788      */
 1789     protected $custom_xmp = '';
 1790 
 1791     /**
 1792      * Custom XMP RDF data.
 1793      * @protected
 1794      * @since 6.3.0 (2019-09-19)
 1795      */
 1796     protected $custom_xmp_rdf = '';
 1797 
 1798     /**
 1799      * Overprint mode array.
 1800      * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008).
 1801      * @protected
 1802      * @since 5.9.152 (2012-03-23)
 1803      */
 1804     protected $overprint = array('OP' => false, 'op' => false, 'OPM' => 0);
 1805 
 1806     /**
 1807      * Alpha mode array.
 1808      * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008).
 1809      * @protected
 1810      * @since 5.9.152 (2012-03-23)
 1811      */
 1812     protected $alpha = array('CA' => 1, 'ca' => 1, 'BM' => '/Normal', 'AIS' => false);
 1813 
 1814     /**
 1815      * Define the page boundaries boxes to be set on document.
 1816      * @protected
 1817      * @since 5.9.152 (2012-03-23)
 1818      */
 1819     protected $page_boxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox');
 1820 
 1821     /**
 1822      * If true print TCPDF meta link.
 1823      * @protected
 1824      * @since 5.9.152 (2012-03-23)
 1825      */
 1826     protected $tcpdflink = true;
 1827 
 1828     /**
 1829      * Cache array for computed GD gamma values.
 1830      * @protected
 1831      * @since 5.9.1632 (2012-06-05)
 1832      */
 1833     protected $gdgammacache = array();
 1834 
 1835     //------------------------------------------------------------
 1836     // METHODS
 1837     //------------------------------------------------------------
 1838 
 1839     /**
 1840      * This is the class constructor.
 1841      * It allows to set up the page format, the orientation and the measure unit used in all the methods (except for the font sizes).
 1842      *
 1843      * IMPORTANT: Please note that this method sets the mb_internal_encoding to ASCII, so if you are using the mbstring module functions with TCPDF you need to correctly set/unset the mb_internal_encoding when needed.
 1844      *
 1845      * @param $orientation (string) page orientation. Possible values are (case insensitive):<ul><li>P or Portrait (default)</li><li>L or Landscape</li><li>'' (empty string) for automatic orientation</li></ul>
 1846      * @param $unit (string) 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.
 1847      * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat().
 1848      * @param $unicode (boolean) TRUE means that the input text is unicode (default = true)
 1849      * @param $encoding (string) Charset encoding (used only when converting back html entities); default is UTF-8.
 1850      * @param $diskcache (boolean) DEPRECATED FEATURE
 1851      * @param $pdfa (integer) If not false, set the document to PDF/A mode and the good version (1 or 3).
 1852      * @public
 1853      * @see getPageSizeFromFormat(), setPageFormat()
 1854      */
 1855     public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) {
 1856         /* Set internal character encoding to ASCII */
 1857         if (function_exists('mb_internal_encoding') AND mb_internal_encoding()) {
 1858             $this->internal_encoding = mb_internal_encoding();
 1859             mb_internal_encoding('ASCII');
 1860         }
 1861         // set file ID for trailer
 1862         $serformat = (is_array($format) ? json_encode($format) : $format);
 1863         $this->file_id = md5(TCPDF_STATIC::getRandomSeed('TCPDF'.$orientation.$unit.$serformat.$encoding));
 1864         $this->font_obj_ids = array();
 1865         $this->page_obj_id = array();
 1866         $this->form_obj_id = array();
 1867 
 1868         // set pdf/a mode
 1869         if ($pdfa != false) {
 1870             $this->pdfa_mode = true;
 1871             $this->pdfa_version = $pdfa;  // 1 or 3
 1872         } else
 1873             $this->pdfa_mode = false;
 1874 
 1875         $this->force_srgb = false;
 1876         // set language direction
 1877         $this->rtl = false;
 1878         $this->tmprtl = false;
 1879         // some checks
 1880         $this->_dochecks();
 1881         // initialization of properties
 1882         $this->isunicode = $unicode;
 1883         $this->page = 0;
 1884         $this->transfmrk[0] = array();
 1885         $this->pagedim = array();
 1886         $this->n = 2;
 1887         $this->buffer = '';
 1888         $this->pages = array();
 1889         $this->state = 0;
 1890         $this->fonts = array();
 1891         $this->FontFiles = array();
 1892         $this->diffs = array();
 1893         $this->images = array();
 1894         $this->links = array();
 1895         $this->gradients = array();
 1896         $this->InFooter = false;
 1897         $this->lasth = 0;
 1898         $this->FontFamily = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica';
 1899         $this->FontStyle = '';
 1900         $this->FontSizePt = 12;
 1901         $this->underline = false;
 1902         $this->overline = false;
 1903         $this->linethrough = false;
 1904         $this->DrawColor = '0 G';
 1905         $this->FillColor = '0 g';
 1906         $this->TextColor = '0 g';
 1907         $this->ColorFlag = false;
 1908         $this->pdflayers = array();
 1909         // encryption values
 1910         $this->encrypted = false;
 1911         $this->last_enc_key = '';
 1912         // standard Unicode fonts
 1913         $this->CoreFonts = array(
 1914             'courier'=>'Courier',
 1915             'courierB'=>'Courier-Bold',
 1916             'courierI'=>'Courier-Oblique',
 1917             'courierBI'=>'Courier-BoldOblique',
 1918             'helvetica'=>'Helvetica',
 1919             'helveticaB'=>'Helvetica-Bold',
 1920             'helveticaI'=>'Helvetica-Oblique',
 1921             'helveticaBI'=>'Helvetica-BoldOblique',
 1922             'times'=>'Times-Roman',
 1923             'timesB'=>'Times-Bold',
 1924             'timesI'=>'Times-Italic',
 1925             'timesBI'=>'Times-BoldItalic',
 1926             'symbol'=>'Symbol',
 1927             'zapfdingbats'=>'ZapfDingbats'
 1928         );
 1929         // set scale factor
 1930         $this->setPageUnit($unit);
 1931         // set page format and orientation
 1932         $this->setPageFormat($format, $orientation);
 1933         // page margins (1 cm)
 1934         $margin = 28.35 / $this->k;
 1935         $this->SetMargins($margin, $margin);
 1936         $this->clMargin = $this->lMargin;
 1937         $this->crMargin = $this->rMargin;
 1938         // internal cell padding
 1939         $cpadding = $margin / 10;
 1940         $this->setCellPaddings($cpadding, 0, $cpadding, 0);
 1941         // cell margins
 1942         $this->setCellMargins(0, 0, 0, 0);
 1943         // line width (0.2 mm)
 1944         $this->LineWidth = 0.57 / $this->k;
 1945         $this->linestyleWidth = sprintf('%F w', ($this->LineWidth * $this->k));
 1946         $this->linestyleCap = '0 J';
 1947         $this->linestyleJoin = '0 j';
 1948         $this->linestyleDash = '[] 0 d';
 1949         // automatic page break
 1950         $this->SetAutoPageBreak(true, (2 * $margin));
 1951         // full width display mode
 1952         $this->SetDisplayMode('fullwidth');
 1953         // compression
 1954         $this->SetCompression();
 1955         // set default PDF version number
 1956         $this->setPDFVersion();
 1957         $this->tcpdflink = true;
 1958         $this->encoding = $encoding;
 1959         $this->HREF = array();
 1960         $this->getFontsList();
 1961         $this->fgcolor = array('R' => 0, 'G' => 0, 'B' => 0);
 1962         $this->strokecolor = array('R' => 0, 'G' => 0, 'B' => 0);
 1963         $this->bgcolor = array('R' => 255, 'G' => 255, 'B' => 255);
 1964         $this->extgstates = array();
 1965         $this->setTextShadow();
 1966         // signature
 1967         $this->sign = false;
 1968         $this->tsa_timestamp = false;
 1969         $this->tsa_data = array();
 1970         $this->signature_appearance = array('page' => 1, 'rect' => '0 0 0 0', 'name' => 'Signature');
 1971         $this->empty_signature_appearance = array();
 1972         // user's rights
 1973         $this->ur['enabled'] = false;
 1974         $this->ur['document'] = '/FullSave';
 1975         $this->ur['annots'] = '/Create/Delete/Modify/Copy/Import/Export';
 1976         $this->ur['form'] = '/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate';
 1977         $this->ur['signature'] = '/Modify';
 1978         $this->ur['ef'] = '/Create/Delete/Modify/Import';
 1979         $this->ur['formex'] = '';
 1980         // set default JPEG quality
 1981         $this->jpeg_quality = 75;
 1982         // initialize some settings
 1983         TCPDF_FONTS::utf8Bidi(array(), '', false, $this->isunicode, $this->CurrentFont);
 1984         // set default font
 1985         $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt);
 1986         $this->setHeaderFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt));
 1987         $this->setFooterFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt));
 1988         // check if PCRE Unicode support is enabled
 1989         if ($this->isunicode AND (@preg_match('/\pL/u', 'a') == 1)) {
 1990             // PCRE unicode support is turned ON
 1991             // \s     : any whitespace character
 1992             // \p{Z}  : any separator
 1993             // \p{Lo} : Unicode letter or ideograph that does not have lowercase and uppercase variants. Is used to chunk chinese words.
 1994             // \xa0   : Unicode Character 'NO-BREAK SPACE' (U+00A0)
 1995             //$this->setSpacesRE('/(?!\xa0)[\s\p{Z}\p{Lo}]/u');
 1996             $this->setSpacesRE('/(?!\xa0)[\s\p{Z}]/u');
 1997         } else {
 1998             // PCRE unicode support is turned OFF
 1999             $this->setSpacesRE('/[^\S\xa0]/');
 2000         }
 2001         $this->default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
 2002         // set document creation and modification timestamp
 2003         $this->doc_creation_timestamp = time();
 2004         $this->doc_modification_timestamp = $this->doc_creation_timestamp;
 2005         // get default graphic vars
 2006         $this->default_graphic_vars = $this->getGraphicVars();
 2007         $this->header_xobj_autoreset = false;
 2008         $this->custom_xmp = '';
 2009         $this->custom_xmp_rdf = '';
 2010         // Call cleanup method after script execution finishes or exit() is called.
 2011         // NOTE: This will not be executed if the process is killed with a SIGTERM or SIGKILL signal.
 2012         register_shutdown_function(array($this, '_destroy'), true);
 2013     }
 2014 
 2015     /**
 2016      * Default destructor.
 2017      * @public
 2018      * @since 1.53.0.TC016
 2019      */
 2020     public function __destruct() {
 2021         // cleanup
 2022         $this->_destroy(true);
 2023     }
 2024 
 2025     /**
 2026      * Set the units of measure for the document.
 2027      * @param $unit (string) 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.
 2028      * @public
 2029      * @since 3.0.015 (2008-06-06)
 2030      */
 2031     public function setPageUnit($unit) {
 2032         $unit = strtolower($unit);
 2033         //Set scale factor
 2034         switch ($unit) {
 2035             // points
 2036             case 'px':
 2037             case 'pt': {
 2038                 $this->k = 1;
 2039                 break;
 2040             }
 2041             // millimeters
 2042             case 'mm': {
 2043                 $this->k = $this->dpi / 25.4;
 2044                 break;
 2045             }
 2046             // centimeters
 2047             case 'cm': {
 2048                 $this->k = $this->dpi / 2.54;
 2049                 break;
 2050             }
 2051             // inches
 2052             case 'in': {
 2053                 $this->k = $this->dpi;
 2054                 break;
 2055             }
 2056             // unsupported unit
 2057             default : {
 2058                 $this->Error('Incorrect unit: '.$unit);
 2059                 break;
 2060             }
 2061         }
 2062         $this->pdfunit = $unit;
 2063         if (isset($this->CurOrientation)) {
 2064             $this->setPageOrientation($this->CurOrientation);
 2065         }
 2066     }
 2067 
 2068     /**
 2069      * Change the format of the current page
 2070      * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() documentation or an array of two numbers (width, height) or an array containing the following measures and options:<ul>
 2071      * <li>['format'] = page format name (one of the above);</li>
 2072      * <li>['Rotate'] : The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.</li>
 2073      * <li>['PZ'] : The page's preferred zoom (magnification) factor.</li>
 2074      * <li>['MediaBox'] : the boundaries of the physical medium on which the page shall be displayed or printed:</li>
 2075      * <li>['MediaBox']['llx'] : lower-left x coordinate</li>
 2076      * <li>['MediaBox']['lly'] : lower-left y coordinate</li>
 2077      * <li>['MediaBox']['urx'] : upper-right x coordinate</li>
 2078      * <li>['MediaBox']['ury'] : upper-right y coordinate</li>
 2079      * <li>['CropBox'] : the visible region of default user space:</li>
 2080      * <li>['CropBox']['llx'] : lower-left x coordinate</li>
 2081      * <li>['CropBox']['lly'] : lower-left y coordinate</li>
 2082      * <li>['CropBox']['urx'] : upper-right x coordinate</li>
 2083      * <li>['CropBox']['ury'] : upper-right y coordinate</li>
 2084      * <li>['BleedBox'] : the region to which the contents of the page shall be clipped when output in a production environment:</li>
 2085      * <li>['BleedBox']['llx'] : lower-left x coordinate</li>
 2086      * <li>['BleedBox']['lly'] : lower-left y coordinate</li>
 2087      * <li>['BleedBox']['urx'] : upper-right x coordinate</li>
 2088      * <li>['BleedBox']['ury'] : upper-right y coordinate</li>
 2089      * <li>['TrimBox'] : the intended dimensions of the finished page after trimming:</li>
 2090      * <li>['TrimBox']['llx'] : lower-left x coordinate</li>
 2091      * <li>['TrimBox']['lly'] : lower-left y coordinate</li>
 2092      * <li>['TrimBox']['urx'] : upper-right x coordinate</li>
 2093      * <li>['TrimBox']['ury'] : upper-right y coordinate</li>
 2094      * <li>['ArtBox'] : the extent of the page's meaningful content:</li>
 2095      * <li>['ArtBox']['llx'] : lower-left x coordinate</li>
 2096      * <li>['ArtBox']['lly'] : lower-left y coordinate</li>
 2097      * <li>['ArtBox']['urx'] : upper-right x coordinate</li>
 2098      * <li>['ArtBox']['ury'] : upper-right y coordinate</li>
 2099      * <li>['BoxColorInfo'] :specify the colours and other visual characteristics that should be used in displaying guidelines on the screen for each of the possible page boundaries other than the MediaBox:</li>
 2100      * <li>['BoxColorInfo'][BOXTYPE]['C'] : an array of three numbers in the range 0-255, representing the components in the DeviceRGB colour space.</li>
 2101      * <li>['BoxColorInfo'][BOXTYPE]['W'] : the guideline width in default user units</li>
 2102      * <li>['BoxColorInfo'][BOXTYPE]['S'] : the guideline style: S = Solid; D = Dashed</li>
 2103      * <li>['BoxColorInfo'][BOXTYPE]['D'] : dash array defining a pattern of dashes and gaps to be used in drawing dashed guidelines</li>
 2104      * <li>['trans'] : the style and duration of the visual transition to use when moving from another page to the given page during a presentation</li>
 2105      * <li>['trans']['Dur'] : The page's display duration (also called its advance timing): the maximum length of time, in seconds, that the page shall be displayed during presentations before the viewer application shall automatically advance to the next page.</li>
 2106      * <li>['trans']['S'] : transition style : Split, Blinds, Box, Wipe, Dissolve, Glitter, R, Fly, Push, Cover, Uncover, Fade</li>
 2107      * <li>['trans']['D'] : The duration of the transition effect, in seconds.</li>
 2108      * <li>['trans']['Dm'] : (Split and Blinds transition styles only) The dimension in which the specified transition effect shall occur: H = Horizontal, V = Vertical. Default value: H.</li>
 2109      * <li>['trans']['M'] : (Split, Box and Fly transition styles only) The direction of motion for the specified transition effect: I = Inward from the edges of the page, O = Outward from the center of the pageDefault value: I.</li>
 2110      * <li>['trans']['Di'] : (Wipe, Glitter, Fly, Cover, Uncover and Push transition styles only) The direction in which the specified transition effect shall moves, expressed in degrees counterclockwise starting from a left-to-right direction. If the value is a number, it shall be one of: 0 = Left to right, 90 = Bottom to top (Wipe only), 180 = Right to left (Wipe only), 270 = Top to bottom, 315 = Top-left to bottom-right (Glitter only). If the value is a name, it shall be None, which is relevant only for the Fly transition when the value of SS is not 1.0. Default value: 0.</li>
 2111      * <li>['trans']['SS'] : (Fly transition style only) The starting or ending scale at which the changes shall be drawn. If M specifies an inward transition, the scale of the changes drawn shall progress from SS to 1.0 over the course of the transition. If M specifies an outward transition, the scale of the changes drawn shall progress from 1.0 to SS over the course of the transition. Default: 1.0.</li>
 2112      * <li>['trans']['B'] : (Fly transition style only) If true, the area that shall be flown in is rectangular and opaque. Default: false.</li>
 2113      * </ul>
 2114      * @param $orientation (string) page orientation. Possible values are (case insensitive):<ul>
 2115      * <li>P or Portrait (default)</li>
 2116      * <li>L or Landscape</li>
 2117      * <li>'' (empty string) for automatic orientation</li>
 2118      * </ul>
 2119      * @protected
 2120      * @since 3.0.015 (2008-06-06)
 2121      * @see getPageSizeFromFormat()
 2122      */
 2123     protected function setPageFormat($format, $orientation='P') {
 2124         if (!empty($format) AND isset($this->pagedim[$this->page])) {
 2125             // remove inherited values
 2126             unset($this->pagedim[$this->page]);
 2127         }
 2128         if (is_string($format)) {
 2129             // get page measures from format name
 2130             $pf = TCPDF_STATIC::getPageSizeFromFormat($format);
 2131             $this->fwPt = $pf[0];
 2132             $this->fhPt = $pf[1];
 2133         } else {
 2134             // the boundaries of the physical medium on which the page shall be displayed or printed
 2135             if (isset($format['MediaBox'])) {
 2136                 $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', $format['MediaBox']['llx'], $format['MediaBox']['lly'], $format['MediaBox']['urx'], $format['MediaBox']['ury'], false, $this->k, $this->pagedim);
 2137                 $this->fwPt = (($format['MediaBox']['urx'] - $format['MediaBox']['llx']) * $this->k);
 2138                 $this->fhPt = (($format['MediaBox']['ury'] - $format['MediaBox']['lly']) * $this->k);
 2139             } else {
 2140                 if (isset($format[0]) AND is_numeric($format[0]) AND isset($format[1]) AND is_numeric($format[1])) {
 2141                     $pf = array(($format[0] * $this->k), ($format[1] * $this->k));
 2142                 } else {
 2143                     if (!isset($format['format'])) {
 2144                         // default value
 2145                         $format['format'] = 'A4';
 2146                     }
 2147                     $pf = TCPDF_STATIC::getPageSizeFromFormat($format['format']);
 2148                 }
 2149                 $this->fwPt = $pf[0];
 2150                 $this->fhPt = $pf[1];
 2151                 $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim);
 2152             }
 2153             // the visible region of default user space
 2154             if (isset($format['CropBox'])) {
 2155                 $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'CropBox', $format['CropBox']['llx'], $format['CropBox']['lly'], $format['CropBox']['urx'], $format['CropBox']['ury'], false, $this->k, $this->pagedim);
 2156             }
 2157             // the region to which the contents of the page shall be clipped when output in a production environment
 2158             if (isset($format['BleedBox'])) {
 2159                 $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'BleedBox', $format['BleedBox']['llx'], $format['BleedBox']['lly'], $format['BleedBox']['urx'], $format['BleedBox']['ury'], false, $this->k, $this->pagedim);
 2160             }
 2161             // the intended dimensions of the finished page after trimming
 2162             if (isset($format['TrimBox'])) {
 2163                 $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'TrimBox', $format['TrimBox']['llx'], $format['TrimBox']['lly'], $format['TrimBox']['urx'], $format['TrimBox']['ury'], false, $this->k, $this->pagedim);
 2164             }
 2165             // the page's meaningful content (including potential white space)
 2166             if (isset($format['ArtBox'])) {
 2167                 $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'ArtBox', $format['ArtBox']['llx'], $format['ArtBox']['lly'], $format['ArtBox']['urx'], $format['ArtBox']['ury'], false, $this->k, $this->pagedim);
 2168             }
 2169             // specify the colours and other visual characteristics that should be used in displaying guidelines on the screen for the various page boundaries
 2170             if (isset($format['BoxColorInfo'])) {
 2171                 $this->pagedim[$this->page]['BoxColorInfo'] = $format['BoxColorInfo'];
 2172             }
 2173             if (isset($format['Rotate']) AND (($format['Rotate'] % 90) == 0)) {
 2174                 // The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.
 2175                 $this->pagedim[$this->page]['Rotate'] = intval($format['Rotate']);
 2176             }
 2177             if (isset($format['PZ'])) {
 2178                 // The page's preferred zoom (magnification) factor
 2179                 $this->pagedim[$this->page]['PZ'] = floatval($format['PZ']);
 2180             }
 2181             if (isset($format['trans'])) {
 2182                 // The style and duration of the visual transition to use when moving from another page to the given page during a presentation
 2183                 if (isset($format['trans']['Dur'])) {
 2184                     // The page's display duration
 2185                     $this->pagedim[$this->page]['trans']['Dur'] = floatval($format['trans']['Dur']);
 2186                 }
 2187                 $stansition_styles = array('Split', 'Blinds', 'Box', 'Wipe', 'Dissolve', 'Glitter', 'R', 'Fly', 'Push', 'Cover', 'Uncover', 'Fade');
 2188                 if (isset($format['trans']['S']) AND in_array($format['trans']['S'], $stansition_styles)) {
 2189                     // The transition style that shall be used when moving to this page from another during a presentation
 2190                     $this->pagedim[$this->page]['trans']['S'] = $format['trans']['S'];
 2191                     $valid_effect = array('Split', 'Blinds');
 2192                     $valid_vals = array('H', 'V');
 2193                     if (isset($format['trans']['Dm']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['Dm'], $valid_vals)) {
 2194                         $this->pagedim[$this->page]['trans']['Dm'] = $format['trans']['Dm'];
 2195                     }
 2196                     $valid_effect = array('Split', 'Box', 'Fly');
 2197                     $valid_vals = array('I', 'O');
 2198                     if (isset($format['trans']['M']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['M'], $valid_vals)) {
 2199                         $this->pagedim[$this->page]['trans']['M'] = $format['trans']['M'];
 2200                     }
 2201                     $valid_effect = array('Wipe', 'Glitter', 'Fly', 'Cover', 'Uncover', 'Push');
 2202                     if (isset($format['trans']['Di']) AND in_array($format['trans']['S'], $valid_effect)) {
 2203                         if (((($format['trans']['Di'] == 90) OR ($format['trans']['Di'] == 180)) AND ($format['trans']['S'] == 'Wipe'))
 2204                             OR (($format['trans']['Di'] == 315) AND ($format['trans']['S'] == 'Glitter'))
 2205                             OR (($format['trans']['Di'] == 0) OR ($format['trans']['Di'] == 270))) {
 2206                             $this->pagedim[$this->page]['trans']['Di'] = intval($format['trans']['Di']);
 2207                         }
 2208                     }
 2209                     if (isset($format['trans']['SS']) AND ($format['trans']['S'] == 'Fly')) {
 2210                         $this->pagedim[$this->page]['trans']['SS'] = floatval($format['trans']['SS']);
 2211                     }
 2212                     if (isset($format['trans']['B']) AND ($format['trans']['B'] === true) AND ($format['trans']['S'] == 'Fly')) {
 2213                         $this->pagedim[$this->page]['trans']['B'] = 'true';
 2214                     }
 2215                 } else {
 2216                     $this->pagedim[$this->page]['trans']['S'] = 'R';
 2217                 }
 2218                 if (isset($format['trans']['D'])) {
 2219                     // The duration of the transition effect, in seconds
 2220                     $this->pagedim[$this->page]['trans']['D'] = floatval($format['trans']['D']);
 2221                 } else {
 2222                     $this->pagedim[$this->page]['trans']['D'] = 1;
 2223                 }
 2224             }
 2225         }
 2226         $this->setPageOrientation($orientation);
 2227     }
 2228 
 2229     /**
 2230      * Set page orientation.
 2231      * @param $orientation (string) page orientation. Possible values are (case insensitive):<ul><li>P or Portrait (default)</li><li>L or Landscape</li><li>'' (empty string) for automatic orientation</li></ul>
 2232      * @param $autopagebreak (boolean) Boolean indicating if auto-page-break mode should be on or off.
 2233      * @param $bottommargin (float) bottom margin of the page.
 2234      * @public
 2235      * @since 3.0.015 (2008-06-06)
 2236      */
 2237     public function setPageOrientation($orientation, $autopagebreak='', $bottommargin='') {
 2238         if (!isset($this->pagedim[$this->page]['MediaBox'])) {
 2239             // the boundaries of the physical medium on which the page shall be displayed or printed
 2240             $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim);
 2241         }
 2242         if (!isset($this->pagedim[$this->page]['CropBox'])) {
 2243             // the visible region of default user space
 2244             $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'CropBox', $this->pagedim[$this->page]['MediaBox']['llx'], $this->pagedim[$this->page]['MediaBox']['lly'], $this->pagedim[$this->page]['MediaBox']['urx'], $this->pagedim[$this->page]['MediaBox']['ury'], true, $this->k, $this->pagedim);
 2245         }
 2246         if (!isset($this->pagedim[$this->page]['BleedBox'])) {
 2247             // the region to which the contents of the page shall be clipped when output in a production environment
 2248             $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'BleedBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim);
 2249         }
 2250         if (!isset($this->pagedim[$this->page]['TrimBox'])) {
 2251             // the intended dimensions of the finished page after trimming
 2252             $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'TrimBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim);
 2253         }
 2254         if (!isset($this->pagedim[$this->page]['ArtBox'])) {
 2255             // the page's meaningful content (including potential white space)
 2256             $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'ArtBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim);
 2257         }
 2258         if (!isset($this->pagedim[$this->page]['Rotate'])) {
 2259             // The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.
 2260             $this->pagedim[$this->page]['Rotate'] = 0;
 2261         }
 2262         if (!isset($this->pagedim[$this->page]['PZ'])) {
 2263             // The page's preferred zoom (magnification) factor
 2264             $this->pagedim[$this->page]['PZ'] = 1;
 2265         }
 2266         if ($this->fwPt > $this->fhPt) {
 2267             // landscape
 2268             $default_orientation = 'L';
 2269         } else {
 2270             // portrait
 2271             $default_orientation = 'P';
 2272         }
 2273         $valid_orientations = array('P', 'L');
 2274         if (empty($orientation)) {
 2275             $orientation = $default_orientation;
 2276         } else {
 2277             $orientation = strtoupper($orientation[0]);
 2278         }
 2279         if (in_array($orientation, $valid_orientations) AND ($orientation != $default_orientation)) {
 2280             $this->CurOrientation = $orientation;
 2281             $this->wPt = $this->fhPt;
 2282             $this->hPt = $this->fwPt;
 2283         } else {
 2284             $this->CurOrientation = $default_orientation;
 2285             $this->wPt = $this->fwPt;
 2286             $this->hPt = $this->fhPt;
 2287         }
 2288         if ((abs($this->pagedim[$this->page]['MediaBox']['urx'] - $this->hPt) < $this->feps) AND (abs($this->pagedim[$this->page]['MediaBox']['ury'] - $this->wPt) < $this->feps)){
 2289             // swap X and Y coordinates (change page orientation)
 2290             $this->pagedim = TCPDF_STATIC::swapPageBoxCoordinates($this->page, $this->pagedim);
 2291         }
 2292         $this->w = ($this->wPt / $this->k);
 2293         $this->h = ($this->hPt / $this->k);
 2294         if (TCPDF_STATIC::empty_string($autopagebreak)) {
 2295             if (isset($this->AutoPageBreak)) {
 2296                 $autopagebreak = $this->AutoPageBreak;
 2297             } else {
 2298                 $autopagebreak = true;
 2299             }
 2300         }
 2301         if (TCPDF_STATIC::empty_string($bottommargin)) {
 2302             if (isset($this->bMargin)) {
 2303                 $bottommargin = $this->bMargin;
 2304             } else {
 2305                 // default value = 2 cm
 2306                 $bottommargin = 2 * 28.35 / $this->k;
 2307             }
 2308         }
 2309         $this->SetAutoPageBreak($autopagebreak, $bottommargin);
 2310         // store page dimensions
 2311         $this->pagedim[$this->page]['w'] = $this->wPt;
 2312         $this->pagedim[$this->page]['h'] = $this->hPt;
 2313         $this->pagedim[$this->page]['wk'] = $this->w;
 2314         $this->pagedim[$this->page]['hk'] = $this->h;
 2315         $this->pagedim[$this->page]['tm'] = $this->tMargin;
 2316         $this->pagedim[$this->page]['bm'] = $bottommargin;
 2317         $this->pagedim[$this->page]['lm'] = $this->lMargin;
 2318         $this->pagedim[$this->page]['rm'] = $this->rMargin;
 2319         $this->pagedim[$this->page]['pb'] = $autopagebreak;
 2320         $this->pagedim[$this->page]['or'] = $this->CurOrientation;
 2321         $this->pagedim[$this->page]['olm'] = $this->original_lMargin;
 2322         $this->pagedim[$this->page]['orm'] = $this->original_rMargin;
 2323     }
 2324 
 2325     /**
 2326      * Set regular expression to detect withespaces or word separators.
 2327      * The pattern delimiter must be the forward-slash character "/".
 2328      * Some example patterns are:
 2329      * <pre>
 2330      * Non-Unicode or missing PCRE unicode support: "/[^\S\xa0]/"
 2331      * Unicode and PCRE unicode support: "/(?!\xa0)[\s\p{Z}]/u"
 2332      * Unicode and PCRE unicode support in Chinese mode: "/(?!\xa0)[\s\p{Z}\p{Lo}]/u"
 2333      * if PCRE unicode support is turned ON ("\P" is the negate class of "\p"):
 2334      *      \s     : any whitespace character
 2335      *      \p{Z}  : any separator
 2336      *      \p{Lo} : Unicode letter or ideograph that does not have lowercase and uppercase variants. Is used to chunk chinese words.
 2337      *      \xa0   : Unicode Character 'NO-BREAK SPACE' (U+00A0)
 2338      * </pre>
 2339      * @param $re (string) regular expression (leave empty for default).
 2340      * @public
 2341      * @since 4.6.016 (2009-06-15)
 2342      */
 2343     public function setSpacesRE($re='/[^\S\xa0]/') {
 2344         $this->re_spaces = $re;
 2345         $re_parts = explode('/', $re);
 2346         // get pattern parts
 2347         $this->re_space = array();
 2348         if (isset($re_parts[1]) AND !empty($re_parts[1])) {
 2349             $this->re_space['p'] = $re_parts[1];
 2350         } else {
 2351             $this->re_space['p'] = '[\s]';
 2352         }
 2353         // set pattern modifiers
 2354         if (isset($re_parts[2]) AND !empty($re_parts[2])) {
 2355             $this->re_space['m'] = $re_parts[2];
 2356         } else {
 2357             $this->re_space['m'] = '';
 2358         }
 2359     }
 2360 
 2361     /**
 2362      * Enable or disable Right-To-Left language mode
 2363      * @param $enable (Boolean) if true enable Right-To-Left language mode.
 2364      * @param $resetx (Boolean) if true reset the X position on direction change.
 2365      * @public
 2366      * @since 2.0.000 (2008-01-03)
 2367      */
 2368     public function setRTL($enable, $resetx=true) {
 2369         $enable = $enable ? true : false;
 2370         $resetx = ($resetx AND ($enable != $this->rtl));
 2371         $this->rtl = $enable;
 2372         $this->tmprtl = false;
 2373         if ($resetx) {
 2374             $this->Ln(0);
 2375         }
 2376     }
 2377 
 2378     /**
 2379      * Return the RTL status
 2380      * @return boolean
 2381      * @public
 2382      * @since 4.0.012 (2008-07-24)
 2383      */
 2384     public function getRTL() {
 2385         return $this->rtl;
 2386     }
 2387 
 2388     /**
 2389      * Force temporary RTL language direction
 2390      * @param $mode (mixed) can be false, 'L' for LTR or 'R' for RTL
 2391      * @public
 2392      * @since 2.1.000 (2008-01-09)
 2393      */
 2394     public function setTempRTL($mode) {
 2395         $newmode = false;
 2396         switch (strtoupper($mode)) {
 2397             case 'LTR':
 2398             case 'L': {
 2399                 if ($this->rtl) {
 2400                     $newmode = 'L';
 2401                 }
 2402                 break;
 2403             }
 2404             case 'RTL':
 2405             case 'R': {
 2406                 if (!$this->rtl) {
 2407                     $newmode = 'R';
 2408                 }
 2409                 break;
 2410             }
 2411             case false:
 2412             default: {
 2413                 $newmode = false;
 2414                 break;
 2415             }
 2416         }
 2417         $this->tmprtl = $newmode;
 2418     }
 2419 
 2420     /**
 2421      * Return the current temporary RTL status
 2422      * @return boolean
 2423      * @public
 2424      * @since 4.8.014 (2009-11-04)
 2425      */
 2426     public function isRTLTextDir() {
 2427         return ($this->rtl OR ($this->tmprtl == 'R'));
 2428     }
 2429 
 2430     /**
 2431      * Set the last cell height.
 2432      * @param $h (float) cell height.
 2433      * @author Nicola Asuni
 2434      * @public
 2435      * @since 1.53.0.TC034
 2436      */
 2437     public function setLastH($h) {
 2438         $this->lasth = $h;
 2439     }
 2440 
 2441     /**
 2442      * Return the cell height
 2443      * @param $fontsize (int) Font size in internal units
 2444      * @param $padding (boolean) If true add cell padding
 2445      * @public
 2446      */
 2447     public function getCellHeight($fontsize, $padding=TRUE) {
 2448         $height = ($fontsize * $this->cell_height_ratio);
 2449         if ($padding) {
 2450             $height += ($this->cell_padding['T'] + $this->cell_padding['B']);
 2451         }
 2452         return round($height, 6);
 2453     }
 2454 
 2455     /**
 2456      * Reset the last cell height.
 2457      * @public
 2458      * @since 5.9.000 (2010-10-03)
 2459      */
 2460     public function resetLastH() {
 2461         $this->lasth = $this->getCellHeight($this->FontSize);
 2462     }
 2463 
 2464     /**
 2465      * Get the last cell height.
 2466      * @return last cell height
 2467      * @public
 2468      * @since 4.0.017 (2008-08-05)
 2469      */
 2470     public function getLastH() {
 2471         return $this->lasth;
 2472     }
 2473 
 2474     /**
 2475      * Set the adjusting factor to convert pixels to user units.
 2476      * @param $scale (float) adjusting factor to convert pixels to user units.
 2477      * @author Nicola Asuni
 2478      * @public
 2479      * @since 1.5.2
 2480      */
 2481     public function setImageScale($scale) {
 2482         $this->imgscale = $scale;
 2483     }
 2484 
 2485     /**
 2486      * Returns the adjusting factor to convert pixels to user units.
 2487      * @return float adjusting factor to convert pixels to user units.
 2488      * @author Nicola Asuni
 2489      * @public
 2490      * @since 1.5.2
 2491      */
 2492     public function getImageScale() {
 2493         return $this->imgscale;
 2494     }
 2495 
 2496     /**
 2497      * Returns an array of page dimensions:
 2498      * <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 user units</li><li>$this->pagedim[$this->page]['hk'] = page height in user units</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><li>$this->pagedim[$this->page]['Rotate'] = The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.</li><li>$this->pagedim[$this->page]['PZ'] = The page's preferred zoom (magnification) factor.</li><li>$this->pagedim[$this->page]['trans'] : the style and duration of the visual transition to use when moving from another page to the given page during a presentation<ul><li>$this->pagedim[$this->page]['trans']['Dur'] = The page's display duration (also called its advance timing): the maximum length of time, in seconds, that the page shall be displayed during presentations before the viewer application shall automatically advance to the next page.</li><li>$this->pagedim[$this->page]['trans']['S'] = transition style : Split, Blinds, Box, Wipe, Dissolve, Glitter, R, Fly, Push, Cover, Uncover, Fade</li><li>$this->pagedim[$this->page]['trans']['D'] = The duration of the transition effect, in seconds.</li><li>$this->pagedim[$this->page]['trans']['Dm'] = (Split and Blinds transition styles only) The dimension in which the specified transition effect shall occur: H = Horizontal, V = Vertical. Default value: H.</li><li>$this->pagedim[$this->page]['trans']['M'] = (Split, Box and Fly transition styles only) The direction of motion for the specified transition effect: I = Inward from the edges of the page, O = Outward from the center of the pageDefault value: I.</li><li>$this->pagedim[$this->page]['trans']['Di'] = (Wipe, Glitter, Fly, Cover, Uncover and Push transition styles only) The direction in which the specified transition effect shall moves, expressed in degrees counterclockwise starting from a left-to-right direction. If the value is a number, it shall be one of: 0 = Left to right, 90 = Bottom to top (Wipe only), 180 = Right to left (Wipe only), 270 = Top to bottom, 315 = Top-left to bottom-right (Glitter only). If the value is a name, it shall be None, which is relevant only for the Fly transition when the value of SS is not 1.0. Default value: 0.</li><li>$this->pagedim[$this->page]['trans']['SS'] = (Fly transition style only) The starting or ending scale at which the changes shall be drawn. If M specifies an inward transition, the scale of the changes drawn shall progress from SS to 1.0 over the course of the transition. If M specifies an outward transition, the scale of the changes drawn shall progress from 1.0 to SS over the course of the transition. Default: 1.0. </li><li>$this->pagedim[$this->page]['trans']['B'] = (Fly transition style only) If true, the area that shall be flown in is rectangular and opaque. Default: false.</li></ul></li><li>$this->pagedim[$this->page]['MediaBox'] : the boundaries of the physical medium on which the page shall be displayed or printed<ul><li>$this->pagedim[$this->page]['MediaBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['MediaBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['MediaBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['MediaBox']['ury'] = upper-right y coordinate in points</li></ul></li><li>$this->pagedim[$this->page]['CropBox'] : the visible region of default user space<ul><li>$this->pagedim[$this->page]['CropBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['CropBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['CropBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['CropBox']['ury'] = upper-right y coordinate in points</li></ul></li><li>$this->pagedim[$this->page]['BleedBox'] : the region to which the contents of the page shall be clipped when output in a production environment<ul><li>$this->pagedim[$this->page]['BleedBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['BleedBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['BleedBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['BleedBox']['ury'] = upper-right y coordinate in points</li></ul></li><li>$this->pagedim[$this->page]['TrimBox'] : the intended dimensions of the finished page after trimming<ul><li>$this->pagedim[$this->page]['TrimBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['TrimBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['TrimBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['TrimBox']['ury'] = upper-right y coordinate in points</li></ul></li><li>$this->pagedim[$this->page]['ArtBox'] : the extent of the page's meaningful content<ul><li>$this->pagedim[$this->page]['ArtBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['ArtBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['ArtBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['ArtBox']['ury'] = upper-right y coordinate in points</li></ul></li></ul>
 2499      * @param $pagenum (int) page number (empty = current page)
 2500      * @return array of page dimensions.
 2501      * @author Nicola Asuni
 2502      * @public
 2503      * @since 4.5.027 (2009-03-16)
 2504      */
 2505     public function getPageDimensions($pagenum='') {
 2506         if (empty($pagenum)) {
 2507             $pagenum = $this->page;
 2508         }
 2509         return $this->pagedim[$pagenum];
 2510     }
 2511 
 2512     /**
 2513      * Returns the page width in units.
 2514      * @param $pagenum (int) page number (empty = current page)
 2515      * @return int page width.
 2516      * @author Nicola Asuni
 2517      * @public
 2518      * @since 1.5.2
 2519      * @see getPageDimensions()
 2520      */
 2521     public function getPageWidth($pagenum='') {
 2522         if (empty($pagenum)) {
 2523             return $this->w;
 2524         }
 2525         return $this->pagedim[$pagenum]['w'];
 2526     }
 2527 
 2528     /**
 2529      * Returns the page height in units.
 2530      * @param $pagenum (int) page number (empty = current page)
 2531      * @return int page height.
 2532      * @author Nicola Asuni
 2533      * @public
 2534      * @since 1.5.2
 2535      * @see getPageDimensions()
 2536      */
 2537     public function getPageHeight($pagenum='') {
 2538         if (empty($pagenum)) {
 2539             return $this->h;
 2540         }
 2541         return $this->pagedim[$pagenum]['h'];
 2542     }
 2543 
 2544     /**
 2545      * Returns the page break margin.
 2546      * @param $pagenum (int) page number (empty = current page)
 2547      * @return int page break margin.
 2548      * @author Nicola Asuni
 2549      * @public
 2550      * @since 1.5.2
 2551      * @see getPageDimensions()
 2552      */
 2553     public function getBreakMargin($pagenum='') {
 2554         if (empty($pagenum)) {
 2555             return $this->bMargin;
 2556         }
 2557         return $this->pagedim[$pagenum]['bm'];
 2558     }
 2559 
 2560     /**
 2561      * Returns the scale factor (number of points in user unit).
 2562      * @return int scale factor.
 2563      * @author Nicola Asuni
 2564      * @public
 2565      * @since 1.5.2
 2566      */
 2567     public function getScaleFactor() {
 2568         return $this->k;
 2569     }
 2570 
 2571     /**
 2572      * Defines the left, top and right margins.
 2573      * @param $left (float) Left margin.
 2574      * @param $top (float) Top margin.
 2575      * @param $right (float) Right margin. Default value is the left one.
 2576      * @param $keepmargins (boolean) if true overwrites the default page margins
 2577      * @public
 2578      * @since 1.0
 2579      * @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak()
 2580      */
 2581     public function SetMargins($left, $top, $right=-1, $keepmargins=false) {
 2582         //Set left, top and right margins
 2583         $this->lMargin = $left;
 2584         $this->tMargin = $top;
 2585         if ($right == -1) {
 2586             $right = $left;
 2587         }
 2588         $this->rMargin = $right;
 2589         if ($keepmargins) {
 2590             // overwrite original values
 2591             $this->original_lMargin = $this->lMargin;
 2592             $this->original_rMargin = $this->rMargin;
 2593         }
 2594     }
 2595 
 2596     /**
 2597      * 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.
 2598      * @param $margin (float) The margin.
 2599      * @public
 2600      * @since 1.4
 2601      * @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
 2602      */
 2603     public function SetLeftMargin($margin) {
 2604         //Set left margin
 2605         $this->lMargin = $margin;
 2606         if (($this->page > 0) AND ($this->x < $margin)) {
 2607             $this->x = $margin;
 2608         }
 2609     }
 2610 
 2611     /**
 2612      * Defines the top margin. The method can be called before creating the first page.
 2613      * @param $margin (float) The margin.
 2614      * @public
 2615      * @since 1.5
 2616      * @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
 2617      */
 2618     public function SetTopMargin($margin) {
 2619         //Set top margin
 2620         $this->tMargin = $margin;
 2621         if (($this->page > 0) AND ($this->y < $margin)) {
 2622             $this->y = $margin;
 2623         }
 2624     }
 2625 
 2626     /**
 2627      * Defines the right margin. The method can be called before creating the first page.
 2628      * @param $margin (float) The margin.
 2629      * @public
 2630      * @since 1.5
 2631      * @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()
 2632      */
 2633     public function SetRightMargin($margin) {
 2634         $this->rMargin = $margin;
 2635         if (($this->page > 0) AND ($this->x > ($this->w - $margin))) {
 2636             $this->x = $this->w - $margin;
 2637         }
 2638     }
 2639 
 2640     /**
 2641      * Set the same internal Cell padding for top, right, bottom, left-
 2642      * @param $pad (float) internal padding.
 2643      * @public
 2644      * @since 2.1.000 (2008-01-09)
 2645      * @see getCellPaddings(), setCellPaddings()
 2646      */
 2647     public function SetCellPadding($pad) {
 2648         if ($pad >= 0) {
 2649             $this->cell_padding['L'] = $pad;
 2650             $this->cell_padding['T'] = $pad;
 2651             $this->cell_padding['R'] = $pad;
 2652             $this->cell_padding['B'] = $pad;
 2653         }
 2654     }
 2655 
 2656     /**
 2657      * Set the internal Cell paddings.
 2658      * @param $left (float) left padding
 2659      * @param $top (float) top padding
 2660      * @param $right (float) right padding
 2661      * @param $bottom (float) bottom padding
 2662      * @public
 2663      * @since 5.9.000 (2010-10-03)
 2664      * @see getCellPaddings(), SetCellPadding()
 2665      */
 2666     public function setCellPaddings($left='', $top='', $right='', $bottom='') {
 2667         if (($left !== '') AND ($left >= 0)) {
 2668             $this->cell_padding['L'] = $left;
 2669         }
 2670         if (($top !== '') AND ($top >= 0)) {
 2671             $this->cell_padding['T'] = $top;
 2672         }
 2673         if (($right !== '') AND ($right >= 0)) {
 2674             $this->cell_padding['R'] = $right;
 2675         }
 2676         if (($bottom !== '') AND ($bottom >= 0)) {
 2677             $this->cell_padding['B'] = $bottom;
 2678         }
 2679     }
 2680 
 2681     /**
 2682      * Get the internal Cell padding array.
 2683      * @return array of padding values
 2684      * @public
 2685      * @since 5.9.000 (2010-10-03)
 2686      * @see setCellPaddings(), SetCellPadding()
 2687      */
 2688     public function getCellPaddings() {
 2689         return $this->cell_padding;
 2690     }
 2691 
 2692     /**
 2693      * Set the internal Cell margins.
 2694      * @param $left (float) left margin
 2695      * @param $top (float) top margin
 2696      * @param $right (float) right margin
 2697      * @param $bottom (float) bottom margin
 2698      * @public
 2699      * @since 5.9.000 (2010-10-03)
 2700      * @see getCellMargins()
 2701      */
 2702     public function setCellMargins($left='', $top='', $right='', $bottom='') {
 2703         if (($left !== '') AND ($left >= 0)) {
 2704             $this->cell_margin['L'] = $left;
 2705         }
 2706         if (($top !== '') AND ($top >= 0)) {
 2707             $this->cell_margin['T'] = $top;
 2708         }
 2709         if (($right !== '') AND ($right >= 0)) {
 2710             $this->cell_margin['R'] = $right;
 2711         }
 2712         if (($bottom !== '') AND ($bottom >= 0)) {
 2713             $this->cell_margin['B'] = $bottom;
 2714         }
 2715     }
 2716 
 2717     /**
 2718      * Get the internal Cell margin array.
 2719      * @return array of margin values
 2720      * @public
 2721      * @since 5.9.000 (2010-10-03)
 2722      * @see setCellMargins()
 2723      */
 2724     public function getCellMargins() {
 2725         return $this->cell_margin;
 2726     }
 2727 
 2728     /**
 2729      * Adjust the internal Cell padding array to take account of the line width.
 2730      * @param $brd (mixed) Indicates if borders must be drawn around the cell. The value can be 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> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)))
 2731      * @return array of adjustments
 2732      * @public
 2733      * @since 5.9.000 (2010-10-03)
 2734      */
 2735     protected function adjustCellPadding($brd=0) {
 2736         if (empty($brd)) {
 2737             return;
 2738         }
 2739         if (is_string($brd)) {
 2740             // convert string to array
 2741             $slen = strlen($brd);
 2742             $newbrd = array();
 2743             for ($i = 0; $i < $slen; ++$i) {
 2744                 $newbrd[$brd[$i]] = true;
 2745             }
 2746             $brd = $newbrd;
 2747         } elseif (($brd === 1) OR ($brd === true) OR (is_numeric($brd) AND (intval($brd) > 0))) {
 2748             $brd = array('LRTB' => true);
 2749         }
 2750         if (!is_array($brd)) {
 2751             return;
 2752         }
 2753         // store current cell padding
 2754         $cp = $this->cell_padding;
 2755         // select border mode
 2756         if (isset($brd['mode'])) {
 2757             $mode = $brd['mode'];
 2758             unset($brd['mode']);
 2759         } else {
 2760             $mode = 'normal';
 2761         }
 2762         // process borders
 2763         foreach ($brd as $border => $style) {
 2764             $line_width = $this->LineWidth;
 2765             if (is_array($style) AND isset($style['width'])) {
 2766                 // get border width
 2767                 $line_width = $style['width'];
 2768             }
 2769             $adj = 0; // line width inside the cell
 2770             switch ($mode) {
 2771                 case 'ext': {
 2772                     $adj = 0;
 2773                     break;
 2774                 }
 2775                 case 'int': {
 2776                     $adj = $line_width;
 2777                     break;
 2778                 }
 2779                 case 'normal':
 2780                 default: {
 2781                     $adj = ($line_width / 2);
 2782                     break;
 2783                 }
 2784             }
 2785             // correct internal cell padding if required to avoid overlap between text and lines
 2786             if ((strpos($border,'T') !== false) AND ($this->cell_padding['T'] < $adj)) {
 2787                 $this->cell_padding['T'] = $adj;
 2788             }
 2789             if ((strpos($border,'R') !== false) AND ($this->cell_padding['R'] < $adj)) {
 2790                 $this->cell_padding['R'] = $adj;
 2791             }
 2792             if ((strpos($border,'B') !== false) AND ($this->cell_padding['B'] < $adj)) {
 2793                 $this->cell_padding['B'] = $adj;
 2794             }
 2795             if ((strpos($border,'L') !== false) AND ($this->cell_padding['L'] < $adj)) {
 2796                 $this->cell_padding['L'] = $adj;
 2797             }
 2798         }
 2799         return array('T' => ($this->cell_padding['T'] - $cp['T']), 'R' => ($this->cell_padding['R'] - $cp['R']), 'B' => ($this->cell_padding['B'] - $cp['B']), 'L' => ($this->cell_padding['L'] - $cp['L']));
 2800     }
 2801 
 2802     /**
 2803      * 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.
 2804      * @param $auto (boolean) Boolean indicating if mode should be on or off.
 2805      * @param $margin (float) Distance from the bottom of the page.
 2806      * @public
 2807      * @since 1.0
 2808      * @see Cell(), MultiCell(), AcceptPageBreak()
 2809      */
 2810     public function SetAutoPageBreak($auto, $margin=0) {
 2811         $this->AutoPageBreak = $auto ? true : false;
 2812         $this->bMargin = $margin;
 2813         $this->PageBreakTrigger = $this->h - $margin;
 2814     }
 2815 
 2816     /**
 2817      * Return the auto-page-break mode (true or false).
 2818      * @return boolean auto-page-break mode
 2819      * @public
 2820      * @since 5.9.088
 2821      */
 2822     public function getAutoPageBreak() {
 2823         return $this->AutoPageBreak;
 2824     }
 2825 
 2826     /**
 2827      * Defines the way the document is to be displayed by the viewer.
 2828      * @param $zoom (mixed) 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>
 2829      * @param $layout (string) 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>
 2830      * @param $mode (string) 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>
 2831      * @public
 2832      * @since 1.2
 2833      */
 2834     public function SetDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') {
 2835         if (($zoom == 'fullpage') OR ($zoom == 'fullwidth') OR ($zoom == 'real') OR ($zoom == 'default') OR (!is_string($zoom))) {
 2836             $this->ZoomMode = $zoom;
 2837         } else {
 2838             $this->Error('Incorrect zoom display mode: '.$zoom);
 2839         }
 2840         $this->LayoutMode = TCPDF_STATIC::getPageLayoutMode($layout);
 2841         $this->PageMode = TCPDF_STATIC::getPageMode($mode);
 2842     }
 2843 
 2844     /**
 2845      * 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.
 2846      * Note: the Zlib extension is required for this feature. If not present, compression will be turned off.
 2847      * @param $compress (boolean) Boolean indicating if compression must be enabled.
 2848      * @public
 2849      * @since 1.4
 2850      */
 2851     public function SetCompression($compress=true) {
 2852         $this->compress = false;
 2853         if (function_exists('gzcompress')) {
 2854             if ($compress) {
 2855                 if ( !$this->pdfa_mode) {
 2856                     $this->compress = true;
 2857                 }
 2858             }
 2859         }
 2860     }
 2861 
 2862     /**
 2863      * Set flag to force sRGB_IEC61966-2.1 black scaled ICC color profile for the whole document.
 2864      * @param $mode (boolean) If true force sRGB output intent.
 2865      * @public
 2866      * @since 5.9.121 (2011-09-28)
 2867      */
 2868     public function setSRGBmode($mode=false) {
 2869         $this->force_srgb = $mode ? true : false;
 2870     }
 2871 
 2872     /**
 2873      * Turn on/off Unicode mode for document information dictionary (meta tags).
 2874      * This has effect only when unicode mode is set to false.
 2875      * @param $unicode (boolean) if true set the meta information in Unicode
 2876      * @since 5.9.027 (2010-12-01)
 2877      * @public
 2878      */
 2879     public function SetDocInfoUnicode($unicode=true) {
 2880         $this->docinfounicode = $unicode ? true : false;
 2881     }
 2882 
 2883     /**
 2884      * Defines the title of the document.
 2885      * @param $title (string) The title.
 2886      * @public
 2887      * @since 1.2
 2888      * @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject()
 2889      */
 2890     public function SetTitle($title) {
 2891         $this->title = $title;
 2892     }
 2893 
 2894     /**
 2895      * Defines the subject of the document.
 2896      * @param $subject (string) The subject.
 2897      * @public
 2898      * @since 1.2
 2899      * @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle()
 2900      */
 2901     public function SetSubject($subject) {
 2902         $this->subject = $subject;
 2903     }
 2904 
 2905     /**
 2906      * Defines the author of the document.
 2907      * @param $author (string) The name of the author.
 2908      * @public
 2909      * @since 1.2
 2910      * @see SetCreator(), SetKeywords(), SetSubject(), SetTitle()
 2911      */
 2912     public function SetAuthor($author) {
 2913         $this->author = $author;
 2914     }
 2915 
 2916     /**
 2917      * Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'.
 2918      * @param $keywords (string) The list of keywords.
 2919      * @public
 2920      * @since 1.2
 2921      * @see SetAuthor(), SetCreator(), SetSubject(), SetTitle()
 2922      */
 2923     public function SetKeywords($keywords) {
 2924         $this->keywords = $keywords;
 2925     }
 2926 
 2927     /**
 2928      * Defines the creator of the document. This is typically the name of the application that generates the PDF.
 2929      * @param $creator (string) The name of the creator.
 2930      * @public
 2931      * @since 1.2
 2932      * @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle()
 2933      */
 2934     public function SetCreator($creator) {
 2935         $this->creator = $creator;
 2936     }
 2937 
 2938     /**
 2939      * Throw an exception or print an error message and die if the K_TCPDF_PARSER_THROW_EXCEPTION_ERROR constant is set to true.
 2940      * @param $msg (string) The error message
 2941      * @public
 2942      * @since 1.0
 2943      */
 2944     public function Error($msg) {
 2945         // unset all class variables
 2946         $this->_destroy(true);
 2947         if (defined('K_TCPDF_THROW_EXCEPTION_ERROR') AND !K_TCPDF_THROW_EXCEPTION_ERROR) {
 2948             die('<strong>TCPDF ERROR: </strong>'.$msg);
 2949         } else {
 2950             throw new Exception('TCPDF ERROR: '.$msg);
 2951         }
 2952     }
 2953 
 2954     /**
 2955      * This method begins the generation of the PDF document.
 2956      * It is not necessary to call it explicitly because AddPage() does it automatically.
 2957      * Note: no page is created by this method
 2958      * @public
 2959      * @since 1.0
 2960      * @see AddPage(), Close()
 2961      */
 2962     public function Open() {
 2963         $this->state = 1;
 2964     }
 2965 
 2966     /**
 2967      * Terminates the PDF document.
 2968      * It is not necessary to call this method explicitly because Output() does it automatically.
 2969      * If the document contains no page, AddPage() is called to prevent from getting an invalid document.
 2970      * @public
 2971      * @since 1.0
 2972      * @see Open(), Output()
 2973      */
 2974     public function Close() {
 2975         if ($this->state == 3) {
 2976             return;
 2977         }
 2978         if ($this->page == 0) {
 2979             $this->AddPage();
 2980         }
 2981         $this->endLayer();
 2982         if ($this->tcpdflink) {
 2983             // save current graphic settings
 2984             $gvars = $this->getGraphicVars();
 2985             $this->setEqualColumns();
 2986             $this->lastpage(true);
 2987             $this->SetAutoPageBreak(false);
 2988             $this->x = 0;
 2989             $this->y = $this->h - (1 / $this->k);
 2990             $this->lMargin = 0;
 2991             $this->_outSaveGraphicsState();
 2992             $font = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica';
 2993             $this->SetFont($font, '', 1);
 2994             $this->setTextRenderingMode(0, false, false);
 2995             $msg = "\x50\x6f\x77\x65\x72\x65\x64\x20\x62\x79\x20\x54\x43\x50\x44\x46\x20\x28\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29";
 2996             $lnk = "\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67";
 2997             $this->Cell(0, 0, $msg, 0, 0, 'L', 0, $lnk, 0, false, 'D', 'B');
 2998             $this->_outRestoreGraphicsState();
 2999             // restore graphic settings
 3000             $this->setGraphicVars($gvars);
 3001         }
 3002         // close page
 3003         $this->endPage();
 3004         // close document
 3005         $this->_enddoc();
 3006         // unset all class variables (except critical ones)
 3007         $this->_destroy(false);
 3008     }
 3009 
 3010     /**
 3011      * Move pointer at the specified document page and update page dimensions.
 3012      * @param $pnum (int) page number (1 ... numpages)
 3013      * @param $resetmargins (boolean) if true reset left, right, top margins and Y position.
 3014      * @public
 3015      * @since 2.1.000 (2008-01-07)
 3016      * @see getPage(), lastpage(), getNumPages()
 3017      */
 3018     public function setPage($pnum, $resetmargins=false) {
 3019         if (($pnum == $this->page) AND ($this->state == 2)) {
 3020             return;
 3021         }
 3022         if (($pnum > 0) AND ($pnum <= $this->numpages)) {
 3023             $this->state = 2;
 3024             // save current graphic settings
 3025             //$gvars = $this->getGraphicVars();
 3026             $oldpage = $this->page;
 3027             $this->page = $pnum;
 3028             $this->wPt = $this->pagedim[$this->page]['w'];
 3029             $this->hPt = $this->pagedim[$this->page]['h'];
 3030             $this->w = $this->pagedim[$this->page]['wk'];
 3031             $this->h = $this->pagedim[$this->page]['hk'];
 3032             $this->tMargin = $this->pagedim[$this->page]['tm'];
 3033             $this->bMargin = $this->pagedim[$this->page]['bm'];
 3034             $this->original_lMargin = $this->pagedim[$this->page]['olm'];
 3035             $this->original_rMargin = $this->pagedim[$this->page]['orm'];
 3036             $this->AutoPageBreak = $this->pagedim[$this->page]['pb'];
 3037             $this->CurOrientation = $this->pagedim[$this->page]['or'];
 3038             $this->SetAutoPageBreak($this->AutoPageBreak, $this->bMargin);
 3039             // restore graphic settings
 3040             //$this->setGraphicVars($gvars);
 3041             if ($resetmargins) {
 3042                 $this->lMargin = $this->pagedim[$this->page]['olm'];
 3043                 $this->rMargin = $this->pagedim[$this->page]['orm'];
 3044                 $this->SetY($this->tMargin);
 3045             } else {
 3046                 // account for booklet mode
 3047                 if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
 3048                     $deltam = $this->pagedim[$this->page]['olm'] - $this->pagedim[$this->page]['orm'];
 3049                     $this->lMargin += $deltam;
 3050                     $this->rMargin -= $deltam;
 3051                 }
 3052             }
 3053         } else {
 3054             $this->Error('Wrong page number on setPage() function: '.$pnum);
 3055         }
 3056     }
 3057 
 3058     /**
 3059      * Reset pointer to the last document page.
 3060      * @param $resetmargins (boolean) if true reset left, right, top margins and Y position.
 3061      * @public
 3062      * @since 2.0.000 (2008-01-04)
 3063      * @see setPage(), getPage(), getNumPages()
 3064      */
 3065     public function lastPage($resetmargins=false) {
 3066         $this->setPage($this->getNumPages(), $resetmargins);
 3067     }
 3068 
 3069     /**
 3070      * Get current document page number.
 3071      * @return int page number
 3072      * @public
 3073      * @since 2.1.000 (2008-01-07)
 3074      * @see setPage(), lastpage(), getNumPages()
 3075      */
 3076     public function getPage() {
 3077         return $this->page;
 3078     }
 3079 
 3080     /**
 3081      * Get the total number of insered pages.
 3082      * @return int number of pages
 3083      * @public
 3084      * @since 2.1.000 (2008-01-07)
 3085      * @see setPage(), getPage(), lastpage()
 3086      */
 3087     public function getNumPages() {
 3088         return $this->numpages;
 3089     }
 3090 
 3091     /**
 3092      * Adds a new TOC (Table Of Content) page to the document.
 3093      * @param $orientation (string) page orientation.
 3094      * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat().
 3095      * @param $keepmargins (boolean) if true overwrites the default page margins with the current margins
 3096      * @public
 3097      * @since 5.0.001 (2010-05-06)
 3098      * @see AddPage(), startPage(), endPage(), endTOCPage()
 3099      */
 3100     public function addTOCPage($orientation='', $format='', $keepmargins=false) {
 3101         $this->AddPage($orientation, $format, $keepmargins, true);
 3102     }
 3103 
 3104     /**
 3105      * Terminate the current TOC (Table Of Content) page
 3106      * @public
 3107      * @since 5.0.001 (2010-05-06)
 3108      * @see AddPage(), startPage(), endPage(), addTOCPage()
 3109      */
 3110     public function endTOCPage() {
 3111         $this->endPage(true);
 3112     }
 3113 
 3114     /**
 3115      * 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).
 3116      * The origin of the coordinate system is at the top-left corner (or top-right for RTL) and increasing ordinates go downwards.
 3117      * @param $orientation (string) page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul>
 3118      * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat().
 3119      * @param $keepmargins (boolean) if true overwrites the default page margins with the current margins
 3120      * @param $tocpage (boolean) if true set the tocpage state to true (the added page will be used to display Table Of Content).
 3121      * @public
 3122      * @since 1.0
 3123      * @see startPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat()
 3124      */
 3125     public function AddPage($orientation='', $format='', $keepmargins=false, $tocpage=false) {
 3126         if ($this->inxobj) {
 3127             // we are inside an XObject template
 3128             return;
 3129         }
 3130         if (!isset($this->original_lMargin) OR $keepmargins) {
 3131             $this->original_lMargin = $this->lMargin;
 3132         }
 3133         if (!isset($this->original_rMargin) OR $keepmargins) {
 3134             $this->original_rMargin = $this->rMargin;
 3135         }
 3136         // terminate previous page
 3137         $this->endPage();
 3138         // start new page
 3139         $this->startPage($orientation, $format, $tocpage);
 3140     }
 3141 
 3142     /**
 3143      * Terminate the current page
 3144      * @param $tocpage (boolean) if true set the tocpage state to false (end the page used to display Table Of Content).
 3145      * @public
 3146      * @since 4.2.010 (2008-11-14)
 3147      * @see AddPage(), startPage(), addTOCPage(), endTOCPage()
 3148      */
 3149     public function endPage($tocpage=false) {
 3150         // check if page is already closed
 3151         if (($this->page == 0) OR ($this->numpages > $this->page) OR (!$this->pageopen[$this->page])) {
 3152             return;
 3153         }
 3154         // print page footer
 3155         $this->setFooter();
 3156         // close page
 3157         $this->_endpage();
 3158         // mark page as closed
 3159         $this->pageopen[$this->page] = false;
 3160         if ($tocpage) {
 3161             $this->tocpage = false;
 3162         }
 3163     }
 3164 
 3165     /**
 3166      * Starts a new page to the document. The page must be closed using the endPage() function.
 3167      * The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards.
 3168      * @param $orientation (string) page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul>
 3169      * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat().
 3170      * @param $tocpage (boolean) if true the page is designated to contain the Table-Of-Content.
 3171      * @since 4.2.010 (2008-11-14)
 3172      * @see AddPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat()
 3173      * @public
 3174      */
 3175     public function startPage($orientation='', $format='', $tocpage=false) {
 3176         if ($tocpage) {
 3177             $this->tocpage = true;
 3178         }
 3179         // move page numbers of documents to be attached
 3180         if ($this->tocpage) {
 3181             // move reference to unexistent pages (used for page attachments)
 3182             // adjust outlines
 3183             $tmpoutlines = $this->outlines;
 3184             foreach ($tmpoutlines as $key => $outline) {
 3185                 if (!$outline['f'] AND ($outline['p'] > $this->numpages)) {
 3186                     $this->outlines[$key]['p'] = ($outline['p'] + 1);
 3187                 }
 3188             }
 3189             // adjust dests
 3190             $tmpdests = $this->dests;
 3191             foreach ($tmpdests as $key => $dest) {
 3192                 if (!$dest['f'] AND ($dest['p'] > $this->numpages)) {
 3193                     $this->dests[$key]['p'] = ($dest['p'] + 1);
 3194                 }
 3195             }
 3196             // adjust links
 3197             $tmplinks = $this->links;
 3198             foreach ($tmplinks as $key => $link) {
 3199                 if (!$link['f'] AND ($link['p'] > $this->numpages)) {
 3200                     $this->links[$key]['p'] = ($link['p'] + 1);
 3201                 }
 3202             }
 3203         }
 3204         if ($this->numpages > $this->page) {
 3205             // this page has been already added
 3206             $this->setPage($this->page + 1);
 3207             $this->SetY($this->tMargin);
 3208             return;
 3209         }
 3210         // start a new page
 3211         if ($this->state == 0) {
 3212             $this->Open();
 3213         }
 3214         ++$this->numpages;
 3215         $this->swapMargins($this->booklet);
 3216         // save current graphic settings
 3217         $gvars = $this->getGraphicVars();
 3218         // start new page
 3219         $this->_beginpage($orientation, $format);
 3220         // mark page as open
 3221         $this->pageopen[$this->page] = true;
 3222         // restore graphic settings
 3223         $this->setGraphicVars($gvars);
 3224         // mark this point
 3225         $this->setPageMark();
 3226         // print page header
 3227         $this->setHeader();
 3228         // restore graphic settings
 3229         $this->setGraphicVars($gvars);
 3230         // mark this point
 3231         $this->setPageMark();
 3232         // print table header (if any)
 3233         $this->setTableHeader();
 3234         // set mark for empty page check
 3235         $this->emptypagemrk[$this->page]= $this->pagelen[$this->page];
 3236     }
 3237 
 3238     /**
 3239      * Set start-writing mark on current page stream used to put borders and fills.
 3240      * Borders and fills are always created after content and inserted on the position marked by this method.
 3241      * This function must be called after calling Image() function for a background image.
 3242      * Background images must be always inserted before calling Multicell() or WriteHTMLCell() or WriteHTML() functions.
 3243      * @public
 3244      * @since 4.0.016 (2008-07-30)
 3245      */
 3246     public function setPageMark() {
 3247         $this->intmrk[$this->page] = $this->pagelen[$this->page];
 3248         $this->bordermrk[$this->page] = $this->intmrk[$this->page];
 3249         $this->setContentMark();
 3250     }
 3251 
 3252     /**
 3253      * Set start-writing mark on selected page.
 3254      * Borders and fills are always created after content and inserted on the position marked by this method.
 3255      * @param $page (int) page number (default is the current page)
 3256      * @protected
 3257      * @since 4.6.021 (2009-07-20)
 3258      */
 3259     protected function setContentMark($page=0) {
 3260         if ($page <= 0) {
 3261             $page = $this->page;
 3262         }
 3263         if (isset($this->footerlen[$page])) {
 3264             $this->cntmrk[$page] = $this->pagelen[$page] - $this->footerlen[$page];
 3265         } else {
 3266             $this->cntmrk[$page] = $this->pagelen[$page];
 3267         }
 3268     }
 3269 
 3270     /**
 3271      * Set header data.
 3272      * @param $ln (string) header image logo
 3273      * @param $lw (string) header image logo width in mm
 3274      * @param $ht (string) string to print as title on document header
 3275      * @param $hs (string) string to print on document header
 3276      * @param $tc (array) RGB array color for text.
 3277      * @param $lc (array) RGB array color for line.
 3278      * @public
 3279      */
 3280     public function setHeaderData($ln='', $lw=0, $ht='', $hs='', $tc=array(0,0,0), $lc=array(0,0,0)) {
 3281         $this->header_logo = $ln;
 3282         $this->header_logo_width = $lw;
 3283         $this->header_title = $ht;
 3284         $this->header_string = $hs;
 3285         $this->header_text_color = $tc;
 3286         $this->header_line_color = $lc;
 3287     }
 3288 
 3289     /**
 3290      * Set footer data.
 3291      * @param $tc (array) RGB array color for text.
 3292      * @param $lc (array) RGB array color for line.
 3293      * @public
 3294      */
 3295     public function setFooterData($tc=array(0,0,0), $lc=array(0,0,0)) {
 3296         $this->footer_text_color = $tc;
 3297         $this->footer_line_color = $lc;
 3298     }
 3299 
 3300     /**
 3301      * Returns header data:
 3302      * <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>
 3303      * @return array()
 3304      * @public
 3305      * @since 4.0.012 (2008-07-24)
 3306      */
 3307     public function getHeaderData() {
 3308         $ret = array();
 3309         $ret['logo'] = $this->header_logo;
 3310         $ret['logo_width'] = $this->header_logo_width;
 3311         $ret['title'] = $this->header_title;
 3312         $ret['string'] = $this->header_string;
 3313         $ret['text_color'] = $this->header_text_color;
 3314         $ret['line_color'] = $this->header_line_color;
 3315         return $ret;
 3316     }
 3317 
 3318     /**
 3319      * Set header margin.
 3320      * (minimum distance between header and top page margin)
 3321      * @param $hm (int) distance in user units
 3322      * @public
 3323      */
 3324     public function setHeaderMargin($hm=10) {
 3325         $this->header_margin = $hm;
 3326     }
 3327 
 3328     /**
 3329      * Returns header margin in user units.
 3330      * @return float
 3331      * @since 4.0.012 (2008-07-24)
 3332      * @public
 3333      */
 3334     public function getHeaderMargin() {
 3335         return $this->header_margin;
 3336     }
 3337 
 3338     /**
 3339      * Set footer margin.
 3340      * (minimum distance between footer and bottom page margin)
 3341      * @param $fm (int) distance in user units
 3342      * @public
 3343      */
 3344     public function setFooterMargin($fm=10) {
 3345         $this->footer_margin = $fm;
 3346     }
 3347 
 3348     /**
 3349      * Returns footer margin in user units.
 3350      * @return float
 3351      * @since 4.0.012 (2008-07-24)
 3352      * @public
 3353      */
 3354     public function getFooterMargin() {
 3355         return $this->footer_margin;
 3356     }
 3357     /**
 3358      * Set a flag to print page header.
 3359      * @param $val (boolean) set to true to print the page header (default), false otherwise.
 3360      * @public
 3361      */
 3362     public function setPrintHeader($val=true) {
 3363         $this->print_header = $val ? true : false;
 3364     }
 3365 
 3366     /**
 3367      * Set a flag to print page footer.
 3368      * @param $val (boolean) set to true to print the page footer (default), false otherwise.
 3369      * @public
 3370      */
 3371     public function setPrintFooter($val=true) {
 3372         $this->print_footer = $val ? true : false;
 3373     }
 3374 
 3375     /**
 3376      * Return the right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image
 3377      * @return float
 3378      * @public
 3379      */
 3380     public function getImageRBX() {
 3381         return $this->img_rb_x;
 3382     }
 3383 
 3384     /**
 3385      * Return the right-bottom (or left-bottom for RTL) corner Y coordinate of last inserted image
 3386      * @return float
 3387      * @public
 3388      */
 3389     public function getImageRBY() {
 3390         return $this->img_rb_y;
 3391     }
 3392 
 3393     /**
 3394      * Reset the xobject template used by Header() method.
 3395      * @public
 3396      */
 3397     public function resetHeaderTemplate() {
 3398         $this->header_xobjid = false;
 3399     }
 3400 
 3401     /**
 3402      * Set a flag to automatically reset the xobject template used by Header() method at each page.
 3403      * @param $val (boolean) set to true to reset Header xobject template at each page, false otherwise.
 3404      * @public
 3405      */
 3406     public function setHeaderTemplateAutoreset($val=true) {
 3407         $this->header_xobj_autoreset = $val ? true : false;
 3408     }
 3409 
 3410     /**
 3411      * This method is used to render the page header.
 3412      * It is automatically called by AddPage() and could be overwritten in your own inherited class.
 3413      * @public
 3414      */
 3415     public function Header() {
 3416         if ($this->header_xobjid === false) {
 3417             // start a new XObject Template
 3418             $this->header_xobjid = $this->startTemplate($this->w, $this->tMargin);
 3419             $headerfont = $this->getHeaderFont();
 3420             $headerdata = $this->getHeaderData();
 3421             $this->y = $this->header_margin;
 3422             if ($this->rtl) {
 3423                 $this->x = $this->w - $this->original_rMargin;
 3424             } else {
 3425                 $this->x = $this->original_lMargin;
 3426             }
 3427             if (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) {
 3428                 $imgtype = TCPDF_IMAGES::getImageFileType(K_PATH_IMAGES.$headerdata['logo']);
 3429                 if (($imgtype == 'eps') OR ($imgtype == 'ai')) {
 3430                     $this->ImageEps(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
 3431                 } elseif ($imgtype == 'svg') {
 3432                     $this->ImageSVG(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
 3433                 } else {
 3434                     $this->Image(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
 3435                 }
 3436                 $imgy = $this->getImageRBY();
 3437             } else {
 3438                 $imgy = $this->y;
 3439             }
 3440             $cell_height = $this->getCellHeight($headerfont[2] / $this->k);
 3441             // set starting margin for text data cell
 3442             if ($this->getRTL()) {
 3443                 $header_x = $this->original_rMargin + ($headerdata['logo_width'] * 1.1);
 3444             } else {
 3445                 $header_x = $this->original_lMargin + ($headerdata['logo_width'] * 1.1);
 3446             }
 3447             $cw = $this->w - $this->original_lMargin - $this->original_rMargin - ($headerdata['logo_width'] * 1.1);
 3448             $this->SetTextColorArray($this->header_text_color);
 3449             // header title
 3450             $this->SetFont($headerfont[0], 'B', $headerfont[2] + 1);
 3451             $this->SetX($header_x);
 3452             $this->Cell($cw, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0);
 3453             // header string
 3454             $this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]);
 3455             $this->SetX($header_x);
 3456             $this->MultiCell($cw, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false, true, 0, 'T', false);
 3457             // print an ending header line
 3458             $this->SetLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $headerdata['line_color']));
 3459             $this->SetY((2.835 / $this->k) + max($imgy, $this->y));
 3460             if ($this->rtl) {
 3461                 $this->SetX($this->original_rMargin);
 3462             } else {
 3463                 $this->SetX($this->original_lMargin);
 3464             }
 3465             $this->Cell(($this->w - $this->original_lMargin - $this->original_rMargin), 0, '', 'T', 0, 'C');
 3466             $this->endTemplate();
 3467         }
 3468         // print header template
 3469         $x = 0;
 3470         $dx = 0;
 3471         if (!$this->header_xobj_autoreset AND $this->booklet AND (($this->page % 2) == 0)) {
 3472             // adjust margins for booklet mode
 3473             $dx = ($this->original_lMargin - $this->original_rMargin);
 3474         }
 3475         if ($this->rtl) {
 3476             $x = $this->w + $dx;
 3477         } else {
 3478             $x = 0 + $dx;
 3479         }
 3480         $this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false);
 3481         if ($this->header_xobj_autoreset) {
 3482             // reset header xobject template at each page
 3483             $this->header_xobjid = false;
 3484         }
 3485     }
 3486 
 3487     /**
 3488      * This method is used to render the page footer.
 3489      * It is automatically called by AddPage() and could be overwritten in your own inherited class.
 3490      * @public
 3491      */
 3492     public function Footer() {
 3493         $cur_y = $this->y;
 3494         $this->SetTextColorArray($this->footer_text_color);
 3495         //set style for cell border
 3496         $line_width = (0.85 / $this->k);
 3497         $this->SetLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $this->footer_line_color));
 3498         //print document barcode
 3499         $barcode = $this->getBarcode();
 3500         if (!empty($barcode)) {
 3501             $this->Ln($line_width);
 3502             $barcode_width = round(($this->w - $this->original_lMargin - $this->original_rMargin) / 3);
 3503             $style = array(
 3504                 'position' => $this->rtl?'R':'L',
 3505                 'align' => $this->rtl?'R':'L',
 3506                 'stretch' => false,
 3507                 'fitwidth' => true,
 3508                 'cellfitalign' => '',
 3509                 'border' => false,
 3510                 'padding' => 0,
 3511                 'fgcolor' => array(0,0,0),
 3512                 'bgcolor' => false,
 3513                 'text' => false
 3514             );
 3515             $this->write1DBarcode($barcode, 'C128', '', $cur_y + $line_width, '', (($this->footer_margin / 3) - $line_width), 0.3, $style, '');
 3516         }
 3517         $w_page = isset($this->l['w_page']) ? $this->l['w_page'].' ' : '';
 3518         if (empty($this->pagegroups)) {
 3519             $pagenumtxt = $w_page.$this->getAliasNumPage().' / '.$this->getAliasNbPages();
 3520         } else {
 3521             $pagenumtxt = $w_page.$this->getPageNumGroupAlias().' / '.$this->getPageGroupAlias();
 3522         }
 3523         $this->SetY($cur_y);
 3524         //Print page number
 3525         if ($this->getRTL()) {
 3526             $this->SetX($this->original_rMargin);
 3527             $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'L');
 3528         } else {
 3529             $this->SetX($this->original_lMargin);
 3530             $this->Cell(0, 0, $this->getAliasRightShift().$pagenumtxt, 'T', 0, 'R');
 3531         }
 3532     }
 3533 
 3534     /**
 3535      * This method is used to render the page header.
 3536      * @protected
 3537      * @since 4.0.012 (2008-07-24)
 3538      */
 3539     protected function setHeader() {
 3540         if (!$this->print_header OR ($this->state != 2)) {
 3541             return;
 3542         }
 3543         $this->InHeader = true;
 3544         $this->setGraphicVars($this->default_graphic_vars);
 3545         $temp_thead = $this->thead;
 3546         $temp_theadMargins = $this->theadMargins;
 3547         $lasth = $this->lasth;
 3548         $newline = $this->newline;
 3549         $this->_outSaveGraphicsState();
 3550         $this->rMargin = $this->original_rMargin;
 3551         $this->lMargin = $this->original_lMargin;
 3552         $this->SetCellPadding(0);
 3553         //set current position
 3554         if ($this->rtl) {
 3555             $this->SetXY($this->original_rMargin, $this->header_margin);
 3556         } else {
 3557             $this->SetXY($this->original_lMargin, $this->header_margin);
 3558         }
 3559         $this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]);
 3560         $this->Header();
 3561         //restore position
 3562         if ($this->rtl) {
 3563             $this->SetXY($this->original_rMargin, $this->tMargin);
 3564         } else {
 3565             $this->SetXY($this->original_lMargin, $this->tMargin);
 3566         }
 3567         $this->_outRestoreGraphicsState();
 3568         $this->lasth = $lasth;
 3569         $this->thead = $temp_thead;
 3570         $this->theadMargins = $temp_theadMargins;
 3571         $this->newline = $newline;
 3572         $this->InHeader = false;
 3573     }
 3574 
 3575     /**
 3576      * This method is used to render the page footer.
 3577      * @protected
 3578      * @since 4.0.012 (2008-07-24)
 3579      */
 3580     protected function setFooter() {
 3581         if ($this->state != 2) {
 3582             return;
 3583         }
 3584         $this->InFooter = true;
 3585         // save current graphic settings
 3586         $gvars = $this->getGraphicVars();
 3587         // mark this point
 3588         $this->footerpos[$this->page] = $this->pagelen[$this->page];
 3589         $this->_out("\n");
 3590         if ($this->print_footer) {
 3591             $this->setGraphicVars($this->default_graphic_vars);
 3592             $this->current_column = 0;
 3593             $this->num_columns = 1;
 3594             $temp_thead = $this->thead;
 3595             $temp_theadMargins = $this->theadMargins;
 3596             $lasth = $this->lasth;
 3597             $this->_outSaveGraphicsState();
 3598             $this->rMargin = $this->original_rMargin;
 3599             $this->lMargin = $this->original_lMargin;
 3600             $this->SetCellPadding(0);
 3601             //set current position
 3602             $footer_y = $this->h - $this->footer_margin;
 3603             if ($this->rtl) {
 3604                 $this->SetXY($this->original_rMargin, $footer_y);
 3605             } else {
 3606                 $this->SetXY($this->original_lMargin, $footer_y);
 3607             }
 3608             $this->SetFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]);
 3609             $this->Footer();
 3610             //restore position
 3611             if ($this->rtl) {
 3612                 $this->SetXY($this->original_rMargin, $this->tMargin);
 3613             } else {
 3614                 $this->SetXY($this->original_lMargin, $this->tMargin);
 3615             }
 3616             $this->_outRestoreGraphicsState();
 3617             $this->lasth = $lasth;
 3618             $this->thead = $temp_thead;
 3619             $this->theadMargins = $temp_theadMargins;
 3620         }
 3621         // restore graphic settings
 3622         $this->setGraphicVars($gvars);
 3623         $this->current_column = $gvars['current_column'];
 3624         $this->num_columns = $gvars['num_columns'];
 3625         // calculate footer length
 3626         $this->footerlen[$this->page] = $this->pagelen[$this->page] - $this->footerpos[$this->page] + 1;
 3627         $this->InFooter = false;
 3628     }
 3629 
 3630     /**
 3631      * Check if we are on the page body (excluding page header and footer).
 3632      * @return true if we are not in page header nor in page footer, false otherwise.
 3633      * @protected
 3634      * @since 5.9.091 (2011-06-15)
 3635      */
 3636     protected function inPageBody() {
 3637         return (($this->InHeader === false) AND ($this->InFooter === false));
 3638     }
 3639 
 3640     /**
 3641      * This method is used to render the table header on new page (if any).
 3642      * @protected
 3643      * @since 4.5.030 (2009-03-25)
 3644      */
 3645     protected function setTableHeader() {
 3646         if ($this->num_columns > 1) {
 3647             // multi column mode
 3648             return;
 3649         }
 3650         if (isset($this->theadMargins['top'])) {
 3651             // restore the original top-margin
 3652             $this->tMargin = $this->theadMargins['top'];
 3653             $this->pagedim[$this->page]['tm'] = $this->tMargin;
 3654             $this->y = $this->tMargin;
 3655         }
 3656         if (!TCPDF_STATIC::empty_string($this->thead) AND (!$this->inthead)) {
 3657             // set margins
 3658             $prev_lMargin = $this->lMargin;
 3659             $prev_rMargin = $this->rMargin;
 3660             $prev_cell_padding = $this->cell_padding;
 3661             $this->lMargin = $this->theadMargins['lmargin'] + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$this->theadMargins['page']]['olm']);
 3662             $this->rMargin = $this->theadMargins['rmargin'] + ($this->pagedim[$this->page]['orm'] - $this->pagedim[$this->theadMargins['page']]['orm']);
 3663             $this->cell_padding = $this->theadMargins['cell_padding'];
 3664             if ($this->rtl) {
 3665                 $this->x = $this->w - $this->rMargin;
 3666             } else {
 3667                 $this->x = $this->lMargin;
 3668             }
 3669             // account for special "cell" mode
 3670             if ($this->theadMargins['cell']) {
 3671                 if ($this->rtl) {
 3672                     $this->x -= $this->cell_padding['R'];
 3673                 } else {
 3674                     $this->x += $this->cell_padding['L'];
 3675                 }
 3676             }
 3677             $gvars = $this->getGraphicVars();
 3678             if (!empty($this->theadMargins['gvars'])) {
 3679                 // set the correct graphic style
 3680                 $this->setGraphicVars($this->theadMargins['gvars']);
 3681                 $this->rMargin = $gvars['rMargin'];
 3682                 $this->lMargin = $gvars['lMargin'];
 3683             }
 3684             // print table header
 3685             $this->writeHTML($this->thead, false, false, false, false, '');
 3686             $this->setGraphicVars($gvars);
 3687             // set new top margin to skip the table headers
 3688             if (!isset($this->theadMargins['top'])) {
 3689                 $this->theadMargins['top'] = $this->tMargin;
 3690             }
 3691             // store end of header position
 3692             if (!isset($this->columns[0]['th'])) {
 3693                 $this->columns[0]['th'] = array();
 3694             }
 3695             $this->columns[0]['th']['\''.$this->page.'\''] = $this->y;
 3696             $this->tMargin = $this->y;
 3697             $this->pagedim[$this->page]['tm'] = $this->tMargin;
 3698             $this->lasth = 0;
 3699             $this->lMargin = $prev_lMargin;
 3700             $this->rMargin = $prev_rMargin;
 3701             $this->cell_padding = $prev_cell_padding;
 3702         }
 3703     }
 3704 
 3705     /**
 3706      * Returns the current page number.
 3707      * @return int page number
 3708      * @public
 3709      * @since 1.0
 3710      * @see getAliasNbPages()
 3711      */
 3712     public function PageNo() {
 3713         return $this->page;
 3714     }
 3715 
 3716     /**
 3717      * Returns the array of spot colors.
 3718      * @return (array) Spot colors array.
 3719      * @public
 3720      * @since 6.0.038 (2013-09-30)
 3721      */
 3722     public function getAllSpotColors() {
 3723         return $this->spot_colors;
 3724     }
 3725 
 3726     /**
 3727      * Defines a new spot color.
 3728      * It can be expressed in RGB components or gray scale.
 3729      * The method can be called before the first page is created and the value is retained from page to page.
 3730      * @param $name (string) Full name of the spot color.
 3731      * @param $c (float) Cyan color for CMYK. Value between 0 and 100.
 3732      * @param $m (float) Magenta color for CMYK. Value between 0 and 100.
 3733      * @param $y (float) Yellow color for CMYK. Value between 0 and 100.
 3734      * @param $k (float) Key (Black) color for CMYK. Value between 0 and 100.
 3735      * @public
 3736      * @since 4.0.024 (2008-09-12)
 3737      * @see SetDrawSpotColor(), SetFillSpotColor(), SetTextSpotColor()
 3738      */
 3739     public function AddSpotColor($name, $c, $m, $y, $k) {
 3740         if (!isset($this->spot_colors[$name])) {
 3741             $i = (1 + count($this->spot_colors));
 3742             $this->spot_colors[$name] = array('C' => $c, 'M' => $m, 'Y' => $y, 'K' => $k, 'name' => $name, 'i' => $i);
 3743         }
 3744     }
 3745 
 3746     /**
 3747      * Set the spot color for the specified type ('draw', 'fill', 'text').
 3748      * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text').
 3749      * @param $name (string) Name of the spot color.
 3750      * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default).
 3751      * @return (string) PDF color command.
 3752      * @public
 3753      * @since 5.9.125 (2011-10-03)
 3754      */
 3755     public function setSpotColor($type, $name, $tint=100) {
 3756         $spotcolor = TCPDF_COLORS::getSpotColor($name, $this->spot_colors);
 3757         if ($spotcolor === false) {
 3758             $this->Error('Undefined spot color: '.$name.', you must add it using the AddSpotColor() method.');
 3759         }
 3760         $tint = (max(0, min(100, $tint)) / 100);
 3761         $pdfcolor = sprintf('/CS%d ', $this->spot_colors[$name]['i']);
 3762         switch ($type) {
 3763             case 'draw': {
 3764                 $pdfcolor .= sprintf('CS %F SCN', $tint);
 3765                 $this->DrawColor = $pdfcolor;
 3766                 $this->strokecolor = $spotcolor;
 3767                 break;
 3768             }
 3769             case 'fill': {
 3770                 $pdfcolor .= sprintf('cs %F scn', $tint);
 3771                 $this->FillColor = $pdfcolor;
 3772                 $this->bgcolor = $spotcolor;
 3773                 break;
 3774             }
 3775             case 'text': {
 3776                 $pdfcolor .= sprintf('cs %F scn', $tint);
 3777                 $this->TextColor = $pdfcolor;
 3778                 $this->fgcolor = $spotcolor;
 3779                 break;
 3780             }
 3781         }
 3782         $this->ColorFlag = ($this->FillColor != $this->TextColor);
 3783         if ($this->state == 2) {
 3784             $this->_out($pdfcolor);
 3785         }
 3786         if ($this->inxobj) {
 3787             // we are inside an XObject template
 3788             $this->xobjects[$this->xobjid]['spot_colors'][$name] = $this->spot_colors[$name];
 3789         }
 3790         return $pdfcolor;
 3791     }
 3792 
 3793     /**
 3794      * Defines the spot color used for all drawing operations (lines, rectangles and cell borders).
 3795      * @param $name (string) Name of the spot color.
 3796      * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default).
 3797      * @public
 3798      * @since 4.0.024 (2008-09-12)
 3799      * @see AddSpotColor(), SetFillSpotColor(), SetTextSpotColor()
 3800      */
 3801     public function SetDrawSpotColor($name, $tint=100) {
 3802         $this->setSpotColor('draw', $name, $tint);
 3803     }
 3804 
 3805     /**
 3806      * Defines the spot color used for all filling operations (filled rectangles and cell backgrounds).
 3807      * @param $name (string) Name of the spot color.
 3808      * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default).
 3809      * @public
 3810      * @since 4.0.024 (2008-09-12)
 3811      * @see AddSpotColor(), SetDrawSpotColor(), SetTextSpotColor()
 3812      */
 3813     public function SetFillSpotColor($name, $tint=100) {
 3814         $this->setSpotColor('fill', $name, $tint);
 3815     }
 3816 
 3817     /**
 3818      * Defines the spot color used for text.
 3819      * @param $name (string) Name of the spot color.
 3820      * @param $tint (int) Intensity of the color (from 0 to 100 ; 100 = full intensity by default).
 3821      * @public
 3822      * @since 4.0.024 (2008-09-12)
 3823      * @see AddSpotColor(), SetDrawSpotColor(), SetFillSpotColor()
 3824      */
 3825     public function SetTextSpotColor($name, $tint=100) {
 3826         $this->setSpotColor('text', $name, $tint);
 3827     }
 3828 
 3829     /**
 3830      * Set the color array for the specified type ('draw', 'fill', 'text').
 3831      * It can be expressed in RGB, CMYK or GRAY SCALE components.
 3832      * The method can be called before the first page is created and the value is retained from page to page.
 3833      * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text').
 3834      * @param $color (array) Array of colors (1=gray, 3=RGB, 4=CMYK or 5=spotcolor=CMYK+name values).
 3835      * @param $ret (boolean) If true do not send the PDF command.
 3836      * @return (string) The PDF command or empty string.
 3837      * @public
 3838      * @since 3.1.000 (2008-06-11)
 3839      */
 3840     public function setColorArray($type, $color, $ret=false) {
 3841         if (is_array($color)) {
 3842             $color = array_values($color);
 3843             // component: grey, RGB red or CMYK cyan
 3844             $c = isset($color[0]) ? $color[0] : -1;
 3845             // component: RGB green or CMYK magenta
 3846             $m = isset($color[1]) ? $color[1] : -1;
 3847             // component: RGB blue or CMYK yellow
 3848             $y = isset($color[2]) ? $color[2] : -1;
 3849             // component: CMYK black
 3850             $k = isset($color[3]) ? $color[3] : -1;
 3851             // color name
 3852             $name = isset($color[4]) ? $color[4] : '';
 3853             if ($c >= 0) {
 3854                 return $this->setColor($type, $c, $m, $y, $k, $ret, $name);
 3855             }
 3856         }
 3857         return '';
 3858     }
 3859 
 3860     /**
 3861      * Defines the color used for all drawing operations (lines, rectangles and cell borders).
 3862      * It can be expressed in RGB, CMYK or GRAY SCALE components.
 3863      * The method can be called before the first page is created and the value is retained from page to page.
 3864      * @param $color (array) Array of colors (1, 3 or 4 values).
 3865      * @param $ret (boolean) If true do not send the PDF command.
 3866      * @return string the PDF command
 3867      * @public
 3868      * @since 3.1.000 (2008-06-11)
 3869      * @see SetDrawColor()
 3870      */
 3871     public function SetDrawColorArray($color, $ret=false) {
 3872         return $this->setColorArray('draw', $color, $ret);
 3873     }
 3874 
 3875     /**
 3876      * Defines the color used for all filling operations (filled rectangles and cell backgrounds).
 3877      * It can be expressed in RGB, CMYK or GRAY SCALE components.
 3878      * The method can be called before the first page is created and the value is retained from page to page.
 3879      * @param $color (array) Array of colors (1, 3 or 4 values).
 3880      * @param $ret (boolean) If true do not send the PDF command.
 3881      * @public
 3882      * @since 3.1.000 (2008-6-11)
 3883      * @see SetFillColor()
 3884      */
 3885     public function SetFillColorArray($color, $ret=false) {
 3886         return $this->setColorArray('fill', $color, $ret);
 3887     }
 3888 
 3889     /**
 3890      * Defines the color used for text. It can be expressed in RGB components or gray scale.
 3891      * The method can be called before the first page is created and the value is retained from page to page.
 3892      * @param $color (array) Array of colors (1, 3 or 4 values).
 3893      * @param $ret (boolean) If true do not send the PDF command.
 3894      * @public
 3895      * @since 3.1.000 (2008-6-11)
 3896      * @see SetFillColor()
 3897      */
 3898     public function SetTextColorArray($color, $ret=false) {
 3899         return $this->setColorArray('text', $color, $ret);
 3900     }
 3901 
 3902     /**
 3903      * Defines the color used by the specified type ('draw', 'fill', 'text').
 3904      * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text').
 3905      * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100).
 3906      * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100).
 3907      * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100).
 3908      * @param $col4 (float) KEY (BLACK) color for CMYK (0-100).
 3909      * @param $ret (boolean) If true do not send the command.
 3910      * @param $name (string) spot color name (if any)
 3911      * @return (string) The PDF command or empty string.
 3912      * @public
 3913      * @since 5.9.125 (2011-10-03)
 3914      */
 3915     public function setColor($type, $col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
 3916         // set default values
 3917         if (!is_numeric($col1)) {
 3918             $col1 = 0;
 3919         }
 3920         if (!is_numeric($col2)) {
 3921             $col2 = -1;
 3922         }
 3923         if (!is_numeric($col3)) {
 3924             $col3 = -1;
 3925         }
 3926         if (!is_numeric($col4)) {
 3927             $col4 = -1;
 3928         }
 3929         // set color by case
 3930         $suffix = '';
 3931         if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
 3932             // Grey scale
 3933             $col1 = max(0, min(255, $col1));
 3934             $intcolor = array('G' => $col1);
 3935             $pdfcolor = sprintf('%F ', ($col1 / 255));
 3936             $suffix = 'g';
 3937         } elseif ($col4 == -1) {
 3938             // RGB
 3939             $col1 = max(0, min(255, $col1));
 3940             $col2 = max(0, min(255, $col2));
 3941             $col3 = max(0, min(255, $col3));
 3942             $intcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3);
 3943             $pdfcolor = sprintf('%F %F %F ', ($col1 / 255), ($col2 / 255), ($col3 / 255));
 3944             $suffix = 'rg';
 3945         } else {
 3946             $col1 = max(0, min(100, $col1));
 3947             $col2 = max(0, min(100, $col2));
 3948             $col3 = max(0, min(100, $col3));
 3949             $col4 = max(0, min(100, $col4));
 3950             if (empty($name)) {
 3951                 // CMYK
 3952                 $intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4);
 3953                 $pdfcolor = sprintf('%F %F %F %F ', ($col1 / 100), ($col2 / 100), ($col3 / 100), ($col4 / 100));
 3954                 $suffix = 'k';
 3955             } else {
 3956                 // SPOT COLOR
 3957                 $intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4, 'name' => $name);
 3958                 $this->AddSpotColor($name, $col1, $col2, $col3, $col4);
 3959                 $pdfcolor = $this->setSpotColor($type, $name, 100);
 3960             }
 3961         }
 3962         switch ($type) {
 3963             case 'draw': {
 3964                 $pdfcolor .= strtoupper($suffix);
 3965                 $this->DrawColor = $pdfcolor;
 3966                 $this->strokecolor = $intcolor;
 3967                 break;
 3968             }
 3969             case 'fill': {
 3970                 $pdfcolor .= $suffix;
 3971                 $this->FillColor = $pdfcolor;
 3972                 $this->bgcolor = $intcolor;
 3973                 break;
 3974             }
 3975             case 'text': {
 3976                 $pdfcolor .= $suffix;
 3977                 $this->TextColor = $pdfcolor;
 3978                 $this->fgcolor = $intcolor;
 3979                 break;
 3980             }
 3981         }
 3982         $this->ColorFlag = ($this->FillColor != $this->TextColor);
 3983         if (($type != 'text') AND ($this->state == 2)) {
 3984             if (!$ret) {
 3985                 $this->_out($pdfcolor);
 3986             }
 3987             return $pdfcolor;
 3988         }
 3989         return '';
 3990     }
 3991 
 3992     /**
 3993      * 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.
 3994      * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100).
 3995      * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100).
 3996      * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100).
 3997      * @param $col4 (float) KEY (BLACK) color for CMYK (0-100).
 3998      * @param $ret (boolean) If true do not send the command.
 3999      * @param $name (string) spot color name (if any)
 4000      * @return string the PDF command
 4001      * @public
 4002      * @since 1.3
 4003      * @see SetDrawColorArray(), SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell()
 4004      */
 4005     public function SetDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
 4006         return $this->setColor('draw', $col1, $col2, $col3, $col4, $ret, $name);
 4007     }
 4008 
 4009     /**
 4010      * 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.
 4011      * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100).
 4012      * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100).
 4013      * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100).
 4014      * @param $col4 (float) KEY (BLACK) color for CMYK (0-100).
 4015      * @param $ret (boolean) If true do not send the command.
 4016      * @param $name (string) Spot color name (if any).
 4017      * @return (string) The PDF command.
 4018      * @public
 4019      * @since 1.3
 4020      * @see SetFillColorArray(), SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell()
 4021      */
 4022     public function SetFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
 4023         return $this->setColor('fill', $col1, $col2, $col3, $col4, $ret, $name);
 4024     }
 4025 
 4026     /**
 4027      * 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.
 4028      * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100).
 4029      * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100).
 4030      * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100).
 4031      * @param $col4 (float) KEY (BLACK) color for CMYK (0-100).
 4032      * @param $ret (boolean) If true do not send the command.
 4033      * @param $name (string) Spot color name (if any).
 4034      * @return (string) Empty string.
 4035      * @public
 4036      * @since 1.3
 4037      * @see SetTextColorArray(), SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell()
 4038      */
 4039     public function SetTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
 4040         return $this->setColor('text', $col1, $col2, $col3, $col4, $ret, $name);
 4041     }
 4042 
 4043     /**
 4044      * Returns the length of a string in user unit. A font must be selected.<br>
 4045      * @param $s (string) The string whose length is to be computed
 4046      * @param $fontname (string) 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.
 4047      * @param $fontstyle (string) 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-through</li><li>O: overline</li></ul> or any combination. The default value is regular.
 4048      * @param $fontsize (float) Font size in points. The default value is the current size.
 4049      * @param $getarray (boolean) if true returns an array of characters widths, if false returns the total length.
 4050      * @return mixed int total string length or array of characted widths
 4051      * @author Nicola Asuni
 4052      * @public
 4053      * @since 1.2
 4054      */
 4055     public function GetStringWidth($s, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) {
 4056         return $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont), $s, $this->tmprtl, $this->isunicode, $this->CurrentFont), $fontname, $fontstyle, $fontsize, $getarray);
 4057     }
 4058 
 4059     /**
 4060      * Returns the string length of an array of chars in user unit or an array of characters widths. A font must be selected.<br>
 4061      * @param $sa (string) The array of chars whose total length is to be computed
 4062      * @param $fontname (string) 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.
 4063      * @param $fontstyle (string) 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 through</li><li>O: overline</li></ul> or any combination. The default value is regular.
 4064      * @param $fontsize (float) Font size in points. The default value is the current size.
 4065      * @param $getarray (boolean) if true returns an array of characters widths, if false returns the total length.
 4066      * @return mixed int total string length or array of characted widths
 4067      * @author Nicola Asuni
 4068      * @public
 4069      * @since 2.4.000 (2008-03-06)
 4070      */
 4071     public function GetArrStringWidth($sa, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) {
 4072         // store current values
 4073         if (!TCPDF_STATIC::empty_string($fontname)) {
 4074             $prev_FontFamily = $this->FontFamily;
 4075             $prev_FontStyle = $this->FontStyle;
 4076             $prev_FontSizePt = $this->FontSizePt;
 4077             $this->SetFont($fontname, $fontstyle, $fontsize, '', 'default', false);
 4078         }
 4079         // convert UTF-8 array to Latin1 if required
 4080         if ($this->isunicode AND (!$this->isUnicodeFont())) {
 4081             $sa = TCPDF_FONTS::UTF8ArrToLatin1Arr($sa);
 4082         }
 4083         $w = 0; // total width
 4084         $wa = array(); // array of characters widths
 4085         foreach ($sa as $ck => $char) {
 4086             // character width
 4087             $cw = $this->GetCharWidth($char, isset($sa[($ck + 1)]));
 4088             $wa[] = $cw;
 4089             $w += $cw;
 4090         }
 4091         // restore previous values
 4092         if (!TCPDF_STATIC::empty_string($fontname)) {
 4093             $this->SetFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt, '', 'default', false);
 4094         }
 4095         if ($getarray) {
 4096             return $wa;
 4097         }
 4098         return $w;
 4099     }
 4100 
 4101     /**
 4102      * Returns the length of the char in user unit for the current font considering current stretching and spacing (tracking).
 4103      * @param $char (int) The char code whose length is to be returned
 4104      * @param $notlast (boolean) If false ignore the font-spacing.
 4105      * @return float char width
 4106      * @author Nicola Asuni
 4107      * @public
 4108      * @since 2.4.000 (2008-03-06)
 4109      */
 4110     public function GetCharWidth($char, $notlast=true) {
 4111         // get raw width
 4112         $chw = $this->getRawCharWidth($char);
 4113         if (($this->font_spacing < 0) OR (($this->font_spacing > 0) AND $notlast)) {
 4114             // increase/decrease font spacing
 4115             $chw += $this->font_spacing;
 4116         }
 4117         if ($this->font_stretching != 100) {
 4118             // fixed stretching mode
 4119             $chw *= ($this->font_stretching / 100);
 4120         }
 4121         return $chw;
 4122     }
 4123 
 4124     /**
 4125      * Returns the length of the char in user unit for the current font.
 4126      * @param $char (int) The char code whose length is to be returned
 4127      * @return float char width
 4128      * @author Nicola Asuni
 4129      * @public
 4130      * @since 5.9.000 (2010-09-28)
 4131      */
 4132     public function getRawCharWidth($char) {
 4133         if ($char == 173) {
 4134             // SHY character will not be printed
 4135             return (0);
 4136         }
 4137         if (isset($this->CurrentFont['cw'][$char])) {
 4138             $w = $this->CurrentFont['cw'][$char];
 4139         } elseif (isset($this->CurrentFont['dw'])) {
 4140             // default width
 4141             $w = $this->CurrentFont['dw'];
 4142         } elseif (isset($this->CurrentFont['cw'][32])) {
 4143             // default width
 4144             $w = $this->CurrentFont['cw'][32];
 4145         } else {
 4146             $w = 600;
 4147         }
 4148         return $this->getAbsFontMeasure($w);
 4149     }
 4150 
 4151     /**
 4152      * Returns the numbero of characters in a string.
 4153      * @param $s (string) The input string.
 4154      * @return int number of characters
 4155      * @public
 4156      * @since 2.0.0001 (2008-01-07)
 4157      */
 4158     public function GetNumChars($s) {
 4159         if ($this->isUnicodeFont()) {
 4160             return count(TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont));
 4161         }
 4162         return strlen($s);
 4163     }
 4164 
 4165     /**
 4166      * Fill the list of available fonts ($this->fontlist).
 4167      * @protected
 4168      * @since 4.0.013 (2008-07-28)
 4169      */
 4170     protected function getFontsList() {
 4171         if (($fontsdir = opendir(TCPDF_FONTS::_getfontpath())) !== false) {
 4172             while (($file = readdir($fontsdir)) !== false) {
 4173                 if (substr($file, -4) == '.php') {
 4174                     array_push($this->fontlist, strtolower(basename($file, '.php')));
 4175                 }
 4176             }
 4177             closedir($fontsdir);
 4178         }
 4179     }
 4180 
 4181     /**
 4182      * Imports a TrueType, Type1, core, or CID0 font and makes it available.
 4183      * It is necessary to generate a font definition file first (read /fonts/utils/README.TXT).
 4184      * 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.
 4185      * @param $family (string) Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font.
 4186      * @param $style (string) 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>
 4187      * @param $fontfile (string) The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
 4188      * @return array containing the font data, or false in case of error.
 4189      * @param $subset (mixed) if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font.
 4190      * @public
 4191      * @since 1.5
 4192      * @see SetFont(), setFontSubsetting()
 4193      */
 4194     public function AddFont($family, $style='', $fontfile='', $subset='default') {
 4195         if ($subset === 'default') {
 4196             $subset = $this->font_subsetting;
 4197         }
 4198         if ($this->pdfa_mode) {
 4199             $subset = false;
 4200         }
 4201         if (TCPDF_STATIC::empty_string($family)) {
 4202             if (!TCPDF_STATIC::empty_string($this->FontFamily)) {
 4203                 $family = $this->FontFamily;
 4204             } else {
 4205                 $this->Error('Empty font family');
 4206             }
 4207         }
 4208         // move embedded styles on $style
 4209         if (substr($family, -1) == 'I') {
 4210             $style .= 'I';
 4211             $family = substr($family, 0, -1);
 4212         }
 4213         if (substr($family, -1) == 'B') {
 4214             $style .= 'B';
 4215             $family = substr($family, 0, -1);
 4216         }
 4217         // normalize family name
 4218         $family = strtolower($family);
 4219         if ((!$this->isunicode) AND ($family == 'arial')) {
 4220             $family = 'helvetica';
 4221         }
 4222         if (($family == 'symbol') OR ($family == 'zapfdingbats')) {
 4223             $style = '';
 4224         }
 4225         if ($this->pdfa_mode AND (isset($this->CoreFonts[$family]))) {
 4226             // all fonts must be embedded
 4227             $family = 'pdfa'.$family;
 4228         }
 4229         $tempstyle = strtoupper($style);
 4230         $style = '';
 4231         // underline
 4232         if (strpos($tempstyle, 'U') !== false) {
 4233             $this->underline = true;
 4234         } else {
 4235             $this->underline = false;
 4236         }
 4237         // line-through (deleted)
 4238         if (strpos($tempstyle, 'D') !== false) {
 4239             $this->linethrough = true;
 4240         } else {
 4241             $this->linethrough = false;
 4242         }
 4243         // overline
 4244         if (strpos($tempstyle, 'O') !== false) {
 4245             $this->overline = true;
 4246         } else {
 4247             $this->overline = false;
 4248         }
 4249         // bold
 4250         if (strpos($tempstyle, 'B') !== false) {
 4251             $style .= 'B';
 4252         }
 4253         // oblique
 4254         if (strpos($tempstyle, 'I') !== false) {
 4255             $style .= 'I';
 4256         }
 4257         $bistyle = $style;
 4258         $fontkey = $family.$style;
 4259         $font_style = $style.($this->underline ? 'U' : '').($this->linethrough ? 'D' : '').($this->overline ? 'O' : '');
 4260         $fontdata = array('fontkey' => $fontkey, 'family' => $family, 'style' => $font_style);
 4261         // check if the font has been already added
 4262         $fb = $this->getFontBuffer($fontkey);
 4263         if ($fb !== false) {
 4264             if ($this->inxobj) {
 4265                 // we are inside an XObject template
 4266                 $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $fb['i'];
 4267             }
 4268             return $fontdata;
 4269         }
 4270         // get specified font directory (if any)
 4271         $fontdir = false;
 4272         if (!TCPDF_STATIC::empty_string($fontfile)) {
 4273             $fontdir = dirname($fontfile);
 4274             if (TCPDF_STATIC::empty_string($fontdir) OR ($fontdir == '.')) {
 4275                 $fontdir = '';
 4276             } else {
 4277                 $fontdir .= '/';
 4278             }
 4279         }
 4280         // true when the font style variation is missing
 4281         $missing_style = false;
 4282         // search and include font file
 4283         if (TCPDF_STATIC::empty_string($fontfile) OR (!@TCPDF_STATIC::file_exists($fontfile))) {
 4284             // build a standard filenames for specified font
 4285             $tmp_fontfile = str_replace(' ', '', $family).strtolower($style).'.php';
 4286             $fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir);
 4287             if (TCPDF_STATIC::empty_string($fontfile)) {
 4288                 $missing_style = true;
 4289                 // try to remove the style part
 4290                 $tmp_fontfile = str_replace(' ', '', $family).'.php';
 4291                 $fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir);
 4292             }
 4293         }
 4294         // include font file
 4295         if (!TCPDF_STATIC::empty_string($fontfile) AND (@TCPDF_STATIC::file_exists($fontfile))) {
 4296             include($fontfile);
 4297         } else {
 4298             $this->Error('Could not include font definition file: '.$family.'');
 4299         }
 4300         // check font parameters
 4301         if ((!isset($type)) OR (!isset($cw))) {
 4302             $this->Error('The font definition file has a bad format: '.$fontfile.'');
 4303         }
 4304         // SET default parameters
 4305         if (!isset($file) OR TCPDF_STATIC::empty_string($file)) {
 4306             $file = '';
 4307         }
 4308         if (!isset($enc) OR TCPDF_STATIC::empty_string($enc)) {
 4309             $enc = '';
 4310         }
 4311         if (!isset($cidinfo) OR TCPDF_STATIC::empty_string($cidinfo)) {
 4312             $cidinfo = array('Registry'=>'Adobe', 'Ordering'=>'Identity', 'Supplement'=>0);
 4313             $cidinfo['uni2cid'] = array();
 4314         }
 4315         if (!isset($ctg) OR TCPDF_STATIC::empty_string($ctg)) {
 4316             $ctg = '';
 4317         }
 4318         if (!isset($desc) OR TCPDF_STATIC::empty_string($desc)) {
 4319             $desc = array();
 4320         }
 4321         if (!isset($up) OR TCPDF_STATIC::empty_string($up)) {
 4322             $up = -100;
 4323         }
 4324         if (!isset($ut) OR TCPDF_STATIC::empty_string($ut)) {
 4325             $ut = 50;
 4326         }
 4327         if (!isset($cw) OR TCPDF_STATIC::empty_string($cw)) {
 4328             $cw = array();
 4329         }
 4330         if (!isset($dw) OR TCPDF_STATIC::empty_string($dw)) {
 4331             // set default width
 4332             if (isset($desc['MissingWidth']) AND ($desc['MissingWidth'] > 0)) {
 4333                 $dw = $desc['MissingWidth'];
 4334             } elseif (isset($cw[32])) {
 4335                 $dw = $cw[32];
 4336             } else {
 4337                 $dw = 600;
 4338             }
 4339         }
 4340         ++$this->numfonts;
 4341         if ($type == 'core') {
 4342             $name = $this->CoreFonts[$fontkey];
 4343             $subset = false;
 4344         } elseif (($type == 'TrueType') OR ($type == 'Type1')) {
 4345             $subset = false;
 4346         } elseif ($type == 'TrueTypeUnicode') {
 4347             $enc = 'Identity-H';
 4348         } elseif ($type == 'cidfont0') {
 4349             if ($this->pdfa_mode) {
 4350                 $this->Error('All fonts must be embedded in PDF/A mode!');
 4351             }
 4352         } else {
 4353             $this->Error('Unknow font type: '.$type.'');
 4354         }
 4355         // set name if unset
 4356         if (!isset($name) OR empty($name)) {
 4357             $name = $fontkey;
 4358         }
 4359         // create artificial font style variations if missing (only works with non-embedded fonts)
 4360         if (($type != 'core') AND $missing_style) {
 4361             // style variations
 4362             $styles = array('' => '', 'B' => ',Bold', 'I' => ',Italic', 'BI' => ',BoldItalic');
 4363             $name .= $styles[$bistyle];
 4364             // artificial bold
 4365             if (strpos($bistyle, 'B') !== false) {
 4366                 if (isset($desc['StemV'])) {
 4367                     // from normal to bold
 4368                     $desc['StemV'] = round($desc['StemV'] * 1.75);
 4369                 } else {
 4370                     // bold
 4371                     $desc['StemV'] = 123;
 4372                 }
 4373             }
 4374             // artificial italic
 4375             if (strpos($bistyle, 'I') !== false) {
 4376                 if (isset($desc['ItalicAngle'])) {
 4377                     $desc['ItalicAngle'] -= 11;
 4378                 } else {
 4379                     $desc['ItalicAngle'] = -11;
 4380                 }
 4381                 if (isset($desc['Flags'])) {
 4382                     $desc['Flags'] |= 64; //bit 7
 4383                 } else {
 4384                     $desc['Flags'] = 64;
 4385                 }
 4386             }
 4387         }
 4388         // check if the array of characters bounding boxes is defined
 4389         if (!isset($cbbox)) {
 4390             $cbbox = array();
 4391         }
 4392         // initialize subsetchars
 4393         $subsetchars = array_fill(0, 255, true);
 4394         $this->setFontBuffer($fontkey, array('fontkey' => $fontkey, 'i' => $this->numfonts, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'cbbox' => $cbbox, 'dw' => $dw, 'enc' => $enc, 'cidinfo' => $cidinfo, 'file' => $file, 'ctg' => $ctg, 'subset' => $subset, 'subsetchars' => $subsetchars));
 4395         if ($this->inxobj) {
 4396             // we are inside an XObject template
 4397             $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $this->numfonts;
 4398         }
 4399         if (isset($diff) AND (!empty($diff))) {
 4400             //Search existing encodings
 4401             $d = 0;
 4402             $nb = count($this->diffs);
 4403             for ($i=1; $i <= $nb; ++$i) {
 4404                 if ($this->diffs[$i] == $diff) {
 4405                     $d = $i;
 4406                     break;
 4407                 }
 4408             }
 4409             if ($d == 0) {
 4410                 $d = $nb + 1;
 4411                 $this->diffs[$d] = $diff;
 4412             }
 4413             $this->setFontSubBuffer($fontkey, 'diff', $d);
 4414         }
 4415         if (!TCPDF_STATIC::empty_string($file)) {
 4416             if (!isset($this->FontFiles[$file])) {
 4417                 if ((strcasecmp($type,'TrueType') == 0) OR (strcasecmp($type, 'TrueTypeUnicode') == 0)) {
 4418                     $this->FontFiles[$file] = array('length1' => $originalsize, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey));
 4419                 } elseif ($type != 'core') {
 4420                     $this->FontFiles[$file] = array('length1' => $size1, 'length2' => $size2, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey));
 4421                 }
 4422             } else {
 4423                 // update fontkeys that are sharing this font file
 4424                 $this->FontFiles[$file]['subset'] = ($this->FontFiles[$file]['subset'] AND $subset);
 4425                 if (!in_array($fontkey, $this->FontFiles[$file]['fontkeys'])) {
 4426                     $this->FontFiles[$file]['fontkeys'][] = $fontkey;
 4427                 }
 4428             }
 4429         }
 4430         return $fontdata;
 4431     }
 4432 
 4433     /**
 4434      * Sets the font used to print character strings.
 4435      * The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe).
 4436      * The method can be called before the first page is created and the font is retained from page to page.
 4437      * If you just wish to change the current font size, it is simpler to call SetFontSize().
 4438      * 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 />
 4439      * @param $family (string) 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.
 4440      * @param $style (string) 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 through</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.
 4441      * @param $size (float) 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
 4442      * @param $fontfile (string) The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
 4443      * @param $subset (mixed) if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font.
 4444      * @param $out (boolean) if true output the font size command, otherwise only set the font properties.
 4445      * @author Nicola Asuni
 4446      * @public
 4447      * @since 1.0
 4448      * @see AddFont(), SetFontSize()
 4449      */
 4450     public function SetFont($family, $style='', $size=null, $fontfile='', $subset='default', $out=true) {
 4451         //Select a font; size given in points
 4452         if ($size === null) {
 4453             $size = $this->FontSizePt;
 4454         }
 4455         if ($size < 0) {
 4456             $size = 0;
 4457         }
 4458         // try to add font (if not already added)
 4459         $fontdata = $this->AddFont($family, $style, $fontfile, $subset);
 4460         $this->FontFamily = $fontdata['family'];
 4461         $this->FontStyle = $fontdata['style'];
 4462         if (isset($this->CurrentFont['fontkey']) AND isset($this->CurrentFont['subsetchars'])) {
 4463             // save subset chars of the previous font
 4464             $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']);
 4465         }
 4466         $this->CurrentFont = $this->getFontBuffer($fontdata['fontkey']);
 4467         $this->SetFontSize($size, $out);
 4468     }
 4469 
 4470     /**
 4471      * Defines the size of the current font.
 4472      * @param $size (float) The font size in points.
 4473      * @param $out (boolean) if true output the font size command, otherwise only set the font properties.
 4474      * @public
 4475      * @since 1.0
 4476      * @see SetFont()
 4477      */
 4478     public function SetFontSize($size, $out=true) {
 4479         $size = (float)$size;
 4480         // font size in points
 4481         $this->FontSizePt = $size;
 4482         // font size in user units
 4483         $this->FontSize = $size / $this->k;
 4484         // calculate some font metrics
 4485         if (isset($this->CurrentFont['desc']['FontBBox'])) {
 4486             $bbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1));
 4487             $font_height = ((intval($bbox[3]) - intval($bbox[1])) * $size / 1000);
 4488         } else {
 4489             $font_height = $size * 1.219;
 4490         }
 4491         if (isset($this->CurrentFont['desc']['Ascent']) AND ($this->CurrentFont['desc']['Ascent'] > 0)) {
 4492             $font_ascent = ($this->CurrentFont['desc']['Ascent'] * $size / 1000);
 4493         }
 4494         if (isset($this->CurrentFont['desc']['Descent']) AND ($this->CurrentFont['desc']['Descent'] <= 0)) {
 4495             $font_descent = (- $this->CurrentFont['desc']['Descent'] * $size / 1000);
 4496         }
 4497         if (!isset($font_ascent) AND !isset($font_descent)) {
 4498             // core font
 4499             $font_ascent = 0.76 * $font_height;
 4500             $font_descent = $font_height - $font_ascent;
 4501         } elseif (!isset($font_descent)) {
 4502             $font_descent = $font_height - $font_ascent;
 4503         } elseif (!isset($font_ascent)) {
 4504             $font_ascent = $font_height - $font_descent;
 4505         }
 4506         $this->FontAscent = ($font_ascent / $this->k);
 4507         $this->FontDescent = ($font_descent / $this->k);
 4508         if ($out AND ($this->page > 0) AND (isset($this->CurrentFont['i'])) AND ($this->state == 2)) {
 4509             $this->_out(sprintf('BT /F%d %F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
 4510         }
 4511     }
 4512 
 4513     /**
 4514      * Returns the bounding box of the current font in user units.
 4515      * @return array
 4516      * @public
 4517      * @since 5.9.152 (2012-03-23)
 4518      */
 4519     public function getFontBBox() {
 4520         $fbbox = array();
 4521         if (isset($this->CurrentFont['desc']['FontBBox'])) {
 4522             $tmpbbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1));
 4523             $fbbox = array_map(array($this,'getAbsFontMeasure'), $tmpbbox);
 4524         } else {
 4525             // Find max width
 4526             if (isset($this->CurrentFont['desc']['MaxWidth'])) {
 4527                 $maxw = $this->getAbsFontMeasure(intval($this->CurrentFont['desc']['MaxWidth']));
 4528             } else {
 4529                 $maxw = 0;
 4530                 if (isset($this->CurrentFont['desc']['MissingWidth'])) {
 4531                     $maxw = max($maxw, $this->CurrentFont['desc']['MissingWidth']);
 4532                 }
 4533                 if (isset($this->CurrentFont['desc']['AvgWidth'])) {
 4534                     $maxw = max($maxw, $this->CurrentFont['desc']['AvgWidth']);
 4535                 }
 4536                 if (isset($this->CurrentFont['dw'])) {
 4537                     $maxw = max($maxw, $this->CurrentFont['dw']);
 4538                 }
 4539                 foreach ($this->CurrentFont['cw'] as $char => $w) {
 4540                     $maxw = max($maxw, $w);
 4541                 }
 4542                 if ($maxw == 0) {
 4543                     $maxw = 600;
 4544                 }
 4545                 $maxw = $this->getAbsFontMeasure($maxw);
 4546             }
 4547             $fbbox = array(0, (0 - $this->FontDescent), $maxw, $this->FontAscent);
 4548         }
 4549         return $fbbox;
 4550     }
 4551 
 4552     /**
 4553      * Convert a relative font measure into absolute value.
 4554      * @param $s (int) Font measure.
 4555      * @return float Absolute measure.
 4556      * @since 5.9.186 (2012-09-13)
 4557      */
 4558     public function getAbsFontMeasure($s) {
 4559         return ($s * $this->FontSize / 1000);
 4560     }
 4561 
 4562     /**
 4563      * Returns the glyph bounding box of the specified character in the current font in user units.
 4564      * @param $char (int) Input character code.
 4565      * @return mixed array(xMin, yMin, xMax, yMax) or FALSE if not defined.
 4566      * @since 5.9.186 (2012-09-13)
 4567      */
 4568     public function getCharBBox($char) {
 4569         $c = intval($char);
 4570         if (isset($this->CurrentFont['cw'][$c])) {
 4571             // glyph is defined ... use zero width & height for glyphs without outlines
 4572             $result = array(0,0,0,0);
 4573             if (isset($this->CurrentFont['cbbox'][$c])) {
 4574                 $result = $this->CurrentFont['cbbox'][$c];
 4575             }
 4576             return array_map(array($this,'getAbsFontMeasure'), $result);
 4577         }
 4578         return false;
 4579     }
 4580 
 4581     /**
 4582      * Return the font descent value
 4583      * @param $font (string) font name
 4584      * @param $style (string) font style
 4585      * @param $size (float) The size (in points)
 4586      * @return int font descent
 4587      * @public
 4588      * @author Nicola Asuni
 4589      * @since 4.9.003 (2010-03-30)
 4590      */
 4591     public function getFontDescent($font, $style='', $size=0) {
 4592         $fontdata = $this->AddFont($font, $style);
 4593         $fontinfo = $this->getFontBuffer($fontdata['fontkey']);
 4594         if (isset($fontinfo['desc']['Descent']) AND ($fontinfo['desc']['Descent'] <= 0)) {
 4595             $descent = (- $fontinfo['desc']['Descent'] * $size / 1000);
 4596         } else {
 4597             $descent = (1.219 * 0.24 * $size);
 4598         }
 4599         return ($descent / $this->k);
 4600     }
 4601 
 4602     /**
 4603      * Return the font ascent value.
 4604      * @param $font (string) font name
 4605      * @param $style (string) font style
 4606      * @param $size (float) The size (in points)
 4607      * @return int font ascent
 4608      * @public
 4609      * @author Nicola Asuni
 4610      * @since 4.9.003 (2010-03-30)
 4611      */
 4612     public function getFontAscent($font, $style='', $size=0) {
 4613         $fontdata = $this->AddFont($font, $style);
 4614         $fontinfo = $this->getFontBuffer($fontdata['fontkey']);
 4615         if (isset($fontinfo['desc']['Ascent']) AND ($fontinfo['desc']['Ascent'] > 0)) {
 4616             $ascent = ($fontinfo['desc']['Ascent'] * $size / 1000);
 4617         } else {
 4618             $ascent = 1.219 * 0.76 * $size;
 4619         }
 4620         return ($ascent / $this->k);
 4621     }
 4622 
 4623     /**
 4624      * Return true in the character is present in the specified font.
 4625      * @param $char (mixed) Character to check (integer value or string)
 4626      * @param $font (string) Font name (family name).
 4627      * @param $style (string) Font style.
 4628      * @return (boolean) true if the char is defined, false otherwise.
 4629      * @public
 4630      * @since 5.9.153 (2012-03-28)
 4631      */
 4632     public function isCharDefined($char, $font='', $style='') {
 4633         if (is_string($char)) {
 4634             // get character code
 4635             $char = TCPDF_FONTS::UTF8StringToArray($char, $this->isunicode, $this->CurrentFont);
 4636             $char = $char[0];
 4637         }
 4638         if (TCPDF_STATIC::empty_string($font)) {
 4639             if (TCPDF_STATIC::empty_string($style)) {
 4640                 return (isset($this->CurrentFont['cw'][intval($char)]));
 4641             }
 4642             $font = $this->FontFamily;
 4643         }
 4644         $fontdata = $this->AddFont($font, $style);
 4645         $fontinfo = $this->getFontBuffer($fontdata['fontkey']);
 4646         return (isset($fontinfo['cw'][intval($char)]));
 4647     }
 4648 
 4649     /**
 4650      * Replace missing font characters on selected font with specified substitutions.
 4651      * @param $text (string) Text to process.
 4652      * @param $font (string) Font name (family name).
 4653      * @param $style (string) Font style.
 4654      * @param $subs (array) Array of possible character substitutions. The key is the character to check (integer value) and the value is a single intege value or an array of possible substitutes.
 4655      * @return (string) Processed text.
 4656      * @public
 4657      * @since 5.9.153 (2012-03-28)
 4658      */
 4659     public function replaceMissingChars($text, $font='', $style='', $subs=array()) {
 4660         if (empty($subs)) {
 4661             return $text;
 4662         }
 4663         if (TCPDF_STATIC::empty_string($font)) {
 4664             $font = $this->FontFamily;
 4665         }
 4666         $fontdata = $this->AddFont($font, $style);
 4667         $fontinfo = $this->getFontBuffer($fontdata['fontkey']);
 4668         $uniarr = TCPDF_FONTS::UTF8StringToArray($text, $this->isunicode, $this->CurrentFont);
 4669         foreach ($uniarr as $k => $chr) {
 4670             if (!isset($fontinfo['cw'][$chr])) {
 4671                 // this character is missing on the selected font
 4672                 if (isset($subs[$chr])) {
 4673                     // we have available substitutions
 4674                     if (is_array($subs[$chr])) {
 4675                         foreach($subs[$chr] as $s) {
 4676                             if (isset($fontinfo['cw'][$s])) {
 4677                                 $uniarr[$k] = $s;
 4678                                 break;
 4679                             }
 4680                         }
 4681                     } elseif (isset($fontinfo['cw'][$subs[$chr]])) {
 4682                         $uniarr[$k] = $subs[$chr];
 4683                     }
 4684                 }
 4685             }
 4686         }
 4687         return TCPDF_FONTS::UniArrSubString(TCPDF_FONTS::UTF8ArrayToUniArray($uniarr, $this->isunicode));
 4688     }
 4689 
 4690     /**
 4691      * Defines the default monospaced font.
 4692      * @param $font (string) Font name.
 4693      * @public
 4694      * @since 4.5.025
 4695      */
 4696     public function SetDefaultMonospacedFont($font) {
 4697         $this->default_monospaced_font = $font;
 4698     }
 4699 
 4700     /**
 4701      * 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 />
 4702      * The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is defined with SetLink().
 4703      * @public
 4704      * @since 1.5
 4705      * @see Cell(), Write(), Image(), Link(), SetLink()
 4706      */
 4707     public function AddLink() {
 4708         // create a new internal link
 4709         $n = count($this->links) + 1;
 4710         $this->links[$n] = array('p' => 0, 'y' => 0, 'f' => false);
 4711         return $n;
 4712     }
 4713 
 4714     /**
 4715      * Defines the page and position a link points to.
 4716      * @param $link (int) The link identifier returned by AddLink()
 4717      * @param $y (float) Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page)
 4718      * @param $page (int|string) Number of target page; -1 indicates the current page (default value). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages.
 4719      * @public
 4720      * @since 1.5
 4721      * @see AddLink()
 4722      */
 4723     public function SetLink($link, $y=0, $page=-1) {
 4724         $fixed = false;
 4725         if (!empty($page) AND (substr($page, 0, 1) == '*')) {
 4726             $page = intval(substr($page, 1));
 4727             // this page number will not be changed when moving/add/deleting pages
 4728             $fixed = true;
 4729         }
 4730         if ($page < 0) {
 4731             $page = $this->page;
 4732         }
 4733         if ($y == -1) {
 4734             $y = $this->y;
 4735         }
 4736         $this->links[$link] = array('p' => $page, 'y' => $y, 'f' => $fixed);
 4737     }
 4738 
 4739     /**
 4740      * Puts a link on a rectangular area of the page.
 4741      * 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.
 4742      * @param $x (float) Abscissa of the upper-left corner of the rectangle
 4743      * @param $y (float) Ordinate of the upper-left corner of the rectangle
 4744      * @param $w (float) Width of the rectangle
 4745      * @param $h (float) Height of the rectangle
 4746      * @param $link (mixed) URL or identifier returned by AddLink()
 4747      * @param $spaces (int) number of spaces on the text to link
 4748      * @public
 4749      * @since 1.5
 4750      * @see AddLink(), Annotation(), Cell(), Write(), Image()
 4751      */
 4752     public function Link($x, $y, $w, $h, $link, $spaces=0) {
 4753         $this->Annotation($x, $y, $w, $h, $link, array('Subtype'=>'Link'), $spaces);
 4754     }
 4755 
 4756     /**
 4757      * Puts a markup annotation on a rectangular area of the page.
 4758      * !!!!THE ANNOTATION SUPPORT IS NOT YET FULLY IMPLEMENTED !!!!
 4759      * @param $x (float) Abscissa of the upper-left corner of the rectangle
 4760      * @param $y (float) Ordinate of the upper-left corner of the rectangle
 4761      * @param $w (float) Width of the rectangle
 4762      * @param $h (float) Height of the rectangle
 4763      * @param $text (string) annotation text or alternate content
 4764      * @param $opt (array) array of options (see section 8.4 of PDF reference 1.7).
 4765      * @param $spaces (int) number of spaces on the text to link
 4766      * @public
 4767      * @since 4.0.018 (2008-08-06)
 4768      */
 4769     public function Annotation($x, $y, $w, $h, $text, $opt=array('Subtype'=>'Text'), $spaces=0) {
 4770         if ($this->inxobj) {
 4771             // store parameters for later use on template
 4772             $this->xobjects[$this->xobjid]['annotations'][] = array('x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'text' => $text, 'opt' => $opt, 'spaces' => $spaces);
 4773             return;
 4774         }
 4775         if ($x === '') {
 4776             $x = $this->x;
 4777         }
 4778         if ($y === '') {
 4779             $y = $this->y;
 4780         }
 4781         // check page for no-write regions and adapt page margins if necessary
 4782         list($x, $y) = $this->checkPageRegions($h, $x, $y);
 4783         // recalculate coordinates to account for graphic transformations
 4784         if (isset($this->transfmatrix) AND !empty($this->transfmatrix)) {
 4785             for ($i=$this->transfmatrix_key; $i > 0; --$i) {
 4786                 $maxid = count($this->transfmatrix[$i]) - 1;
 4787                 for ($j=$maxid; $j >= 0; --$j) {
 4788                     $ctm = $this->transfmatrix[$i][$j];
 4789                     if (isset($ctm['a'])) {
 4790                         $x = $x * $this->k;
 4791                         $y = ($this->h - $y) * $this->k;
 4792                         $w = $w * $this->k;
 4793                         $h = $h * $this->k;
 4794                         // top left
 4795                         $xt = $x;
 4796                         $yt = $y;
 4797                         $x1 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
 4798                         $y1 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
 4799                         // top right
 4800                         $xt = $x + $w;
 4801                         $yt = $y;
 4802                         $x2 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
 4803                         $y2 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
 4804                         // bottom left
 4805                         $xt = $x;
 4806                         $yt = $y - $h;
 4807                         $x3 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
 4808                         $y3 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
 4809                         // bottom right
 4810                         $xt = $x + $w;
 4811                         $yt = $y - $h;
 4812                         $x4 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
 4813                         $y4 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
 4814                         // new coordinates (rectangle area)
 4815                         $x = min($x1, $x2, $x3, $x4);
 4816                         $y = max($y1, $y2, $y3, $y4);
 4817                         $w = (max($x1, $x2, $x3, $x4) - $x) / $this->k;
 4818                         $h = ($y - min($y1, $y2, $y3, $y4)) / $this->k;
 4819                         $x = $x / $this->k;
 4820                         $y = $this->h - ($y / $this->k);
 4821                     }
 4822                 }
 4823             }
 4824         }
 4825         if ($this->page <= 0) {
 4826             $page = 1;
 4827         } else {
 4828             $page = $this->page;
 4829         }
 4830         if (!isset($this->PageAnnots[$page])) {
 4831             $this->PageAnnots[$page] = array();
 4832         }
 4833         $this->PageAnnots[$page][] = array('n' => ++$this->n, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'txt' => $text, 'opt' => $opt, 'numspaces' => $spaces);
 4834         if (!$this->pdfa_mode || ($this->pdfa_mode && $this->pdfa_version == 3)) {
 4835             if ((($opt['Subtype'] == 'FileAttachment') OR ($opt['Subtype'] == 'Sound')) AND (!TCPDF_STATIC::empty_string($opt['FS']))
 4836                 AND (@TCPDF_STATIC::file_exists($opt['FS']) OR TCPDF_STATIC::isValidURL($opt['FS']))
 4837                 AND (!isset($this->embeddedfiles[basename($opt['FS'])]))) {