source-class-TCPDF

It appears that you are using AdBlocking software. The cost of running this website is covered by advertisements. If you like it please feel free to a small amount of money to secure the future of this website.
    1: <?php
    2: //============================================================+
    3: // File name   : tcpdf.php
    4: // Version     : 6.2.13
    5: // Begin       : 2002-08-03
    6: // Last Update : 2015-06-18
    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-2015 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 ImagMagick (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 ImagMagick (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.2.8
  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.2.8
  132:  * @author Nicola Asuni - info@tecnick.com
  133:  */
  134: class TCPDF {
  135: 
  136:     // Protected properties
  137: 
  138:     /**
  139:      * Current page number.
  140:      * @protected
  141:      */
  142:     protected $page;
  143: 
  144:     /**
  145:      * Current object number.
  146:      * @protected
  147:      */
  148:     protected $n;
  149: 
  150:     /**
  151:      * Array of object offsets.
  152:      * @protected
  153:      */
  154:     protected $offsets = array();
  155: 
  156:     /**
  157:      * Array of object IDs for each page.
  158:      * @protected
  159:      */
  160:     protected $pageobjects = array();
  161: 
  162:     /**
  163:      * Buffer holding in-memory PDF.
  164:      * @protected
  165:      */
  166:     protected $buffer;
  167: 
  168:     /**
  169:      * Array containing pages.
  170:      * @protected
  171:      */
  172:     protected $pages = array();
  173: 
  174:     /**
  175:      * Current document state.
  176:      * @protected
  177:      */
  178:     protected $state;
  179: 
  180:     /**
  181:      * Compression flag.
  182:      * @protected
  183:      */
  184:     protected $compress;
  185: 
  186:     /**
  187:      * Current page orientation (P = Portrait, L = Landscape).
  188:      * @protected
  189:      */
  190:     protected $CurOrientation;
  191: 
  192:     /**
  193:      * Page dimensions.
  194:      * @protected
  195:      */
  196:     protected $pagedim = array();
  197: 
  198:     /**
  199:      * Scale factor (number of points in user unit).
  200:      * @protected
  201:      */
  202:     protected $k;
  203: 
  204:     /**
  205:      * Width of page format in points.
  206:      * @protected
  207:      */
  208:     protected $fwPt;
  209: 
  210:     /**
  211:      * Height of page format in points.
  212:      * @protected
  213:      */
  214:     protected $fhPt;
  215: 
  216:     /**
  217:      * Current width of page in points.
  218:      * @protected
  219:      */
  220:     protected $wPt;
  221: 
  222:     /**
  223:      * Current height of page in points.
  224:      * @protected
  225:      */
  226:     protected $hPt;
  227: 
  228:     /**
  229:      * Current width of page in user unit.
  230:      * @protected
  231:      */
  232:     protected $w;
  233: 
  234:     /**
  235:      * Current height of page in user unit.
  236:      * @protected
  237:      */
  238:     protected $h;
  239: 
  240:     /**
  241:      * Left margin.
  242:      * @protected
  243:      */
  244:     protected $lMargin;
  245: 
  246:     /**
  247:      * Right margin.
  248:      * @protected
  249:      */
  250:     protected $rMargin;
  251: 
  252:     /**
  253:      * Cell left margin (used by regions).
  254:      * @protected
  255:      */
  256:     protected $clMargin;
  257: 
  258:     /**
  259:      * Cell right margin (used by regions).
  260:      * @protected
  261:      */
  262:     protected $crMargin;
  263: 
  264:     /**
  265:      * Top margin.
  266:      * @protected
  267:      */
  268:     protected $tMargin;
  269: 
  270:     /**
  271:      * Page break margin.
  272:      * @protected
  273:      */
  274:     protected $bMargin;
  275: 
  276:     /**
  277:      * Array of cell internal paddings ('T' => top, 'R' => right, 'B' => bottom, 'L' => left).
  278:      * @since 5.9.000 (2010-10-03)
  279:      * @protected
  280:      */
  281:     protected $cell_padding = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0);
  282: 
  283:     /**
  284:      * Array of cell margins ('T' => top, 'R' => right, 'B' => bottom, 'L' => left).
  285:      * @since 5.9.000 (2010-10-04)
  286:      * @protected
  287:      */
  288:     protected $cell_margin = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0);
  289: 
  290:     /**
  291:      * Current horizontal position in user unit for cell positioning.
  292:      * @protected
  293:      */
  294:     protected $x;
  295: 
  296:     /**
  297:      * Current vertical position in user unit for cell positioning.
  298:      * @protected
  299:      */
  300:     protected $y;
  301: 
  302:     /**
  303:      * Height of last cell printed.
  304:      * @protected
  305:      */
  306:     protected $lasth;
  307: 
  308:     /**
  309:      * Line width in user unit.
  310:      * @protected
  311:      */
  312:     protected $LineWidth;
  313: 
  314:     /**
  315:      * Array of standard font names.
  316:      * @protected
  317:      */
  318:     protected $CoreFonts;
  319: 
  320:     /**
  321:      * Array of used fonts.
  322:      * @protected
  323:      */
  324:     protected $fonts = array();
  325: 
  326:     /**
  327:      * Array of font files.
  328:      * @protected
  329:      */
  330:     protected $FontFiles = array();
  331: 
  332:     /**
  333:      * Array of encoding differences.
  334:      * @protected
  335:      */
  336:     protected $diffs = array();
  337: 
  338:     /**
  339:      * Array of used images.
  340:      * @protected
  341:      */
  342:     protected $images = array();
  343: 
  344:     /**
  345:      * Depth of the svg tag, to keep track if the svg tag is a subtag or the root tag.
  346:      * @protected
  347:      */
  348:     protected $svg_tag_depth = 0;
  349: 
  350:     /**
  351:      * Array of Annotations in pages.
  352:      * @protected
  353:      */
  354:     protected $PageAnnots = array();
  355: 
  356:     /**
  357:      * Array of internal links.
  358:      * @protected
  359:      */
  360:     protected $links = array();
  361: 
  362:     /**
  363:      * Current font family.
  364:      * @protected
  365:      */
  366:     protected $FontFamily;
  367: 
  368:     /**
  369:      * Current font style.
  370:      * @protected
  371:      */
  372:     protected $FontStyle;
  373: 
  374:     /**
  375:      * Current font ascent (distance between font top and baseline).
  376:      * @protected
  377:      * @since 2.8.000 (2007-03-29)
  378:      */
  379:     protected $FontAscent;
  380: 
  381:     /**
  382:      * Current font descent (distance between font bottom and baseline).
  383:      * @protected
  384:      * @since 2.8.000 (2007-03-29)
  385:      */
  386:     protected $FontDescent;
  387: 
  388:     /**
  389:      * Underlining flag.
  390:      * @protected
  391:      */
  392:     protected $underline;
  393: 
  394:     /**
  395:      * Overlining flag.
  396:      * @protected
  397:      */
  398:     protected $overline;
  399: 
  400:     /**
  401:      * Current font info.
  402:      * @protected
  403:      */
  404:     protected $CurrentFont;
  405: 
  406:     /**
  407:      * Current font size in points.
  408:      * @protected
  409:      */
  410:     protected $FontSizePt;
  411: 
  412:     /**
  413:      * Current font size in user unit.
  414:      * @protected
  415:      */
  416:     protected $FontSize;
  417: 
  418:     /**
  419:      * Commands for drawing color.
  420:      * @protected
  421:      */
  422:     protected $DrawColor;
  423: 
  424:     /**
  425:      * Commands for filling color.
  426:      * @protected
  427:      */
  428:     protected $FillColor;
  429: 
  430:     /**
  431:      * Commands for text color.
  432:      * @protected
  433:      */
  434:     protected $TextColor;
  435: 
  436:     /**
  437:      * Indicates whether fill and text colors are different.
  438:      * @protected
  439:      */
  440:     protected $ColorFlag;
  441: 
  442:     /**
  443:      * Automatic page breaking.
  444:      * @protected
  445:      */
  446:     protected $AutoPageBreak;
  447: 
  448:     /**
  449:      * Threshold used to trigger page breaks.
  450:      * @protected
  451:      */
  452:     protected $PageBreakTrigger;
  453: 
  454:     /**
  455:      * Flag set when processing page header.
  456:      * @protected
  457:      */
  458:     protected $InHeader = false;
  459: 
  460:     /**
  461:      * Flag set when processing page footer.
  462:      * @protected
  463:      */
  464:     protected $InFooter = false;
  465: 
  466:     /**
  467:      * Zoom display mode.
  468:      * @protected
  469:      */
  470:     protected $ZoomMode;
  471: 
  472:     /**
  473:      * Layout display mode.
  474:      * @protected
  475:      */
  476:     protected $LayoutMode;
  477: 
  478:     /**
  479:      * If true set the document information dictionary in Unicode.
  480:      * @protected
  481:      */
  482:     protected $docinfounicode = true;
  483: 
  484:     /**
  485:      * Document title.
  486:      * @protected
  487:      */
  488:     protected $title = '';
  489: 
  490:     /**
  491:      * Document subject.
  492:      * @protected
  493:      */
  494:     protected $subject = '';
  495: 
  496:     /**
  497:      * Document author.
  498:      * @protected
  499:      */
  500:     protected $author = '';
  501: 
  502:     /**
  503:      * Document keywords.
  504:      * @protected
  505:      */
  506:     protected $keywords = '';
  507: 
  508:     /**
  509:      * Document creator.
  510:      * @protected
  511:      */
  512:     protected $creator = '';
  513: 
  514:     /**
  515:      * Starting page number.
  516:      * @protected
  517:      */
  518:     protected $starting_page_number = 1;
  519: 
  520:     /**
  521:      * The right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image.
  522:      * @since 2002-07-31
  523:      * @author Nicola Asuni
  524:      * @protected
  525:      */
  526:     protected $img_rb_x;
  527: 
  528:     /**
  529:      * The right-bottom corner Y coordinate of last inserted image.
  530:      * @since 2002-07-31
  531:      * @author Nicola Asuni
  532:      * @protected
  533:      */
  534:     protected $img_rb_y;
  535: 
  536:     /**
  537:      * Adjusting factor to convert pixels to user units.
  538:      * @since 2004-06-14
  539:      * @author Nicola Asuni
  540:      * @protected
  541:      */
  542:     protected $imgscale = 1;
  543: 
  544:     /**
  545:      * Boolean flag set to true when the input text is unicode (require unicode fonts).
  546:      * @since 2005-01-02
  547:      * @author Nicola Asuni
  548:      * @protected
  549:      */
  550:     protected $isunicode = false;
  551: 
  552:     /**
  553:      * PDF version.
  554:      * @since 1.5.3
  555:      * @protected
  556:      */
  557:     protected $PDFVersion = '1.7';
  558: 
  559:     /**
  560:      * ID of the stored default header template (-1 = not set).
  561:      * @protected
  562:      */
  563:     protected $header_xobjid = false;
  564: 
  565:     /**
  566:      * If true reset the Header Xobject template at each page
  567:      * @protected
  568:      */
  569:     protected $header_xobj_autoreset = false;
  570: 
  571:     /**
  572:      * Minimum distance between header and top page margin.
  573:      * @protected
  574:      */
  575:     protected $header_margin;
  576: 
  577:     /**
  578:      * Minimum distance between footer and bottom page margin.
  579:      * @protected
  580:      */
  581:     protected $footer_margin;
  582: 
  583:     /**
  584:      * Original left margin value.
  585:      * @protected
  586:      * @since 1.53.0.TC013
  587:      */
  588:     protected $original_lMargin;
  589: 
  590:     /**
  591:      * Original right margin value.
  592:      * @protected
  593:      * @since 1.53.0.TC013
  594:      */
  595:     protected $original_rMargin;
  596: 
  597:     /**
  598:      * Default font used on page header.
  599:      * @protected
  600:      */
  601:     protected $header_font;
  602: 
  603:     /**
  604:      * Default font used on page footer.
  605:      * @protected
  606:      */
  607:     protected $footer_font;
  608: 
  609:     /**
  610:      * Language templates.
  611:      * @protected
  612:      */
  613:     protected $l;
  614: 
  615:     /**
  616:      * Barcode to print on page footer (only if set).
  617:      * @protected
  618:      */
  619:     protected $barcode = false;
  620: 
  621:     /**
  622:      * Boolean flag to print/hide page header.
  623:      * @protected
  624:      */
  625:     protected $print_header = true;
  626: 
  627:     /**
  628:      * Boolean flag to print/hide page footer.
  629:      * @protected
  630:      */
  631:     protected $print_footer = true;
  632: 
  633:     /**
  634:      * Header image logo.
  635:      * @protected
  636:      */
  637:     protected $header_logo = '';
  638: 
  639:     /**
  640:      * Width of header image logo in user units.
  641:      * @protected
  642:      */
  643:     protected $header_logo_width = 30;
  644: 
  645:     /**
  646:      * Title to be printed on default page header.
  647:      * @protected
  648:      */
  649:     protected $header_title = '';
  650: 
  651:     /**
  652:      * String to pring on page header after title.
  653:      * @protected
  654:      */
  655:     protected $header_string = '';
  656: 
  657:     /**
  658:      * Color for header text (RGB array).
  659:      * @since 5.9.174 (2012-07-25)
  660:      * @protected
  661:      */
  662:     protected $header_text_color = array(0,0,0);
  663: 
  664:     /**
  665:      * Color for header line (RGB array).
  666:      * @since 5.9.174 (2012-07-25)
  667:      * @protected
  668:      */
  669:     protected $header_line_color = array(0,0,0);
  670: 
  671:     /**
  672:      * Color for footer text (RGB array).
  673:      * @since 5.9.174 (2012-07-25)
  674:      * @protected
  675:      */
  676:     protected $footer_text_color = array(0,0,0);
  677: 
  678:     /**
  679:      * Color for footer line (RGB array).
  680:      * @since 5.9.174 (2012-07-25)
  681:      * @protected
  682:      */
  683:     protected $footer_line_color = array(0,0,0);
  684: 
  685:     /**
  686:      * Text shadow data array.
  687:      * @since 5.9.174 (2012-07-25)
  688:      * @protected
  689:      */
  690:     protected $txtshadow = array('enabled'=>false, 'depth_w'=>0, 'depth_h'=>0, 'color'=>false, 'opacity'=>1, 'blend_mode'=>'Normal');
  691: 
  692:     /**
  693:      * Default number of columns for html table.
  694:      * @protected
  695:      */
  696:     protected $default_table_columns = 4;
  697: 
  698:     // variables for html parser
  699: 
  700:     /**
  701:      * HTML PARSER: array to store current link and rendering styles.
  702:      * @protected
  703:      */
  704:     protected $HREF = array();
  705: 
  706:     /**
  707:      * List of available fonts on filesystem.
  708:      * @protected
  709:      */
  710:     protected $fontlist = array();
  711: 
  712:     /**
  713:      * Current foreground color.
  714:      * @protected
  715:      */
  716:     protected $fgcolor;
  717: 
  718:     /**
  719:      * HTML PARSER: array of boolean values, true in case of ordered list (OL), false otherwise.
  720:      * @protected
  721:      */
  722:     protected $listordered = array();
  723: 
  724:     /**
  725:      * HTML PARSER: array count list items on nested lists.
  726:      * @protected
  727:      */
  728:     protected $listcount = array();
  729: 
  730:     /**
  731:      * HTML PARSER: current list nesting level.
  732:      * @protected
  733:      */
  734:     protected $listnum = 0;
  735: 
  736:     /**
  737:      * HTML PARSER: indent amount for lists.
  738:      * @protected
  739:      */
  740:     protected $listindent = 0;
  741: 
  742:     /**
  743:      * HTML PARSER: current list indententation level.
  744:      * @protected
  745:      */
  746:     protected $listindentlevel = 0;
  747: 
  748:     /**
  749:      * Current background color.
  750:      * @protected
  751:      */
  752:     protected $bgcolor;
  753: 
  754:     /**
  755:      * Temporary font size in points.
  756:      * @protected
  757:      */
  758:     protected $tempfontsize = 10;
  759: 
  760:     /**
  761:      * Spacer string for LI tags.
  762:      * @protected
  763:      */
  764:     protected $lispacer = '';
  765: 
  766:     /**
  767:      * Default encoding.
  768:      * @protected
  769:      * @since 1.53.0.TC010
  770:      */
  771:     protected $encoding = 'UTF-8';
  772: 
  773:     /**
  774:      * PHP internal encoding.
  775:      * @protected
  776:      * @since 1.53.0.TC016
  777:      */
  778:     protected $internal_encoding;
  779: 
  780:     /**
  781:      * Boolean flag to indicate if the document language is Right-To-Left.
  782:      * @protected
  783:      * @since 2.0.000
  784:      */
  785:     protected $rtl = false;
  786: 
  787:     /**
  788:      * Boolean flag used to force RTL or LTR string direction.
  789:      * @protected
  790:      * @since 2.0.000
  791:      */
  792:     protected $tmprtl = false;
  793: 
  794:     // --- Variables used for document encryption:
  795: 
  796:     /**
  797:      * IBoolean flag indicating whether document is protected.
  798:      * @protected
  799:      * @since 2.0.000 (2008-01-02)
  800:      */
  801:     protected $encrypted;
  802: 
  803:     /**
  804:      * Array containing encryption settings.
  805:      * @protected
  806:      * @since 5.0.005 (2010-05-11)
  807:      */
  808:     protected $encryptdata = array();
  809: 
  810:     /**
  811:      * Last RC4 key encrypted (cached for optimisation).
  812:      * @protected
  813:      * @since 2.0.000 (2008-01-02)
  814:      */
  815:     protected $last_enc_key;
  816: 
  817:     /**
  818:      * Last RC4 computed key.
  819:      * @protected
  820:      * @since 2.0.000 (2008-01-02)
  821:      */
  822:     protected $last_enc_key_c;
  823: 
  824:     /**
  825:      * File ID (used on document trailer).
  826:      * @protected
  827:      * @since 5.0.005 (2010-05-12)
  828:      */
  829:     protected $file_id;
  830: 
  831:     // --- bookmark ---
  832: 
  833:     /**
  834:      * Outlines for bookmark.
  835:      * @protected
  836:      * @since 2.1.002 (2008-02-12)
  837:      */
  838:     protected $outlines = array();
  839: 
  840:     /**
  841:      * Outline root for bookmark.
  842:      * @protected
  843:      * @since 2.1.002 (2008-02-12)
  844:      */
  845:     protected $OutlineRoot;
  846: 
  847:     // --- javascript and form ---
  848: 
  849:     /**
  850:      * Javascript code.
  851:      * @protected
  852:      * @since 2.1.002 (2008-02-12)
  853:      */
  854:     protected $javascript = '';
  855: 
  856:     /**
  857:      * Javascript counter.
  858:      * @protected
  859:      * @since 2.1.002 (2008-02-12)
  860:      */
  861:     protected $n_js;
  862: 
  863:     /**
  864:      * line through state
  865:      * @protected
  866:      * @since 2.8.000 (2008-03-19)
  867:      */
  868:     protected $linethrough;
  869: 
  870:     /**
  871:      * Array with additional document-wide usage rights for the document.
  872:      * @protected
  873:      * @since 5.8.014 (2010-08-23)
  874:      */
  875:     protected $ur = array();
  876: 
  877:     /**
  878:      * DPI (Dot Per Inch) Document Resolution (do not change).
  879:      * @protected
  880:      * @since 3.0.000 (2008-03-27)
  881:      */
  882:     protected $dpi = 72;
  883: 
  884:     /**
  885:      * Array of page numbers were a new page group was started (the page numbers are the keys of the array).
  886:      * @protected
  887:      * @since 3.0.000 (2008-03-27)
  888:      */
  889:     protected $newpagegroup = array();
  890: 
  891:     /**
  892:      * Array that contains the number of pages in each page group.
  893:      * @protected
  894:      * @since 3.0.000 (2008-03-27)
  895:      */
  896:     protected $pagegroups = array();
  897: 
  898:     /**
  899:      * Current page group number.
  900:      * @protected
  901:      * @since 3.0.000 (2008-03-27)
  902:      */
  903:     protected $currpagegroup = 0;
  904: 
  905:     /**
  906:      * Array of transparency objects and parameters.
  907:      * @protected
  908:      * @since 3.0.000 (2008-03-27)
  909:      */
  910:     protected $extgstates;
  911: 
  912:     /**
  913:      * Set the default JPEG compression quality (1-100).
  914:      * @protected
  915:      * @since 3.0.000 (2008-03-27)
  916:      */
  917:     protected $jpeg_quality;
  918: 
  919:     /**
  920:      * Default cell height ratio.
  921:      * @protected
  922:      * @since 3.0.014 (2008-05-23)
  923:      */
  924:     protected $cell_height_ratio = K_CELL_HEIGHT_RATIO;
  925: 
  926:     /**
  927:      * PDF viewer preferences.
  928:      * @protected
  929:      * @since 3.1.000 (2008-06-09)
  930:      */
  931:     protected $viewer_preferences;
  932: 
  933:     /**
  934:      * A name object specifying how the document should be displayed when opened.
  935:      * @protected
  936:      * @since 3.1.000 (2008-06-09)
  937:      */
  938:     protected $PageMode;
  939: 
  940:     /**
  941:      * Array for storing gradient information.
  942:      * @protected
  943:      * @since 3.1.000 (2008-06-09)
  944:      */
  945:     protected $gradients = array();
  946: 
  947:     /**
  948:      * Array used to store positions inside the pages buffer (keys are the page numbers).
  949:      * @protected
  950:      * @since 3.2.000 (2008-06-26)
  951:      */
  952:     protected $intmrk = array();
  953: 
  954:     /**
  955:      * Array used to store positions inside the pages buffer (keys are the page numbers).
  956:      * @protected
  957:      * @since 5.7.000 (2010-08-03)
  958:      */
  959:     protected $bordermrk = array();
  960: 
  961:     /**
  962:      * Array used to store page positions to track empty pages (keys are the page numbers).
  963:      * @protected
  964:      * @since 5.8.007 (2010-08-18)
  965:      */
  966:     protected $emptypagemrk = array();
  967: 
  968:     /**
  969:      * Array used to store content positions inside the pages buffer (keys are the page numbers).
  970:      * @protected
  971:      * @since 4.6.021 (2009-07-20)
  972:      */
  973:     protected $cntmrk = array();
  974: 
  975:     /**
  976:      * Array used to store footer positions of each page.
  977:      * @protected
  978:      * @since 3.2.000 (2008-07-01)
  979:      */
  980:     protected $footerpos = array();
  981: 
  982:     /**
  983:      * Array used to store footer length of each page.
  984:      * @protected
  985:      * @since 4.0.014 (2008-07-29)
  986:      */
  987:     protected $footerlen = array();
  988: 
  989:     /**
  990:      * Boolean flag to indicate if a new line is created.
  991:      * @protected
  992:      * @since 3.2.000 (2008-07-01)
  993:      */
  994:     protected $newline = true;
  995: 
  996:     /**
  997:      * End position of the latest inserted line.
  998:      * @protected
  999:      * @since 3.2.000 (2008-07-01)
 1000:      */
 1001:     protected $endlinex = 0;
 1002: 
 1003:     /**
 1004:      * PDF string for width value of the last line.
 1005:      * @protected
 1006:      * @since 4.0.006 (2008-07-16)
 1007:      */
 1008:     protected $linestyleWidth = '';
 1009: 
 1010:     /**
 1011:      * PDF string for CAP value of the last line.
 1012:      * @protected
 1013:      * @since 4.0.006 (2008-07-16)
 1014:      */
 1015:     protected $linestyleCap = '0 J';
 1016: 
 1017:     /**
 1018:      * PDF string for join value of the last line.
 1019:      * @protected
 1020:      * @since 4.0.006 (2008-07-16)
 1021:      */
 1022:     protected $linestyleJoin = '0 j';
 1023: 
 1024:     /**
 1025:      * PDF string for dash value of the last line.
 1026:      * @protected
 1027:      * @since 4.0.006 (2008-07-16)
 1028:      */
 1029:     protected $linestyleDash = '[] 0 d';
 1030: 
 1031:     /**
 1032:      * Boolean flag to indicate if marked-content sequence is open.
 1033:      * @protected
 1034:      * @since 4.0.013 (2008-07-28)
 1035:      */
 1036:     protected $openMarkedContent = false;
 1037: 
 1038:     /**
 1039:      * Count the latest inserted vertical spaces on HTML.
 1040:      * @protected
 1041:      * @since 4.0.021 (2008-08-24)
 1042:      */
 1043:     protected $htmlvspace = 0;
 1044: 
 1045:     /**
 1046:      * Array of Spot colors.
 1047:      * @protected
 1048:      * @since 4.0.024 (2008-09-12)
 1049:      */
 1050:     protected $spot_colors = array();
 1051: 
 1052:     /**
 1053:      * Symbol used for HTML unordered list items.
 1054:      * @protected
 1055:      * @since 4.0.028 (2008-09-26)
 1056:      */
 1057:     protected $lisymbol = '';
 1058: 
 1059:     /**
 1060:      * String used to mark the beginning and end of EPS image blocks.
 1061:      * @protected
 1062:      * @since 4.1.000 (2008-10-18)
 1063:      */
 1064:     protected $epsmarker = 'x#!#EPS#!#x';
 1065: 
 1066:     /**
 1067:      * Array of transformation matrix.
 1068:      * @protected
 1069:      * @since 4.2.000 (2008-10-29)
 1070:      */
 1071:     protected $transfmatrix = array();
 1072: 
 1073:     /**
 1074:      * Current key for transformation matrix.
 1075:      * @protected
 1076:      * @since 4.8.005 (2009-09-17)
 1077:      */
 1078:     protected $transfmatrix_key = 0;
 1079: 
 1080:     /**
 1081:      * Booklet mode for double-sided pages.
 1082:      * @protected
 1083:      * @since 4.2.000 (2008-10-29)
 1084:      */
 1085:     protected $booklet = false;
 1086: 
 1087:     /**
 1088:      * Epsilon value used for float calculations.
 1089:      * @protected
 1090:      * @since 4.2.000 (2008-10-29)
 1091:      */
 1092:     protected $feps = 0.005;
 1093: 
 1094:     /**
 1095:      * Array used for custom vertical spaces for HTML tags.
 1096:      * @protected
 1097:      * @since 4.2.001 (2008-10-30)
 1098:      */
 1099:     protected $tagvspaces = array();
 1100: 
 1101:     /**
 1102:      * HTML PARSER: custom indent amount for lists. Negative value means disabled.
 1103:      * @protected
 1104:      * @since 4.2.007 (2008-11-12)
 1105:      */
 1106:     protected $customlistindent = -1;
 1107: 
 1108:     /**
 1109:      * Boolean flag to indicate if the border of the cell sides that cross the page should be removed.
 1110:      * @protected
 1111:      * @since 4.2.010 (2008-11-14)
 1112:      */
 1113:     protected $opencell = true;
 1114: 
 1115:     /**
 1116:      * Array of files to embedd.
 1117:      * @protected
 1118:      * @since 4.4.000 (2008-12-07)
 1119:      */
 1120:     protected $embeddedfiles = array();
 1121: 
 1122:     /**
 1123:      * Boolean flag to indicate if we are inside a PRE tag.
 1124:      * @protected
 1125:      * @since 4.4.001 (2008-12-08)
 1126:      */
 1127:     protected $premode = false;
 1128: 
 1129:     /**
 1130:      * Array used to store positions of graphics transformation blocks inside the page buffer.
 1131:      * keys are the page numbers
 1132:      * @protected
 1133:      * @since 4.4.002 (2008-12-09)
 1134:      */
 1135:     protected $transfmrk = array();
 1136: 
 1137:     /**
 1138:      * Default color for html links.
 1139:      * @protected
 1140:      * @since 4.4.003 (2008-12-09)
 1141:      */
 1142:     protected $htmlLinkColorArray = array(0, 0, 255);
 1143: 
 1144:     /**
 1145:      * Default font style to add to html links.
 1146:      * @protected
 1147:      * @since 4.4.003 (2008-12-09)
 1148:      */
 1149:     protected $htmlLinkFontStyle = 'U';
 1150: 
 1151:     /**
 1152:      * Counts the number of pages.
 1153:      * @protected
 1154:      * @since 4.5.000 (2008-12-31)
 1155:      */
 1156:     protected $numpages = 0;
 1157: 
 1158:     /**
 1159:      * Array containing page lengths in bytes.
 1160:      * @protected
 1161:      * @since 4.5.000 (2008-12-31)
 1162:      */
 1163:     protected $pagelen = array();
 1164: 
 1165:     /**
 1166:      * Counts the number of pages.
 1167:      * @protected
 1168:      * @since 4.5.000 (2008-12-31)
 1169:      */
 1170:     protected $numimages = 0;
 1171: 
 1172:     /**
 1173:      * Store the image keys.
 1174:      * @protected
 1175:      * @since 4.5.000 (2008-12-31)
 1176:      */
 1177:     protected $imagekeys = array();
 1178: 
 1179:     /**
 1180:      * Length of the buffer in bytes.
 1181:      * @protected
 1182:      * @since 4.5.000 (2008-12-31)
 1183:      */
 1184:     protected $bufferlen = 0;
 1185: 
 1186:     /**
 1187:      * Counts the number of fonts.
 1188:      * @protected
 1189:      * @since 4.5.000 (2009-01-02)
 1190:      */
 1191:     protected $numfonts = 0;
 1192: 
 1193:     /**
 1194:      * Store the font keys.
 1195:      * @protected
 1196:      * @since 4.5.000 (2009-01-02)
 1197:      */
 1198:     protected $fontkeys = array();
 1199: 
 1200:     /**
 1201:      * Store the font object IDs.
 1202:      * @protected
 1203:      * @since 4.8.001 (2009-09-09)
 1204:      */
 1205:     protected $font_obj_ids = array();
 1206: 
 1207:     /**
 1208:      * Store the fage status (true when opened, false when closed).
 1209:      * @protected
 1210:      * @since 4.5.000 (2009-01-02)
 1211:      */
 1212:     protected $pageopen = array();
 1213: 
 1214:     /**
 1215:      * Default monospace font.
 1216:      * @protected
 1217:      * @since 4.5.025 (2009-03-10)
 1218:      */
 1219:     protected $default_monospaced_font = 'courier';
 1220: 
 1221:     /**
 1222:      * Cloned copy of the current class object.
 1223:      * @protected
 1224:      * @since 4.5.029 (2009-03-19)
 1225:      */
 1226:     protected $objcopy;
 1227: 
 1228:     /**
 1229:      * Array used to store the lengths of cache files.
 1230:      * @protected
 1231:      * @since 4.5.029 (2009-03-19)
 1232:      */
 1233:     protected $cache_file_length = array();
 1234: 
 1235:     /**
 1236:      * Table header content to be repeated on each new page.
 1237:      * @protected
 1238:      * @since 4.5.030 (2009-03-20)
 1239:      */
 1240:     protected $thead = '';
 1241: 
 1242:     /**
 1243:      * Margins used for table header.
 1244:      * @protected
 1245:      * @since 4.5.030 (2009-03-20)
 1246:      */
 1247:     protected $theadMargins = array();
 1248: 
 1249:     /**
 1250:      * Boolean flag to enable document digital signature.
 1251:      * @protected
 1252:      * @since 4.6.005 (2009-04-24)
 1253:      */
 1254:     protected $sign = false;
 1255: 
 1256:     /**
 1257:      * Digital signature data.
 1258:      * @protected
 1259:      * @since 4.6.005 (2009-04-24)
 1260:      */
 1261:     protected $signature_data = array();
 1262: 
 1263:     /**
 1264:      * Digital signature max length.
 1265:      * @protected
 1266:      * @since 4.6.005 (2009-04-24)
 1267:      */
 1268:     protected $signature_max_length = 11742;
 1269: 
 1270:     /**
 1271:      * Data for digital signature appearance.
 1272:      * @protected
 1273:      * @since 5.3.011 (2010-06-16)
 1274:      */
 1275:     protected $signature_appearance = array('page' => 1, 'rect' => '0 0 0 0');
 1276: 
 1277:     /**
 1278:      * Array of empty digital signature appearances.
 1279:      * @protected
 1280:      * @since 5.9.101 (2011-07-06)
 1281:      */
 1282:     protected $empty_signature_appearance = array();
 1283: 
 1284:     /**
 1285:      * Boolean flag to enable document timestamping with TSA.
 1286:      * @protected
 1287:      * @since 6.0.085 (2014-06-19)
 1288:      */
 1289:     protected $tsa_timestamp = false;
 1290: 
 1291:     /**
 1292:      * Timestamping data.
 1293:      * @protected
 1294:      * @since 6.0.085 (2014-06-19)
 1295:      */
 1296:     protected $tsa_data = array();
 1297: 
 1298:     /**
 1299:      * Regular expression used to find blank characters (required for word-wrapping).
 1300:      * @protected
 1301:      * @since 4.6.006 (2009-04-28)
 1302:      */
 1303:     protected $re_spaces = '/[^\S\xa0]/';
 1304: 
 1305:     /**
 1306:      * Array of $re_spaces parts.
 1307:      * @protected
 1308:      * @since 5.5.011 (2010-07-09)
 1309:      */
 1310:     protected $re_space = array('p' => '[^\S\xa0]', 'm' => '');
 1311: 
 1312:     /**
 1313:      * Digital signature object ID.
 1314:      * @protected
 1315:      * @since 4.6.022 (2009-06-23)
 1316:      */
 1317:     protected $sig_obj_id = 0;
 1318: 
 1319:     /**
 1320:      * ID of page objects.
 1321:      * @protected
 1322:      * @since 4.7.000 (2009-08-29)
 1323:      */
 1324:     protected $page_obj_id = array();
 1325: 
 1326:     /**
 1327:      * List of form annotations IDs.
 1328:      * @protected
 1329:      * @since 4.8.000 (2009-09-07)
 1330:      */
 1331:     protected $form_obj_id = array();
 1332: 
 1333:     /**
 1334:      * 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.
 1335:      * @protected
 1336:      * @since 4.8.000 (2009-09-07)
 1337:      */
 1338:     protected $default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
 1339: 
 1340:     /**
 1341:      * Javascript objects array.
 1342:      * @protected
 1343:      * @since 4.8.000 (2009-09-07)
 1344:      */
 1345:     protected $js_objects = array();
 1346: 
 1347:     /**
 1348:      * Current form action (used during XHTML rendering).
 1349:      * @protected
 1350:      * @since 4.8.000 (2009-09-07)
 1351:      */
 1352:     protected $form_action = '';
 1353: 
 1354:     /**
 1355:      * Current form encryption type (used during XHTML rendering).
 1356:      * @protected
 1357:      * @since 4.8.000 (2009-09-07)
 1358:      */
 1359:     protected $form_enctype = 'application/x-www-form-urlencoded';
 1360: 
 1361:     /**
 1362:      * Current method to submit forms.
 1363:      * @protected
 1364:      * @since 4.8.000 (2009-09-07)
 1365:      */
 1366:     protected $form_mode = 'post';
 1367: 
 1368:     /**
 1369:      * List of fonts used on form fields (fontname => fontkey).
 1370:      * @protected
 1371:      * @since 4.8.001 (2009-09-09)
 1372:      */
 1373:     protected $annotation_fonts = array();
 1374: 
 1375:     /**
 1376:      * List of radio buttons parent objects.
 1377:      * @protected
 1378:      * @since 4.8.001 (2009-09-09)
 1379:      */
 1380:     protected $radiobutton_groups = array();
 1381: 
 1382:     /**
 1383:      * List of radio group objects IDs.
 1384:      * @protected
 1385:      * @since 4.8.001 (2009-09-09)
 1386:      */
 1387:     protected $radio_groups = array();
 1388: 
 1389:     /**
 1390:      * Text indentation value (used for text-indent CSS attribute).
 1391:      * @protected
 1392:      * @since 4.8.006 (2009-09-23)
 1393:      */
 1394:     protected $textindent = 0;
 1395: 
 1396:     /**
 1397:      * Store page number when startTransaction() is called.
 1398:      * @protected
 1399:      * @since 4.8.006 (2009-09-23)
 1400:      */
 1401:     protected $start_transaction_page = 0;
 1402: 
 1403:     /**
 1404:      * Store Y position when startTransaction() is called.
 1405:      * @protected
 1406:      * @since 4.9.001 (2010-03-28)
 1407:      */
 1408:     protected $start_transaction_y = 0;
 1409: 
 1410:     /**
 1411:      * True when we are printing the thead section on a new page.
 1412:      * @protected
 1413:      * @since 4.8.027 (2010-01-25)
 1414:      */
 1415:     protected $inthead = false;
 1416: 
 1417:     /**
 1418:      * Array of column measures (width, space, starting Y position).
 1419:      * @protected
 1420:      * @since 4.9.001 (2010-03-28)
 1421:      */
 1422:     protected $columns = array();
 1423: 
 1424:     /**
 1425:      * Number of colums.
 1426:      * @protected
 1427:      * @since 4.9.001 (2010-03-28)
 1428:      */
 1429:     protected $num_columns = 1;
 1430: 
 1431:     /**
 1432:      * Current column number.
 1433:      * @protected
 1434:      * @since 4.9.001 (2010-03-28)
 1435:      */
 1436:     protected $current_column = 0;
 1437: 
 1438:     /**
 1439:      * Starting page for columns.
 1440:      * @protected
 1441:      * @since 4.9.001 (2010-03-28)
 1442:      */
 1443:     protected $column_start_page = 0;
 1444: 
 1445:     /**
 1446:      * Maximum page and column selected.
 1447:      * @protected
 1448:      * @since 5.8.000 (2010-08-11)
 1449:      */
 1450:     protected $maxselcol = array('page' => 0, 'column' => 0);
 1451: 
 1452:     /**
 1453:      * Array of: X difference between table cell x start and starting page margin, cellspacing, cellpadding.
 1454:      * @protected
 1455:      * @since 5.8.000 (2010-08-11)
 1456:      */
 1457:     protected $colxshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0));
 1458: 
 1459:     /**
 1460:      * 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.
 1461:      * @protected
 1462:      * @since 4.9.008 (2010-04-03)
 1463:      */
 1464:     protected $textrendermode = 0;
 1465: 
 1466:     /**
 1467:      * Text stroke width in doc units.
 1468:      * @protected
 1469:      * @since 4.9.008 (2010-04-03)
 1470:      */
 1471:     protected $textstrokewidth = 0;
 1472: 
 1473:     /**
 1474:      * Current stroke color.
 1475:      * @protected
 1476:      * @since 4.9.008 (2010-04-03)
 1477:      */
 1478:     protected $strokecolor;
 1479: 
 1480:     /**
 1481:      * Default unit of measure for document.
 1482:      * @protected
 1483:      * @since 5.0.000 (2010-04-22)
 1484:      */
 1485:     protected $pdfunit = 'mm';
 1486: 
 1487:     /**
 1488:      * Boolean flag true when we are on TOC (Table Of Content) page.
 1489:      * @protected
 1490:      */
 1491:     protected $tocpage = false;
 1492: 
 1493:     /**
 1494:      * Boolean flag: if true convert vector images (SVG, EPS) to raster image using GD or ImageMagick library.
 1495:      * @protected
 1496:      * @since 5.0.000 (2010-04-26)
 1497:      */
 1498:     protected $rasterize_vector_images = false;
 1499: 
 1500:     /**
 1501:      * Boolean flag: if true enables font subsetting by default.
 1502:      * @protected
 1503:      * @since 5.3.002 (2010-06-07)
 1504:      */
 1505:     protected $font_subsetting = true;
 1506: 
 1507:     /**
 1508:      * Array of default graphic settings.
 1509:      * @protected
 1510:      * @since 5.5.008 (2010-07-02)
 1511:      */
 1512:     protected $default_graphic_vars = array();
 1513: 
 1514:     /**
 1515:      * Array of XObjects.
 1516:      * @protected
 1517:      * @since 5.8.014 (2010-08-23)
 1518:      */
 1519:     protected $xobjects = array();
 1520: 
 1521:     /**
 1522:      * Boolean value true when we are inside an XObject.
 1523:      * @protected
 1524:      * @since 5.8.017 (2010-08-24)
 1525:      */
 1526:     protected $inxobj = false;
 1527: 
 1528:     /**
 1529:      * Current XObject ID.
 1530:      * @protected
 1531:      * @since 5.8.017 (2010-08-24)
 1532:      */
 1533:     protected $xobjid = '';
 1534: 
 1535:     /**
 1536:      * Percentage of character stretching.
 1537:      * @protected
 1538:      * @since 5.9.000 (2010-09-29)
 1539:      */
 1540:     protected $font_stretching = 100;
 1541: 
 1542:     /**
 1543:      * Increases or decreases the space between characters in a text by the specified amount (tracking).
 1544:      * @protected
 1545:      * @since 5.9.000 (2010-09-29)
 1546:      */
 1547:     protected $font_spacing = 0;
 1548: 
 1549:     /**
 1550:      * Array of no-write regions.
 1551:      * ('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)
 1552:      * @protected
 1553:      * @since 5.9.003 (2010-10-14)
 1554:      */
 1555:     protected $page_regions = array();
 1556: 
 1557:     /**
 1558:      * Boolean value true when page region check is active.
 1559:      * @protected
 1560:      */
 1561:     protected $check_page_regions = true;
 1562: 
 1563:     /**
 1564:      * Array of PDF layers data.
 1565:      * @protected
 1566:      * @since 5.9.102 (2011-07-13)
 1567:      */
 1568:     protected $pdflayers = array();
 1569: 
 1570:     /**
 1571:      * A dictionary of names and corresponding destinations (Dests key on document Catalog).
 1572:      * @protected
 1573:      * @since 5.9.097 (2011-06-23)
 1574:      */
 1575:     protected $dests = array();
 1576: 
 1577:     /**
 1578:      * Object ID for Named Destinations
 1579:      * @protected
 1580:      * @since 5.9.097 (2011-06-23)
 1581:      */
 1582:     protected $n_dests;
 1583: 
 1584:     /**
 1585:      * Embedded Files Names
 1586:      * @protected
 1587:      * @since 5.9.204 (2013-01-23)
 1588:      */
 1589:     protected $efnames = array();
 1590: 
 1591:     /**
 1592:      * Directory used for the last SVG image.
 1593:      * @protected
 1594:      * @since 5.0.000 (2010-05-05)
 1595:      */
 1596:     protected $svgdir = '';
 1597: 
 1598:     /**
 1599:      *  Deafult unit of measure for SVG.
 1600:      * @protected
 1601:      * @since 5.0.000 (2010-05-02)
 1602:      */
 1603:     protected $svgunit = 'px';
 1604: 
 1605:     /**
 1606:      * Array of SVG gradients.
 1607:      * @protected
 1608:      * @since 5.0.000 (2010-05-02)
 1609:      */
 1610:     protected $svggradients = array();
 1611: 
 1612:     /**
 1613:      * ID of last SVG gradient.
 1614:      * @protected
 1615:      * @since 5.0.000 (2010-05-02)
 1616:      */
 1617:     protected $svggradientid = 0;
 1618: 
 1619:     /**
 1620:      * Boolean value true when in SVG defs group.
 1621:      * @protected
 1622:      * @since 5.0.000 (2010-05-02)
 1623:      */
 1624:     protected $svgdefsmode = false;
 1625: 
 1626:     /**
 1627:      * Array of SVG defs.
 1628:      * @protected
 1629:      * @since 5.0.000 (2010-05-02)
 1630:      */
 1631:     protected $svgdefs = array();
 1632: 
 1633:     /**
 1634:      * Boolean value true when in SVG clipPath tag.
 1635:      * @protected
 1636:      * @since 5.0.000 (2010-04-26)
 1637:      */
 1638:     protected $svgclipmode = false;
 1639: 
 1640:     /**
 1641:      * Array of SVG clipPath commands.
 1642:      * @protected
 1643:      * @since 5.0.000 (2010-05-02)
 1644:      */
 1645:     protected $svgclippaths = array();
 1646: 
 1647:     /**
 1648:      * Array of SVG clipPath tranformation matrix.
 1649:      * @protected
 1650:      * @since 5.8.022 (2010-08-31)
 1651:      */
 1652:     protected $svgcliptm = array();
 1653: 
 1654:     /**
 1655:      * ID of last SVG clipPath.
 1656:      * @protected
 1657:      * @since 5.0.000 (2010-05-02)
 1658:      */
 1659:     protected $svgclipid = 0;
 1660: 
 1661:     /**
 1662:      * SVG text.
 1663:      * @protected
 1664:      * @since 5.0.000 (2010-05-02)
 1665:      */
 1666:     protected $svgtext = '';
 1667: 
 1668:     /**
 1669:      * SVG text properties.
 1670:      * @protected
 1671:      * @since 5.8.013 (2010-08-23)
 1672:      */
 1673:     protected $svgtextmode = array();
 1674: 
 1675:     /**
 1676:      * Array of SVG properties.
 1677:      * @protected
 1678:      * @since 5.0.000 (2010-05-02)
 1679:      */
 1680:     protected $svgstyles = array(array(
 1681:         'alignment-baseline' => 'auto',
 1682:         'baseline-shift' => 'baseline',
 1683:         'clip' => 'auto',
 1684:         'clip-path' => 'none',
 1685:         'clip-rule' => 'nonzero',
 1686:         'color' => 'black',
 1687:         'color-interpolation' => 'sRGB',
 1688:         'color-interpolation-filters' => 'linearRGB',
 1689:         'color-profile' => 'auto',
 1690:         'color-rendering' => 'auto',
 1691:         'cursor' => 'auto',
 1692:         'direction' => 'ltr',
 1693:         'display' => 'inline',
 1694:         'dominant-baseline' => 'auto',
 1695:         'enable-background' => 'accumulate',
 1696:         'fill' => 'black',
 1697:         'fill-opacity' => 1,
 1698:         'fill-rule' => 'nonzero',
 1699:         'filter' => 'none',
 1700:         'flood-color' => 'black',
 1701:         'flood-opacity' => 1,
 1702:         'font' => '',
 1703:         'font-family' => 'helvetica',
 1704:         'font-size' => 'medium',
 1705:         'font-size-adjust' => 'none',
 1706:         'font-stretch' => 'normal',
 1707:         'font-style' => 'normal',
 1708:         'font-variant' => 'normal',
 1709:         'font-weight' => 'normal',
 1710:         'glyph-orientation-horizontal' => '0deg',
 1711:         'glyph-orientation-vertical' => 'auto',
 1712:         'image-rendering' => 'auto',
 1713:         'kerning' => 'auto',
 1714:         'letter-spacing' => 'normal',
 1715:         'lighting-color' => 'white',
 1716:         'marker' => '',
 1717:         'marker-end' => 'none',
 1718:         'marker-mid' => 'none',
 1719:         'marker-start' => 'none',
 1720:         'mask' => 'none',
 1721:         'opacity' => 1,
 1722:         'overflow' => 'auto',
 1723:         'pointer-events' => 'visiblePainted',
 1724:         'shape-rendering' => 'auto',
 1725:         'stop-color' => 'black',
 1726:         'stop-opacity' => 1,
 1727:         'stroke' => 'none',
 1728:         'stroke-dasharray' => 'none',
 1729:         'stroke-dashoffset' => 0,
 1730:         'stroke-linecap' => 'butt',
 1731:         'stroke-linejoin' => 'miter',
 1732:         'stroke-miterlimit' => 4,
 1733:         'stroke-opacity' => 1,
 1734:         'stroke-width' => 1,
 1735:         'text-anchor' => 'start',
 1736:         'text-decoration' => 'none',
 1737:         'text-rendering' => 'auto',
 1738:         'unicode-bidi' => 'normal',
 1739:         'visibility' => 'visible',
 1740:         'word-spacing' => 'normal',
 1741:         'writing-mode' => 'lr-tb',
 1742:         'text-color' => 'black',
 1743:         'transfmatrix' => array(1, 0, 0, 1, 0, 0)
 1744:         ));
 1745: 
 1746:     /**
 1747:      * If true force sRGB color profile for all document.
 1748:      * @protected
 1749:      * @since 5.9.121 (2011-09-28)
 1750:      */
 1751:     protected $force_srgb = false;
 1752: 
 1753:     /**
 1754:      * If true set the document to PDF/A mode.
 1755:      * @protected
 1756:      * @since 5.9.121 (2011-09-27)
 1757:      */
 1758:     protected $pdfa_mode = false;
 1759: 
 1760:     /**
 1761:      * Document creation date-time
 1762:      * @protected
 1763:      * @since 5.9.152 (2012-03-22)
 1764:      */
 1765:     protected $doc_creation_timestamp;
 1766: 
 1767:     /**
 1768:      * Document modification date-time
 1769:      * @protected
 1770:      * @since 5.9.152 (2012-03-22)
 1771:      */
 1772:     protected $doc_modification_timestamp;
 1773: 
 1774:     /**
 1775:      * Custom XMP data.
 1776:      * @protected
 1777:      * @since 5.9.128 (2011-10-06)
 1778:      */
 1779:     protected $custom_xmp = '';
 1780: 
 1781:     /**
 1782:      * Overprint mode array.
 1783:      * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008).
 1784:      * @protected
 1785:      * @since 5.9.152 (2012-03-23)
 1786:      */
 1787:     protected $overprint = array('OP' => false, 'op' => false, 'OPM' => 0);
 1788: 
 1789:     /**
 1790:      * Alpha mode array.
 1791:      * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008).
 1792:      * @protected
 1793:      * @since 5.9.152 (2012-03-23)
 1794:      */
 1795:     protected $alpha = array('CA' => 1, 'ca' => 1, 'BM' => '/Normal', 'AIS' => false);
 1796: 
 1797:     /**
 1798:      * Define the page boundaries boxes to be set on document.
 1799:      * @protected
 1800:      * @since 5.9.152 (2012-03-23)
 1801:      */
 1802:     protected $page_boxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox');
 1803: 
 1804:     /**
 1805:      * If true print TCPDF meta link.
 1806:      * @protected
 1807:      * @since 5.9.152 (2012-03-23)
 1808:      */
 1809:     protected $tcpdflink = true;
 1810: 
 1811:     /**
 1812:      * Cache array for computed GD gamma values.
 1813:      * @protected
 1814:      * @since 5.9.1632 (2012-06-05)
 1815:      */
 1816:     protected $gdgammacache = array();
 1817: 
 1818:     //------------------------------------------------------------
 1819:     // METHODS
 1820:     //------------------------------------------------------------
 1821: 
 1822:     /**
 1823:      * This is the class constructor.
 1824:      * It allows to set up the page format, the orientation and the measure unit used in all the methods (except for the font sizes).
 1825:      *
 1826:      * 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.
 1827:      *
 1828:      * @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>
 1829:      * @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.
 1830:      * @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().
 1831:      * @param $unicode (boolean) TRUE means that the input text is unicode (default = true)
 1832:      * @param $encoding (string) Charset encoding (used only when converting back html entities); default is UTF-8.
 1833:      * @param $diskcache (boolean) DEPRECATED FEATURE
 1834:      * @param $pdfa (boolean) If TRUE set the document to PDF/A mode.
 1835:      * @public
 1836:      * @see getPageSizeFromFormat(), setPageFormat()
 1837:      */
 1838:     public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) {
 1839:         /* Set internal character encoding to ASCII */
 1840:         if (function_exists('mb_internal_encoding') AND mb_internal_encoding()) {
 1841:             $this->internal_encoding = mb_internal_encoding();
 1842:             mb_internal_encoding('ASCII');
 1843:         }
 1844:         // set file ID for trailer
 1845:         $serformat = (is_array($format) ? json_encode($format) : $format);
 1846:         $this->file_id = md5(TCPDF_STATIC::getRandomSeed('TCPDF'.$orientation.$unit.$serformat.$encoding));
 1847:         $this->font_obj_ids = array();
 1848:         $this->page_obj_id = array();
 1849:         $this->form_obj_id = array();
 1850:         // set pdf/a mode
 1851:         $this->pdfa_mode = $pdfa;
 1852:         $this->force_srgb = false;
 1853:         // set language direction
 1854:         $this->rtl = false;
 1855:         $this->tmprtl = false;
 1856:         // some checks
 1857:         $this->_dochecks();
 1858:         // initialization of properties
 1859:         $this->isunicode = $unicode;
 1860:         $this->page = 0;
 1861:         $this->transfmrk[0] = array();
 1862:         $this->pagedim = array();
 1863:         $this->n = 2;
 1864:         $this->buffer = '';
 1865:         $this->pages = array();
 1866:         $this->state = 0;
 1867:         $this->fonts = array();
 1868:         $this->FontFiles = array();
 1869:         $this->diffs = array();
 1870:         $this->images = array();
 1871:         $this->links = array();
 1872:         $this->gradients = array();
 1873:         $this->InFooter = false;
 1874:         $this->lasth = 0;
 1875:         $this->FontFamily = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica';
 1876:         $this->FontStyle = '';
 1877:         $this->FontSizePt = 12;
 1878:         $this->underline = false;
 1879:         $this->overline = false;
 1880:         $this->linethrough = false;
 1881:         $this->DrawColor = '0 G';
 1882:         $this->FillColor = '0 g';
 1883:         $this->TextColor = '0 g';
 1884:         $this->ColorFlag = false;
 1885:         $this->pdflayers = array();
 1886:         // encryption values
 1887:         $this->encrypted = false;
 1888:         $this->last_enc_key = '';
 1889:         // standard Unicode fonts
 1890:         $this->CoreFonts = array(
 1891:             'courier'=>'Courier',
 1892:             'courierB'=>'Courier-Bold',
 1893:             'courierI'=>'Courier-Oblique',
 1894:             'courierBI'=>'Courier-BoldOblique',
 1895:             'helvetica'=>'Helvetica',
 1896:             'helveticaB'=>'Helvetica-Bold',
 1897:             'helveticaI'=>'Helvetica-Oblique',
 1898:             'helveticaBI'=>'Helvetica-BoldOblique',
 1899:             'times'=>'Times-Roman',
 1900:             'timesB'=>'Times-Bold',
 1901:             'timesI'=>'Times-Italic',
 1902:             'timesBI'=>'Times-BoldItalic',
 1903:             'symbol'=>'Symbol',
 1904:             'zapfdingbats'=>'ZapfDingbats'
 1905:         );
 1906:         // set scale factor
 1907:         $this->setPageUnit($unit);
 1908:         // set page format and orientation
 1909:         $this->setPageFormat($format, $orientation);
 1910:         // page margins (1 cm)
 1911:         $margin = 28.35 / $this->k;
 1912:         $this->SetMargins($margin, $margin);
 1913:         $this->clMargin = $this->lMargin;
 1914:         $this->crMargin = $this->rMargin;
 1915:         // internal cell padding
 1916:         $cpadding = $margin / 10;
 1917:         $this->setCellPaddings($cpadding, 0, $cpadding, 0);
 1918:         // cell margins
 1919:         $this->setCellMargins(0, 0, 0, 0);
 1920:         // line width (0.2 mm)
 1921:         $this->LineWidth = 0.57 / $this->k;
 1922:         $this->linestyleWidth = sprintf('%F w', ($this->LineWidth * $this->k));
 1923:         $this->linestyleCap = '0 J';
 1924:         $this->linestyleJoin = '0 j';
 1925:         $this->linestyleDash = '[] 0 d';
 1926:         // automatic page break
 1927:         $this->SetAutoPageBreak(true, (2 * $margin));
 1928:         // full width display mode
 1929:         $this->SetDisplayMode('fullwidth');
 1930:         // compression
 1931:         $this->SetCompression();
 1932:         // set default PDF version number
 1933:         $this->setPDFVersion();
 1934:         $this->tcpdflink = true;
 1935:         $this->encoding = $encoding;
 1936:         $this->HREF = array();
 1937:         $this->getFontsList();
 1938:         $this->fgcolor = array('R' => 0, 'G' => 0, 'B' => 0);
 1939:         $this->strokecolor = array('R' => 0, 'G' => 0, 'B' => 0);
 1940:         $this->bgcolor = array('R' => 255, 'G' => 255, 'B' => 255);
 1941:         $this->extgstates = array();
 1942:         $this->setTextShadow();
 1943:         // signature
 1944:         $this->sign = false;
 1945:         $this->tsa_timestamp = false;
 1946:         $this->tsa_data = array();
 1947:         $this->signature_appearance = array('page' => 1, 'rect' => '0 0 0 0', 'name' => 'Signature');
 1948:         $this->empty_signature_appearance = array();
 1949:         // user's rights
 1950:         $this->ur['enabled'] = false;
 1951:         $this->ur['document'] = '/FullSave';
 1952:         $this->ur['annots'] = '/Create/Delete/Modify/Copy/Import/Export';
 1953:         $this->ur['form'] = '/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate';
 1954:         $this->ur['signature'] = '/Modify';
 1955:         $this->ur['ef'] = '/Create/Delete/Modify/Import';
 1956:         $this->ur['formex'] = '';
 1957:         // set default JPEG quality
 1958:         $this->jpeg_quality = 75;
 1959:         // initialize some settings
 1960:         TCPDF_FONTS::utf8Bidi(array(''), '', false, $this->isunicode, $this->CurrentFont);
 1961:         // set default font
 1962:         $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt);
 1963:         $this->setHeaderFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt));
 1964:         $this->setFooterFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt));
 1965:         // check if PCRE Unicode support is enabled
 1966:         if ($this->isunicode AND (@preg_match('/\pL/u', 'a') == 1)) {
 1967:             // PCRE unicode support is turned ON
 1968:             // \s     : any whitespace character
 1969:             // \p{Z}  : any separator
 1970:             // \p{Lo} : Unicode letter or ideograph that does not have lowercase and uppercase variants. Is used to chunk chinese words.
 1971:             // \xa0   : Unicode Character 'NO-BREAK SPACE' (U+00A0)
 1972:             //$this->setSpacesRE('/(?!\xa0)[\s\p{Z}\p{Lo}]/u');
 1973:             $this->setSpacesRE('/(?!\xa0)[\s\p{Z}]/u');
 1974:         } else {
 1975:             // PCRE unicode support is turned OFF
 1976:             $this->setSpacesRE('/[^\S\xa0]/');
 1977:         }
 1978:         $this->default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
 1979:         // set document creation and modification timestamp
 1980:         $this->doc_creation_timestamp = time();
 1981:         $this->doc_modification_timestamp = $this->doc_creation_timestamp;
 1982:         // get default graphic vars
 1983:         $this->default_graphic_vars = $this->getGraphicVars();
 1984:         $this->header_xobj_autoreset = false;
 1985:         $this->custom_xmp = '';
 1986:         // Call cleanup method after script execution finishes or exit() is called.
 1987:         // NOTE: This will not be executed if the process is killed with a SIGTERM or SIGKILL signal.
 1988:         register_shutdown_function(array($this, '_destroy'), true);
 1989:     }
 1990: 
 1991:     /**
 1992:      * Default destructor.
 1993:      * @public
 1994:      * @since 1.53.0.TC016
 1995:      */
 1996:     public function __destruct() {
 1997:         // restore internal encoding
 1998:         if (isset($this->internal_encoding) AND !empty($this->internal_encoding)) {
 1999:             mb_internal_encoding($this->internal_encoding);
 2000:         }
 2001:         // cleanup
 2002:         $this->_destroy(true);
 2003:     }
 2004: 
 2005:     /**
 2006:      * Set the units of measure for the document.
 2007:      * @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.
 2008:      * @public
 2009:      * @since 3.0.015 (2008-06-06)
 2010:      */
 2011:     public function setPageUnit($unit) {
 2012:         $unit = strtolower($unit);
 2013:         //Set scale factor
 2014:         switch ($unit) {
 2015:             // points
 2016:             case 'px':
 2017:             case 'pt': {
 2018:                 $this->k = 1;
 2019:                 break;
 2020:             }
 2021:             // millimeters
 2022:             case 'mm': {
 2023:                 $this->k = $this->dpi / 25.4;
 2024:                 break;
 2025:             }
 2026:             // centimeters
 2027:             case 'cm': {
 2028:                 $this->k = $this->dpi / 2.54;
 2029:                 break;
 2030:             }
 2031:             // inches
 2032:             case 'in': {
 2033:                 $this->k = $this->dpi;
 2034:                 break;
 2035:             }
 2036:             // unsupported unit
 2037:             default : {
 2038:                 $this->Error('Incorrect unit: '.$unit);
 2039:                 break;
 2040:             }
 2041:         }
 2042:         $this->pdfunit = $unit;
 2043:         if (isset($this->CurOrientation)) {
 2044:             $this->setPageOrientation($this->CurOrientation);
 2045:         }
 2046:     }
 2047: 
 2048:     /**
 2049:      * Change the format of the current page
 2050:      * @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>
 2051:      * <li>['format'] = page format name (one of the above);</li>
 2052:      * <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>
 2053:      * <li>['PZ'] : The page's preferred zoom (magnification) factor.</li>
 2054:      * <li>['MediaBox'] : the boundaries of the physical medium on which the page shall be displayed or printed:</li>
 2055:      * <li>['MediaBox']['llx'] : lower-left x coordinate</li>
 2056:      * <li>['MediaBox']['lly'] : lower-left y coordinate</li>
 2057:      * <li>['MediaBox']['urx'] : upper-right x coordinate</li>
 2058:      * <li>['MediaBox']['ury'] : upper-right y coordinate</li>
 2059:      * <li>['CropBox'] : the visible region of default user space:</li>
 2060:      * <li>['CropBox']['llx'] : lower-left x coordinate</li>
 2061:      * <li>['CropBox']['lly'] : lower-left y coordinate</li>
 2062:      * <li>['CropBox']['urx'] : upper-right x coordinate</li>
 2063:      * <li>['CropBox']['ury'] : upper-right y coordinate</li>
 2064:      * <li>['BleedBox'] : the region to which the contents of the page shall be clipped when output in a production environment:</li>
 2065:      * <li>['BleedBox']['llx'] : lower-left x coordinate</li>
 2066:      * <li>['BleedBox']['lly'] : lower-left y coordinate</li>
 2067:      * <li>['BleedBox']['urx'] : upper-right x coordinate</li>
 2068:      * <li>['BleedBox']['ury'] : upper-right y coordinate</li>
 2069:      * <li>['TrimBox'] : the intended dimensions of the finished page after trimming:</li>
 2070:      * <li>['TrimBox']['llx'] : lower-left x coordinate</li>
 2071:      * <li>['TrimBox']['lly'] : lower-left y coordinate</li>
 2072:      * <li>['TrimBox']['urx'] : upper-right x coordinate</li>
 2073:      * <li>['TrimBox']['ury'] : upper-right y coordinate</li>
 2074:      * <li>['ArtBox'] : the extent of the page's meaningful content:</li>
 2075:      * <li>['ArtBox']['llx'] : lower-left x coordinate</li>
 2076:      * <li>['ArtBox']['lly'] : lower-left y coordinate</li>
 2077:      * <li>['ArtBox']['urx'] : upper-right x coordinate</li>
 2078:      * <li>['ArtBox']['ury'] : upper-right y coordinate</li>
 2079:      * <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>
 2080:      * <li>['BoxColorInfo'][BOXTYPE]['C'] : an array of three numbers in the range 0-255, representing the components in the DeviceRGB colour space.</li>
 2081:      * <li>['BoxColorInfo'][BOXTYPE]['W'] : the guideline width in default user units</li>
 2082:      * <li>['BoxColorInfo'][BOXTYPE]['S'] : the guideline style: S = Solid; D = Dashed</li>
 2083:      * <li>['BoxColorInfo'][BOXTYPE]['D'] : dash array defining a pattern of dashes and gaps to be used in drawing dashed guidelines</li>
 2084:      * <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>
 2085:      * <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>
 2086:      * <li>['trans']['S'] : transition style : Split, Blinds, Box, Wipe, Dissolve, Glitter, R, Fly, Push, Cover, Uncover, Fade</li>
 2087:      * <li>['trans']['D'] : The duration of the transition effect, in seconds.</li>
 2088:      * <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>
 2089:      * <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>
 2090:      * <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>
 2091:      * <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>
 2092:      * <li>['trans']['B'] : (Fly transition style only) If true, the area that shall be flown in is rectangular and opaque. Default: false.</li>
 2093:      * </ul>
 2094:      * @param $orientation (string) page orientation. Possible values are (case insensitive):<ul>
 2095:      * <li>P or Portrait (default)</li>
 2096:      * <li>L or Landscape</li>
 2097:      * <li>'' (empty string) for automatic orientation</li>
 2098:      * </ul>
 2099:      * @protected
 2100:      * @since 3.0.015 (2008-06-06)
 2101:      * @see getPageSizeFromFormat()
 2102:      */
 2103:     protected function setPageFormat($format, $orientation='P') {
 2104:         if (!empty($format) AND isset($this->pagedim[$this->page])) {
 2105:             // remove inherited values
 2106:             unset($this->pagedim[$this->page]);
 2107:         }
 2108:         if (is_string($format)) {
 2109:             // get page measures from format name
 2110:             $pf = TCPDF_STATIC::getPageSizeFromFormat($format);
 2111:             $this->fwPt = $pf[0];
 2112:             $this->fhPt = $pf[1];
 2113:         } else {
 2114:             // the boundaries of the physical medium on which the page shall be displayed or printed
 2115:             if (isset($format['MediaBox'])) {
 2116:                 $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);
 2117:                 $this->fwPt = (($format['MediaBox']['urx'] - $format['MediaBox']['llx']) * $this->k);
 2118:                 $this->fhPt = (($format['MediaBox']['ury'] - $format['MediaBox']['lly']) * $this->k);
 2119:             } else {
 2120:                 if (isset($format[0]) AND is_numeric($format[0]) AND isset($format[1]) AND is_numeric($format[1])) {
 2121:                     $pf = array(($format[0] * $this->k), ($format[1] * $this->k));
 2122:                 } else {
 2123:                     if (!isset($format['format'])) {
 2124:                         // default value
 2125:                         $format['format'] = 'A4';
 2126:                     }
 2127:                     $pf = TCPDF_STATIC::getPageSizeFromFormat($format['format']);
 2128:                 }
 2129:                 $this->fwPt = $pf[0];
 2130:                 $this->fhPt = $pf[1];
 2131:                 $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim);
 2132:             }
 2133:             // the visible region of default user space
 2134:             if (isset($format['CropBox'])) {
 2135:                 $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);
 2136:             }
 2137:             // the region to which the contents of the page shall be clipped when output in a production environment
 2138:             if (isset($format['BleedBox'])) {
 2139:                 $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);
 2140:             }
 2141:             // the intended dimensions of the finished page after trimming
 2142:             if (isset($format['TrimBox'])) {
 2143:                 $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);
 2144:             }
 2145:             // the page's meaningful content (including potential white space)
 2146:             if (isset($format['ArtBox'])) {
 2147:                 $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);
 2148:             }
 2149:             // specify the colours and other visual characteristics that should be used in displaying guidelines on the screen for the various page boundaries
 2150:             if (isset($format['BoxColorInfo'])) {
 2151:                 $this->pagedim[$this->page]['BoxColorInfo'] = $format['BoxColorInfo'];
 2152:             }
 2153:             if (isset($format['Rotate']) AND (($format['Rotate'] % 90) == 0)) {
 2154:                 // The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.
 2155:                 $this->pagedim[$this->page]['Rotate'] = intval($format['Rotate']);
 2156:             }
 2157:             if (isset($format['PZ'])) {
 2158:                 // The page's preferred zoom (magnification) factor
 2159:                 $this->pagedim[$this->page]['PZ'] = floatval($format['PZ']);
 2160:             }
 2161:             if (isset($format['trans'])) {
 2162:                 // The style and duration of the visual transition to use when moving from another page to the given page during a presentation
 2163:                 if (isset($format['trans']['Dur'])) {
 2164:                     // The page's display duration
 2165:                     $this->pagedim[$this->page]['trans']['Dur'] = floatval($format['trans']['Dur']);
 2166:                 }
 2167:                 $stansition_styles = array('Split', 'Blinds', 'Box', 'Wipe', 'Dissolve', 'Glitter', 'R', 'Fly', 'Push', 'Cover', 'Uncover', 'Fade');
 2168:                 if (isset($format['trans']['S']) AND in_array($format['trans']['S'], $stansition_styles)) {
 2169:                     // The transition style that shall be used when moving to this page from another during a presentation
 2170:                     $this->pagedim[$this->page]['trans']['S'] = $format['trans']['S'];
 2171:                     $valid_effect = array('Split', 'Blinds');
 2172:                     $valid_vals = array('H', 'V');
 2173:                     if (isset($format['trans']['Dm']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['Dm'], $valid_vals)) {
 2174:                         $this->pagedim[$this->page]['trans']['Dm'] = $format['trans']['Dm'];
 2175:                     }
 2176:                     $valid_effect = array('Split', 'Box', 'Fly');
 2177:                     $valid_vals = array('I', 'O');
 2178:                     if (isset($format['trans']['M']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['M'], $valid_vals)) {
 2179:                         $this->pagedim[$this->page]['trans']['M'] = $format['trans']['M'];
 2180:                     }
 2181:                     $valid_effect = array('Wipe', 'Glitter', 'Fly', 'Cover', 'Uncover', 'Push');
 2182:                     if (isset($format['trans']['Di']) AND in_array($format['trans']['S'], $valid_effect)) {
 2183:                         if (((($format['trans']['Di'] == 90) OR ($format['trans']['Di'] == 180)) AND ($format['trans']['S'] == 'Wipe'))
 2184:                             OR (($format['trans']['Di'] == 315) AND ($format['trans']['S'] == 'Glitter'))
 2185:                             OR (($format['trans']['Di'] == 0) OR ($format['trans']['Di'] == 270))) {
 2186:                             $this->pagedim[$this->page]['trans']['Di'] = intval($format['trans']['Di']);
 2187:                         }
 2188:                     }
 2189:                     if (isset($format['trans']['SS']) AND ($format['trans']['S'] == 'Fly')) {
 2190:                         $this->pagedim[$this->page]['trans']['SS'] = floatval($format['trans']['SS']);
 2191:                     }
 2192:                     if (isset($format['trans']['B']) AND ($format['trans']['B'] === true) AND ($format['trans']['S'] == 'Fly')) {
 2193:                         $this->pagedim[$this->page]['trans']['B'] = 'true';
 2194:                     }
 2195:                 } else {
 2196:                     $this->pagedim[$this->page]['trans']['S'] = 'R';
 2197:                 }
 2198:                 if (isset($format['trans']['D'])) {
 2199:                     // The duration of the transition effect, in seconds
 2200:                     $this->pagedim[$this->page]['trans']['D'] = floatval($format['trans']['D']);
 2201:                 } else {
 2202:                     $this->pagedim[$this->page]['trans']['D'] = 1;
 2203:                 }
 2204:             }
 2205:         }
 2206:         $this->setPageOrientation($orientation);
 2207:     }
 2208: 
 2209:     /**
 2210:      * Set page orientation.
 2211:      * @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>
 2212:      * @param $autopagebreak (boolean) Boolean indicating if auto-page-break mode should be on or off.
 2213:      * @param $bottommargin (float) bottom margin of the page.
 2214:      * @public
 2215:      * @since 3.0.015 (2008-06-06)
 2216:      */
 2217:     public function setPageOrientation($orientation, $autopagebreak='', $bottommargin='') {
 2218:         if (!isset($this->pagedim[$this->page]['MediaBox'])) {
 2219:             // the boundaries of the physical medium on which the page shall be displayed or printed
 2220:             $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim);
 2221:         }
 2222:         if (!isset($this->pagedim[$this->page]['CropBox'])) {
 2223:             // the visible region of default user space
 2224:             $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);
 2225:         }
 2226:         if (!isset($this->pagedim[$this->page]['BleedBox'])) {
 2227:             // the region to which the contents of the page shall be clipped when output in a production environment
 2228:             $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);
 2229:         }
 2230:         if (!isset($this->pagedim[$this->page]['TrimBox'])) {
 2231:             // the intended dimensions of the finished page after trimming
 2232:             $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);
 2233:         }
 2234:         if (!isset($this->pagedim[$this->page]['ArtBox'])) {
 2235:             // the page's meaningful content (including potential white space)
 2236:             $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);
 2237:         }
 2238:         if (!isset($this->pagedim[$this->page]['Rotate'])) {
 2239:             // The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.
 2240:             $this->pagedim[$this->page]['Rotate'] = 0;
 2241:         }
 2242:         if (!isset($this->pagedim[$this->page]['PZ'])) {
 2243:             // The page's preferred zoom (magnification) factor
 2244:             $this->pagedim[$this->page]['PZ'] = 1;
 2245:         }
 2246:         if ($this->fwPt > $this->fhPt) {
 2247:             // landscape
 2248:             $default_orientation = 'L';
 2249:         } else {
 2250:             // portrait
 2251:             $default_orientation = 'P';
 2252:         }
 2253:         $valid_orientations = array('P', 'L');
 2254:         if (empty($orientation)) {
 2255:             $orientation = $default_orientation;
 2256:         } else {
 2257:             $orientation = strtoupper($orientation[0]);
 2258:         }
 2259:         if (in_array($orientation, $valid_orientations) AND ($orientation != $default_orientation)) {
 2260:             $this->CurOrientation = $orientation;
 2261:             $this->wPt = $this->fhPt;
 2262:             $this->hPt = $this->fwPt;
 2263:         } else {
 2264:             $this->CurOrientation = $default_orientation;
 2265:             $this->wPt = $this->fwPt;
 2266:             $this->hPt = $this->fhPt;
 2267:         }
 2268:         if ((abs($this->pagedim[$this->page]['MediaBox']['urx'] - $this->hPt) < $this->feps) AND (abs($this->pagedim[$this->page]['MediaBox']['ury'] - $this->wPt) < $this->feps)){
 2269:             // swap X and Y coordinates (change page orientation)
 2270:             $this->pagedim = TCPDF_STATIC::swapPageBoxCoordinates($this->page, $this->pagedim);
 2271:         }
 2272:         $this->w = ($this->wPt / $this->k);
 2273:         $this->h = ($this->hPt / $this->k);
 2274:         if (TCPDF_STATIC::empty_string($autopagebreak)) {
 2275:             if (isset($this->AutoPageBreak)) {
 2276:                 $autopagebreak = $this->AutoPageBreak;
 2277:             } else {
 2278:                 $autopagebreak = true;
 2279:             }
 2280:         }
 2281:         if (TCPDF_STATIC::empty_string($bottommargin)) {
 2282:             if (isset($this->bMargin)) {
 2283:                 $bottommargin = $this->bMargin;
 2284:             } else {
 2285:                 // default value = 2 cm
 2286:                 $bottommargin = 2 * 28.35 / $this->k;
 2287:             }
 2288:         }
 2289:         $this->SetAutoPageBreak($autopagebreak, $bottommargin);
 2290:         // store page dimensions
 2291:         $this->pagedim[$this->page]['w'] = $this->wPt;
 2292:         $this->pagedim[$this->page]['h'] = $this->hPt;
 2293:         $this->pagedim[$this->page]['wk'] = $this->w;
 2294:         $this->pagedim[$this->page]['hk'] = $this->h;
 2295:         $this->pagedim[$this->page]['tm'] = $this->tMargin;
 2296:         $this->pagedim[$this->page]['bm'] = $bottommargin;
 2297:         $this->pagedim[$this->page]['lm'] = $this->lMargin;
 2298:         $this->pagedim[$this->page]['rm'] = $this->rMargin;
 2299:         $this->pagedim[$this->page]['pb'] = $autopagebreak;
 2300:         $this->pagedim[$this->page]['or'] = $this->CurOrientation;
 2301:         $this->pagedim[$this->page]['olm'] = $this->original_lMargin;
 2302:         $this->pagedim[$this->page]['orm'] = $this->original_rMargin;
 2303:     }
 2304: 
 2305:     /**
 2306:      * Set regular expression to detect withespaces or word separators.
 2307:      * The pattern delimiter must be the forward-slash character "/".
 2308:      * Some example patterns are:
 2309:      * <pre>
 2310:      * Non-Unicode or missing PCRE unicode support: "/[^\S\xa0]/"
 2311:      * Unicode and PCRE unicode support: "/(?!\xa0)[\s\p{Z}]/u"
 2312:      * Unicode and PCRE unicode support in Chinese mode: "/(?!\xa0)[\s\p{Z}\p{Lo}]/u"
 2313:      * if PCRE unicode support is turned ON ("\P" is the negate class of "\p"):
 2314:      *      \s     : any whitespace character
 2315:      *      \p{Z}  : any separator
 2316:      *      \p{Lo} : Unicode letter or ideograph that does not have lowercase and uppercase variants. Is used to chunk chinese words.
 2317:      *      \xa0   : Unicode Character 'NO-BREAK SPACE' (U+00A0)
 2318:      * </pre>
 2319:      * @param $re (string) regular expression (leave empty for default).
 2320:      * @public
 2321:      * @since 4.6.016 (2009-06-15)
 2322:      */
 2323:     public function setSpacesRE($re='/[^\S\xa0]/') {
 2324:         $this->re_spaces = $re;
 2325:         $re_parts = explode('/', $re);
 2326:         // get pattern parts
 2327:         $this->re_space = array();
 2328:         if (isset($re_parts[1]) AND !empty($re_parts[1])) {
 2329:             $this->re_space['p'] = $re_parts[1];
 2330:         } else {
 2331:             $this->re_space['p'] = '[\s]';
 2332:         }
 2333:         // set pattern modifiers
 2334:         if (isset($re_parts[2]) AND !empty($re_parts[2])) {
 2335:             $this->re_space['m'] = $re_parts[2];
 2336:         } else {
 2337:             $this->re_space['m'] = '';
 2338:         }
 2339:     }
 2340: 
 2341:     /**
 2342:      * Enable or disable Right-To-Left language mode
 2343:      * @param $enable (Boolean) if true enable Right-To-Left language mode.
 2344:      * @param $resetx (Boolean) if true reset the X position on direction change.
 2345:      * @public
 2346:      * @since 2.0.000 (2008-01-03)
 2347:      */
 2348:     public function setRTL($enable, $resetx=true) {
 2349:         $enable = $enable ? true : false;
 2350:         $resetx = ($resetx AND ($enable != $this->rtl));
 2351:         $this->rtl = $enable;
 2352:         $this->tmprtl = false;
 2353:         if ($resetx) {
 2354:             $this->Ln(0);
 2355:         }
 2356:     }
 2357: 
 2358:     /**
 2359:      * Return the RTL status
 2360:      * @return boolean
 2361:      * @public
 2362:      * @since 4.0.012 (2008-07-24)
 2363:      */
 2364:     public function getRTL() {
 2365:         return $this->rtl;
 2366:     }
 2367: 
 2368:     /**
 2369:      * Force temporary RTL language direction
 2370:      * @param $mode (mixed) can be false, 'L' for LTR or 'R' for RTL
 2371:      * @public
 2372:      * @since 2.1.000 (2008-01-09)
 2373:      */
 2374:     public function setTempRTL($mode) {
 2375:         $newmode = false;
 2376:         switch (strtoupper($mode)) {
 2377:             case 'LTR':
 2378:             case 'L': {
 2379:                 if ($this->rtl) {
 2380:                     $newmode = 'L';
 2381:                 }
 2382:                 break;
 2383:             }
 2384:             case 'RTL':
 2385:             case 'R': {
 2386:                 if (!$this->rtl) {
 2387:                     $newmode = 'R';
 2388:                 }
 2389:                 break;
 2390:             }
 2391:             case false:
 2392:             default: {
 2393:                 $newmode = false;
 2394:                 break;
 2395:             }
 2396:         }
 2397:         $this->tmprtl = $newmode;
 2398:     }
 2399: 
 2400:     /**
 2401:      * Return the current temporary RTL status
 2402:      * @return boolean
 2403:      * @public
 2404:      * @since 4.8.014 (2009-11-04)
 2405:      */
 2406:     public function isRTLTextDir() {
 2407:         return ($this->rtl OR ($this->tmprtl == 'R'));
 2408:     }
 2409: 
 2410:     /**
 2411:      * Set the last cell height.
 2412:      * @param $h (float) cell height.
 2413:      * @author Nicola Asuni
 2414:      * @public
 2415:      * @since 1.53.0.TC034
 2416:      */
 2417:     public function setLastH($h) {
 2418:         $this->lasth = $h;
 2419:     }
 2420: 
 2421:     /**
 2422:      * Return the cell height
 2423:      * @param $fontsize (int) Font size in internal units
 2424:      * @param $padding (boolean) If true add cell padding
 2425:      * @public
 2426:      */
 2427:     public function getCellHeight($fontsize, $padding=TRUE) {
 2428:         $height = ($fontsize * $this->cell_height_ratio);
 2429:         if ($padding) {
 2430:             $height += ($this->cell_padding['T'] + $this->cell_padding['B']);
 2431:         }
 2432:         return round($height, 6);
 2433:     }
 2434: 
 2435:     /**
 2436:      * Reset the last cell height.
 2437:      * @public
 2438:      * @since 5.9.000 (2010-10-03)
 2439:      */
 2440:     public function resetLastH() {
 2441:         $this->lasth = $this->getCellHeight($this->FontSize);
 2442:     }
 2443: 
 2444:     /**
 2445:      * Get the last cell height.
 2446:      * @return last cell height
 2447:      * @public
 2448:      * @since 4.0.017 (2008-08-05)
 2449:      */
 2450:     public function getLastH() {
 2451:         return $this->lasth;
 2452:     }
 2453: 
 2454:     /**
 2455:      * Set the adjusting factor to convert pixels to user units.
 2456:      * @param $scale (float) adjusting factor to convert pixels to user units.
 2457:      * @author Nicola Asuni
 2458:      * @public
 2459:      * @since 1.5.2
 2460:      */
 2461:     public function setImageScale($scale) {
 2462:         $this->imgscale = $scale;
 2463:     }
 2464: 
 2465:     /**
 2466:      * Returns the adjusting factor to convert pixels to user units.
 2467:      * @return float adjusting factor to convert pixels to user units.
 2468:      * @author Nicola Asuni
 2469:      * @public
 2470:      * @since 1.5.2
 2471:      */
 2472:     public function getImageScale() {
 2473:         return $this->imgscale;
 2474:     }
 2475: 
 2476:     /**
 2477:      * Returns an array of page dimensions:
 2478:      * <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>
 2479:      * @param $pagenum (int) page number (empty = current page)
 2480:      * @return array of page dimensions.
 2481:      * @author Nicola Asuni
 2482:      * @public
 2483:      * @since 4.5.027 (2009-03-16)
 2484:      */
 2485:     public function getPageDimensions($pagenum='') {
 2486:         if (empty($pagenum)) {
 2487:             $pagenum = $this->page;
 2488:         }
 2489:         return $this->pagedim[$pagenum];
 2490:     }
 2491: 
 2492:     /**
 2493:      * Returns the page width in units.
 2494:      * @param $pagenum (int) page number (empty = current page)
 2495:      * @return int page width.
 2496:      * @author Nicola Asuni
 2497:      * @public
 2498:      * @since 1.5.2
 2499:      * @see getPageDimensions()
 2500:      */
 2501:     public function getPageWidth($pagenum='') {
 2502:         if (empty($pagenum)) {
 2503:             return $this->w;
 2504:         }
 2505:         return $this->pagedim[$pagenum]['w'];
 2506:     }
 2507: 
 2508:     /**
 2509:      * Returns the page height in units.
 2510:      * @param $pagenum (int) page number (empty = current page)
 2511:      * @return int page height.
 2512:      * @author Nicola Asuni
 2513:      * @public
 2514:      * @since 1.5.2
 2515:      * @see getPageDimensions()
 2516:      */
 2517:     public function getPageHeight($pagenum='') {
 2518:         if (empty($pagenum)) {
 2519:             return $this->h;
 2520:         }
 2521:         return $this->pagedim[$pagenum]['h'];
 2522:     }
 2523: 
 2524:     /**
 2525:      * Returns the page break margin.
 2526:      * @param $pagenum (int) page number (empty = current page)
 2527:      * @return int page break margin.
 2528:      * @author Nicola Asuni
 2529:      * @public
 2530:      * @since 1.5.2
 2531:      * @see getPageDimensions()
 2532:      */
 2533:     public function getBreakMargin($pagenum='') {
 2534:         if (empty($pagenum)) {
 2535:             return $this->bMargin;
 2536:         }
 2537:         return $this->pagedim[$pagenum]['bm'];
 2538:     }
 2539: 
 2540:     /**
 2541:      * Returns the scale factor (number of points in user unit).
 2542:      * @return int scale factor.
 2543:      * @author Nicola Asuni
 2544:      * @public
 2545:      * @since 1.5.2
 2546:      */
 2547:     public function getScaleFactor() {
 2548:         return $this->k;
 2549:     }
 2550: 
 2551:     /**
 2552:      * Defines the left, top and right margins.
 2553:      * @param $left (float) Left margin.
 2554:      * @param $top (float) Top margin.
 2555:      * @param $right (float) Right margin. Default value is the left one.
 2556:      * @param $keepmargins (boolean) if true overwrites the default page margins
 2557:      * @public
 2558:      * @since 1.0
 2559:      * @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak()
 2560:      */
 2561:     public function SetMargins($left, $top, $right=-1, $keepmargins=false) {
 2562:         //Set left, top and right margins
 2563:         $this->lMargin = $left;
 2564:         $this->tMargin = $top;
 2565:         if ($right == -1) {
 2566:             $right = $left;
 2567:         }
 2568:         $this->rMargin = $right;
 2569:         if ($keepmargins) {
 2570:             // overwrite original values
 2571:             $this->original_lMargin = $this->lMargin;
 2572:             $this->original_rMargin = $this->rMargin;
 2573:         }
 2574:     }
 2575: 
 2576:     /**
 2577:      * 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.
 2578:      * @param $margin (float) The margin.
 2579:      * @public
 2580:      * @since 1.4
 2581:      * @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
 2582:      */
 2583:     public function SetLeftMargin($margin) {
 2584:         //Set left margin
 2585:         $this->lMargin = $margin;
 2586:         if (($this->page > 0) AND ($this->x < $margin)) {
 2587:             $this->x = $margin;
 2588:         }
 2589:     }
 2590: 
 2591:     /**
 2592:      * Defines the top margin. The method can be called before creating the first page.
 2593:      * @param $margin (float) The margin.
 2594:      * @public
 2595:      * @since 1.5
 2596:      * @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()
 2597:      */
 2598:     public function SetTopMargin($margin) {
 2599:         //Set top margin
 2600:         $this->tMargin = $margin;
 2601:         if (($this->page > 0) AND ($this->y < $margin)) {
 2602:             $this->y = $margin;
 2603:         }
 2604:     }
 2605: 
 2606:     /**
 2607:      * Defines the right margin. The method can be called before creating the first page.
 2608:      * @param $margin (float) The margin.
 2609:      * @public
 2610:      * @since 1.5
 2611:      * @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()
 2612:      */
 2613:     public function SetRightMargin($margin) {
 2614:         $this->rMargin = $margin;
 2615:         if (($this->page > 0) AND ($this->x > ($this->w - $margin))) {
 2616:             $this->x = $this->w - $margin;
 2617:         }
 2618:     }
 2619: 
 2620:     /**
 2621:      * Set the same internal Cell padding for top, right, bottom, left-
 2622:      * @param $pad (float) internal padding.
 2623:      * @public
 2624:      * @since 2.1.000 (2008-01-09)
 2625:      * @see getCellPaddings(), setCellPaddings()
 2626:      */
 2627:     public function SetCellPadding($pad) {
 2628:         if ($pad >= 0) {
 2629:             $this->cell_padding['L'] = $pad;
 2630:             $this->cell_padding['T'] = $pad;
 2631:             $this->cell_padding['R'] = $pad;
 2632:             $this->cell_padding['B'] = $pad;
 2633:         }
 2634:     }
 2635: 
 2636:     /**
 2637:      * Set the internal Cell paddings.
 2638:      * @param $left (float) left padding
 2639:      * @param $top (float) top padding
 2640:      * @param $right (float) right padding
 2641:      * @param $bottom (float) bottom padding
 2642:      * @public
 2643:      * @since 5.9.000 (2010-10-03)
 2644:      * @see getCellPaddings(), SetCellPadding()
 2645:      */
 2646:     public function setCellPaddings($left='', $top='', $right='', $bottom='') {
 2647:         if (($left !== '') AND ($left >= 0)) {
 2648:             $this->cell_padding['L'] = $left;
 2649:         }
 2650:         if (($top !== '') AND ($top >= 0)) {
 2651:             $this->cell_padding['T'] = $top;
 2652:         }
 2653:         if (($right !== '') AND ($right >= 0)) {
 2654:             $this->cell_padding['R'] = $right;
 2655:         }
 2656:         if (($bottom !== '') AND ($bottom >= 0)) {
 2657:             $this->cell_padding['B'] = $bottom;
 2658:         }
 2659:     }
 2660: 
 2661:     /**
 2662:      * Get the internal Cell padding array.
 2663:      * @return array of padding values
 2664:      * @public
 2665:      * @since 5.9.000 (2010-10-03)
 2666:      * @see setCellPaddings(), SetCellPadding()
 2667:      */
 2668:     public function getCellPaddings() {
 2669:         return $this->cell_padding;
 2670:     }
 2671: 
 2672:     /**
 2673:      * Set the internal Cell margins.
 2674:      * @param $left (float) left margin
 2675:      * @param $top (float) top margin
 2676:      * @param $right (float) right margin
 2677:      * @param $bottom (float) bottom margin
 2678:      * @public
 2679:      * @since 5.9.000 (2010-10-03)
 2680:      * @see getCellMargins()
 2681:      */
 2682:     public function setCellMargins($left='', $top='', $right='', $bottom='') {
 2683:         if (($left !== '') AND ($left >= 0)) {
 2684:             $this->cell_margin['L'] = $left;
 2685:         }
 2686:         if (($top !== '') AND ($top >= 0)) {
 2687:             $this->cell_margin['T'] = $top;
 2688:         }
 2689:         if (($right !== '') AND ($right >= 0)) {
 2690:             $this->cell_margin['R'] = $right;
 2691:         }
 2692:         if (($bottom !== '') AND ($bottom >= 0)) {
 2693:             $this->cell_margin['B'] = $bottom;
 2694:         }
 2695:     }
 2696: 
 2697:     /**
 2698:      * Get the internal Cell margin array.
 2699:      * @return array of margin values
 2700:      * @public
 2701:      * @since 5.9.000 (2010-10-03)
 2702:      * @see setCellMargins()
 2703:      */
 2704:     public function getCellMargins() {
 2705:         return $this->cell_margin;
 2706:     }
 2707: 
 2708:     /**
 2709:      * Adjust the internal Cell padding array to take account of the line width.
 2710:      * @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)))
 2711:      * @return array of adjustments
 2712:      * @public
 2713:      * @since 5.9.000 (2010-10-03)
 2714:      */
 2715:     protected function adjustCellPadding($brd=0) {
 2716:         if (empty($brd)) {
 2717:             return;
 2718:         }
 2719:         if (is_string($brd)) {
 2720:             // convert string to array
 2721:             $slen = strlen($brd);
 2722:             $newbrd = array();
 2723:             for ($i = 0; $i < $slen; ++$i) {
 2724:                 $newbrd[$brd[$i]] = true;
 2725:             }
 2726:             $brd = $newbrd;
 2727:         } elseif (($brd === 1) OR ($brd === true) OR (is_numeric($brd) AND (intval($brd) > 0))) {
 2728:             $brd = array('LRTB' => true);
 2729:         }
 2730:         if (!is_array($brd)) {
 2731:             return;
 2732:         }
 2733:         // store current cell padding
 2734:         $cp = $this->cell_padding;
 2735:         // select border mode
 2736:         if (isset($brd['mode'])) {
 2737:             $mode = $brd['mode'];
 2738:             unset($brd['mode']);
 2739:         } else {
 2740:             $mode = 'normal';
 2741:         }
 2742:         // process borders
 2743:         foreach ($brd as $border => $style) {
 2744:             $line_width = $this->LineWidth;
 2745:             if (is_array($style) AND isset($style['width'])) {
 2746:                 // get border width
 2747:                 $line_width = $style['width'];
 2748:             }
 2749:             $adj = 0; // line width inside the cell
 2750:             switch ($mode) {
 2751:                 case 'ext': {
 2752:                     $adj = 0;
 2753:                     break;
 2754:                 }
 2755:                 case 'int': {
 2756:                     $adj = $line_width;
 2757:                     break;
 2758:                 }
 2759:                 case 'normal':
 2760:                 default: {
 2761:                     $adj = ($line_width / 2);
 2762:                     break;
 2763:                 }
 2764:             }
 2765:             // correct internal cell padding if required to avoid overlap between text and lines
 2766:             if ((strpos($border,'T') !== false) AND ($this->cell_padding['T'] < $adj)) {
 2767:                 $this->cell_padding['T'] = $adj;
 2768:             }
 2769:             if ((strpos($border,'R') !== false) AND ($this->cell_padding['R'] < $adj)) {
 2770:                 $this->cell_padding['R'] = $adj;
 2771:             }
 2772:             if ((strpos($border,'B') !== false) AND ($this->cell_padding['B'] < $adj)) {
 2773:                 $this->cell_padding['B'] = $adj;
 2774:             }
 2775:             if ((strpos($border,'L') !== false) AND ($this->cell_padding['L'] < $adj)) {
 2776:                 $this->cell_padding['L'] = $adj;
 2777:             }
 2778:         }
 2779:         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']));
 2780:     }
 2781: 
 2782:     /**
 2783:      * 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.
 2784:      * @param $auto (boolean) Boolean indicating if mode should be on or off.
 2785:      * @param $margin (float) Distance from the bottom of the page.
 2786:      * @public
 2787:      * @since 1.0
 2788:      * @see Cell(), MultiCell(), AcceptPageBreak()
 2789:      */
 2790:     public function SetAutoPageBreak($auto, $margin=0) {
 2791:         $this->AutoPageBreak = $auto ? true : false;
 2792:         $this->bMargin = $margin;
 2793:         $this->PageBreakTrigger = $this->h - $margin;
 2794:     }
 2795: 
 2796:     /**
 2797:      * Return the auto-page-break mode (true or false).
 2798:      * @return boolean auto-page-break mode
 2799:      * @public
 2800:      * @since 5.9.088
 2801:      */
 2802:     public function getAutoPageBreak() {
 2803:         return $this->AutoPageBreak;
 2804:     }
 2805: 
 2806:     /**
 2807:      * Defines the way the document is to be displayed by the viewer.
 2808:      * @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>
 2809:      * @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>
 2810:      * @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>
 2811:      * @public
 2812:      * @since 1.2
 2813:      */
 2814:     public function SetDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') {
 2815:         if (($zoom == 'fullpage') OR ($zoom == 'fullwidth') OR ($zoom == 'real') OR ($zoom == 'default') OR (!is_string($zoom))) {
 2816:             $this->ZoomMode = $zoom;
 2817:         } else {
 2818:             $this->Error('Incorrect zoom display mode: '.$zoom);
 2819:         }
 2820:         $this->LayoutMode = TCPDF_STATIC::getPageLayoutMode($layout);
 2821:         $this->PageMode = TCPDF_STATIC::getPageMode($mode);
 2822:     }
 2823: 
 2824:     /**
 2825:      * 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.
 2826:      * Note: the Zlib extension is required for this feature. If not present, compression will be turned off.
 2827:      * @param $compress (boolean) Boolean indicating if compression must be enabled.
 2828:      * @public
 2829:      * @since 1.4
 2830:      */
 2831:     public function SetCompression($compress=true) {
 2832:         if (function_exists('gzcompress')) {
 2833:             $this->compress = $compress ? true : false;
 2834:         } else {
 2835:             $this->compress = false;
 2836:         }
 2837:     }
 2838: 
 2839:     /**
 2840:      * Set flag to force sRGB_IEC61966-2.1 black scaled ICC color profile for the whole document.
 2841:      * @param $mode (boolean) If true force sRGB output intent.
 2842:      * @public
 2843:      * @since 5.9.121 (2011-09-28)
 2844:      */
 2845:     public function setSRGBmode($mode=false) {
 2846:         $this->force_srgb = $mode ? true : false;
 2847:     }
 2848: 
 2849:     /**
 2850:      * Turn on/off Unicode mode for document information dictionary (meta tags).
 2851:      * This has effect only when unicode mode is set to false.
 2852:      * @param $unicode (boolean) if true set the meta information in Unicode
 2853:      * @since 5.9.027 (2010-12-01)
 2854:      * @public
 2855:      */
 2856:     public function SetDocInfoUnicode($unicode=true) {
 2857:         $this->docinfounicode = $unicode ? true : false;
 2858:     }
 2859: 
 2860:     /**
 2861:      * Defines the title of the document.
 2862:      * @param $title (string) The title.
 2863:      * @public
 2864:      * @since 1.2
 2865:      * @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject()
 2866:      */
 2867:     public function SetTitle($title) {
 2868:         $this->title = $title;
 2869:     }
 2870: 
 2871:     /**
 2872:      * Defines the subject of the document.
 2873:      * @param $subject (string) The subject.
 2874:      * @public
 2875:      * @since 1.2
 2876:      * @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle()
 2877:      */
 2878:     public function SetSubject($subject) {
 2879:         $this->subject = $subject;
 2880:     }
 2881: 
 2882:     /**
 2883:      * Defines the author of the document.
 2884:      * @param $author (string) The name of the author.
 2885:      * @public
 2886:      * @since 1.2
 2887:      * @see SetCreator(), SetKeywords(), SetSubject(), SetTitle()
 2888:      */
 2889:     public function SetAuthor($author) {
 2890:         $this->author = $author;
 2891:     }
 2892: 
 2893:     /**
 2894:      * Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'.
 2895:      * @param $keywords (string) The list of keywords.
 2896:      * @public
 2897:      * @since 1.2
 2898:      * @see SetAuthor(), SetCreator(), SetSubject(), SetTitle()
 2899:      */
 2900:     public function SetKeywords($keywords) {
 2901:         $this->keywords = $keywords;
 2902:     }
 2903: 
 2904:     /**
 2905:      * Defines the creator of the document. This is typically the name of the application that generates the PDF.
 2906:      * @param $creator (string) The name of the creator.
 2907:      * @public
 2908:      * @since 1.2
 2909:      * @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle()
 2910:      */
 2911:     public function SetCreator($creator) {
 2912:         $this->creator = $creator;
 2913:     }
 2914: 
 2915:     /**
 2916:      * Throw an exception or print an error message and die if the K_TCPDF_PARSER_THROW_EXCEPTION_ERROR constant is set to true.
 2917:      * @param $msg (string) The error message
 2918:      * @public
 2919:      * @since 1.0
 2920:      */
 2921:     public function Error($msg) {
 2922:         // unset all class variables
 2923:         $this->_destroy(true);
 2924:         if (defined('K_TCPDF_THROW_EXCEPTION_ERROR') AND !K_TCPDF_THROW_EXCEPTION_ERROR) {
 2925:             die('<strong>TCPDF ERROR: </strong>'.$msg);
 2926:         } else {
 2927:             throw new Exception('TCPDF ERROR: '.$msg);
 2928:         }
 2929:     }
 2930: 
 2931:     /**
 2932:      * This method begins the generation of the PDF document.
 2933:      * It is not necessary to call it explicitly because AddPage() does it automatically.
 2934:      * Note: no page is created by this method
 2935:      * @public
 2936:      * @since 1.0
 2937:      * @see AddPage(), Close()
 2938:      */
 2939:     public function Open() {
 2940:         $this->state = 1;
 2941:     }
 2942: 
 2943:     /**
 2944:      * Terminates the PDF document.
 2945:      * It is not necessary to call this method explicitly because Output() does it automatically.
 2946:      * If the document contains no page, AddPage() is called to prevent from getting an invalid document.
 2947:      * @public
 2948:      * @since 1.0
 2949:      * @see Open(), Output()
 2950:      */
 2951:     public function Close() {
 2952:         if ($this->state == 3) {
 2953:             return;
 2954:         }
 2955:         if ($this->page == 0) {
 2956:             $this->AddPage();
 2957:         }
 2958:         $this->endLayer();
 2959:         if ($this->tcpdflink) {
 2960:             // save current graphic settings
 2961:             $gvars = $this->getGraphicVars();
 2962:             $this->setEqualColumns();
 2963:             $this->lastpage(true);
 2964:             $this->SetAutoPageBreak(false);
 2965:             $this->x = 0;
 2966:             $this->y = $this->h - (1 / $this->k);
 2967:             $this->lMargin = 0;
 2968:             $this->_outSaveGraphicsState();
 2969:             $font = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica';
 2970:             $this->SetFont($font, '', 1);
 2971:             $this->setTextRenderingMode(0, false, false);
 2972:             $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";
 2973:             $lnk = "\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67";
 2974:             $this->Cell(0, 0, $msg, 0, 0, 'L', 0, $lnk, 0, false, 'D', 'B');
 2975:             $this->_outRestoreGraphicsState();
 2976:             // restore graphic settings
 2977:             $this->setGraphicVars($gvars);
 2978:         }
 2979:         // close page
 2980:         $this->endPage();
 2981:         // close document
 2982:         $this->_enddoc();
 2983:         // unset all class variables (except critical ones)
 2984:         $this->_destroy(false);
 2985:     }
 2986: 
 2987:     /**
 2988:      * Move pointer at the specified document page and update page dimensions.
 2989:      * @param $pnum (int) page number (1 ... numpages)
 2990:      * @param $resetmargins (boolean) if true reset left, right, top margins and Y position.
 2991:      * @public
 2992:      * @since 2.1.000 (2008-01-07)
 2993:      * @see getPage(), lastpage(), getNumPages()
 2994:      */
 2995:     public function setPage($pnum, $resetmargins=false) {
 2996:         if (($pnum == $this->page) AND ($this->state == 2)) {
 2997:             return;
 2998:         }
 2999:         if (($pnum > 0) AND ($pnum <= $this->numpages)) {
 3000:             $this->state = 2;
 3001:             // save current graphic settings
 3002:             //$gvars = $this->getGraphicVars();
 3003:             $oldpage = $this->page;
 3004:             $this->page = $pnum;
 3005:             $this->wPt = $this->pagedim[$this->page]['w'];
 3006:             $this->hPt = $this->pagedim[$this->page]['h'];
 3007:             $this->w = $this->pagedim[$this->page]['wk'];
 3008:             $this->h = $this->pagedim[$this->page]['hk'];
 3009:             $this->tMargin = $this->pagedim[$this->page]['tm'];
 3010:             $this->bMargin = $this->pagedim[$this->page]['bm'];
 3011:             $this->original_lMargin = $this->pagedim[$this->page]['olm'];
 3012:             $this->original_rMargin = $this->pagedim[$this->page]['orm'];
 3013:             $this->AutoPageBreak = $this->pagedim[$this->page]['pb'];
 3014:             $this->CurOrientation = $this->pagedim[$this->page]['or'];
 3015:             $this->SetAutoPageBreak($this->AutoPageBreak, $this->bMargin);
 3016:             // restore graphic settings
 3017:             //$this->setGraphicVars($gvars);
 3018:             if ($resetmargins) {
 3019:                 $this->lMargin = $this->pagedim[$this->page]['olm'];
 3020:                 $this->rMargin = $this->pagedim[$this->page]['orm'];
 3021:                 $this->SetY($this->tMargin);
 3022:             } else {
 3023:                 // account for booklet mode
 3024:                 if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
 3025:                     $deltam = $this->pagedim[$this->page]['olm'] - $this->pagedim[$this->page]['orm'];
 3026:                     $this->lMargin += $deltam;
 3027:                     $this->rMargin -= $deltam;
 3028:                 }
 3029:             }
 3030:         } else {
 3031:             $this->Error('Wrong page number on setPage() function: '.$pnum);
 3032:         }
 3033:     }
 3034: 
 3035:     /**
 3036:      * Reset pointer to the last document page.
 3037:      * @param $resetmargins (boolean) if true reset left, right, top margins and Y position.
 3038:      * @public
 3039:      * @since 2.0.000 (2008-01-04)
 3040:      * @see setPage(), getPage(), getNumPages()
 3041:      */
 3042:     public function lastPage($resetmargins=false) {
 3043:         $this->setPage($this->getNumPages(), $resetmargins);
 3044:     }
 3045: 
 3046:     /**
 3047:      * Get current document page number.
 3048:      * @return int page number
 3049:      * @public
 3050:      * @since 2.1.000 (2008-01-07)
 3051:      * @see setPage(), lastpage(), getNumPages()
 3052:      */
 3053:     public function getPage() {
 3054:         return $this->page;
 3055:     }
 3056: 
 3057:     /**
 3058:      * Get the total number of insered pages.
 3059:      * @return int number of pages
 3060:      * @public
 3061:      * @since 2.1.000 (2008-01-07)
 3062:      * @see setPage(), getPage(), lastpage()
 3063:      */
 3064:     public function getNumPages() {
 3065:         return $this->numpages;
 3066:     }
 3067: 
 3068:     /**
 3069:      * Adds a new TOC (Table Of Content) page to the document.
 3070:      * @param $orientation (string) page orientation.
 3071:      * @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().
 3072:      * @param $keepmargins (boolean) if true overwrites the default page margins with the current margins
 3073:      * @public
 3074:      * @since 5.0.001 (2010-05-06)
 3075:      * @see AddPage(), startPage(), endPage(), endTOCPage()
 3076:      */
 3077:     public function addTOCPage($orientation='', $format='', $keepmargins=false) {
 3078:         $this->AddPage($orientation, $format, $keepmargins, true);
 3079:     }
 3080: 
 3081:     /**
 3082:      * Terminate the current TOC (Table Of Content) page
 3083:      * @public
 3084:      * @since 5.0.001 (2010-05-06)
 3085:      * @see AddPage(), startPage(), endPage(), addTOCPage()
 3086:      */
 3087:     public function endTOCPage() {
 3088:         $this->endPage(true);
 3089:     }
 3090: 
 3091:     /**
 3092:      * 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).
 3093:      * The origin of the coordinate system is at the top-left corner (or top-right for RTL) and increasing ordinates go downwards.
 3094:      * @param $orientation (string) page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul>
 3095:      * @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().
 3096:      * @param $keepmargins (boolean) if true overwrites the default page margins with the current margins
 3097:      * @param $tocpage (boolean) if true set the tocpage state to true (the added page will be used to display Table Of Content).
 3098:      * @public
 3099:      * @since 1.0
 3100:      * @see startPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat()
 3101:      */
 3102:     public function AddPage($orientation='', $format='', $keepmargins=false, $tocpage=false) {
 3103:         if ($this->inxobj) {
 3104:             // we are inside an XObject template
 3105:             return;
 3106:         }
 3107:         if (!isset($this->original_lMargin) OR $keepmargins) {
 3108:             $this->original_lMargin = $this->lMargin;
 3109:         }
 3110:         if (!isset($this->original_rMargin) OR $keepmargins) {
 3111:             $this->original_rMargin = $this->rMargin;
 3112:         }
 3113:         // terminate previous page
 3114:         $this->endPage();
 3115:         // start new page
 3116:         $this->startPage($orientation, $format, $tocpage);
 3117:     }
 3118: 
 3119:     /**
 3120:      * Terminate the current page
 3121:      * @param $tocpage (boolean) if true set the tocpage state to false (end the page used to display Table Of Content).
 3122:      * @public
 3123:      * @since 4.2.010 (2008-11-14)
 3124:      * @see AddPage(), startPage(), addTOCPage(), endTOCPage()
 3125:      */
 3126:     public function endPage($tocpage=false) {
 3127:         // check if page is already closed
 3128:         if (($this->page == 0) OR ($this->numpages > $this->page) OR (!$this->pageopen[$this->page])) {
 3129:             return;
 3130:         }
 3131:         // print page footer
 3132:         $this->setFooter();
 3133:         // close page
 3134:         $this->_endpage();
 3135:         // mark page as closed
 3136:         $this->pageopen[$this->page] = false;
 3137:         if ($tocpage) {
 3138:             $this->tocpage = false;
 3139:         }
 3140:     }
 3141: 
 3142:     /**
 3143:      * Starts a new page to the document. The page must be closed using the endPage() function.
 3144:      * The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards.
 3145:      * @param $orientation (string) page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul>
 3146:      * @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().
 3147:      * @param $tocpage (boolean) if true the page is designated to contain the Table-Of-Content.
 3148:      * @since 4.2.010 (2008-11-14)
 3149:      * @see AddPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat()
 3150:      * @public
 3151:      */
 3152:     public function startPage($orientation='', $format='', $tocpage=false) {
 3153:         if ($tocpage) {
 3154:             $this->tocpage = true;
 3155:         }
 3156:         // move page numbers of documents to be attached
 3157:         if ($this->tocpage) {
 3158:             // move reference to unexistent pages (used for page attachments)
 3159:             // adjust outlines
 3160:             $tmpoutlines = $this->outlines;
 3161:             foreach ($tmpoutlines as $key => $outline) {
 3162:                 if (!$outline['f'] AND ($outline['p'] > $this->numpages)) {
 3163:                     $this->outlines[$key]['p'] = ($outline['p'] + 1);
 3164:                 }
 3165:             }
 3166:             // adjust dests
 3167:             $tmpdests = $this->dests;
 3168:             foreach ($tmpdests as $key => $dest) {
 3169:                 if (!$dest['f'] AND ($dest['p'] > $this->numpages)) {
 3170:                     $this->dests[$key]['p'] = ($dest['p'] + 1);
 3171:                 }
 3172:             }
 3173:             // adjust links
 3174:             $tmplinks = $this->links;
 3175:             foreach ($tmplinks as $key => $link) {
 3176:                 if (!$link['f'] AND ($link['p'] > $this->numpages)) {
 3177:                     $this->links[$key]['p'] = ($link['p'] + 1);
 3178:                 }
 3179:             }
 3180:         }
 3181:         if ($this->numpages > $this->page) {
 3182:             // this page has been already added
 3183:             $this->setPage($this->page + 1);
 3184:             $this->SetY($this->tMargin);
 3185:             return;
 3186:         }
 3187:         // start a new page
 3188:         if ($this->state == 0) {
 3189:             $this->Open();
 3190:         }
 3191:         ++$this->numpages;
 3192:         $this->swapMargins($this->booklet);
 3193:         // save current graphic settings
 3194:         $gvars = $this->getGraphicVars();
 3195:         // start new page
 3196:         $this->_beginpage($orientation, $format);
 3197:         // mark page as open
 3198:         $this->pageopen[$this->page] = true;
 3199:         // restore graphic settings
 3200:         $this->setGraphicVars($gvars);
 3201:         // mark this point
 3202:         $this->setPageMark();
 3203:         // print page header
 3204:         $this->setHeader();
 3205:         // restore graphic settings
 3206:         $this->setGraphicVars($gvars);
 3207:         // mark this point
 3208:         $this->setPageMark();
 3209:         // print table header (if any)
 3210:         $this->setTableHeader();
 3211:         // set mark for empty page check
 3212:         $this->emptypagemrk[$this->page]= $this->pagelen[$this->page];
 3213:     }
 3214: 
 3215:     /**
 3216:      * Set start-writing mark on current page stream used to put borders and fills.
 3217:      * Borders and fills are always created after content and inserted on the position marked by this method.
 3218:      * This function must be called after calling Image() function for a background image.
 3219:      * Background images must be always inserted before calling Multicell() or WriteHTMLCell() or WriteHTML() functions.
 3220:      * @public
 3221:      * @since 4.0.016 (2008-07-30)
 3222:      */
 3223:     public function setPageMark() {
 3224:         $this->intmrk[$this->page] = $this->pagelen[$this->page];
 3225:         $this->bordermrk[$this->page] = $this->intmrk[$this->page];
 3226:         $this->setContentMark();
 3227:     }
 3228: 
 3229:     /**
 3230:      * Set start-writing mark on selected page.
 3231:      * Borders and fills are always created after content and inserted on the position marked by this method.
 3232:      * @param $page (int) page number (default is the current page)
 3233:      * @protected
 3234:      * @since 4.6.021 (2009-07-20)
 3235:      */
 3236:     protected function setContentMark($page=0) {
 3237:         if ($page <= 0) {
 3238:             $page = $this->page;
 3239:         }
 3240:         if (isset($this->footerlen[$page])) {
 3241:             $this->cntmrk[$page] = $this->pagelen[$page] - $this->footerlen[$page];
 3242:         } else {
 3243:             $this->cntmrk[$page] = $this->pagelen[$page];
 3244:         }
 3245:     }
 3246: 
 3247:     /**
 3248:      * Set header data.
 3249:      * @param $ln (string) header image logo
 3250:      * @param $lw (string) header image logo width in mm
 3251:      * @param $ht (string) string to print as title on document header
 3252:      * @param $hs (string) string to print on document header
 3253:      * @param $tc (array) RGB array color for text.
 3254:      * @param $lc (array) RGB array color for line.
 3255:      * @public
 3256:      */
 3257:     public function setHeaderData($ln='', $lw=0, $ht='', $hs='', $tc=array(0,0,0), $lc=array(0,0,0)) {
 3258:         $this->header_logo = $ln;
 3259:         $this->header_logo_width = $lw;
 3260:         $this->header_title = $ht;
 3261:         $this->header_string = $hs;
 3262:         $this->header_text_color = $tc;
 3263:         $this->header_line_color = $lc;
 3264:     }
 3265: 
 3266:     /**
 3267:      * Set footer data.
 3268:      * @param $tc (array) RGB array color for text.
 3269:      * @param $lc (array) RGB array color for line.
 3270:      * @public
 3271:      */
 3272:     public function setFooterData($tc=array(0,0,0), $lc=array(0,0,0)) {
 3273:         $this->footer_text_color = $tc;
 3274:         $this->footer_line_color = $lc;
 3275:     }
 3276: 
 3277:     /**
 3278:      * Returns header data:
 3279:      * <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>
 3280:      * @return array()
 3281:      * @public
 3282:      * @since 4.0.012 (2008-07-24)
 3283:      */
 3284:     public function getHeaderData() {
 3285:         $ret = array();
 3286:         $ret['logo'] = $this->header_logo;
 3287:         $ret['logo_width'] = $this->header_logo_width;
 3288:         $ret['title'] = $this->header_title;
 3289:         $ret['string'] = $this->header_string;
 3290:         $ret['text_color'] = $this->header_text_color;
 3291:         $ret['line_color'] = $this->header_line_color;
 3292:         return $ret;
 3293:     }
 3294: 
 3295:     /**
 3296:      * Set header margin.
 3297:      * (minimum distance between header and top page margin)
 3298:      * @param $hm (int) distance in user units
 3299:      * @public
 3300:      */
 3301:     public function setHeaderMargin($hm=10) {
 3302:         $this->header_margin = $hm;
 3303:     }
 3304: 
 3305:     /**
 3306:      * Returns header margin in user units.
 3307:      * @return float
 3308:      * @since 4.0.012 (2008-07-24)
 3309:      * @public
 3310:      */
 3311:     public function getHeaderMargin() {
 3312:         return $this->header_margin;
 3313:     }
 3314: 
 3315:     /**
 3316:      * Set footer margin.
 3317:      * (minimum distance between footer and bottom page margin)
 3318:      * @param $fm (int) distance in user units
 3319:      * @public
 3320:      */
 3321:     public function setFooterMargin($fm=10) {
 3322:         $this->footer_margin = $fm;
 3323:     }
 3324: 
 3325:     /**
 3326:      * Returns footer margin in user units.
 3327:      * @return float
 3328:      * @since 4.0.012 (2008-07-24)
 3329:      * @public
 3330:      */
 3331:     public function getFooterMargin() {
 3332:         return $this->footer_margin;
 3333:     }
 3334:     /**
 3335:      * Set a flag to print page header.
 3336:      * @param $val (boolean) set to true to print the page header (default), false otherwise.
 3337:      * @public
 3338:      */
 3339:     public function setPrintHeader($val=true) {
 3340:         $this->print_header = $val ? true : false;
 3341:     }
 3342: 
 3343:     /**
 3344:      * Set a flag to print page footer.
 3345:      * @param $val (boolean) set to true to print the page footer (default), false otherwise.
 3346:      * @public
 3347:      */
 3348:     public function setPrintFooter($val=true) {
 3349:         $this->print_footer = $val ? true : false;
 3350:     }
 3351: 
 3352:     /**
 3353:      * Return the right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image
 3354:      * @return float
 3355:      * @public
 3356:      */
 3357:     public function getImageRBX() {
 3358:         return $this->img_rb_x;
 3359:     }
 3360: 
 3361:     /**
 3362:      * Return the right-bottom (or left-bottom for RTL) corner Y coordinate of last inserted image
 3363:      * @return float
 3364:      * @public
 3365:      */
 3366:     public function getImageRBY() {
 3367:         return $this->img_rb_y;
 3368:     }
 3369: 
 3370:     /**
 3371:      * Reset the xobject template used by Header() method.
 3372:      * @public
 3373:      */
 3374:     public function resetHeaderTemplate() {
 3375:         $this->header_xobjid = false;
 3376:     }
 3377: 
 3378:     /**
 3379:      * Set a flag to automatically reset the xobject template used by Header() method at each page.
 3380:      * @param $val (boolean) set to true to reset Header xobject template at each page, false otherwise.
 3381:      * @public
 3382:      */
 3383:     public function setHeaderTemplateAutoreset($val=true) {
 3384:         $this->header_xobj_autoreset = $val ? true : false;
 3385:     }
 3386: 
 3387:     /**
 3388:      * This method is used to render the page header.
 3389:      * It is automatically called by AddPage() and could be overwritten in your own inherited class.
 3390:      * @public
 3391:      */
 3392:     public function Header() {
 3393:         if ($this->header_xobjid === false) {
 3394:             // start a new XObject Template
 3395:             $this->header_xobjid = $this->startTemplate($this->w, $this->tMargin);
 3396:             $headerfont = $this->getHeaderFont();
 3397:             $headerdata = $this->getHeaderData();
 3398:             $this->y = $this->header_margin;
 3399:             if ($this->rtl) {
 3400:                 $this->x = $this->w - $this->original_rMargin;
 3401:             } else {
 3402:                 $this->x = $this->original_lMargin;
 3403:             }
 3404:             if (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) {
 3405:                 $imgtype = TCPDF_IMAGES::getImageFileType(K_PATH_IMAGES.$headerdata['logo']);
 3406:                 if (($imgtype == 'eps') OR ($imgtype == 'ai')) {
 3407:                     $this->ImageEps(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
 3408:                 } elseif ($imgtype == 'svg') {
 3409:                     $this->ImageSVG(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
 3410:                 } else {
 3411:                     $this->Image(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
 3412:                 }
 3413:                 $imgy = $this->getImageRBY();
 3414:             } else {
 3415:                 $imgy = $this->y;
 3416:             }
 3417:             $cell_height = $this->getCellHeight($headerfont[2] / $this->k);
 3418:             // set starting margin for text data cell
 3419:             if ($this->getRTL()) {
 3420:                 $header_x = $this->original_rMargin + ($headerdata['logo_width'] * 1.1);
 3421:             } else {
 3422:                 $header_x = $this->original_lMargin + ($headerdata['logo_width'] * 1.1);
 3423:             }
 3424:             $cw = $this->w - $this->original_lMargin - $this->original_rMargin - ($headerdata['logo_width'] * 1.1);
 3425:             $this->SetTextColorArray($this->header_text_color);
 3426:             // header title
 3427:             $this->SetFont($headerfont[0], 'B', $headerfont[2] + 1);
 3428:             $this->SetX($header_x);
 3429:             $this->Cell($cw, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0);
 3430:             // header string
 3431:             $this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]);
 3432:             $this->SetX($header_x);
 3433:             $this->MultiCell($cw, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false, true, 0, 'T', false);
 3434:             // print an ending header line
 3435:             $this->SetLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $headerdata['line_color']));
 3436:             $this->SetY((2.835 / $this->k) + max($imgy, $this->y));
 3437:             if ($this->rtl) {
 3438:                 $this->SetX($this->original_rMargin);
 3439:             } else {
 3440:                 $this->SetX($this->original_lMargin);
 3441:             }
 3442:             $this->Cell(($this->w - $this->original_lMargin - $this->original_rMargin), 0, '', 'T', 0, 'C');
 3443:             $this->endTemplate();
 3444:         }
 3445:         // print header template
 3446:         $x = 0;
 3447:         $dx = 0;
 3448:         if (!$this->header_xobj_autoreset AND $this->booklet AND (($this->page % 2) == 0)) {
 3449:             // adjust margins for booklet mode
 3450:             $dx = ($this->original_lMargin - $this->original_rMargin);
 3451:         }
 3452:         if ($this->rtl) {
 3453:             $x = $this->w + $dx;
 3454:         } else {
 3455:             $x = 0 + $dx;
 3456:         }
 3457:         $this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false);
 3458:         if ($this->header_xobj_autoreset) {
 3459:             // reset header xobject template at each page
 3460:             $this->header_xobjid = false;
 3461:         }
 3462:     }
 3463: 
 3464:     /**
 3465:      * This method is used to render the page footer.
 3466:      * It is automatically called by AddPage() and could be overwritten in your own inherited class.
 3467:      * @public
 3468:      */
 3469:     public function Footer() {
 3470:         $cur_y = $this->y;
 3471:         $this->SetTextColorArray($this->footer_text_color);
 3472:         //set style for cell border
 3473:         $line_width = (0.85 / $this->k);
 3474:         $this->SetLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $this->footer_line_color));
 3475:         //print document barcode
 3476:         $barcode = $this->getBarcode();
 3477:         if (!empty($barcode)) {
 3478:             $this->Ln($line_width);
 3479:             $barcode_width = round(($this->w - $this->original_lMargin - $this->original_rMargin) / 3);
 3480:             $style = array(
 3481:                 'position' => $this->rtl?'R':'L',
 3482:                 'align' => $this->rtl?'R':'L',
 3483:                 'stretch' => false,
 3484:                 'fitwidth' => true,
 3485:                 'cellfitalign' => '',
 3486:                 'border' => false,
 3487:                 'padding' => 0,
 3488:                 'fgcolor' => array(0,0,0),
 3489:                 'bgcolor' => false,
 3490:                 'text' => false
 3491:             );
 3492:             $this->write1DBarcode($barcode, 'C128', '', $cur_y + $line_width, '', (($this->footer_margin / 3) - $line_width), 0.3, $style, '');
 3493:         }
 3494:         $w_page = isset($this->l['w_page']) ? $this->l['w_page'].' ' : '';
 3495:         if (empty($this->pagegroups)) {
 3496:             $pagenumtxt = $w_page.$this->getAliasNumPage().' / '.$this->getAliasNbPages();
 3497:         } else {
 3498:             $pagenumtxt = $w_page.$this->getPageNumGroupAlias().' / '.$this->getPageGroupAlias();
 3499:         }
 3500:         $this->SetY($cur_y);
 3501:         //Print page number
 3502:         if ($this->getRTL()) {
 3503:             $this->SetX($this->original_rMargin);
 3504:             $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'L');
 3505:         } else {
 3506:             $this->SetX($this->original_lMargin);
 3507:             $this->Cell(0, 0, $this->getAliasRightShift().$pagenumtxt, 'T', 0, 'R');
 3508:         }
 3509:     }
 3510: 
 3511:     /**
 3512:      * This method is used to render the page header.
 3513:      * @protected
 3514:      * @since 4.0.012 (2008-07-24)
 3515:      */
 3516:     protected function setHeader() {
 3517:         if (!$this->print_header OR ($this->state != 2)) {
 3518:             return;
 3519:         }
 3520:         $this->InHeader = true;
 3521:         $this->setGraphicVars($this->default_graphic_vars);
 3522:         $temp_thead = $this->thead;
 3523:         $temp_theadMargins = $this->theadMargins;
 3524:         $lasth = $this->lasth;
 3525:         $newline = $this->newline;
 3526:         $this->_outSaveGraphicsState();
 3527:         $this->rMargin = $this->original_rMargin;
 3528:         $this->lMargin = $this->original_lMargin;
 3529:         $this->SetCellPadding(0);
 3530:         //set current position
 3531:         if ($this->rtl) {
 3532:             $this->SetXY($this->original_rMargin, $this->header_margin);
 3533:         } else {
 3534:             $this->SetXY($this->original_lMargin, $this->header_margin);
 3535:         }
 3536:         $this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]);
 3537:         $this->Header();
 3538:         //restore position
 3539:         if ($this->rtl) {
 3540:             $this->SetXY($this->original_rMargin, $this->tMargin);
 3541:         } else {
 3542:             $this->SetXY($this->original_lMargin, $this->tMargin);
 3543:         }
 3544:         $this->_outRestoreGraphicsState();
 3545:         $this->lasth = $lasth;
 3546:         $this->thead = $temp_thead;
 3547:         $this->theadMargins = $temp_theadMargins;
 3548:         $this->newline = $newline;
 3549:         $this->InHeader = false;
 3550:     }
 3551: 
 3552:     /**
 3553:      * This method is used to render the page footer.
 3554:      * @protected
 3555:      * @since 4.0.012 (2008-07-24)
 3556:      */
 3557:     protected function setFooter() {
 3558:         if ($this->state != 2) {
 3559:             return;
 3560:         }
 3561:         $this->InFooter = true;
 3562:         // save current graphic settings
 3563:         $gvars = $this->getGraphicVars();
 3564:         // mark this point
 3565:         $this->footerpos[$this->page] = $this->pagelen[$this->page];
 3566:         $this->_out("\n");
 3567:         if ($this->print_footer) {
 3568:             $this->setGraphicVars($this->default_graphic_vars);
 3569:             $this->current_column = 0;
 3570:             $this->num_columns = 1;
 3571:             $temp_thead = $this->thead;
 3572:             $temp_theadMargins = $this->theadMargins;
 3573:             $lasth = $this->lasth;
 3574:             $this->_outSaveGraphicsState();
 3575:             $this->rMargin = $this->original_rMargin;
 3576:             $this->lMargin = $this->original_lMargin;
 3577:             $this->SetCellPadding(0);
 3578:             //set current position
 3579:             $footer_y = $this->h - $this->footer_margin;
 3580:             if ($this->rtl) {
 3581:                 $this->SetXY($this->original_rMargin, $footer_y);
 3582:             } else {
 3583:                 $this->SetXY($this->original_lMargin, $footer_y);
 3584:             }
 3585:             $this->SetFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]);
 3586:             $this->Footer();
 3587:             //restore position
 3588:             if ($this->rtl) {
 3589:                 $this->SetXY($this->original_rMargin, $this->tMargin);
 3590:             } else {
 3591:                 $this->SetXY($this->original_lMargin, $this->tMargin);
 3592:             }
 3593:             $this->_outRestoreGraphicsState();
 3594:             $this->lasth = $lasth;
 3595:             $this->thead = $temp_thead;
 3596:             $this->theadMargins = $temp_theadMargins;
 3597:         }
 3598:         // restore graphic settings
 3599:         $this->setGraphicVars($gvars);
 3600:         $this->current_column = $gvars['current_column'];
 3601:         $this->num_columns = $gvars['num_columns'];
 3602:         // calculate footer length
 3603:         $this->footerlen[$this->page] = $this->pagelen[$this->page] - $this->footerpos[$this->page] + 1;
 3604:         $this->InFooter = false;
 3605:     }
 3606: 
 3607:     /**
 3608:      * Check if we are on the page body (excluding page header and footer).
 3609:      * @return true if we are not in page header nor in page footer, false otherwise.
 3610:      * @protected
 3611:      * @since 5.9.091 (2011-06-15)
 3612:      */
 3613:     protected function inPageBody() {
 3614:         return (($this->InHeader === false) AND ($this->InFooter === false));
 3615:     }
 3616: 
 3617:     /**
 3618:      * This method is used to render the table header on new page (if any).
 3619:      * @protected
 3620:      * @since 4.5.030 (2009-03-25)
 3621:      */
 3622:     protected function setTableHeader() {
 3623:         if ($this->num_columns > 1) {
 3624:             // multi column mode
 3625:             return;
 3626:         }
 3627:         if (isset($this->theadMargins['top'])) {
 3628:             // restore the original top-margin
 3629:             $this->tMargin = $this->theadMargins['top'];
 3630:             $this->pagedim[$this->page]['tm'] = $this->tMargin;
 3631:             $this->y = $this->tMargin;
 3632:         }
 3633:         if (!TCPDF_STATIC::empty_string($this->thead) AND (!$this->inthead)) {
 3634:             // set margins
 3635:             $prev_lMargin = $this->lMargin;
 3636:             $prev_rMargin = $this->rMargin;
 3637:             $prev_cell_padding = $this->cell_padding;
 3638:             $this->lMargin = $this->theadMargins['lmargin'] + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$this->theadMargins['page']]['olm']);
 3639:             $this->rMargin = $this->theadMargins['rmargin'] + ($this->pagedim[$this->page]['orm'] - $this->pagedim[$this->theadMargins['page']]['orm']);
 3640:             $this->cell_padding = $this->theadMargins['cell_padding'];
 3641:             if ($this->rtl) {
 3642:                 $this->x = $this->w - $this->rMargin;
 3643:             } else {
 3644:                 $this->x = $this->lMargin;
 3645:             }
 3646:             // account for special "cell" mode
 3647:             if ($this->theadMargins['cell']) {
 3648:                 if ($this->rtl) {
 3649:                     $this->x -= $this->cell_padding['R'];
 3650:                 } else {
 3651:                     $this->x += $this->cell_padding['L'];
 3652:                 }
 3653:             }
 3654:             $gvars = $this->getGraphicVars();
 3655:             if (!empty($this->theadMargins['gvars'])) {
 3656:                 // set the correct graphic style
 3657:                 $this->setGraphicVars($this->theadMargins['gvars']);
 3658:                 $this->rMargin = $gvars['rMargin'];
 3659:                 $this->lMargin = $gvars['lMargin'];
 3660:             }
 3661:             // print table header
 3662:             $this->writeHTML($this->thead, false, false, false, false, '');
 3663:             $this->setGraphicVars($gvars);
 3664:             // set new top margin to skip the table headers
 3665:             if (!isset($this->theadMargins['top'])) {
 3666:                 $this->theadMargins['top'] = $this->tMargin;
 3667:             }
 3668:             // store end of header position
 3669:             if (!isset($this->columns[0]['th'])) {
 3670:                 $this->columns[0]['th'] = array();
 3671:             }
 3672:             $this->columns[0]['th']['\''.$this->page.'\''] = $this->y;
 3673:             $this->tMargin = $this->y;
 3674:             $this->pagedim[$this->page]['tm'] = $this->tMargin;
 3675:             $this->lasth = 0;
 3676:             $this->lMargin = $prev_lMargin;
 3677:             $this->rMargin = $prev_rMargin;
 3678:             $this->cell_padding = $prev_cell_padding;
 3679:         }
 3680:     }
 3681: 
 3682:     /**
 3683:      * Returns the current page number.
 3684:      * @return int page number
 3685:      * @public
 3686:      * @since 1.0
 3687:      * @see getAliasNbPages()
 3688:      */
 3689:     public function PageNo() {
 3690:         return $this->page;
 3691:     }
 3692: 
 3693:     /**
 3694:      * Returns the array of spot colors.
 3695:      * @return (array) Spot colors array.
 3696:      * @public
 3697:      * @since 6.0.038 (2013-09-30)
 3698:      */
 3699:     public function getAllSpotColors() {
 3700:         return $this->spot_colors;
 3701:     }
 3702: 
 3703:     /**
 3704:      * Defines a new spot color.
 3705:      * It can be expressed in RGB components or gray scale.
 3706:      * The method can be called before the first page is created and the value is retained from page to page.
 3707:      * @param $name (string) Full name of the spot color.
 3708:      * @param $c (float) Cyan color for CMYK. Value between 0 and 100.
 3709:      * @param $m (float) Magenta color for CMYK. Value between 0 and 100.
 3710:      * @param $y (float) Yellow color for CMYK. Value between 0 and 100.
 3711:      * @param $k (float) Key (Black) color for CMYK. Value between 0 and 100.
 3712:      * @public
 3713:      * @since 4.0.024 (2008-09-12)
 3714:      * @see SetDrawSpotColor(), SetFillSpotColor(), SetTextSpotColor()
 3715:      */
 3716:     public function AddSpotColor($name, $c, $m, $y, $k) {
 3717:         if (!isset($this->spot_colors[$name])) {
 3718:             $i = (1 + count($this->spot_colors));
 3719:             $this->spot_colors[$name] = array('C' => $c, 'M' => $m, 'Y' => $y, 'K' => $k, 'name' => $name, 'i' => $i);
 3720:         }
 3721:     }
 3722: 
 3723:     /**
 3724:      * Set the spot color for the specified type ('draw', 'fill', 'text').
 3725:      * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text').
 3726:      * @param $name (string) Name of the spot color.
 3727:      * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default).
 3728:      * @return (string) PDF color command.
 3729:      * @public
 3730:      * @since 5.9.125 (2011-10-03)
 3731:      */
 3732:     public function setSpotColor($type, $name, $tint=100) {
 3733:         $spotcolor = TCPDF_COLORS::getSpotColor($name, $this->spot_colors);
 3734:         if ($spotcolor === false) {
 3735:             $this->Error('Undefined spot color: '.$name.', you must add it using the AddSpotColor() method.');
 3736:         }
 3737:         $tint = (max(0, min(100, $tint)) / 100);
 3738:         $pdfcolor = sprintf('/CS%d ', $this->spot_colors[$name]['i']);
 3739:         switch ($type) {
 3740:             case 'draw': {
 3741:                 $pdfcolor .= sprintf('CS %F SCN', $tint);
 3742:                 $this->DrawColor = $pdfcolor;
 3743:                 $this->strokecolor = $spotcolor;
 3744:                 break;
 3745:             }
 3746:             case 'fill': {
 3747:                 $pdfcolor .= sprintf('cs %F scn', $tint);
 3748:                 $this->FillColor = $pdfcolor;
 3749:                 $this->bgcolor = $spotcolor;
 3750:                 break;
 3751:             }
 3752:             case 'text': {
 3753:                 $pdfcolor .= sprintf('cs %F scn', $tint);
 3754:                 $this->TextColor = $pdfcolor;
 3755:                 $this->fgcolor = $spotcolor;
 3756:                 break;
 3757:             }
 3758:         }
 3759:         $this->ColorFlag = ($this->FillColor != $this->TextColor);
 3760:         if ($this->state == 2) {
 3761:             $this->_out($pdfcolor);
 3762:         }
 3763:         if ($this->inxobj) {
 3764:             // we are inside an XObject template
 3765:             $this->xobjects[$this->xobjid]['spot_colors'][$name] = $this->spot_colors[$name];
 3766:         }
 3767:         return $pdfcolor;
 3768:     }
 3769: 
 3770:     /**
 3771:      * Defines the spot color used for all drawing operations (lines, rectangles and cell borders).
 3772:      * @param $name (string) Name of the spot color.
 3773:      * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default).
 3774:      * @public
 3775:      * @since 4.0.024 (2008-09-12)
 3776:      * @see AddSpotColor(), SetFillSpotColor(), SetTextSpotColor()
 3777:      */
 3778:     public function SetDrawSpotColor($name, $tint=100) {
 3779:         $this->setSpotColor('draw', $name, $tint);
 3780:     }
 3781: 
 3782:     /**
 3783:      * Defines the spot color used for all filling operations (filled rectangles and cell backgrounds).
 3784:      * @param $name (string) Name of the spot color.
 3785:      * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default).
 3786:      * @public
 3787:      * @since 4.0.024 (2008-09-12)
 3788:      * @see AddSpotColor(), SetDrawSpotColor(), SetTextSpotColor()
 3789:      */
 3790:     public function SetFillSpotColor($name, $tint=100) {
 3791:         $this->setSpotColor('fill', $name, $tint);
 3792:     }
 3793: 
 3794:     /**
 3795:      * Defines the spot color used for text.
 3796:      * @param $name (string) Name of the spot color.
 3797:      * @param $tint (int) Intensity of the color (from 0 to 100 ; 100 = full intensity by default).
 3798:      * @public
 3799:      * @since 4.0.024 (2008-09-12)
 3800:      * @see AddSpotColor(), SetDrawSpotColor(), SetFillSpotColor()
 3801:      */
 3802:     public function SetTextSpotColor($name, $tint=100) {
 3803:         $this->setSpotColor('text', $name, $tint);
 3804:     }
 3805: 
 3806:     /**
 3807:      * Set the color array for the specified type ('draw', 'fill', 'text').
 3808:      * It can be expressed in RGB, CMYK or GRAY SCALE components.
 3809:      * The method can be called before the first page is created and the value is retained from page to page.
 3810:      * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text').
 3811:      * @param $color (array) Array of colors (1=gray, 3=RGB, 4=CMYK or 5=spotcolor=CMYK+name values).
 3812:      * @param $ret (boolean) If true do not send the PDF command.
 3813:      * @return (string) The PDF command or empty string.
 3814:      * @public
 3815:      * @since 3.1.000 (2008-06-11)
 3816:      */
 3817:     public function setColorArray($type, $color, $ret=false) {
 3818:         if (is_array($color)) {
 3819:             $color = array_values($color);
 3820:             // component: grey, RGB red or CMYK cyan
 3821:             $c = isset($color[0]) ? $color[0] : -1;
 3822:             // component: RGB green or CMYK magenta
 3823:             $m = isset($color[1]) ? $color[1] : -1;
 3824:             // component: RGB blue or CMYK yellow
 3825:             $y = isset($color[2]) ? $color[2] : -1;
 3826:             // component: CMYK black
 3827:             $k = isset($color[3]) ? $color[3] : -1;
 3828:             // color name
 3829:             $name = isset($color[4]) ? $color[4] : '';
 3830:             if ($c >= 0) {
 3831:                 return $this->setColor($type, $c, $m, $y, $k, $ret, $name);
 3832:             }
 3833:         }
 3834:         return '';
 3835:     }
 3836: 
 3837:     /**
 3838:      * Defines the color used for all drawing operations (lines, rectangles and cell borders).
 3839:      * It can be expressed in RGB, CMYK or GRAY SCALE components.
 3840:      * The method can be called before the first page is created and the value is retained from page to page.
 3841:      * @param $color (array) Array of colors (1, 3 or 4 values).
 3842:      * @param $ret (boolean) If true do not send the PDF command.
 3843:      * @return string the PDF command
 3844:      * @public
 3845:      * @since 3.1.000 (2008-06-11)
 3846:      * @see SetDrawColor()
 3847:      */
 3848:     public function SetDrawColorArray($color, $ret=false) {
 3849:         return $this->setColorArray('draw', $color, $ret);
 3850:     }
 3851: 
 3852:     /**
 3853:      * Defines the color used for all filling operations (filled rectangles and cell backgrounds).
 3854:      * It can be expressed in RGB, CMYK or GRAY SCALE components.
 3855:      * The method can be called before the first page is created and the value is retained from page to page.
 3856:      * @param $color (array) Array of colors (1, 3 or 4 values).
 3857:      * @param $ret (boolean) If true do not send the PDF command.
 3858:      * @public
 3859:      * @since 3.1.000 (2008-6-11)
 3860:      * @see SetFillColor()
 3861:      */
 3862:     public function SetFillColorArray($color, $ret=false) {
 3863:         return $this->setColorArray('fill', $color, $ret);
 3864:     }
 3865: 
 3866:     /**
 3867:      * Defines the color used for text. It can be expressed in RGB components or gray scale.
 3868:      * The method can be called before the first page is created and the value is retained from page to page.
 3869:      * @param $color (array) Array of colors (1, 3 or 4 values).
 3870:      * @param $ret (boolean) If true do not send the PDF command.
 3871:      * @public
 3872:      * @since 3.1.000 (2008-6-11)
 3873:      * @see SetFillColor()
 3874:      */
 3875:     public function SetTextColorArray($color, $ret=false) {
 3876:         return $this->setColorArray('text', $color, $ret);
 3877:     }
 3878: 
 3879:     /**
 3880:      * Defines the color used by the specified type ('draw', 'fill', 'text').
 3881:      * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text').
 3882:      * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100).
 3883:      * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100).
 3884:      * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100).
 3885:      * @param $col4 (float) KEY (BLACK) color for CMYK (0-100).
 3886:      * @param $ret (boolean) If true do not send the command.
 3887:      * @param $name (string) spot color name (if any)
 3888:      * @return (string) The PDF command or empty string.
 3889:      * @public
 3890:      * @since 5.9.125 (2011-10-03)
 3891:      */
 3892:     public function setColor($type, $col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
 3893:         // set default values
 3894:         if (!is_numeric($col1)) {
 3895:             $col1 = 0;
 3896:         }
 3897:         if (!is_numeric($col2)) {
 3898:             $col2 = -1;
 3899:         }
 3900:         if (!is_numeric($col3)) {
 3901:             $col3 = -1;
 3902:         }
 3903:         if (!is_numeric($col4)) {
 3904:             $col4 = -1;
 3905:         }
 3906:         // set color by case
 3907:         $suffix = '';
 3908:         if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
 3909:             // Grey scale
 3910:             $col1 = max(0, min(255, $col1));
 3911:             $intcolor = array('G' => $col1);
 3912:             $pdfcolor = sprintf('%F ', ($col1 / 255));
 3913:             $suffix = 'g';
 3914:         } elseif ($col4 == -1) {
 3915:             // RGB
 3916:             $col1 = max(0, min(255, $col1));
 3917:             $col2 = max(0, min(255, $col2));
 3918:             $col3 = max(0, min(255, $col3));
 3919:             $intcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3);
 3920:             $pdfcolor = sprintf('%F %F %F ', ($col1 / 255), ($col2 / 255), ($col3 / 255));
 3921:             $suffix = 'rg';
 3922:         } else {
 3923:             $col1 = max(0, min(100, $col1));
 3924:             $col2 = max(0, min(100, $col2));
 3925:             $col3 = max(0, min(100, $col3));
 3926:             $col4 = max(0, min(100, $col4));
 3927:             if (empty($name)) {
 3928:                 // CMYK
 3929:                 $intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4);
 3930:                 $pdfcolor = sprintf('%F %F %F %F ', ($col1 / 100), ($col2 / 100), ($col3 / 100), ($col4 / 100));
 3931:                 $suffix = 'k';
 3932:             } else {
 3933:                 // SPOT COLOR
 3934:                 $intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4, 'name' => $name);
 3935:                 $this->AddSpotColor($name, $col1, $col2, $col3, $col4);
 3936:                 $pdfcolor = $this->setSpotColor($type, $name, 100);
 3937:             }
 3938:         }
 3939:         switch ($type) {
 3940:             case 'draw': {
 3941:                 $pdfcolor .= strtoupper($suffix);
 3942:                 $this->DrawColor = $pdfcolor;
 3943:                 $this->strokecolor = $intcolor;
 3944:                 break;
 3945:             }
 3946:             case 'fill': {
 3947:                 $pdfcolor .= $suffix;
 3948:                 $this->FillColor = $pdfcolor;
 3949:                 $this->bgcolor = $intcolor;
 3950:                 break;
 3951:             }
 3952:             case 'text': {
 3953:                 $pdfcolor .= $suffix;
 3954:                 $this->TextColor = $pdfcolor;
 3955:                 $this->fgcolor = $intcolor;
 3956:                 break;
 3957:             }
 3958:         }
 3959:         $this->ColorFlag = ($this->FillColor != $this->TextColor);
 3960:         if (($type != 'text') AND ($this->state == 2)) {
 3961:             if (!$ret) {
 3962:                 $this->_out($pdfcolor);
 3963:             }
 3964:             return $pdfcolor;
 3965:         }
 3966:         return '';
 3967:     }
 3968: 
 3969:     /**
 3970:      * 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.
 3971:      * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100).
 3972:      * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100).
 3973:      * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100).
 3974:      * @param $col4 (float) KEY (BLACK) color for CMYK (0-100).
 3975:      * @param $ret (boolean) If true do not send the command.
 3976:      * @param $name (string) spot color name (if any)
 3977:      * @return string the PDF command
 3978:      * @public
 3979:      * @since 1.3
 3980:      * @see SetDrawColorArray(), SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell()
 3981:      */
 3982:     public function SetDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
 3983:         return $this->setColor('draw', $col1, $col2, $col3, $col4, $ret, $name);
 3984:     }
 3985: 
 3986:     /**
 3987:      * 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.
 3988:      * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100).
 3989:      * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100).
 3990:      * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100).
 3991:      * @param $col4 (float) KEY (BLACK) color for CMYK (0-100).
 3992:      * @param $ret (boolean) If true do not send the command.
 3993:      * @param $name (string) Spot color name (if any).
 3994:      * @return (string) The PDF command.
 3995:      * @public
 3996:      * @since 1.3
 3997:      * @see SetFillColorArray(), SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell()
 3998:      */
 3999:     public function SetFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
 4000:         return $this->setColor('fill', $col1, $col2, $col3, $col4, $ret, $name);
 4001:     }
 4002: 
 4003:     /**
 4004:      * 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.
 4005:      * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100).
 4006:      * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100).
 4007:      * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100).
 4008:      * @param $col4 (float) KEY (BLACK) color for CMYK (0-100).
 4009:      * @param $ret (boolean) If true do not send the command.
 4010:      * @param $name (string) Spot color name (if any).
 4011:      * @return (string) Empty string.
 4012:      * @public
 4013:      * @since 1.3
 4014:      * @see SetTextColorArray(), SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell()
 4015:      */
 4016:     public function SetTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
 4017:         return $this->setColor('text', $col1, $col2, $col3, $col4, $ret, $name);
 4018:     }
 4019: 
 4020:     /**
 4021:      * Returns the length of a string in user unit. A font must be selected.<br>
 4022:      * @param $s (string) The string whose length is to be computed
 4023:      * @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.
 4024:      * @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.
 4025:      * @param $fontsize (float) Font size in points. The default value is the current size.
 4026:      * @param $getarray (boolean) if true returns an array of characters widths, if false returns the total length.
 4027:      * @return mixed int total string length or array of characted widths
 4028:      * @author Nicola Asuni
 4029:      * @public
 4030:      * @since 1.2
 4031:      */
 4032:     public function GetStringWidth($s, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) {
 4033:         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);
 4034:     }
 4035: 
 4036:     /**
 4037:      * Returns the string length of an array of chars in user unit or an array of characters widths. A font must be selected.<br>
 4038:      * @param $sa (string) The array of chars whose total length is to be computed
 4039:      * @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.
 4040:      * @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.
 4041:      * @param $fontsize (float) Font size in points. The default value is the current size.
 4042:      * @param $getarray (boolean) if true returns an array of characters widths, if false returns the total length.
 4043:      * @return mixed int total string length or array of characted widths
 4044:      * @author Nicola Asuni
 4045:      * @public
 4046:      * @since 2.4.000 (2008-03-06)
 4047:      */
 4048:     public function GetArrStringWidth($sa, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) {
 4049:         // store current values
 4050:         if (!TCPDF_STATIC::empty_string($fontname)) {
 4051:             $prev_FontFamily = $this->FontFamily;
 4052:             $prev_FontStyle = $this->FontStyle;
 4053:             $prev_FontSizePt = $this->FontSizePt;
 4054:             $this->SetFont($fontname, $fontstyle, $fontsize, '', 'default', false);
 4055:         }
 4056:         // convert UTF-8 array to Latin1 if required
 4057:         if ($this->isunicode AND (!$this->isUnicodeFont())) {
 4058:             $sa = TCPDF_FONTS::UTF8ArrToLatin1Arr($sa);
 4059:         }
 4060:         $w = 0; // total width
 4061:         $wa = array(); // array of characters widths
 4062:         foreach ($sa as $ck => $char) {
 4063:             // character width
 4064:             $cw = $this->GetCharWidth($char, isset($sa[($ck + 1)]));
 4065:             $wa[] = $cw;
 4066:             $w += $cw;
 4067:         }
 4068:         // restore previous values
 4069:         if (!TCPDF_STATIC::empty_string($fontname)) {
 4070:             $this->SetFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt, '', 'default', false);
 4071:         }
 4072:         if ($getarray) {
 4073:             return $wa;
 4074:         }
 4075:         return $w;
 4076:     }
 4077: 
 4078:     /**
 4079:      * Returns the length of the char in user unit for the current font considering current stretching and spacing (tracking).
 4080:      * @param $char (int) The char code whose length is to be returned
 4081:      * @param $notlast (boolean) If false ignore the font-spacing.
 4082:      * @return float char width
 4083:      * @author Nicola Asuni
 4084:      * @public
 4085:      * @since 2.4.000 (2008-03-06)
 4086:      */
 4087:     public function GetCharWidth($char, $notlast=true) {
 4088:         // get raw width
 4089:         $chw = $this->getRawCharWidth($char);
 4090:         if (($this->font_spacing < 0) OR (($this->font_spacing > 0) AND $notlast)) {
 4091:             // increase/decrease font spacing
 4092:             $chw += $this->font_spacing;
 4093:         }
 4094:         if ($this->font_stretching != 100) {
 4095:             // fixed stretching mode
 4096:             $chw *= ($this->font_stretching / 100);
 4097:         }
 4098:         return $chw;
 4099:     }
 4100: 
 4101:     /**
 4102:      * Returns the length of the char in user unit for the current font.
 4103:      * @param $char (int) The char code whose length is to be returned
 4104:      * @return float char width
 4105:      * @author Nicola Asuni
 4106:      * @public
 4107:      * @since 5.9.000 (2010-09-28)
 4108:      */
 4109:     public function getRawCharWidth($char) {
 4110:         if ($char == 173) {
 4111:             // SHY character will not be printed
 4112:             return (0);
 4113:         }
 4114:         if (isset($this->CurrentFont['cw'][$char])) {
 4115:             $w = $this->CurrentFont['cw'][$char];
 4116:         } elseif (isset($this->CurrentFont['dw'])) {
 4117:             // default width
 4118:             $w = $this->CurrentFont['dw'];
 4119:         } elseif (isset($this->CurrentFont['cw'][32])) {
 4120:             // default width
 4121:             $w = $this->CurrentFont['cw'][32];
 4122:         } else {
 4123:             $w = 600;
 4124:         }
 4125:         return $this->getAbsFontMeasure($w);
 4126:     }
 4127: 
 4128:     /**
 4129:      * Returns the numbero of characters in a string.
 4130:      * @param $s (string) The input string.
 4131:      * @return int number of characters
 4132:      * @public
 4133:      * @since 2.0.0001 (2008-01-07)
 4134:      */
 4135:     public function GetNumChars($s) {
 4136:         if ($this->isUnicodeFont()) {
 4137:             return count(TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont));
 4138:         }
 4139:         return strlen($s);
 4140:     }
 4141: 
 4142:     /**
 4143:      * Fill the list of available fonts ($this->fontlist).
 4144:      * @protected
 4145:      * @since 4.0.013 (2008-07-28)
 4146:      */
 4147:     protected function getFontsList() {
 4148:         if (($fontsdir = opendir(TCPDF_FONTS::_getfontpath())) !== false) {
 4149:             while (($file = readdir($fontsdir)) !== false) {
 4150:                 if (substr($file, -4) == '.php') {
 4151:                     array_push($this->fontlist, strtolower(basename($file, '.php')));
 4152:                 }
 4153:             }
 4154:             closedir($fontsdir);
 4155:         }
 4156:     }
 4157: 
 4158:     /**
 4159:      * Imports a TrueType, Type1, core, or CID0 font and makes it available.
 4160:      * It is necessary to generate a font definition file first (read /fonts/utils/README.TXT).
 4161:      * 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.
 4162:      * @param $family (string) Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font.
 4163:      * @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>
 4164:      * @param $fontfile (string) The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
 4165:      * @return array containing the font data, or false in case of error.
 4166:      * @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.
 4167:      * @public
 4168:      * @since 1.5
 4169:      * @see SetFont(), setFontSubsetting()
 4170:      */
 4171:     public function AddFont($family, $style='', $fontfile='', $subset='default') {
 4172:         if ($subset === 'default') {
 4173:             $subset = $this->font_subsetting;
 4174:         }
 4175:         if ($this->pdfa_mode) {
 4176:             $subset = false;
 4177:         }
 4178:         if (TCPDF_STATIC::empty_string($family)) {
 4179:             if (!TCPDF_STATIC::empty_string($this->FontFamily)) {
 4180:                 $family = $this->FontFamily;
 4181:             } else {
 4182:                 $this->Error('Empty font family');
 4183:             }
 4184:         }
 4185:         // move embedded styles on $style
 4186:         if (substr($family, -1) == 'I') {
 4187:             $style .= 'I';
 4188:             $family = substr($family, 0, -1);
 4189:         }
 4190:         if (substr($family, -1) == 'B') {
 4191:             $style .= 'B';
 4192:             $family = substr($family, 0, -1);
 4193:         }
 4194:         // normalize family name
 4195:         $family = strtolower($family);
 4196:         if ((!$this->isunicode) AND ($family == 'arial')) {
 4197:             $family = 'helvetica';
 4198:         }
 4199:         if (($family == 'symbol') OR ($family == 'zapfdingbats')) {
 4200:             $style = '';
 4201:         }
 4202:         if ($this->pdfa_mode AND (isset($this->CoreFonts[$family]))) {
 4203:             // all fonts must be embedded
 4204:             $family = 'pdfa'.$family;
 4205:         }
 4206:         $tempstyle = strtoupper($style);
 4207:         $style = '';
 4208:         // underline
 4209:         if (strpos($tempstyle, 'U') !== false) {
 4210:             $this->underline = true;
 4211:         } else {
 4212:             $this->underline = false;
 4213:         }
 4214:         // line-through (deleted)
 4215:         if (strpos($tempstyle, 'D') !== false) {
 4216:             $this->linethrough = true;
 4217:         } else {
 4218:             $this->linethrough = false;
 4219:         }
 4220:         // overline
 4221:         if (strpos($tempstyle, 'O') !== false) {
 4222:             $this->overline = true;
 4223:         } else {
 4224:             $this->overline = false;
 4225:         }
 4226:         // bold
 4227:         if (strpos($tempstyle, 'B') !== false) {
 4228:             $style .= 'B';
 4229:         }
 4230:         // oblique
 4231:         if (strpos($tempstyle, 'I') !== false) {
 4232:             $style .= 'I';
 4233:         }
 4234:         $bistyle = $style;
 4235:         $fontkey = $family.$style;
 4236:         $font_style = $style.($this->underline ? 'U' : '').($this->linethrough ? 'D' : '').($this->overline ? 'O' : '');
 4237:         $fontdata = array('fontkey' => $fontkey, 'family' => $family, 'style' => $font_style);
 4238:         // check if the font has been already added
 4239:         $fb = $this->getFontBuffer($fontkey);
 4240:         if ($fb !== false) {
 4241:             if ($this->inxobj) {
 4242:                 // we are inside an XObject template
 4243:                 $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $fb['i'];
 4244:             }
 4245:             return $fontdata;
 4246:         }
 4247:         // get specified font directory (if any)
 4248:         $fontdir = false;
 4249:         if (!TCPDF_STATIC::empty_string($fontfile)) {
 4250:             $fontdir = dirname($fontfile);
 4251:             if (TCPDF_STATIC::empty_string($fontdir) OR ($fontdir == '.')) {
 4252:                 $fontdir = '';
 4253:             } else {
 4254:                 $fontdir .= '/';
 4255:             }
 4256:         }
 4257:         // true when the font style variation is missing
 4258:         $missing_style = false;
 4259:         // search and include font file
 4260:         if (TCPDF_STATIC::empty_string($fontfile) OR (!@file_exists($fontfile))) {
 4261:             // build a standard filenames for specified font
 4262:             $tmp_fontfile = str_replace(' ', '', $family).strtolower($style).'.php';
 4263:             $fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir);
 4264:             if (TCPDF_STATIC::empty_string($fontfile)) {
 4265:                 $missing_style = true;
 4266:                 // try to remove the style part
 4267:                 $tmp_fontfile = str_replace(' ', '', $family).'.php';
 4268:                 $fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir);
 4269:             }
 4270:         }
 4271:         // include font file
 4272:         if (!TCPDF_STATIC::empty_string($fontfile) AND (@file_exists($fontfile))) {
 4273:             include($fontfile);
 4274:         } else {
 4275:             $this->Error('Could not include font definition file: '.$family.'');
 4276:         }
 4277:         // check font parameters
 4278:         if ((!isset($type)) OR (!isset($cw))) {
 4279:             $this->Error('The font definition file has a bad format: '.$fontfile.'');
 4280:         }
 4281:         // SET default parameters
 4282:         if (!isset($file) OR TCPDF_STATIC::empty_string($file)) {
 4283:             $file = '';
 4284:         }
 4285:         if (!isset($enc) OR TCPDF_STATIC::empty_string($enc)) {
 4286:             $enc = '';
 4287:         }
 4288:         if (!isset($cidinfo) OR TCPDF_STATIC::empty_string($cidinfo)) {
 4289:             $cidinfo = array('Registry'=>'Adobe', 'Ordering'=>'Identity', 'Supplement'=>0);
 4290:             $cidinfo['uni2cid'] = array();
 4291:         }
 4292:         if (!isset($ctg) OR TCPDF_STATIC::empty_string($ctg)) {
 4293:             $ctg = '';
 4294:         }
 4295:         if (!isset($desc) OR TCPDF_STATIC::empty_string($desc)) {
 4296:             $desc = array();
 4297:         }
 4298:         if (!isset($up) OR TCPDF_STATIC::empty_string($up)) {
 4299:             $up = -100;
 4300:         }
 4301:         if (!isset($ut) OR TCPDF_STATIC::empty_string($ut)) {
 4302:             $ut = 50;
 4303:         }
 4304:         if (!isset($cw) OR TCPDF_STATIC::empty_string($cw)) {
 4305:             $cw = array();
 4306:         }
 4307:         if (!isset($dw) OR TCPDF_STATIC::empty_string($dw)) {
 4308:             // set default width
 4309:             if (isset($desc['MissingWidth']) AND ($desc['MissingWidth'] > 0)) {
 4310:                 $dw = $desc['MissingWidth'];
 4311:             } elseif (isset($cw[32])) {
 4312:                 $dw = $cw[32];
 4313:             } else {
 4314:                 $dw = 600;
 4315:             }
 4316:         }
 4317:         ++$this->numfonts;
 4318:         if ($type == 'core') {
 4319:             $name = $this->CoreFonts[$fontkey];
 4320:             $subset = false;
 4321:         } elseif (($type == 'TrueType') OR ($type == 'Type1')) {
 4322:             $subset = false;
 4323:         } elseif ($type == 'TrueTypeUnicode') {
 4324:             $enc = 'Identity-H';
 4325:         } elseif ($type == 'cidfont0') {
 4326:             if ($this->pdfa_mode) {
 4327:                 $this->Error('All fonts must be embedded in PDF/A mode!');
 4328:             }
 4329:         } else {
 4330:             $this->Error('Unknow font type: '.$type.'');
 4331:         }
 4332:         // set name if unset
 4333:         if (!isset($name) OR empty($name)) {
 4334:             $name = $fontkey;
 4335:         }
 4336:         // create artificial font style variations if missing (only works with non-embedded fonts)
 4337:         if (($type != 'core') AND $missing_style) {
 4338:             // style variations
 4339:             $styles = array('' => '', 'B' => ',Bold', 'I' => ',Italic', 'BI' => ',BoldItalic');
 4340:             $name .= $styles[$bistyle];
 4341:             // artificial bold
 4342:             if (strpos($bistyle, 'B') !== false) {
 4343:                 if (isset($desc['StemV'])) {
 4344:                     // from normal to bold
 4345:                     $desc['StemV'] = round($desc['StemV'] * 1.75);
 4346:                 } else {
 4347:                     // bold
 4348:                     $desc['StemV'] = 123;
 4349:                 }
 4350:             }
 4351:             // artificial italic
 4352:             if (strpos($bistyle, 'I') !== false) {
 4353:                 if (isset($desc['ItalicAngle'])) {
 4354:                     $desc['ItalicAngle'] -= 11;
 4355:                 } else {
 4356:                     $desc['ItalicAngle'] = -11;
 4357:                 }
 4358:                 if (isset($desc['Flags'])) {
 4359:                     $desc['Flags'] |= 64; //bit 7
 4360:                 } else {
 4361:                     $desc['Flags'] = 64;
 4362:                 }
 4363:             }
 4364:         }
 4365:         // check if the array of characters bounding boxes is defined
 4366:         if (!isset($cbbox)) {
 4367:             $cbbox = array();
 4368:         }
 4369:         // initialize subsetchars
 4370:         $subsetchars = array_fill(0, 255, true);
 4371:         $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));
 4372:         if ($this->inxobj) {
 4373:             // we are inside an XObject template
 4374:             $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $this->numfonts;
 4375:         }
 4376:         if (isset($diff) AND (!empty($diff))) {
 4377:             //Search existing encodings
 4378:             $d = 0;
 4379:             $nb = count($this->diffs);
 4380:             for ($i=1; $i <= $nb; ++$i) {
 4381:                 if ($this->diffs[$i] == $diff) {
 4382:                     $d = $i;
 4383:                     break;
 4384:                 }
 4385:             }
 4386:             if ($d == 0) {
 4387:                 $d = $nb + 1;
 4388:                 $this->diffs[$d] = $diff;
 4389:             }
 4390:             $this->setFontSubBuffer($fontkey, 'diff', $d);
 4391:         }
 4392:         if (!TCPDF_STATIC::empty_string($file)) {
 4393:             if (!isset($this->FontFiles[$file])) {
 4394:                 if ((strcasecmp($type,'TrueType') == 0) OR (strcasecmp($type, 'TrueTypeUnicode') == 0)) {
 4395:                     $this->FontFiles[$file] = array('length1' => $originalsize, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey));
 4396:                 } elseif ($type != 'core') {
 4397:                     $this->FontFiles[$file] = array('length1' => $size1, 'length2' => $size2, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey));
 4398:                 }
 4399:             } else {
 4400:                 // update fontkeys that are sharing this font file
 4401:                 $this->FontFiles[$file]['subset'] = ($this->FontFiles[$file]['subset'] AND $subset);
 4402:                 if (!in_array($fontkey, $this->FontFiles[$file]['fontkeys'])) {
 4403:                     $this->FontFiles[$file]['fontkeys'][] = $fontkey;
 4404:                 }
 4405:             }
 4406:         }
 4407:         return $fontdata;
 4408:     }
 4409: 
 4410:     /**
 4411:      * Sets the font used to print character strings.
 4412:      * The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe).
 4413:      * The method can be called before the first page is created and the font is retained from page to page.
 4414:      * If you just wish to change the current font size, it is simpler to call SetFontSize().
 4415:      * 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 />
 4416:      * @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.
 4417:      * @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.
 4418:      * @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
 4419:      * @param $fontfile (string) The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
 4420:      * @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.
 4421:      * @param $out (boolean) if true output the font size command, otherwise only set the font properties.
 4422:      * @author Nicola Asuni
 4423:      * @public
 4424:      * @since 1.0
 4425:      * @see AddFont(), SetFontSize()
 4426:      */
 4427:     public function SetFont($family, $style='', $size=null, $fontfile='', $subset='default', $out=true) {
 4428:         //Select a font; size given in points
 4429:         if ($size === null) {
 4430:             $size = $this->FontSizePt;
 4431:         }
 4432:         if ($size < 0) {
 4433:             $size = 0;
 4434:         }
 4435:         // try to add font (if not already added)
 4436:         $fontdata = $this->AddFont($family, $style, $fontfile, $subset);
 4437:         $this->FontFamily = $fontdata['family'];
 4438:         $this->FontStyle = $fontdata['style'];
 4439:         if (isset($this->CurrentFont['fontkey']) AND isset($this->CurrentFont['subsetchars'])) {
 4440:             // save subset chars of the previous font
 4441:             $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']);
 4442:         }
 4443:         $this->CurrentFont = $this->getFontBuffer($fontdata['fontkey']);
 4444:         $this->SetFontSize($size, $out);
 4445:     }
 4446: 
 4447:     /**
 4448:      * Defines the size of the current font.
 4449:      * @param $size (float) The font size in points.
 4450:      * @param $out (boolean) if true output the font size command, otherwise only set the font properties.
 4451:      * @public
 4452:      * @since 1.0
 4453:      * @see SetFont()
 4454:      */
 4455:     public function SetFontSize($size, $out=true) {
 4456:         // font size in points
 4457:         $this->FontSizePt = $size;
 4458:         // font size in user units
 4459:         $this->FontSize = $size / $this->k;
 4460:         // calculate some font metrics
 4461:         if (isset($this->CurrentFont['desc']['FontBBox'])) {
 4462:             $bbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1));
 4463:             $font_height = ((intval($bbox[3]) - intval($bbox[1])) * $size / 1000);
 4464:         } else {
 4465:             $font_height = $size * 1.219;
 4466:         }
 4467:         if (isset($this->CurrentFont['desc']['Ascent']) AND ($this->CurrentFont['desc']['Ascent'] > 0)) {
 4468:             $font_ascent = ($this->CurrentFont['desc']['Ascent'] * $size / 1000);
 4469:         }
 4470:         if (isset($this->CurrentFont['desc']['Descent']) AND ($this->CurrentFont['desc']['Descent'] <= 0)) {
 4471:             $font_descent = (- $this->CurrentFont['desc']['Descent'] * $size / 1000);
 4472:         }
 4473:         if (!isset($font_ascent) AND !isset($font_descent)) {
 4474:             // core font
 4475:             $font_ascent = 0.76 * $font_height;
 4476:             $font_descent = $font_height - $font_ascent;
 4477:         } elseif (!isset($font_descent)) {
 4478:             $font_descent = $font_height - $font_ascent;
 4479:         } elseif (!isset($font_ascent)) {
 4480:             $font_ascent = $font_height - $font_descent;
 4481:         }
 4482:         $this->FontAscent = ($font_ascent / $this->k);
 4483:         $this->FontDescent = ($font_descent / $this->k);
 4484:         if ($out AND ($this->page > 0) AND (isset($this->CurrentFont['i'])) AND ($this->state == 2)) {
 4485:             $this->_out(sprintf('BT /F%d %F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
 4486:         }
 4487:     }
 4488: 
 4489:     /**
 4490:      * Returns the bounding box of the current font in user units.
 4491:      * @return array
 4492:      * @public
 4493:      * @since 5.9.152 (2012-03-23)
 4494:      */
 4495:     public function getFontBBox() {
 4496:         $fbbox = array();
 4497:         if (isset($this->CurrentFont['desc']['FontBBox'])) {
 4498:             $tmpbbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1));
 4499:             $fbbox = array_map(array($this,'getAbsFontMeasure'), $tmpbbox);
 4500:         } else {
 4501:             // Find max width
 4502:             if (isset($this->CurrentFont['desc']['MaxWidth'])) {
 4503:                 $maxw = $this->getAbsFontMeasure(intval($this->CurrentFont['desc']['MaxWidth']));
 4504:             } else {
 4505:                 $maxw = 0;
 4506:                 if (isset($this->CurrentFont['desc']['MissingWidth'])) {
 4507:                     $maxw = max($maxw, $this->CurrentFont['desc']['MissingWidth']);
 4508:                 }
 4509:                 if (isset($this->CurrentFont['desc']['AvgWidth'])) {
 4510:                     $maxw = max($maxw, $this->CurrentFont['desc']['AvgWidth']);
 4511:                 }
 4512:                 if (isset($this->CurrentFont['dw'])) {
 4513:                     $maxw = max($maxw, $this->CurrentFont['dw']);
 4514:                 }
 4515:                 foreach ($this->CurrentFont['cw'] as $char => $w) {
 4516:                     $maxw = max($maxw, $w);
 4517:                 }
 4518:                 if ($maxw == 0) {
 4519:                     $maxw = 600;
 4520:                 }
 4521:                 $maxw = $this->getAbsFontMeasure($maxw);
 4522:             }
 4523:             $fbbox = array(0, (0 - $this->FontDescent), $maxw, $this->FontAscent);
 4524:         }
 4525:         return $fbbox;
 4526:     }
 4527: 
 4528:     /**
 4529:      * Convert a relative font measure into absolute value.
 4530:      * @param $s (int) Font measure.
 4531:      * @return float Absolute measure.
 4532:      * @since 5.9.186 (2012-09-13)
 4533:      */
 4534:     public function getAbsFontMeasure($s) {
 4535:         return ($s * $this->FontSize / 1000);
 4536:     }
 4537: 
 4538:     /**
 4539:      * Returns the glyph bounding box of the specified character in the current font in user units.
 4540:      * @param $char (int) Input character code.
 4541:      * @return mixed array(xMin, yMin, xMax, yMax) or FALSE if not defined.
 4542:      * @since 5.9.186 (2012-09-13)
 4543:      */
 4544:     public function getCharBBox($char) {
 4545:         $c = intval($char);
 4546:         if (isset($this->CurrentFont['cw'][$c])) {
 4547:             // glyph is defined ... use zero width & height for glyphs without outlines
 4548:             $result = array(0,0,0,0);
 4549:             if (isset($this->CurrentFont['cbbox'][$c])) {
 4550:                 $result = $this->CurrentFont['cbbox'][$c];
 4551:             }
 4552:             return array_map(array($this,'getAbsFontMeasure'), $result);
 4553:         }
 4554:         return false;
 4555:     }
 4556: 
 4557:     /**
 4558:      * Return the font descent value
 4559:      * @param $font (string) font name
 4560:      * @param $style (string) font style
 4561:      * @param $size (float) The size (in points)
 4562:      * @return int font descent
 4563:      * @public
 4564:      * @author Nicola Asuni
 4565:      * @since 4.9.003 (2010-03-30)
 4566:      */
 4567:     public function getFontDescent($font, $style='', $size=0) {
 4568:         $fontdata = $this->AddFont($font, $style);
 4569:         $fontinfo = $this->getFontBuffer($fontdata['fontkey']);
 4570:         if (isset($fontinfo['desc']['Descent']) AND ($fontinfo['desc']['Descent'] <= 0)) {
 4571:             $descent = (- $fontinfo['desc']['Descent'] * $size / 1000);
 4572:         } else {
 4573:             $descent = (1.219 * 0.24 * $size);
 4574:         }
 4575:         return ($descent / $this->k);
 4576:     }
 4577: 
 4578:     /**
 4579:      * Return the font ascent value.
 4580:      * @param $font (string) font name
 4581:      * @param $style (string) font style
 4582:      * @param $size (float) The size (in points)
 4583:      * @return int font ascent
 4584:      * @public
 4585:      * @author Nicola Asuni
 4586:      * @since 4.9.003 (2010-03-30)
 4587:      */
 4588:     public function getFontAscent($font, $style='', $size=0) {
 4589:         $fontdata = $this->AddFont($font, $style);
 4590:         $fontinfo = $this->getFontBuffer($fontdata['fontkey']);
 4591:         if (isset($fontinfo['desc']['Ascent']) AND ($fontinfo['desc']['Ascent'] > 0)) {
 4592:             $ascent = ($fontinfo['desc']['Ascent'] * $size / 1000);
 4593:         } else {
 4594:             $ascent = 1.219 * 0.76 * $size;
 4595:         }
 4596:         return ($ascent / $this->k);
 4597:     }
 4598: 
 4599:     /**
 4600:      * Return true in the character is present in the specified font.
 4601:      * @param $char (mixed) Character to check (integer value or string)
 4602:      * @param $font (string) Font name (family name).
 4603:      * @param $style (string) Font style.
 4604:      * @return (boolean) true if the char is defined, false otherwise.
 4605:      * @public
 4606:      * @since 5.9.153 (2012-03-28)
 4607:      */
 4608:     public function isCharDefined($char, $font='', $style='') {
 4609:         if (is_string($char)) {
 4610:             // get character code
 4611:             $char = TCPDF_FONTS::UTF8StringToArray($char, $this->isunicode, $this->CurrentFont);
 4612:             $char = $char[0];
 4613:         }
 4614:         if (TCPDF_STATIC::empty_string($font)) {
 4615:             if (TCPDF_STATIC::empty_string($style)) {
 4616:                 return (isset($this->CurrentFont['cw'][intval($char)]));
 4617:             }
 4618:             $font = $this->FontFamily;
 4619:         }
 4620:         $fontdata = $this->AddFont($font, $style);
 4621:         $fontinfo = $this->getFontBuffer($fontdata['fontkey']);
 4622:         return (isset($fontinfo['cw'][intval($char)]));
 4623:     }
 4624: 
 4625:     /**
 4626:      * Replace missing font characters on selected font with specified substitutions.
 4627:      * @param $text (string) Text to process.
 4628:      * @param $font (string) Font name (family name).
 4629:      * @param $style (string) Font style.
 4630:      * @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.
 4631:      * @return (string) Processed text.
 4632:      * @public
 4633:      * @since 5.9.153 (2012-03-28)
 4634:      */
 4635:     public function replaceMissingChars($text, $font='', $style='', $subs=array()) {
 4636:         if (empty($subs)) {
 4637:             return $text;
 4638:         }
 4639:         if (TCPDF_STATIC::empty_string($font)) {
 4640:             $font = $this->FontFamily;
 4641:         }
 4642:         $fontdata = $this->AddFont($font, $style);
 4643:         $fontinfo = $this->getFontBuffer($fontdata['fontkey']);
 4644:         $uniarr = TCPDF_FONTS::UTF8StringToArray($text, $this->isunicode, $this->CurrentFont);
 4645:         foreach ($uniarr as $k => $chr) {
 4646:             if (!isset($fontinfo['cw'][$chr])) {
 4647:                 // this character is missing on the selected font
 4648:                 if (isset($subs[$chr])) {
 4649:                     // we have available substitutions
 4650:                     if (is_array($subs[$chr])) {
 4651:                         foreach($subs[$chr] as $s) {
 4652:                             if (isset($fontinfo['cw'][$s])) {
 4653:                                 $uniarr[$k] = $s;
 4654:                                 break;
 4655:                             }
 4656:                         }
 4657:                     } elseif (isset($fontinfo['cw'][$subs[$chr]])) {
 4658:                         $uniarr[$k] = $subs[$chr];
 4659:                     }
 4660:                 }
 4661:             }
 4662:         }
 4663:         return TCPDF_FONTS::UniArrSubString(TCPDF_FONTS::UTF8ArrayToUniArray($uniarr, $this->isunicode));
 4664:     }
 4665: 
 4666:     /**
 4667:      * Defines the default monospaced font.
 4668:      * @param $font (string) Font name.
 4669:      * @public
 4670:      * @since 4.5.025
 4671:      */
 4672:     public function SetDefaultMonospacedFont($font) {
 4673:         $this->default_monospaced_font = $font;
 4674:     }
 4675: 
 4676:     /**
 4677:      * 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 />
 4678:      * The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is defined with SetLink().
 4679:      * @public
 4680:      * @since 1.5
 4681:      * @see Cell(), Write(), Image(), Link(), SetLink()
 4682:      */
 4683:     public function AddLink() {
 4684:         // create a new internal link
 4685:         $n = count($this->links) + 1;
 4686:         $this->links[$n] = array('p' => 0, 'y' => 0, 'f' => false);
 4687:         return $n;
 4688:     }
 4689: 
 4690:     /**
 4691:      * Defines the page and position a link points to.
 4692:      * @param $link (int) The link identifier returned by AddLink()
 4693:      * @param $y (float) Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page)
 4694:      * @param $page (int) 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.
 4695:      * @public
 4696:      * @since 1.5
 4697:      * @see AddLink()
 4698:      */
 4699:     public function SetLink($link, $y=0, $page=-1) {
 4700:         $fixed = false;
 4701:         if (!empty($page) AND ($page[0] == '*')) {
 4702:             $page = intval(substr($page, 1));
 4703:             // this page number will not be changed when moving/add/deleting pages
 4704:             $fixed = true;
 4705:         }
 4706:         if ($page < 0) {
 4707:             $page = $this->page;
 4708:         }
 4709:         if ($y == -1) {
 4710:             $y = $this->y;
 4711:         }
 4712:         $this->links[$link] = array('p' => $page, 'y' => $y, 'f' => $fixed);
 4713:     }
 4714: 
 4715:     /**
 4716:      * Puts a link on a rectangular area of the page.
 4717:      * 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.
 4718:      * @param $x (float) Abscissa of the upper-left corner of the rectangle
 4719:      * @param $y (float) Ordinate of the upper-left corner of the rectangle
 4720:      * @param $w (float) Width of the rectangle
 4721:      * @param $h (float) Height of the rectangle
 4722:      * @param $link (mixed) URL or identifier returned by AddLink()
 4723:      * @param $spaces (int) number of spaces on the text to link
 4724:      * @public
 4725:      * @since 1.5
 4726:      * @see AddLink(), Annotation(), Cell(), Write(), Image()
 4727:      */
 4728:     public function Link($x, $y, $w, $h, $link, $spaces=0) {
 4729:         $this->Annotation($x, $y, $w, $h, $link, array('Subtype'=>'Link'), $spaces);
 4730:     }
 4731: 
 4732:     /**
 4733:      * Puts a markup annotation on a rectangular area of the page.
 4734:      * !!!!THE ANNOTATION SUPPORT IS NOT YET FULLY IMPLEMENTED !!!!
 4735:      * @param $x (float) Abscissa of the upper-left corner of the rectangle
 4736:      * @param $y (float) Ordinate of the upper-left corner of the rectangle
 4737:      * @param $w (float) Width of the rectangle
 4738:      * @param $h (float) Height of the rectangle
 4739:      * @param $text (string) annotation text or alternate content
 4740:      * @param $opt (array) array of options (see section 8.4 of PDF reference 1.7).
 4741:      * @param $spaces (int) number of spaces on the text to link
 4742:      * @public
 4743:      * @since 4.0.018 (2008-08-06)
 4744:      */
 4745:     public function Annotation($x, $y, $w, $h, $text, $opt=array('Subtype'=>'Text'), $spaces=0) {
 4746:         if ($this->inxobj) {
 4747:             // store parameters for later use on template
 4748:             $this->xobjects[$this->xobjid]['annotations'][] = array('x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'text' => $text, 'opt' => $opt, 'spaces' => $spaces);
 4749:             return;
 4750:         }
 4751:         if ($x === '') {
 4752:             $x = $this->x;
 4753:         }
 4754:         if ($y === '') {
 4755:             $y = $this->y;
 4756:         }
 4757:         // check page for no-write regions and adapt page margins if necessary
 4758:         list($x, $y) = $this->checkPageRegions($h, $x, $y);
 4759:         // recalculate coordinates to account for graphic transformations
 4760:         if (isset($this->transfmatrix) AND !empty($this->transfmatrix)) {
 4761:             for ($i=$this->transfmatrix_key; $i > 0; --$i) {
 4762:                 $maxid = count($this->transfmatrix[$i]) - 1;
 4763:                 for ($j=$maxid; $j >= 0; --$j) {
 4764:                     $ctm = $this->transfmatrix[$i][$j];
 4765:                     if (isset($ctm['a'])) {
 4766:                         $x = $x * $this->k;
 4767:                         $y = ($this->h - $y) * $this->k;
 4768:                         $w = $w * $this->k;
 4769:                         $h = $h * $this->k;
 4770:                         // top left
 4771:                         $xt = $x;
 4772:                         $yt = $y;
 4773:                         $x1 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
 4774:                         $y1 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
 4775:                         // top right
 4776:                         $xt = $x + $w;
 4777:                         $yt = $y;
 4778:                         $x2 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
 4779:                         $y2 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
 4780:                         // bottom left
 4781:                         $xt = $x;
 4782:                         $yt = $y - $h;
 4783:                         $x3 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
 4784:                         $y3 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
 4785:                         // bottom right
 4786:                         $xt = $x + $w;
 4787:                         $yt = $y - $h;
 4788:                         $x4 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
 4789:                         $y4 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
 4790:                         // new coordinates (rectangle area)
 4791:                         $x = min($x1, $x2, $x3, $x4);
 4792:                         $y = max($y1, $y2, $y3, $y4);
 4793:                         $w = (max($x1, $x2, $x3, $x4) - $x) / $this->k;
 4794:                         $h = ($y - min($y1, $y2, $y3, $y4)) / $this->k;
 4795:                         $x = $x / $this->k;
 4796:                         $y = $this->h - ($y / $this->k);
 4797:                     }
 4798:                 }
 4799:             }
 4800:         }
 4801:         if ($this->page <= 0) {
 4802:             $page = 1;
 4803:         } else {
 4804:             $page = $this->page;
 4805:         }
 4806:         if (!isset($this->PageAnnots[$page])) {
 4807:             $this->PageAnnots[$page] = array();
 4808:         }
 4809:         $this->PageAnnots[$page][] = array('n' => ++$this->n, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'txt' => $text, 'opt' => $opt, 'numspaces' => $spaces);
 4810:         if (!$this->pdfa_mode) {
 4811:             if ((($opt['Subtype'] == 'FileAttachment') OR ($opt['Subtype'] == 'Sound')) AND (!TCPDF_STATIC::empty_string($opt['FS']))
 4812:                 AND (@file_exists($opt['FS']) OR TCPDF_STATIC::isValidURL($opt['FS']))
 4813:                 AND (!isset($this->embeddedfiles[basename($opt['FS'])]))) {
 4814:                 $this->embeddedfiles[basename($opt['FS'])] = array('f' => ++$this->n, 'n' => ++$this->n, 'file' => $opt['FS']);
 4815:             }
 4816:         }
 4817:         // Add widgets annotation's icons
 4818:         if (isset($opt['mk']['i']) AND @file_exists($opt['mk']['i'])) {
 4819:             $this->Image($opt['mk']['i'], '', '', 10, 10, '', '', '', false, 300, '', false, false, 0, false, true);
 4820:         }
 4821:         if (isset($opt['mk']['ri']) AND @file_exists($opt['mk']['ri'])) {
 4822:             $this->Image($opt['mk']['ri'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true);
 4823:         }
 4824:         if (isset($opt['mk']['ix']) AND @file_exists($opt['mk']['ix'])) {
 4825:             $this->Image($opt['mk']['ix'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true);
 4826:         }
 4827:     }
 4828: 
 4829:     /**
 4830:      * Embedd the attached files.
 4831:      * @since 4.4.000 (2008-12-07)
 4832:      * @protected
 4833:      * @see Annotation()
 4834:      */
 4835:     protected function _putEmbeddedFiles() {
 4836:         if ($this->pdfa_mode) {
 4837:             // embedded files are not allowed in PDF/A mode
 4838:             return;
 4839:         }
 4840:         reset($this->embeddedfiles);
 4841:         foreach ($this->embeddedfiles as $filename => $filedata) {
 4842:             $data = TCPDF_STATIC::fileGetContents($filedata['file']);
 4843:             if ($data !== FALSE) {
 4844:                 $rawsize = strlen($data);
 4845:                 if ($rawsize > 0) {
 4846:                     // update name tree
 4847:                     $this->efnames[$filename] = $filedata['f'].' 0 R';
 4848:                     // embedded file specification object
 4849:                     $out = $this->_getobj($filedata['f'])."\n";
 4850:                     $out .= '<</Type /Filespec /F '.$this->_datastring($filename, $filedata['f']).' /EF <</F '.$filedata['n'].' 0 R>> >>';
 4851:                     $out .= "\n".'endobj';
 4852:                     $this->_out($out);
 4853:                     // embedded file object
 4854:                     $filter = '';
 4855:                     if ($this->compress) {
 4856:                         $data = gzcompress($data);
 4857:                         $filter = ' /Filter /FlateDecode';
 4858:                     }
 4859:                     $stream = $this->_getrawstream($data, $filedata['n']);
 4860:                     $out = $this->_getobj($filedata['n'])."\n";
 4861:                     $out .= '<< /Type /EmbeddedFile'.$filter.' /Length '.strlen($stream).' /Params <</Size '.$rawsize.'>> >>';
 4862:                     $out .= ' stream'."\n".$stream."\n".'endstream';
 4863:                     $out .= "\n".'endobj';
 4864:                     $this->_out($out);
 4865:                 }
 4866:             }
 4867:         }
 4868:     }
 4869: 
 4870:     /**
 4871:      * Prints a text cell at the specified position.
 4872:      * This method allows to place a string precisely on the page.
 4873:      * @param $x (float) Abscissa of the cell origin
 4874:      * @param $y (float) Ordinate of the cell origin
 4875:      * @param $txt (string) String to print
 4876:      * @param $fstroke (int) outline size in user units (false = disable)
 4877:      * @param $fclip (boolean) if true activate clipping mode (you must call StartTransform() before this function and StopTransform() to stop the clipping tranformation).
 4878:      * @param $ffill (boolean) if true fills the text
 4879:      * @param $border (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)))
 4880:      * @param $ln (int) Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
 4881:      * @param $align (string) Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul>
 4882:      * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false).
 4883:      * @param $link (mixed) URL or identifier returned by AddLink().
 4884:      * @param $stretch (int) font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible.
 4885:      * @param $ignore_min_height (boolean) if true ignore automatic minimum height value.
 4886:      * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li><li>B : cell bottom</li></ul>
 4887:      * @param $valign (string) text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>C : center</li><li>B : bottom</li></ul>
 4888:      * @param $rtloff (boolean) if true uses the page top-left corner as origin of axis for $x and $y initial position.
 4889:      * @public
 4890:      * @since 1.0
 4891:      * @see Cell(), Write(), MultiCell(), WriteHTML(), WriteHTMLCell()
 4892:      */
 4893:     public function Text($x, $y, $txt, $fstroke=false, $fclip=false, $ffill=true, $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M', $rtloff=false) {
 4894:         $textrendermode = $this->textrendermode;
 4895:         $textstrokewidth = $this->textstrokewidth;
 4896:         $this->setTextRenderingMode($fstroke, $ffill, $fclip);
 4897:         $this->SetXY($x, $y, $rtloff);
 4898:         $this->Cell(0, 0, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height, $calign, $valign);
 4899:         // restore previous rendering mode
 4900:         $this->textrendermode = $textrendermode;
 4901:         $this->textstrokewidth = $textstrokewidth;
 4902:     }
 4903: 
 4904:     /**
 4905:      * Whenever a page break condition is met, the method is called, and the break is issued or not depending on the returned value.
 4906:      * The default implementation returns a value according to the mode selected by SetAutoPageBreak().<br />
 4907:      * This method is called automatically and should not be called directly by the application.
 4908:      * @return boolean
 4909:      * @public
 4910:      * @since 1.4
 4911:      * @see SetAutoPageBreak()
 4912:      */
 4913:     public function AcceptPageBreak() {
 4914:         if ($this->num_columns > 1) {
 4915:             // multi column mode
 4916:             if ($this->current_column < ($this->num_columns - 1)) {
 4917:                 // go to next column
 4918:                 $this->selectColumn($this->current_column + 1);
 4919:             } elseif ($this->AutoPageBreak) {
 4920:                 // add a new page
 4921:                 $this->AddPage();
 4922:                 // set first column
 4923:                 $this->selectColumn(0);
 4924:             }
 4925:             // avoid page breaking from checkPageBreak()
 4926:             return false;
 4927:         }
 4928:         return $this->AutoPageBreak;
 4929:     }
 4930: 
 4931:     /**
 4932:      * Add page if needed.
 4933:      * @param $h (float) Cell height. Default value: 0.
 4934:      * @param $y (mixed) starting y position, leave empty for current position.
 4935:      * @param $addpage (boolean) if true add a page, otherwise only return the true/false state
 4936:      * @return boolean true in case of page break, false otherwise.
 4937:      * @since 3.2.000 (2008-07-01)
 4938:      * @protected
 4939:      */
 4940:     protected function checkPageBreak($h=0, $y='', $addpage=true) {
 4941:         if (TCPDF_STATIC::empty_string($y)) {
 4942:             $y = $this->y;
 4943:         }
 4944:         $current_page = $this->page;
 4945:         if ((($y + $h) > $this->PageBreakTrigger) AND ($this->inPageBody()) AND ($this->AcceptPageBreak())) {
 4946:             if ($addpage) {
 4947:                 //Automatic page break
 4948:                 $x = $this->x;
 4949:                 $this->AddPage($this->CurOrientation);
 4950:                 $this->y = $this->tMargin;
 4951:                 $oldpage = $this->page - 1;
 4952:                 if ($this->rtl) {
 4953:                     if ($this->pagedim[$this->page]['orm'] != $this->pagedim[$oldpage]['orm']) {
 4954:                         $this->x = $x - ($this->pagedim[$this->page]['orm'] - $this->pagedim[$oldpage]['orm']);
 4955:                     } else {
 4956:                         $this->x = $x;
 4957:                     }
 4958:                 } else {
 4959:                     if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
 4960:                         $this->x = $x + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$oldpage]['olm']);
 4961:                     } else {
 4962:                         $this->x = $x;
 4963:                     }
 4964:                 }
 4965:             }
 4966:             return true;
 4967:         }
 4968:         if ($current_page != $this->page) {
 4969:             // account for columns mode
 4970:             return true;
 4971:         }
 4972:         return false;
 4973:     }
 4974: 
 4975:     /**
 4976:      * Prints a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.<br />
 4977:      * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.
 4978:      * @param $w (float) Cell width. If 0, the cell extends up to the right margin.
 4979:      * @param $h (float) Cell height. Default value: 0.
 4980:      * @param $txt (string) String to print. Default value: empty string.
 4981:      * @param $border (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)))
 4982:      * @param $ln (int) Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul> Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
 4983:      * @param $align (string) Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul>
 4984:      * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false).
 4985:      * @param $link (mixed) URL or identifier returned by AddLink().
 4986:      * @param $stretch (int) font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible.
 4987:      * @param $ignore_min_height (boolean) if true ignore automatic minimum height value.
 4988:      * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>C : center</li><li>B : cell bottom</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li></ul>
 4989:      * @param $valign (string) text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>C : center</li><li>B : bottom</li></ul>
 4990:      * @public
 4991:      * @since 1.0
 4992:      * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak()
 4993:      */
 4994:     public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') {
 4995:         $prev_cell_margin = $this->cell_margin;
 4996:         $prev_cell_padding = $this->cell_padding;
 4997:         $this->adjustCellPadding($border);
 4998:         if (!$ignore_min_height) {
 4999:             $min_cell_height = $this->getCellHeight($this->FontSize);
 5000:             if ($h < $min_cell_height) {
 5001:                 $h = $min_cell_height;
 5002:             }
 5003:         }
 5004:         $this->checkPageBreak($h + $this->cell_margin['T'] + $this->cell_margin['B']);
 5005:         // apply text shadow if enabled
 5006:         if ($this->txtshadow['enabled']) {
 5007:             // save data
 5008:             $x = $this->x;
 5009:             $y = $this->y;
 5010:             $bc = $this->bgcolor;
 5011:             $fc = $this->fgcolor;
 5012:             $sc = $this->strokecolor;
 5013:             $alpha = $this->alpha;
 5014:             // print shadow
 5015:             $this->x += $this->txtshadow['depth_w'];
 5016:             $this->y += $this->txtshadow['depth_h'];
 5017:             $this->SetFillColorArray($this->txtshadow['color']);
 5018:             $this->SetTextColorArray($this->txtshadow['color']);
 5019:             $this->SetDrawColorArray($this->txtshadow['color']);
 5020:             if ($this->txtshadow['opacity'] != $alpha['CA']) {
 5021:                 $this->setAlpha($this->txtshadow['opacity'], $this->txtshadow['blend_mode']);
 5022:             }
 5023:             if ($this->state == 2) {
 5024:                 $this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, true, $calign, $valign));
 5025:             }
 5026:             //restore data
 5027:             $this->x = $x;
 5028:             $this->y = $y;
 5029:             $this->SetFillColorArray($bc);
 5030:             $this->SetTextColorArray($fc);
 5031:             $this->SetDrawColorArray($sc);
 5032:             if ($this->txtshadow['opacity'] != $alpha['CA']) {
 5033:                 $this->setAlpha($alpha['CA'], $alpha['BM'], $alpha['ca'], $alpha['AIS']);
 5034:             }
 5035:         }
 5036:         if ($this->state == 2) {
 5037:             $this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, true, $calign, $valign));
 5038:         }
 5039:         $this->cell_padding = $prev_cell_padding;
 5040:         $this->cell_margin = $prev_cell_margin;
 5041:     }
 5042: 
 5043:     /**
 5044:      * Returns the PDF string code to print a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.<br />
 5045:      * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.
 5046:      * @param $w (float) Cell width. If 0, the cell extends up to the right margin.
 5047:      * @param $h (float) Cell height. Default value: 0.
 5048:      * @param $txt (string) String to print. Default value: empty string.
 5049:      * @param $border (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)))
 5050:      * @param $ln (int) Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
 5051:      * @param $align (string) Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul>
 5052:      * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false).
 5053:      * @param $link (mixed) URL or identifier returned by AddLink().
 5054:      * @param $stretch (int) font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible.
 5055:      * @param $ignore_min_height (boolean) if true ignore automatic minimum height value.
 5056:      * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>C : center</li><li>B : cell bottom</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li></ul>
 5057:      * @param $valign (string) text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>M : middle</li><li>B : bottom</li></ul>
 5058:      * @return string containing cell code
 5059:      * @protected
 5060:      * @since 1.0
 5061:      * @see Cell()
 5062:      */
 5063:     protected function getCellCode($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') {
 5064:         // replace 'NO-BREAK SPACE' (U+00A0) character with a simple space
 5065:         $txt = str_replace(TCPDF_FONTS::unichr(160, $this->isunicode), ' ', $txt);
 5066:         $prev_cell_margin = $this->cell_margin;
 5067:         $prev_cell_padding = $this->cell_padding;
 5068:         $txt = TCPDF_STATIC::removeSHY($txt, $this->isunicode);
 5069:         $rs = ''; //string to be returned
 5070:         $this->adjustCellPadding($border);
 5071:         if (!$ignore_min_height) {
 5072:             $min_cell_height = $this->getCellHeight($this->FontSize);
 5073:             if ($h < $min_cell_height) {
 5074:                 $h = $min_cell_height;
 5075:             }
 5076:         }
 5077:         $k = $this->k;
 5078:         // check page for no-write regions and adapt page margins if necessary
 5079:         list($this->x, $this->y) = $this->checkPageRegions($h, $this->x, $this->y);
 5080:         if ($this->rtl) {
 5081:             $x = $this->x - $this->cell_margin['R'];
 5082:         } else {
 5083:             $x = $this->x + $this->cell_margin['L'];
 5084:         }
 5085:         $y = $this->y + $this->cell_margin['T'];
 5086:         $prev_font_stretching = $this->font_stretching;
 5087:         $prev_font_spacing = $this->font_spacing;
 5088:         // cell vertical alignment
 5089:         switch ($calign) {
 5090:             case 'A': {
 5091:                 // font top
 5092:                 switch ($valign) {
 5093:                     case 'T': {
 5094:                         // top
 5095:                         $y -= $this->cell_padding['T'];
 5096:                         break;
 5097:                     }
 5098:                     case 'B': {
 5099:                         // bottom
 5100:                         $y -= ($h - $this->cell_padding['B'] - $this->FontAscent - $this->FontDescent);
 5101:                         break;
 5102:                     }
 5103:                     default:
 5104:                     case 'C':
 5105:                     case 'M': {
 5106:                         // center
 5107:                         $y -= (($h - $this->FontAscent - $this->FontDescent) / 2);
 5108:                         break;
 5109:                     }
 5110:                 }
 5111:                 break;
 5112:             }
 5113:             case 'L': {
 5114:                 // font baseline
 5115:                 switch ($valign) {
 5116:                     case 'T': {
 5117:                         // top
 5118:                         $y -= ($this->cell_padding['T'] + $this->FontAscent);
 5119:                         break;
 5120:                     }
 5121:                     case 'B': {
 5122:                         // bottom
 5123:                         $y -= ($h - $this->cell_padding['B'] - $this->FontDescent);
 5124:                         break;
 5125:                     }
 5126:                     default:
 5127:                     case 'C':
 5128:                     case 'M': {
 5129:                         // center
 5130:                         $y -= (($h + $this->FontAscent - $this->FontDescent) / 2);
 5131:                         break;
 5132:                     }
 5133:                 }
 5134:                 break;
 5135:             }
 5136:             case 'D': {
 5137:                 // font bottom
 5138:                 switch ($valign) {
 5139:                     case 'T': {
 5140:                         // top
 5141:                         $y -= ($this->cell_padding['T'] + $this->FontAscent + $this->FontDescent);
 5142:                         break;
 5143:                     }
 5144:                     case 'B': {
 5145:                         // bottom
 5146:                         $y -= ($h - $this->cell_padding['B']);
 5147:                         break;
 5148:                     }
 5149:                     default:
 5150:                     case 'C':
 5151:                     case 'M': {
 5152:                         // center
 5153:                         $y -= (($h + $this->FontAscent + $this->FontDescent) / 2);
 5154:                         break;
 5155:                     }
 5156:                 }
 5157:                 break;
 5158:             }
 5159:             case 'B': {
 5160:                 // cell bottom
 5161:                 $y -= $h;
 5162:                 break;
 5163:             }
 5164:             case 'C':
 5165:             case 'M': {
 5166:                 // cell center
 5167:                 $y -= ($h / 2);
 5168:                 break;
 5169:             }
 5170:             default:
 5171:             case 'T': {
 5172:                 // cell top
 5173:                 break;
 5174:             }
 5175:         }
 5176:         // text vertical alignment
 5177:         switch ($valign) {
 5178:             case 'T': {
 5179:                 // top
 5180:                 $yt = $y + $this->cell_padding['T'];
 5181:                 break;
 5182:             }
 5183:             case 'B': {
 5184:                 // bottom
 5185:                 $yt = $y + $h - $this->cell_padding['B'] - $this->FontAscent - $this->FontDescent;
 5186:                 break;
 5187:             }
 5188:             default:
 5189:             case 'C':
 5190:             case 'M': {
 5191:                 // center
 5192:                 $yt = $y + (($h - $this->FontAscent - $this->FontDescent) / 2);
 5193:                 break;
 5194:             }
 5195:         }
 5196:         $basefonty = $yt + $this->FontAscent;
 5197:         if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) {
 5198:             if ($this->rtl) {
 5199:                 $w = $x - $this->lMargin;
 5200:             } else {
 5201:                 $w = $this->w - $this->rMargin - $x;
 5202:             }
 5203:         }
 5204:         $s = '';
 5205:         // fill and borders
 5206:         if (is_string($border) AND (strlen($border) == 4)) {
 5207:             // full border
 5208:             $border = 1;
 5209:         }
 5210:         if ($fill OR ($border == 1)) {
 5211:             if ($fill) {
 5212:                 $op = ($border == 1) ? 'B' : 'f';
 5213:             } else {
 5214:                 $op = 'S';
 5215:             }
 5216:             if ($this->rtl) {
 5217:                 $xk = (($x - $w) * $k);
 5218:             } else {
 5219:                 $xk = ($x * $k);
 5220:             }
 5221:             $s .= sprintf('%F %F %F %F re %s ', $xk, (($this->h - $y) * $k), ($w * $k), (-$h * $k), $op);
 5222:         }
 5223:         // draw borders
 5224:         $s .= $this->getCellBorder($x, $y, $w, $h, $border);
 5225:         if ($txt != '') {
 5226:             $txt2 = $txt;
 5227:             if ($this->isunicode) {
 5228:                 if (($this->CurrentFont['type'] == 'core') OR ($this->CurrentFont['type'] == 'TrueType') OR ($this->CurrentFont['type'] == 'Type1')) {
 5229:                     $txt2 = TCPDF_FONTS::UTF8ToLatin1($txt2, $this->isunicode, $this->CurrentFont);
 5230:                 } else {
 5231:                     $unicode = TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont); // array of UTF-8 unicode values
 5232:                     $unicode = TCPDF_FONTS::utf8Bidi($unicode, '', $this->tmprtl, $this->isunicode, $this->CurrentFont);
 5233:                     // replace thai chars (if any)
 5234:                     if (defined('K_THAI_TOPCHARS') AND (K_THAI_TOPCHARS == true)) {
 5235:                         // number of chars
 5236:                         $numchars = count($unicode);
 5237:                         // po pla, for far, for fan
 5238:                         $longtail = array(0x0e1b, 0x0e1d, 0x0e1f);
 5239:                         // do chada, to patak
 5240:                         $lowtail = array(0x0e0e, 0x0e0f);
 5241:                         // mai hun arkad, sara i, sara ii, sara ue, sara uee
 5242:                         $upvowel = array(0x0e31, 0x0e34, 0x0e35, 0x0e36, 0x0e37);
 5243:                         // mai ek, mai tho, mai tri, mai chattawa, karan
 5244:                         $tonemark = array(0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c);
 5245:                         // sara u, sara uu, pinthu
 5246:                         $lowvowel = array(0x0e38, 0x0e39, 0x0e3a);
 5247:                         $output = array();
 5248:                         for ($i = 0; $i < $numchars; $i++) {
 5249:                             if (($unicode[$i] >= 0x0e00) && ($unicode[$i] <= 0x0e5b)) {
 5250:                                 $ch0 = $unicode[$i];
 5251:                                 $ch1 = ($i > 0) ? $unicode[($i - 1)] : 0;
 5252:                                 $ch2 = ($i > 1) ? $unicode[($i - 2)] : 0;
 5253:                                 $chn = ($i < ($numchars - 1)) ? $unicode[($i + 1)] : 0;
 5254:                                 if (in_array($ch0, $tonemark)) {
 5255:                                     if ($chn == 0x0e33) {
 5256:                                         // sara um
 5257:                                         if (in_array($ch1, $longtail)) {
 5258:                                             // tonemark at upper left
 5259:                                             $output[] = $this->replaceChar($ch0, (0xf713 + $ch0 - 0x0e48));
 5260:                                         } else {
 5261:                                             // tonemark at upper right (normal position)
 5262:                                             $output[] = $ch0;
 5263:                                         }
 5264:                                     } elseif (in_array($ch1, $longtail) OR (in_array($ch2, $longtail) AND in_array($ch1, $lowvowel))) {
 5265:                                         // tonemark at lower left
 5266:                                         $output[] = $this->replaceChar($ch0, (0xf705 + $ch0 - 0x0e48));
 5267:                                     } elseif (in_array($ch1, $upvowel)) {
 5268:                                         if (in_array($ch2, $longtail)) {
 5269:                                             // tonemark at upper left
 5270:                                             $output[] = $this->replaceChar($ch0, (0xf713 + $ch0 - 0x0e48));
 5271:                                         } else {
 5272:                                             // tonemark at upper right (normal position)
 5273:                                             $output[] = $ch0;
 5274:                                         }
 5275:                                     } else {
 5276:                                         // tonemark at lower right
 5277:                                         $output[] = $this->replaceChar($ch0, (0xf70a + $ch0 - 0x0e48));
 5278:                                     }
 5279:                                 } elseif (($ch0 == 0x0e33) AND (in_array($ch1, $longtail) OR (in_array($ch2, $longtail) AND in_array($ch1, $tonemark)))) {
 5280:                                     // add lower left nikhahit and sara aa
 5281:                                     if ($this->isCharDefined(0xf711) AND $this->isCharDefined(0x0e32)) {
 5282:                                         $output[] = 0xf711;
 5283:                                         $this->CurrentFont['subsetchars'][0xf711] = true;
 5284:                                         $output[] = 0x0e32;
 5285:                                         $this->CurrentFont['subsetchars'][0x0e32] = true;
 5286:                                     } else {
 5287:                                         $output[] = $ch0;
 5288:                                     }
 5289:                                 } elseif (in_array($ch1, $longtail)) {
 5290:                                     if ($ch0 == 0x0e31) {
 5291:                                         // lower left mai hun arkad
 5292:                                         $output[] = $this->replaceChar($ch0, 0xf710);
 5293:                                     } elseif (in_array($ch0, $upvowel)) {
 5294:                                         // lower left
 5295:                                         $output[] = $this->replaceChar($ch0, (0xf701 + $ch0 - 0x0e34));
 5296:                                     } elseif ($ch0 == 0x0e47) {
 5297:                                         // lower left mai tai koo
 5298:                                         $output[] = $this->replaceChar($ch0, 0xf712);
 5299:                                     } else {
 5300:                                         // normal character
 5301:                                         $output[] = $ch0;
 5302:                                     }
 5303:                                 } elseif (in_array($ch1, $lowtail) AND in_array($ch0, $lowvowel)) {
 5304:                                     // lower vowel
 5305:                                     $output[] = $this->replaceChar($ch0, (0xf718 + $ch0 - 0x0e38));
 5306:                                 } elseif (($ch0 == 0x0e0d) AND in_array($chn, $lowvowel)) {
 5307:                                     // yo ying without lower part
 5308:                                     $output[] = $this->replaceChar($ch0, 0xf70f);
 5309:                                 } elseif (($ch0 == 0x0e10) AND in_array($chn, $lowvowel)) {
 5310:                                     // tho santan without lower part
 5311:                                     $output[] = $this->replaceChar($ch0, 0xf700);
 5312:                                 } else {
 5313:                                     $output[] = $ch0;
 5314:                                 }
 5315:                             } else {
 5316:                                 // non-thai character
 5317:                                 $output[] = $unicode[$i];
 5318:                             }
 5319:                         }
 5320:                         $unicode = $output;
 5321:                         // update font subsetchars
 5322:                         $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']);
 5323:                     } // end of K_THAI_TOPCHARS
 5324:                     $txt2 = TCPDF_FONTS::arrUTF8ToUTF16BE($unicode, false);
 5325:                 }
 5326:             }
 5327:             $txt2 = TCPDF_STATIC::_escape($txt2);
 5328:             // get current text width (considering general font stretching and spacing)
 5329:             $txwidth = $this->GetStringWidth($txt);
 5330:             $width = $txwidth;
 5331:             // check for stretch mode
 5332:             if ($stretch > 0) {
 5333:                 // calculate ratio between cell width and text width
 5334:                 if ($width <= 0) {
 5335:                     $ratio = 1;
 5336:                 } else {
 5337:                     $ratio = (($w - $this->cell_padding['L'] - $this->cell_padding['R']) / $width);
 5338:                 }
 5339:                 // check if stretching is required
 5340:                 if (($ratio < 1) OR (($ratio > 1) AND (($stretch % 2) == 0))) {
 5341:                     // the text will be stretched to fit cell width
 5342:                     if ($stretch > 2) {
 5343:                         // set new character spacing
 5344:                         $this->font_spacing += ($w - $this->cell_padding['L'] - $this->cell_padding['R'] - $width) / (max(($this->GetNumChars($txt) - 1), 1) * ($this->font_stretching / 100));
 5345:                     } else {
 5346:                         // set new horizontal stretching
 5347:                         $this->font_stretching *= $ratio;
 5348:                     }
 5349:                     // recalculate text width (the text fills the entire cell)
 5350:                     $width = $w - $this->cell_padding['L'] - $this->cell_padding['R'];
 5351:                     // reset alignment
 5352:                     $align = '';
 5353:                 }
 5354:             }
 5355:             if ($this->font_stretching != 100) {
 5356:                 // apply font stretching
 5357:                 $rs .= sprintf('BT %F Tz ET ', $this->font_stretching);
 5358:             }
 5359:             if ($this->font_spacing != 0) {
 5360:                 // increase/decrease font spacing
 5361:                 $rs .= sprintf('BT %F Tc ET ', ($this->font_spacing * $this->k));
 5362:             }
 5363:             if ($this->ColorFlag AND ($this->textrendermode < 4)) {
 5364:                 $s .= 'q '.$this->TextColor.' ';
 5365:             }
 5366:             // rendering mode
 5367:             $s .= sprintf('BT %d Tr %F w ET ', $this->textrendermode, ($this->textstrokewidth * $this->k));
 5368:             // count number of spaces
 5369:             $ns = substr_count($txt, chr(32));
 5370:             // Justification
 5371:             $spacewidth = 0;
 5372:             if (($align == 'J') AND ($ns > 0)) {
 5373:                 if ($this->isUnicodeFont()) {
 5374:                     // get string width without spaces
 5375:                     $width = $this->GetStringWidth(str_replace(' ', '', $txt));
 5376:                     // calculate average space width
 5377:                     $spacewidth = -1000 * ($w - $width - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1) / ($this->FontSize?$this->FontSize:1);
 5378:                     if ($this->font_stretching != 100) {
 5379:                         // word spacing is affected by stretching
 5380:                         $spacewidth /= ($this->font_stretching / 100);
 5381:                     }
 5382:                     // set word position to be used with TJ operator
 5383:                     $txt2 = str_replace(chr(0).chr(32), ') '.sprintf('%F', $spacewidth).' (', $txt2);
 5384:                     $unicode_justification = true;
 5385:                 } else {
 5386:                     // get string width
 5387:                     $width = $txwidth;
 5388:                     // new space width
 5389:                     $spacewidth = (($w - $width - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1)) * $this->k;
 5390:                     if ($this->font_stretching != 100) {
 5391:                         // word spacing (Tw) is affected by stretching
 5392:                         $spacewidth /= ($this->font_stretching / 100);
 5393:                     }
 5394:                     // set word spacing
 5395:                     $rs .= sprintf('BT %F Tw ET ', $spacewidth);
 5396:                 }
 5397:                 $width = $w - $this->cell_padding['L'] - $this->cell_padding['R'];
 5398:             }
 5399:             // replace carriage return characters
 5400:             $txt2 = str_replace("\r", ' ', $txt2);
 5401:             switch ($align) {
 5402:                 case 'C': {
 5403:                     $dx = ($w - $width) / 2;
 5404:                     break;
 5405:                 }
 5406:                 case 'R': {
 5407:                     if ($this->rtl) {
 5408:                         $dx = $this->cell_padding['R'];
 5409:                     } else {
 5410:                         $dx = $w - $width - $this->cell_padding['R'];
 5411:                     }
 5412:                     break;
 5413:                 }
 5414:                 case 'L': {
 5415:                     if ($this->rtl) {
 5416:                         $dx = $w - $width - $this->cell_padding['L'];
 5417:                     } else {
 5418:                         $dx = $this->cell_padding['L'];
 5419:                     }
 5420:                     break;
 5421:                 }
 5422:                 case 'J':
 5423:                 default: {
 5424:                     if ($this->rtl) {
 5425:                         $dx = $this->cell_padding['R'];
 5426:                     } else {
 5427:                         $dx = $this->cell_padding['L'];
 5428:                     }
 5429:                     break;
 5430:                 }
 5431:             }
 5432:             if ($this->rtl) {
 5433:                 $xdx = $x - $dx - $width;
 5434:             } else {
 5435:                 $xdx = $x + $dx;
 5436:             }
 5437:             $xdk = $xdx * $k;
 5438:             // print text
 5439:             $s .= sprintf('BT %F %F Td [(%s)] TJ ET', $xdk, (($this->h - $basefonty) * $k), $txt2);
 5440:             if (isset($uniblock)) {
 5441:                 // print overlapping characters as separate string
 5442:                 $xshift = 0; // horizontal shift
 5443:                 $ty = (($this->h - $basefonty + (0.2 * $this->FontSize)) * $k);
 5444:                 $spw = (($w - $txwidth - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1));
 5445:                 foreach ($uniblock as $uk => $uniarr) {
 5446:                     if (($uk % 2) == 0) {
 5447:                         // x space to skip
 5448:                         if ($spacewidth != 0) {
 5449:                             // justification shift
 5450:                             $xshift += (count(array_keys($uniarr, 32)) * $spw);
 5451:                         }
 5452:                         $xshift += $this->GetArrStringWidth($uniarr); // + shift justification
 5453:                     } else {
 5454:                         // character to print
 5455:                         $topchr = TCPDF_FONTS::arrUTF8ToUTF16BE($uniarr, false);
 5456:                         $topchr = TCPDF_STATIC::_escape($topchr);
 5457:                         $s .= sprintf(' BT %F %F Td [(%s)] TJ ET', ($xdk + ($xshift * $k)), $ty, $topchr);
 5458:                     }
 5459:                 }
 5460:             }
 5461:             if ($this->underline) {
 5462:                 $s .= ' '.$this->_dounderlinew($xdx, $basefonty, $width);
 5463:             }
 5464:             if ($this->linethrough) {
 5465:                 $s .= ' '.$this->_dolinethroughw($xdx, $basefonty, $width);
 5466:             }
 5467:             if ($this->overline) {
 5468:                 $s .= ' '.$this->_dooverlinew($xdx, $basefonty, $width);
 5469:             }
 5470:             if ($this->ColorFlag AND ($this->textrendermode < 4)) {
 5471:                 $s .= ' Q';
 5472:             }
 5473:             if ($link) {
 5474:                 $this->Link($xdx, $yt, $width, ($this->FontAscent + $this->FontDescent), $link, $ns);
 5475:             }
 5476:         }
 5477:         // output cell
 5478:         if ($s) {
 5479:             // output cell
 5480:             $rs .= $s;
 5481:             if ($this->font_spacing != 0) {
 5482:                 // reset font spacing mode
 5483:                 $rs .= ' BT 0 Tc ET';
 5484:             }
 5485:             if ($this->font_stretching != 100) {
 5486:                 // reset font stretching mode
 5487:                 $rs .= ' BT 100 Tz ET';
 5488:             }
 5489:         }
 5490:         // reset word spacing
 5491:         if (!$this->isUnicodeFont() AND ($align == 'J')) {
 5492:             $rs .= ' BT 0 Tw ET';
 5493:         }
 5494:         // reset stretching and spacing
 5495:         $this->font_stretching = $prev_font_stretching;
 5496:         $this->font_spacing = $prev_font_spacing;
 5497:         $this->lasth = $h;
 5498:         if ($ln > 0) {
 5499:             //Go to the beginning of the next line
 5500:             $this->y = $y + $h + $this->cell_margin['B'];
 5501:             if ($ln == 1) {
 5502:                 if ($this->rtl) {
 5503:                     $this->x = $this->w - $this->rMargin;
 5504:                 } else {
 5505:                     $this->x = $this->lMargin;
 5506:                 }
 5507:             }
 5508:         } else {
 5509:             // go left or right by case
 5510:             if ($this->rtl) {
 5511:                 $this->x = $x - $w - $this->cell_margin['L'];
 5512:             } else {
 5513:                 $this->x = $x + $w + $this->cell_margin['R'];
 5514:             }
 5515:         }
 5516:         $gstyles = ''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor."\n";
 5517:         $rs = $gstyles.$rs;
 5518:         $this->cell_padding = $prev_cell_padding;
 5519:         $this->cell_margin = $prev_cell_margin;
 5520:         return $rs;
 5521:     }
 5522: 
 5523:     /**
 5524:      * Replace a char if is defined on the current font.
 5525:      * @param $oldchar (int) Integer code (unicode) of the character to replace.
 5526:      * @param $newchar (int) Integer code (unicode) of the new character.
 5527:      * @return int the replaced char or the old char in case the new char i not defined
 5528:      * @protected
 5529:      * @since 5.9.167 (2012-06-22)
 5530:      */
 5531:     protected function replaceChar($oldchar, $newchar) {
 5532:         if ($this->isCharDefined($newchar)) {
 5533:             // add the new char on the subset list
 5534:             $this->CurrentFont['subsetchars'][$newchar] = true;
 5535:             // return the new character
 5536:             return $newchar;
 5537:         }
 5538:         // return the old char
 5539:         return $oldchar;
 5540:     }
 5541: 
 5542:     /**
 5543:      * Returns the code to draw the cell border
 5544:      * @param $x (float) X coordinate.
 5545:      * @param $y (float) Y coordinate.
 5546:      * @param $w (float) Cell width.
 5547:      * @param $h (float) Cell height.
 5548:      * @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)))
 5549:      * @return string containing cell border code
 5550:      * @protected
 5551:      * @see SetLineStyle()
 5552:      * @since 5.7.000 (2010-08-02)
 5553:      */
 5554:     protected function getCellBorder($x, $y, $w, $h, $brd) {
 5555:         $s = ''; // string to be returned
 5556:         if (empty($brd)) {
 5557:             return $s;
 5558:         }
 5559:         if ($brd == 1) {
 5560:             $brd = array('LRTB' => true);
 5561:         }
 5562:         // calculate coordinates for border
 5563:         $k = $this->k;
 5564:         if ($this->rtl) {
 5565:             $xeL = ($x - $w) * $k;
 5566:             $xeR = $x * $k;
 5567:         } else {
 5568:             $xeL = $x * $k;
 5569:             $xeR = ($x + $w) * $k;
 5570:         }
 5571:         $yeL = (($this->h - ($y + $h)) * $k);
 5572:         $yeT = (($this->h - $y) * $k);
 5573:         $xeT = $xeL;
 5574:         $xeB = $xeR;
 5575:         $yeR = $yeT;
 5576:         $yeB = $yeL;
 5577:         if (is_string($brd)) {
 5578:             // convert string to array
 5579:             $slen = strlen($brd);
 5580:             $newbrd = array();
 5581:             for ($i = 0; $i < $slen; ++$i) {
 5582:                 $newbrd[$brd[$i]] = array('cap' => 'square', 'join' => 'miter');
 5583:             }
 5584:             $brd = $newbrd;
 5585:         }
 5586:         if (isset($brd['mode'])) {
 5587:             $mode = $brd['mode'];
 5588:             unset($brd['mode']);
 5589:         } else {
 5590:             $mode = 'normal';
 5591:         }
 5592:         foreach ($brd as $border => $style) {
 5593:             if (is_array($style) AND !empty($style)) {
 5594:                 // apply border style
 5595:                 $prev_style = $this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' ';
 5596:                 $s .= $this->SetLineStyle($style, true)."\n";
 5597:             }
 5598:             switch ($mode) {
 5599:                 case 'ext': {
 5600:                     $off = (($this->LineWidth / 2) * $k);
 5601:                     $xL = $xeL - $off;
 5602:                     $xR = $xeR + $off;
 5603:                     $yT = $yeT + $off;
 5604:                     $yL = $yeL - $off;
 5605:                     $xT = $xL;
 5606:                     $xB = $xR;
 5607:                     $yR = $yT;
 5608:                     $yB = $yL;
 5609:                     $w += $this->LineWidth;
 5610:                     $h += $this->LineWidth;
 5611:                     break;
 5612:                 }
 5613:                 case 'int': {
 5614:                     $off = ($this->LineWidth / 2) * $k;
 5615:                     $xL = $xeL + $off;
 5616:                     $xR = $xeR - $off;
 5617:                     $yT = $yeT - $off;
 5618:                     $yL = $yeL + $off;
 5619:                     $xT = $xL;
 5620:                     $xB = $xR;
 5621:                     $yR = $yT;
 5622:                     $yB = $yL;
 5623:                     $w -= $this->LineWidth;
 5624:                     $h -= $this->LineWidth;
 5625:                     break;
 5626:                 }
 5627:                 case 'normal':
 5628:                 default: {
 5629:                     $xL = $xeL;
 5630:                     $xT = $xeT;
 5631:                     $xB = $xeB;
 5632:                     $xR = $xeR;
 5633:                     $yL = $yeL;
 5634:                     $yT = $yeT;
 5635:                     $yB = $yeB;
 5636:                     $yR = $yeR;
 5637:                     break;
 5638:                 }
 5639:             }
 5640:             // draw borders by case
 5641:             if (strlen($border) == 4) {
 5642:                 $s .= sprintf('%F %F %F %F re S ', $xT, $yT, ($w * $k), (-$h * $k));
 5643:             } elseif (strlen($border) == 3) {
 5644:                 if (strpos($border,'B') === false) { // LTR
 5645:                     $s .= sprintf('%F %F m ', $xL, $yL);
 5646:                     $s .= sprintf('%F %F l ', $xT, $yT);
 5647:                     $s .= sprintf('%F %F l ', $xR, $yR);
 5648:                     $s .= sprintf('%F %F l ', $xB, $yB);
 5649:                     $s .= 'S ';
 5650:                 } elseif (strpos($border,'L') === false) { // TRB
 5651:                     $s .= sprintf('%F %F m ', $xT, $yT);
 5652:                     $s .= sprintf('%F %F l ', $xR, $yR);
 5653:                     $s .= sprintf('%F %F l ', $xB, $yB);
 5654:                     $s .= sprintf('%F %F l ', $xL, $yL);
 5655:                     $s .= 'S ';
 5656:                 } elseif (strpos($border,'T') === false) { // RBL
 5657:                     $s .= sprintf('%F %F m ', $xR, $yR);
 5658:                     $s .= sprintf('%F %F l ', $xB, $yB);
 5659:                     $s .= sprintf('%F %F l ', $xL, $yL);
 5660:                     $s .= sprintf('%F %F l ', $xT, $yT);
 5661:                     $s .= 'S ';
 5662:                 } elseif (strpos($border,'R') === false) { // BLT
 5663:                     $s .= sprintf('%F %F m ', $xB, $yB);
 5664:                     $s .= sprintf('%F %F l ', $xL, $yL);
 5665:                     $s .= sprintf('%F %F l ', $xT, $yT);
 5666:                     $s .= sprintf('%F %F l ', $xR, $yR);
 5667:                     $s .= 'S ';
 5668:                 }
 5669:             } elseif (strlen($border) == 2) {
 5670:                 if ((strpos($border,'L') !== false) AND (strpos($border,'T') !== false)) { // LT
 5671:                     $s .= sprintf('%F %F m ', $xL, $yL);
 5672:                     $s .= sprintf('%F %F l ', $xT, $yT);
 5673:                     $s .= sprintf('%F %F l ', $xR, $yR);
 5674:                     $s .= 'S ';
 5675:                 } elseif ((strpos($border,'T') !== false) AND (strpos($border,'R') !== false)) { // TR
 5676:                     $s .= sprintf('%F %F m ', $xT, $yT);
 5677:                     $s .= sprintf('%F %F l ', $xR, $yR);
 5678:                     $s .= sprintf('%F %F l ', $xB, $yB);
 5679:                     $s .= 'S ';
 5680:                 } elseif ((strpos($border,'R') !== false) AND (strpos($border,'B') !== false)) { // RB
 5681:                     $s .= sprintf('%F %F m ', $xR, $yR);
 5682:                     $s .= sprintf('%F %F l ', $xB, $yB);
 5683:                     $s .= sprintf('%F %F l ', $xL, $yL);
 5684:                     $s .= 'S ';
 5685:                 } elseif ((strpos($border,'B') !== false) AND (strpos($border,'L') !== false)) { // BL
 5686:                     $s .= sprintf('%F %F m ', $xB, $yB);
 5687:                     $s .= sprintf('%F %F l ', $xL, $yL);
 5688:                     $s .= sprintf('%F %F l ', $xT, $yT);
 5689:                     $s .= 'S ';
 5690:                 } elseif ((strpos($border,'L') !== false) AND (strpos($border,'R') !== false)) { // LR
 5691:                     $s .= sprintf('%F %F m ', $xL, $yL);
 5692:                     $s .= sprintf('%F %F l ', $xT, $yT);
 5693:                     $s .= 'S ';
 5694:                     $s .= sprintf('%F %F m ', $xR, $yR);
 5695:                     $s .= sprintf('%F %F l ', $xB, $yB);
 5696:                     $s .= 'S ';
 5697:                 } elseif ((strpos($border,'T') !== false) AND (strpos($border,'B') !== false)) { // TB
 5698:                     $s .= sprintf('%F %F m ', $xT, $yT);
 5699:                     $s .= sprintf('%F %F l ', $xR, $yR);
 5700:                     $s .= 'S ';
 5701:                     $s .= sprintf('%F %F m ', $xB, $yB);
 5702:                     $s .= sprintf('%F %F l ', $xL, $yL);
 5703:                     $s .= 'S ';
 5704:                 }
 5705:             } else { // strlen($border) == 1
 5706:                 if (strpos($border,'L') !== false) { // L
 5707:                     $s .= sprintf('%F %F m ', $xL, $yL);
 5708:                     $s .= sprintf('%F %F l ', $xT, $yT);
 5709:                     $s .= 'S ';
 5710:                 } elseif (strpos($border,'T') !== false) { // T
 5711:                     $s .= sprintf('%F %F m ', $xT, $yT);
 5712:                     $s .= sprintf('%F %F l ', $xR, $yR);
 5713:                     $s .= 'S ';
 5714:                 } elseif (strpos($border,'R') !== false) { // R
 5715:                     $s .= sprintf('%F %F m ', $xR, $yR);
 5716:                     $s .= sprintf('%F %F l ', $xB, $yB);
 5717:                     $s .= 'S ';
 5718:                 } elseif (strpos($border,'B') !== false) { // B
 5719:                     $s .= sprintf('%F %F m ', $xB, $yB);
 5720:                     $s .= sprintf('%F %F l ', $xL, $yL);
 5721:                     $s .= 'S ';
 5722:                 }
 5723:             }
 5724:             if (is_array($style) AND !empty($style)) {
 5725:                 // reset border style to previous value
 5726:                 $s .= "\n".$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor."\n";
 5727:             }
 5728:         }
 5729:         return $s;
 5730:     }
 5731: 
 5732:     /**
 5733:      * This method allows printing text with line breaks.
 5734:      * They can be automatic (as soon as the text reaches the right border of the cell) or explicit (via the \n character). As many cells as necessary are output, one below the other.<br />
 5735:      * Text can be aligned, centered or justified. The cell block can be framed and the background painted.
 5736:      * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page.
 5737:      * @param $h (float) Cell minimum height. The cell extends automatically if needed.
 5738:      * @param $txt (string) String to print
 5739:      * @param $border (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)))
 5740:      * @param $align (string) Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align</li><li>C: center</li><li>R: right align</li><li>J: justification (default value when $ishtml=false)</li></ul>
 5741:      * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false).
 5742:      * @param $ln (int) Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line [DEFAULT]</li><li>2: below</li></ul>
 5743:      * @param $x (float) x position in user units
 5744:      * @param $y (float) y position in user units
 5745:      * @param $reseth (boolean) if true reset the last cell height (default true).
 5746:      * @param $stretch (int) font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible.
 5747:      * @param $ishtml (boolean) INTERNAL USE ONLY -- set to true if $txt is HTML content (default = false). Never set this parameter to true, use instead writeHTMLCell() or writeHTML() methods.
 5748:      * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width.
 5749:      * @param $maxh (float) maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. This feature works only when $ishtml=false.
 5750:      * @param $valign (string) Vertical alignment of text (requires $maxh = $h > 0). Possible values are:<ul><li>T: TOP</li><li>M: middle</li><li>B: bottom</li></ul>. This feature works only when $ishtml=false and the cell must fit in a single page.
 5751:      * @param $fitcell (boolean) if true attempt to fit all the text within the cell by reducing the font size (do not work in HTML mode). $maxh must be greater than 0 and equal to $h.
 5752:      * @return int Return the number of cells or 1 for html mode.
 5753:      * @public
 5754:      * @since 1.3
 5755:      * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), Cell(), Write(), SetAutoPageBreak()
 5756:      */
 5757:     public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0, $valign='T', $fitcell=false) {
 5758:         $prev_cell_margin = $this->cell_margin;
 5759:         $prev_cell_padding = $this->cell_padding;
 5760:         // adjust internal padding
 5761:         $this->adjustCellPadding($border);
 5762:         $mc_padding = $this->cell_padding;
 5763:         $mc_margin = $this->cell_margin;
 5764:         $this->cell_padding['T'] = 0;
 5765:         $this->cell_padding['B'] = 0;
 5766:         $this->setCellMargins(0, 0, 0, 0);
 5767:         if (TCPDF_STATIC::empty_string($this->lasth) OR $reseth) {
 5768:             // reset row height
 5769:             $this->resetLastH();
 5770:         }
 5771:         if (!TCPDF_STATIC::empty_string($y)) {
 5772:             $this->SetY($y);
 5773:         } else {
 5774:             $y = $this->GetY();
 5775:         }
 5776:         $resth = 0;
 5777:         if (($h > 0) AND $this->inPageBody() AND (($y + $h + $mc_margin['T'] + $mc_margin['B']) > $this->PageBreakTrigger)) {
 5778:             // spit cell in more pages/columns
 5779:             $newh = ($this->PageBreakTrigger - $y);
 5780:             $resth = ($h - $newh); // cell to be printed on the next page/column
 5781:             $h = $newh;
 5782:         }
 5783:         // get current page number
 5784:         $startpage = $this->page;
 5785:         // get current column
 5786:         $startcolumn = $this->current_column;
 5787:         if (!TCPDF_STATIC::empty_string($x)) {
 5788:             $this->SetX($x);
 5789:         } else {
 5790:             $x = $this->GetX();
 5791:         }
 5792:         // check page for no-write regions and adapt page margins if necessary
 5793:         list($x, $y) = $this->checkPageRegions(0, $x, $y);
 5794:         // apply margins
 5795:         $oy = $y + $mc_margin['T'];
 5796:         if ($this->rtl) {
 5797:             $ox = ($this->w - $x - $mc_margin['R']);
 5798:         } else {
 5799:             $ox = ($x + $mc_margin['L']);
 5800:         }
 5801:         $this->x = $ox;
 5802:         $this->y = $oy;
 5803:         // set width
 5804:         if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) {
 5805:             if ($this->rtl) {
 5806:                 $w = ($this->x - $this->lMargin - $mc_margin['L']);
 5807:             } else {
 5808:                 $w = ($this->w - $this->x - $this->rMargin - $mc_margin['R']);
 5809:             }
 5810:         }
 5811:         // store original margin values
 5812:         $lMargin = $this->lMargin;
 5813:         $rMargin = $this->rMargin;
 5814:         if ($this->rtl) {
 5815:             $this->rMargin = ($this->w - $this->x);
 5816:             $this->lMargin = ($this->x - $w);
 5817:         } else {
 5818:             $this->lMargin = ($this->x);
 5819:             $this->rMargin = ($this->w - $this->x - $w);
 5820:         }
 5821:         $this->clMargin = $this->lMargin;
 5822:         $this->crMargin = $this->rMargin;
 5823:         if ($autopadding) {
 5824:             // add top padding
 5825:             $this->y += $mc_padding['T'];
 5826:         }
 5827:         if ($ishtml) { // ******* Write HTML text
 5828:             $this->writeHTML($txt, true, false, $reseth, true, $align);
 5829:             $nl = 1;
 5830:         } else { // ******* Write simple text
 5831:             $prev_FontSizePt = $this->FontSizePt;
 5832:             if ($fitcell) {
 5833:                 // ajust height values
 5834:                 $tobottom = ($this->h - $this->y - $this->bMargin - $this->cell_padding['T'] - $this->cell_padding['B']);
 5835:                 $h = $maxh = max(min($h, $tobottom), min($maxh, $tobottom));
 5836:             }
 5837:             // vertical alignment
 5838:             if ($maxh > 0) {
 5839:                 // get text height
 5840:                 $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border);
 5841:                 if ($fitcell AND ($text_height > $maxh) AND ($this->FontSizePt > 1)) {
 5842:                     // try to reduce font size to fit text on cell (use a quick search algorithm)
 5843:                     $fmin = 1;
 5844:                     $fmax = $this->FontSizePt;
 5845:                     $diff_epsilon = (1 / $this->k); // one point (min resolution)
 5846:                     $maxit = (2 * min(100, max(10, intval($fmax)))); // max number of iterations
 5847:                     while ($maxit >= 0) {
 5848:                         $fmid = (($fmax + $fmin) / 2);
 5849:                         $this->SetFontSize($fmid, false);
 5850:                         $this->resetLastH();
 5851:                         $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border);
 5852:                         $diff = ($maxh - $text_height);
 5853:                         if ($diff >= 0) {
 5854:                             if ($diff <= $diff_epsilon) {
 5855:                                 break;
 5856:                             }
 5857:                             $fmin = $fmid;
 5858:                         } else {
 5859:                             $fmax = $fmid;
 5860:                         }
 5861:                         --$maxit;
 5862:                     }
 5863:                     if ($maxit < 0) {
 5864:                         // premature exit, we get the minimum font value to fit the cell
 5865:                         $this->SetFontSize($fmin);
 5866:                         $this->resetLastH();
 5867:                         $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border);
 5868:                     } else {
 5869:                         $this->SetFontSize($fmid);
 5870:                         $this->resetLastH();
 5871:                     }
 5872:                 }
 5873:                 if ($text_height < $maxh) {
 5874:                     if ($valign == 'M') {
 5875:                         // text vertically centered
 5876:                         $this->y += (($maxh - $text_height) / 2);
 5877:                     } elseif ($valign == 'B') {
 5878:                         // text vertically aligned on bottom
 5879:                         $this->y += ($maxh - $text_height);
 5880:                     }
 5881:                 }
 5882:             }
 5883:             $nl = $this->Write($this->lasth, $txt, '', 0, $align, true, $stretch, false, true, $maxh, 0, $mc_margin);
 5884:             if ($fitcell) {
 5885:                 // restore font size
 5886:                 $this->SetFontSize($prev_FontSizePt);
 5887:             }
 5888:         }
 5889:         if ($autopadding) {
 5890:             // add bottom padding
 5891:             $this->y += $mc_padding['B'];
 5892:         }
 5893:         // Get end-of-text Y position
 5894:         $currentY = $this->y;
 5895:         // get latest page number
 5896:         $endpage = $this->page;
 5897:         if ($resth > 0) {
 5898:             $skip = ($endpage - $startpage);
 5899:             $tmpresth = $resth;
 5900:             while ($tmpresth > 0) {
 5901:                 if ($skip <= 0) {
 5902:                     // add a page (or trig AcceptPageBreak() for multicolumn mode)
 5903:                     $this->checkPageBreak($this->PageBreakTrigger + 1);
 5904:                 }
 5905:                 if ($this->num_columns > 1) {
 5906:                     $tmpresth -= ($this->h - $this->y - $this->bMargin);
 5907:                 } else {
 5908:                     $tmpresth -= ($this->h - $this->tMargin - $this->bMargin);
 5909:                 }
 5910:                 --$skip;
 5911:             }
 5912:             $currentY = $this->y;
 5913:             $endpage = $this->page;
 5914:         }
 5915:         // get latest column
 5916:         $endcolumn = $this->current_column;
 5917:         if ($this->num_columns == 0) {
 5918:             $this->num_columns = 1;
 5919:         }
 5920:         // disable page regions check
 5921:         $check_page_regions = $this->check_page_regions;
 5922:         $this->check_page_regions = false;
 5923:         // get border modes
 5924:         $border_start = TCPDF_STATIC::getBorderMode($border, $position='start', $this->opencell);
 5925:         $border_end = TCPDF_STATIC::getBorderMode($border, $position='end', $this->opencell);
 5926:         $border_middle = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell);
 5927:         // design borders around HTML cells.
 5928:         for ($page = $startpage; $page <= $endpage; ++$page) { // for each page
 5929:             $ccode = '';
 5930:             $this->setPage($page);
 5931:             if ($this->num_columns < 2) {
 5932:                 // single-column mode
 5933:                 $this->SetX($x);
 5934:                 $this->y = $this->tMargin;
 5935:             }
 5936:             // account for margin changes
 5937:             if ($page > $startpage) {
 5938:                 if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) {
 5939:                     $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']);
 5940:                 } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) {
 5941:                     $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']);
 5942:                 }
 5943:             }
 5944:             if ($startpage == $endpage) {
 5945:                 // single page
 5946:                 for ($column = $startcolumn; $column <= $endcolumn; ++$column) { // for each column
 5947:                     if ($column != $this->current_column) {
 5948:                         $this->selectColumn($column);
 5949:                     }
 5950:                     if ($this->rtl) {
 5951:                         $this->x -= $mc_margin['R'];
 5952:                     } else {
 5953:                         $this->x += $mc_margin['L'];
 5954:                     }
 5955:                     if ($startcolumn == $endcolumn) { // single column
 5956:                         $cborder = $border;
 5957:                         $h = max($h, ($currentY - $oy));
 5958:                         $this->y = $oy;
 5959:                     } elseif ($column == $startcolumn) { // first column
 5960:                         $cborder = $border_start;
 5961:                         $this->y = $oy;
 5962:                         $h = $this->h - $this->y - $this->bMargin;
 5963:                     } elseif ($column == $endcolumn) { // end column
 5964:                         $cborder = $border_end;
 5965:                         $h = $currentY - $this->y;
 5966:                         if ($resth > $h) {
 5967:                             $h = $resth;
 5968:                         }
 5969:                     } else { // middle column
 5970:                         $cborder = $border_middle;
 5971:                         $h = $this->h - $this->y - $this->bMargin;
 5972:                         $resth -= $h;
 5973:                     }
 5974:                     $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
 5975:                 } // end for each column
 5976:             } elseif ($page == $startpage) { // first page
 5977:                 for ($column = $startcolumn; $column < $this->num_columns; ++$column) { // for each column
 5978:                     if ($column != $this->current_column) {
 5979:                         $this->selectColumn($column);
 5980:                     }
 5981:                     if ($this->rtl) {
 5982:                         $this->x -= $mc_margin['R'];
 5983:                     } else {
 5984:                         $this->x += $mc_margin['L'];
 5985:                     }
 5986:                     if ($column == $startcolumn) { // first column
 5987:                         $cborder = $border_start;
 5988:                         $this->y = $oy;
 5989:                         $h = $this->h - $this->y - $this->bMargin;
 5990:                     } else { // middle column
 5991:                         $cborder = $border_middle;
 5992:                         $h = $this->h - $this->y - $this->bMargin;
 5993:                         $resth -= $h;
 5994:                     }
 5995:                     $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
 5996:                 } // end for each column
 5997:             } elseif ($page == $endpage) { // last page
 5998:                 for ($column = 0; $column <= $endcolumn; ++$column) { // for each column
 5999:                     if ($column != $this->current_column) {
 6000:                         $this->selectColumn($column);
 6001:                     }
 6002:                     if ($this->rtl) {
 6003:                         $this->x -= $mc_margin['R'];
 6004:                     } else {
 6005:                         $this->x += $mc_margin['L'];
 6006:                     }
 6007:                     if ($column == $endcolumn) {
 6008:                         // end column
 6009:                         $cborder = $border_end;
 6010:                         $h = $currentY - $this->y;
 6011:                         if ($resth > $h) {
 6012:                             $h = $resth;
 6013:                         }
 6014:                     } else {
 6015:                         // middle column
 6016:                         $cborder = $border_middle;
 6017:                         $h = $this->h - $this->y - $this->bMargin;
 6018:                         $resth -= $h;
 6019:                     }
 6020:                     $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
 6021:                 } // end for each column
 6022:             } else { // middle page
 6023:                 for ($column = 0; $column < $this->num_columns; ++$column) { // for each column
 6024:                     $this->selectColumn($column);
 6025:                     if ($this->rtl) {
 6026:                         $this->x -= $mc_margin['R'];
 6027:                     } else {
 6028:                         $this->x += $mc_margin['L'];
 6029:                     }
 6030:                     $cborder = $border_middle;
 6031:                     $h = $this->h - $this->y - $this->bMargin;
 6032:                     $resth -= $h;
 6033:                     $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
 6034:                 } // end for each column
 6035:             }
 6036:             if ($cborder OR $fill) {
 6037:                 $offsetlen = strlen($ccode);
 6038:                 // draw border and fill
 6039:                 if ($this->inxobj) {
 6040:                     // we are inside an XObject template
 6041:                     if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) {
 6042:                         $pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']);
 6043:                         $pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey];
 6044:                         $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen;
 6045:                     } else {
 6046:                         $pagemark = $this->xobjects[$this->xobjid]['intmrk'];
 6047:                         $this->xobjects[$this->xobjid]['intmrk'] += $offsetlen;
 6048:                     }
 6049:                     $pagebuff = $this->xobjects[$this->xobjid]['outdata'];
 6050:                     $pstart = substr($pagebuff, 0, $pagemark);
 6051:                     $pend = substr($pagebuff, $pagemark);
 6052:                     $this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend;
 6053:                 } else {
 6054:                     if (end($this->transfmrk[$this->page]) !== false) {
 6055:                         $pagemarkkey = key($this->transfmrk[$this->page]);
 6056:                         $pagemark = $this->transfmrk[$this->page][$pagemarkkey];
 6057:                         $this->transfmrk[$this->page][$pagemarkkey] += $offsetlen;
 6058:                     } elseif ($this->InFooter) {
 6059:                         $pagemark = $this->footerpos[$this->page];
 6060:                         $this->footerpos[$this->page] += $offsetlen;
 6061:                     } else {
 6062:                         $pagemark = $this->intmrk[$this->page];
 6063:                         $this->intmrk[$this->page] += $offsetlen;
 6064:                     }
 6065:                     $pagebuff = $this->getPageBuffer($this->page);
 6066:                     $pstart = substr($pagebuff, 0, $pagemark);
 6067:                     $pend = substr($pagebuff, $pagemark);
 6068:                     $this->setPageBuffer($this->page, $pstart.$ccode.$pend);
 6069:                 }
 6070:             }
 6071:         } // end for each page
 6072:         // restore page regions check
 6073:         $this->check_page_regions = $check_page_regions;
 6074:         // Get end-of-cell Y position
 6075:         $currentY = $this->GetY();
 6076:         // restore previous values
 6077:         if ($this->num_columns > 1) {
 6078:             $this->selectColumn();
 6079:         } else {
 6080:             // restore original margins
 6081:             $this->lMargin = $lMargin;
 6082:             $this->rMargin = $rMargin;
 6083:             if ($this->page > $startpage) {
 6084:                 // check for margin variations between pages (i.e. booklet mode)
 6085:                 $dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$startpage]['olm']);
 6086:                 $dr = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$startpage]['orm']);
 6087:                 if (($dl != 0) OR ($dr != 0)) {
 6088:                     $this->lMargin += $dl;
 6089:                     $this->rMargin += $dr;
 6090:                 }
 6091:             }
 6092:         }
 6093:         if ($ln > 0) {
 6094:             //Go to the beginning of the next line
 6095:             $this->SetY($currentY + $mc_margin['B']);
 6096:             if ($ln == 2) {
 6097:                 $this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']);
 6098:             }
 6099:         } else {
 6100:             // go left or right by case
 6101:             $this->setPage($startpage);
 6102:             $this->y = $y;
 6103:             $this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']);
 6104:         }
 6105:         $this->setContentMark();
 6106:         $this->cell_padding = $prev_cell_padding;
 6107:         $this->cell_margin = $prev_cell_margin;
 6108:         $this->clMargin = $this->lMargin;
 6109:         $this->crMargin = $this->rMargin;
 6110:         return $nl;
 6111:     }
 6112: 
 6113:     /**
 6114:      * This method return the estimated number of lines for print a simple text string using Multicell() method.
 6115:      * @param $txt (string) String for calculating his height
 6116:      * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page.
 6117:      * @param $reseth (boolean) if true reset the last cell height (default false).
 6118:      * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width (default true).
 6119:      * @param $cellpadding (float) Internal cell padding, if empty uses default cell padding.
 6120:      * @param $border (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)))
 6121:      * @return float Return the minimal height needed for multicell method for printing the $txt param.
 6122:      * @author Alexander Escalona Fern\E1ndez, Nicola Asuni
 6123:      * @public
 6124:      * @since 4.5.011
 6125:      */
 6126:     public function getNumLines($txt, $w=0, $reseth=false, $autopadding=true, $cellpadding='', $border=0) {
 6127:         if ($txt === NULL) {
 6128:             return 0;
 6129:         }
 6130:         if ($txt === '') {
 6131:             // empty string
 6132:             return 1;
 6133:         }
 6134:         // adjust internal padding
 6135:         $prev_cell_padding = $this->cell_padding;
 6136:         $prev_lasth = $this->lasth;
 6137:         if (is_array($cellpadding)) {
 6138:             $this->cell_padding = $cellpadding;
 6139:         }
 6140:         $this->adjustCellPadding($border);
 6141:         if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) {
 6142:             if ($this->rtl) {
 6143:                 $w = $this->x - $this->lMargin;
 6144:             } else {
 6145:                 $w = $this->w - $this->rMargin - $this->x;
 6146:             }
 6147:         }
 6148:         $wmax = $w - $this->cell_padding['L'] - $this->cell_padding['R'];
 6149:         if ($reseth) {
 6150:             // reset row height
 6151:             $this->resetLastH();
 6152:         }
 6153:         $lines = 1;
 6154:         $sum = 0;
 6155:         $chars = TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont), $txt, $this->tmprtl, $this->isunicode, $this->CurrentFont);
 6156:         $charsWidth = $this->GetArrStringWidth($chars, '', '', 0, true);
 6157:         $length = count($chars);
 6158:         $lastSeparator = -1;
 6159:         for ($i = 0; $i < $length; ++$i) {
 6160:             $c = $chars[$i];
 6161:             $charWidth = $charsWidth[$i];
 6162:             if (($c != 160)
 6163:                     AND (($c == 173)
 6164:                         OR preg_match($this->re_spaces, TCPDF_FONTS::unichr($c, $this->isunicode))
 6165:                         OR (($c == 45)
 6166:                             AND ($i > 0) AND ($i < ($length - 1))
 6167:                             AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($chars[($i - 1)], $this->isunicode))
 6168:                             AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($chars[($i + 1)], $this->isunicode))
 6169:                         )
 6170:                     )
 6171:                 ) {
 6172:                 $lastSeparator = $i;
 6173:             }
 6174:             if ((($sum + $charWidth) > $wmax) OR ($c == 10)) {
 6175:                 ++$lines;
 6176:                 if ($c == 10) {
 6177:                     $lastSeparator = -1;
 6178:                     $sum = 0;
 6179:                 } elseif ($lastSeparator != -1) {
 6180:                     $i = $lastSeparator;
 6181:                     $lastSeparator = -1;
 6182:                     $sum = 0;
 6183:                 } else {
 6184:                     $sum = $charWidth;
 6185:                 }
 6186:             } else {
 6187:                 $sum += $charWidth;
 6188:             }
 6189:         }
 6190:         if ($chars[($length - 1)] == 10) {
 6191:             --$lines;
 6192:         }
 6193:         $this->cell_padding = $prev_cell_padding;
 6194:         $this->lasth = $prev_lasth;
 6195:         return $lines;
 6196:     }
 6197: 
 6198:     /**
 6199:      * This method return the estimated height needed for printing a simple text string using the Multicell() method.
 6200:      * Generally, if you want to know the exact height for a block of content you can use the following alternative technique:
 6201:      * @pre
 6202:      *  // store current object
 6203:      *  $pdf->startTransaction();
 6204:      *  // store starting values
 6205:      *  $start_y = $pdf->GetY();
 6206:      *  $start_page = $pdf->getPage();
 6207:      *  // call your printing functions with your parameters
 6208:      *  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 6209:      *  $pdf->MultiCell($w=0, $h=0, $txt, $border=1, $align='L', $fill=false, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0);
 6210:      *  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 6211:      *  // get the new Y
 6212:      *  $end_y = $pdf->GetY();
 6213:      *  $end_page = $pdf->getPage();
 6214:      *  // calculate height
 6215:      *  $height = 0;
 6216:      *  if ($end_page == $start_page) {
 6217:      *      $height = $end_y - $start_y;
 6218:      *  } else {
 6219:      *      for ($page=$start_page; $page <= $end_page; ++$page) {
 6220:      *          $this->setPage($page);
 6221:      *          if ($page == $start_page) {
 6222:      *              // first page
 6223:      *              $height = $this->h - $start_y - $this->bMargin;
 6224:      *          } elseif ($page == $end_page) {
 6225:      *              // last page
 6226:      *              $height = $end_y - $this->tMargin;
 6227:      *          } else {
 6228:      *              $height = $this->h - $this->tMargin - $this->bMargin;
 6229:      *          }
 6230:      *      }
 6231:      *  }
 6232:      *  // restore previous object
 6233:      *  $pdf = $pdf->rollbackTransaction();
 6234:      *
 6235:      * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page.
 6236:      * @param $txt (string) String for calculating his height
 6237:      * @param $reseth (boolean) if true reset the last cell height (default false).
 6238:      * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width (default true).
 6239:      * @param $cellpadding (float) Internal cell padding, if empty uses default cell padding.
 6240:      * @param $border (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)))
 6241:      * @return float Return the minimal height needed for multicell method for printing the $txt param.
 6242:      * @author Nicola Asuni, Alexander Escalona Fern\E1ndez
 6243:      * @public
 6244:      */
 6245:     public function getStringHeight($w, $txt, $reseth=false, $autopadding=true, $cellpadding='', $border=0) {
 6246:         // adjust internal padding
 6247:         $prev_cell_padding = $this->cell_padding;
 6248:         $prev_lasth = $this->lasth;
 6249:         if (is_array($cellpadding)) {
 6250:             $this->cell_padding = $cellpadding;
 6251:         }
 6252:         $this->adjustCellPadding($border);
 6253:         $lines = $this->getNumLines($txt, $w, $reseth, $autopadding, $cellpadding, $border);
 6254:         $height = $this->getCellHeight(($lines * $this->FontSize), $autopadding);
 6255:         $this->cell_padding = $prev_cell_padding;
 6256:         $this->lasth = $prev_lasth;
 6257:         return $height;
 6258:     }
 6259: 
 6260:     /**
 6261:      * This method prints text from the current position.<br />
 6262:      * @param $h (float) Line height
 6263:      * @param $txt (string) String to print
 6264:      * @param $link (mixed) URL or identifier returned by AddLink()
 6265:      * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false).
 6266:      * @param $align (string) Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul>
 6267:      * @param $ln (boolean) if true set cursor at the bottom of the line, otherwise set cursor at the top of the line.
 6268:      * @param $stretch (int) font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible.
 6269:      * @param $firstline (boolean) if true prints only the first line and return the remaining string.
 6270:      * @param $firstblock (boolean) if true the string is the starting of a line.
 6271: