PageRenderTime 165ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 3ms

/php/codeigniter/pdf/application/third_party/mpdf/mpdf.php

https://github.com/4vconnect/api
PHP | 13093 lines | 10645 code | 1254 blank | 1194 comment | 4453 complexity | f4f475cdb5506e9156998951b51e7bcc MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. // ******************************************************************************
  3. // Software: mPDF, Unicode-HTML Free PDF generator *
  4. // Version: 5.7 based on *
  5. // FPDF by Olivier PLATHEY *
  6. // HTML2FPDF by Renato Coelho *
  7. // Date: 2013-07-14 *
  8. // Author: Ian Back <ianb@bpm1.com> *
  9. // License: GPL *
  10. // *
  11. // Changes: See changelog.txt *
  12. // ******************************************************************************
  13. define('mPDF_VERSION','5.7');
  14. //Scale factor
  15. define('_MPDFK', (72/25.4));
  16. /*-- HTML-CSS --*/
  17. define('AUTOFONT_CJK',1);
  18. define('AUTOFONT_THAIVIET',2);
  19. define('AUTOFONT_RTL',4);
  20. define('AUTOFONT_INDIC',8);
  21. define('AUTOFONT_ALL',15);
  22. define('_BORDER_ALL',15);
  23. define('_BORDER_TOP',8);
  24. define('_BORDER_RIGHT',4);
  25. define('_BORDER_BOTTOM',2);
  26. define('_BORDER_LEFT',1);
  27. /*-- END HTML-CSS --*/
  28. if (!defined('_MPDF_PATH')) define('_MPDF_PATH', dirname(preg_replace('/\\\\/','/',__FILE__)) . '/');
  29. if (!defined('_MPDF_URI')) define('_MPDF_URI',_MPDF_PATH);
  30. require_once(_MPDF_PATH.'includes/functions.php');
  31. require_once(_MPDF_PATH.'config_cp.php');
  32. if (!defined('_JPGRAPH_PATH')) define("_JPGRAPH_PATH", _MPDF_PATH.'jpgraph/');
  33. if (!defined('_MPDF_TEMP_PATH')) define("_MPDF_TEMP_PATH", _MPDF_PATH.'tmp/');
  34. if (!defined('_MPDF_TTFONTPATH')) { define('_MPDF_TTFONTPATH',_MPDF_PATH.'ttfonts/'); }
  35. if (!defined('_MPDF_TTFONTDATAPATH')) { define('_MPDF_TTFONTDATAPATH',_MPDF_PATH.'ttfontdata/'); }
  36. $errorlevel=error_reporting();
  37. $errorlevel=error_reporting($errorlevel & ~E_NOTICE);
  38. //error_reporting(E_ALL);
  39. if(function_exists("date_default_timezone_set")) {
  40. if (ini_get("date.timezone")=="") { date_default_timezone_set("Europe/London"); }
  41. }
  42. if (!function_exists("mb_strlen")) { die("Error - mPDF requires mb_string functions. Ensure that PHP is compiled with php_mbstring.dll enabled."); }
  43. if (!defined('PHP_VERSION_ID')) {
  44. $version = explode('.', PHP_VERSION);
  45. define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
  46. }
  47. // Machine dependent number of bytes used to pack "double" into binary (used in cacheTables)
  48. $test = pack("d", 134455.474557333333666);
  49. define("_DSIZE", strlen($test));
  50. class mPDF
  51. {
  52. ///////////////////////////////
  53. // EXTERNAL (PUBLIC) VARIABLES
  54. // Define these in config.php
  55. ///////////////////////////////
  56. var $CJKforceend; // mPDF 5.6.40
  57. // mPDF 5.6.34
  58. var $h2bookmarks;
  59. var $h2toc;
  60. var $decimal_align; // mPDF 5.6.13
  61. var $margBuffer; // mPDF 5.4.04
  62. var $splitTableBorderWidth; // mPDF 5.4.16
  63. var $cacheTables;
  64. var $bookmarkStyles;
  65. var $useActiveForms;
  66. var $repackageTTF;
  67. var $allowCJKorphans;
  68. var $allowCJKoverflow;
  69. var $useKerning;
  70. var $restrictColorSpace;
  71. var $bleedMargin;
  72. var $crossMarkMargin;
  73. var $cropMarkMargin;
  74. var $cropMarkLength;
  75. var $nonPrintMargin;
  76. var $PDFX;
  77. var $PDFXauto;
  78. var $PDFA;
  79. var $PDFAauto;
  80. var $ICCProfile;
  81. var $printers_info;
  82. var $iterationCounter;
  83. var $smCapsScale;
  84. var $smCapsStretch;
  85. var $backupSubsFont;
  86. var $backupSIPFont;
  87. var $debugfonts;
  88. var $useAdobeCJK;
  89. var $percentSubset;
  90. var $maxTTFFilesize;
  91. var $BMPonly;
  92. var $tableMinSizePriority;
  93. var $dpi;
  94. var $watermarkImgAlphaBlend;
  95. var $watermarkImgBehind;
  96. var $justifyB4br;
  97. var $packTableData;
  98. var $pgsIns;
  99. var $simpleTables;
  100. var $enableImports;
  101. var $debug;
  102. var $showStats;
  103. var $setAutoTopMargin;
  104. var $setAutoBottomMargin;
  105. var $autoMarginPadding;
  106. var $collapseBlockMargins;
  107. var $falseBoldWeight;
  108. var $normalLineheight;
  109. var $progressBar;
  110. var $incrementFPR1;
  111. var $incrementFPR2;
  112. var $incrementFPR3;
  113. var $incrementFPR4;
  114. var $SHYlang;
  115. var $SHYleftmin;
  116. var $SHYrightmin;
  117. var $SHYcharmin;
  118. var $SHYcharmax;
  119. var $SHYlanguages;
  120. // PageNumber Conditional Text
  121. var $pagenumPrefix;
  122. var $pagenumSuffix;
  123. var $nbpgPrefix;
  124. var $nbpgSuffix;
  125. var $showImageErrors;
  126. var $allow_output_buffering;
  127. var $autoPadding;
  128. var $useGraphs;
  129. var $autoFontGroupSize;
  130. var $tabSpaces;
  131. var $useLang;
  132. var $restoreBlockPagebreaks;
  133. var $watermarkTextAlpha;
  134. var $watermarkImageAlpha;
  135. var $watermark_size;
  136. var $watermark_pos;
  137. var $annotSize;
  138. var $annotMargin;
  139. var $annotOpacity;
  140. var $title2annots;
  141. var $keepColumns;
  142. var $keep_table_proportions;
  143. var $ignore_table_widths;
  144. var $ignore_table_percents;
  145. var $list_align_style;
  146. var $list_number_suffix;
  147. var $useSubstitutions;
  148. var $CSSselectMedia;
  149. var $forcePortraitHeaders;
  150. var $forcePortraitMargins;
  151. var $displayDefaultOrientation;
  152. var $ignore_invalid_utf8;
  153. var $allowedCSStags;
  154. var $onlyCoreFonts;
  155. var $allow_charset_conversion;
  156. var $jSWord;
  157. var $jSmaxChar;
  158. var $jSmaxCharLast;
  159. var $jSmaxWordLast;
  160. var $max_colH_correction;
  161. var $table_error_report;
  162. var $table_error_report_param;
  163. var $biDirectional;
  164. var $text_input_as_HTML;
  165. var $anchor2Bookmark;
  166. var $list_indent_first_level;
  167. var $shrink_tables_to_fit;
  168. var $allow_html_optional_endtags;
  169. var $img_dpi;
  170. var $defaultheaderfontsize;
  171. var $defaultheaderfontstyle;
  172. var $defaultheaderline;
  173. var $defaultfooterfontsize;
  174. var $defaultfooterfontstyle;
  175. var $defaultfooterline;
  176. var $header_line_spacing;
  177. var $footer_line_spacing;
  178. var $pregUHCchars;
  179. var $pregSJISchars;
  180. var $pregCJKchars;
  181. var $pregASCIIchars1;
  182. var $pregASCIIchars2;
  183. var $pregASCIIchars3;
  184. var $pregVIETchars;
  185. var $pregVIETPluschars;
  186. var $pregRTLchars;
  187. var $pregHEBchars;
  188. var $pregARABICchars;
  189. var $pregNonARABICchars;
  190. // INDIC
  191. var $pregHIchars;
  192. var $pregBNchars;
  193. var $pregPAchars;
  194. var $pregGUchars;
  195. var $pregORchars;
  196. var $pregTAchars;
  197. var $pregTEchars;
  198. var $pregKNchars;
  199. var $pregMLchars;
  200. var $pregSHchars;
  201. var $pregINDextra;
  202. var $mirrorMargins;
  203. var $default_lineheight_correction;
  204. var $watermarkText;
  205. var $watermarkImage;
  206. var $showWatermarkText;
  207. var $showWatermarkImage;
  208. var $fontsizes;
  209. // Aliases for backward compatability
  210. var $UnvalidatedText; // alias = $watermarkText
  211. var $TopicIsUnvalidated; // alias = $showWatermarkText
  212. var $useOddEven; // alias = $mirrorMargins
  213. var $useSubstitutionsMB; // alias = $useSubstitutions
  214. //////////////////////
  215. // CLASS OBJECTS
  216. //////////////////////
  217. var $cssmgr;
  218. var $grad;
  219. var $bmp;
  220. var $wmf;
  221. var $tocontents;
  222. var $form;
  223. var $directw;
  224. //////////////////////
  225. // INTERNAL VARIABLES
  226. //////////////////////
  227. var $writingToC; // mPDF 5.6.38
  228. // mPDF 5.6.01
  229. var $layers;
  230. var $current_layer;
  231. var $open_layer_pane;
  232. var $decimal_offset; // mPDF 5.6.13
  233. var $inMeter; // mPDF 5.5.09
  234. var $CJKleading;
  235. var $CJKfollowing;
  236. var $CJKoverflow;
  237. var $textshadow;
  238. var $colsums;
  239. var $spanborder;
  240. var $spanborddet;
  241. var $visibility;
  242. var $useRC128encryption;
  243. var $uniqid;
  244. var $kerning;
  245. var $fixedlSpacing;
  246. var $minwSpacing;
  247. var $lSpacingCSS;
  248. var $wSpacingCSS;
  249. var $listDir;
  250. var $spotColorIDs;
  251. var $SVGcolors;
  252. var $spotColors;
  253. var $defTextColor;
  254. var $defDrawColor;
  255. var $defFillColor;
  256. var $tableBackgrounds;
  257. var $inlineDisplayOff;
  258. var $kt_y00;
  259. var $kt_p00;
  260. var $upperCase;
  261. var $checkSIP;
  262. var $checkSMP;
  263. var $checkCJK;
  264. var $tableCJK;
  265. var $watermarkImgAlpha;
  266. var $PDFAXwarnings;
  267. var $MetadataRoot;
  268. var $OutputIntentRoot;
  269. var $InfoRoot;
  270. var $current_filename;
  271. var $parsers;
  272. var $current_parser;
  273. var $_obj_stack;
  274. var $_don_obj_stack;
  275. var $_current_obj_id;
  276. var $tpls;
  277. var $tpl;
  278. var $tplprefix;
  279. var $_res;
  280. var $pdf_version;
  281. var $noImageFile;
  282. var $lastblockbottommargin;
  283. var $baselineC;
  284. var $subPos;
  285. var $subArrMB;
  286. var $ReqFontStyle;
  287. var $tableClipPath ;
  288. var $forceExactLineheight;
  289. var $listOcc;
  290. var $fullImageHeight;
  291. var $inFixedPosBlock; // Internal flag for position:fixed block
  292. var $fixedPosBlock; // Buffer string for position:fixed block
  293. var $fixedPosBlockDepth;
  294. var $fixedPosBlockBBox;
  295. var $fixedPosBlockSave;
  296. var $maxPosL;
  297. var $maxPosR;
  298. var $loaded;
  299. var $extraFontSubsets;
  300. var $docTemplateStart; // Internal flag for page (page no. -1) that docTemplate starts on
  301. var $time0;
  302. // Classes
  303. var $indic;
  304. var $barcode;
  305. var $SHYpatterns;
  306. var $loadedSHYpatterns;
  307. var $loadedSHYdictionary;
  308. var $SHYdictionary;
  309. var $SHYdictionaryWords;
  310. var $spanbgcolorarray;
  311. var $default_font;
  312. var $list_lineheight;
  313. var $headerbuffer;
  314. var $lastblocklevelchange;
  315. var $nestedtablejustfinished;
  316. var $linebreakjustfinished;
  317. var $cell_border_dominance_L;
  318. var $cell_border_dominance_R;
  319. var $cell_border_dominance_T;
  320. var $cell_border_dominance_B;
  321. var $table_keep_together;
  322. var $plainCell_properties;
  323. var $inherit_lineheight;
  324. var $listitemtype;
  325. var $shrin_k1;
  326. var $outerfilled;
  327. var $blockContext;
  328. var $floatDivs;
  329. var $patterns;
  330. var $pageBackgrounds;
  331. var $bodyBackgroundGradient;
  332. var $bodyBackgroundImage;
  333. var $bodyBackgroundColor;
  334. var $writingHTMLheader; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
  335. var $writingHTMLfooter;
  336. var $autoFontGroups;
  337. var $angle;
  338. var $gradients;
  339. var $kwt_Reference;
  340. var $kwt_BMoutlines;
  341. var $kwt_toc;
  342. var $tbrot_Reference;
  343. var $tbrot_BMoutlines;
  344. var $tbrot_toc;
  345. var $col_Reference;
  346. var $col_BMoutlines;
  347. var $col_toc;
  348. var $currentGraphId;
  349. var $graphs;
  350. var $floatbuffer;
  351. var $floatmargins;
  352. var $bullet;
  353. var $bulletarray;
  354. var $rtlAsArabicFarsi; // DEPRACATED
  355. var $currentLang;
  356. var $default_lang;
  357. var $default_available_fonts;
  358. var $pageTemplate;
  359. var $docTemplate;
  360. var $docTemplateContinue;
  361. var $arabGlyphs;
  362. var $arabHex;
  363. var $persianGlyphs;
  364. var $persianHex;
  365. var $arabVowels;
  366. var $arabPrevLink;
  367. var $arabNextLink;
  368. var $formobjects; // array of Form Objects for WMF
  369. var $InlineProperties;
  370. var $InlineAnnots;
  371. var $ktAnnots;
  372. var $tbrot_Annots;
  373. var $kwt_Annots;
  374. var $columnAnnots;
  375. var $columnForms;
  376. var $PageAnnots;
  377. var $pageDim; // Keep track of page wxh for orientation changes - set in _beginpage, used in _putannots
  378. var $breakpoints;
  379. var $tableLevel;
  380. var $tbctr;
  381. var $innermostTableLevel;
  382. var $saveTableCounter;
  383. var $cellBorderBuffer;
  384. var $saveHTMLFooter_height;
  385. var $saveHTMLFooterE_height;
  386. var $firstPageBoxHeader;
  387. var $firstPageBoxHeaderEven;
  388. var $firstPageBoxFooter;
  389. var $firstPageBoxFooterEven;
  390. var $page_box;
  391. var $show_marks; // crop or cross marks
  392. var $basepathIsLocal;
  393. var $use_kwt;
  394. var $kwt;
  395. var $kwt_height;
  396. var $kwt_y0;
  397. var $kwt_x0;
  398. var $kwt_buffer;
  399. var $kwt_Links;
  400. var $kwt_moved;
  401. var $kwt_saved;
  402. var $PageNumSubstitutions;
  403. var $table_borders_separate;
  404. var $base_table_properties;
  405. var $borderstyles;
  406. var $listjustfinished;
  407. var $blockjustfinished;
  408. var $orig_bMargin;
  409. var $orig_tMargin;
  410. var $orig_lMargin;
  411. var $orig_rMargin;
  412. var $orig_hMargin;
  413. var $orig_fMargin;
  414. var $pageheaders;
  415. var $pagefooters;
  416. var $pageHTMLheaders;
  417. var $pageHTMLfooters;
  418. var $saveHTMLHeader;
  419. var $saveHTMLFooter;
  420. var $HTMLheaderPageLinks;
  421. var $HTMLheaderPageAnnots;
  422. var $HTMLheaderPageForms;
  423. // See config_fonts.php for these next 5 values
  424. var $available_unifonts;
  425. var $sans_fonts;
  426. var $serif_fonts;
  427. var $mono_fonts;
  428. var $defaultSubsFont;
  429. // List of ALL available CJK fonts (incl. styles) (Adobe add-ons) hw removed
  430. var $available_CJK_fonts;
  431. var $HTMLHeader;
  432. var $HTMLFooter;
  433. var $HTMLHeaderE;
  434. var $HTMLFooterE;
  435. var $bufferoutput;
  436. var $showdefaultpagenos; // DEPRACATED -left for backward compatability
  437. // CJK fonts
  438. var $Big5_widths;
  439. var $GB_widths;
  440. var $SJIS_widths;
  441. var $UHC_widths;
  442. // SetProtection
  443. var $encrypted; //whether document is protected
  444. var $Uvalue; //U entry in pdf document
  445. var $Ovalue; //O entry in pdf document
  446. var $Pvalue; //P entry in pdf document
  447. var $enc_obj_id; //encryption object id
  448. var $last_rc4_key; //last RC4 key encrypted (cached for optimisation)
  449. var $last_rc4_key_c; //last RC4 computed key
  450. var $encryption_key;
  451. var $padding; //used for encryption
  452. // Bookmark
  453. var $BMoutlines;
  454. var $OutlineRoot;
  455. // INDEX
  456. var $ColActive;
  457. var $Reference;
  458. var $CurrCol;
  459. var $NbCol;
  460. var $y0; //Top ordinate of columns
  461. var $ColL;
  462. var $ColWidth;
  463. var $ColGap;
  464. // COLUMNS
  465. var $ColR;
  466. var $ChangeColumn;
  467. var $columnbuffer;
  468. var $ColDetails;
  469. var $columnLinks;
  470. var $colvAlign;
  471. // Substitutions
  472. var $substitute; // Array of substitution strings e.g. <ttz>112</ttz>
  473. var $entsearch; // Array of HTML entities (>ASCII 127) to substitute
  474. var $entsubstitute; // Array of substitution decimal unicode for the Hi entities
  475. // Default values if no style sheet offered (cf. http://www.w3.org/TR/CSS21/sample.html)
  476. var $defaultCSS;
  477. var $linemaxfontsize;
  478. var $lineheight_correction;
  479. var $lastoptionaltag; // Save current block item which HTML specifies optionsl endtag
  480. var $pageoutput;
  481. var $charset_in;
  482. var $blk;
  483. var $blklvl;
  484. var $ColumnAdjust;
  485. var $ws; // Word spacing
  486. var $HREF;
  487. var $pgwidth;
  488. var $fontlist;
  489. var $oldx;
  490. var $oldy;
  491. var $B;
  492. var $U; //underlining flag
  493. var $S; // SmallCaps flag
  494. var $I;
  495. var $tdbegin;
  496. var $table;
  497. var $cell;
  498. var $col;
  499. var $row;
  500. var $divbegin;
  501. var $divalign;
  502. var $divwidth;
  503. var $divheight;
  504. var $divrevert;
  505. var $spanbgcolor;
  506. var $spanlvl;
  507. var $listlvl;
  508. var $listnum;
  509. var $listtype;
  510. var $listoccur;
  511. var $listlist;
  512. var $listitem;
  513. var $pjustfinished;
  514. var $ignorefollowingspaces;
  515. var $SUP;
  516. var $SUB;
  517. var $SMALL;
  518. var $BIG;
  519. var $toupper;
  520. var $tolower;
  521. var $capitalize;
  522. var $dash_on;
  523. var $dotted_on;
  524. var $strike;
  525. var $textbuffer;
  526. var $currentfontstyle;
  527. var $currentfontfamily;
  528. var $currentfontsize;
  529. var $colorarray;
  530. var $bgcolorarray;
  531. var $internallink;
  532. var $enabledtags;
  533. var $lineheight;
  534. var $basepath;
  535. var $textparam;
  536. var $specialcontent;
  537. var $selectoption;
  538. var $objectbuffer;
  539. // Table Rotation
  540. var $table_rotate;
  541. var $tbrot_maxw;
  542. var $tbrot_maxh;
  543. var $tablebuffer;
  544. var $tbrot_align;
  545. var $tbrot_Links;
  546. var $divbuffer; // Buffer used when keeping DIV on one page
  547. var $keep_block_together; // Keep a Block from page-break-inside: avoid
  548. var $ktLinks; // Keep-together Block links array
  549. var $ktBlock; // Keep-together Block array
  550. var $ktForms;
  551. var $ktReference;
  552. var $ktBMoutlines;
  553. var $_kttoc;
  554. var $tbrot_y0;
  555. var $tbrot_x0;
  556. var $tbrot_w;
  557. var $tbrot_h;
  558. var $mb_enc;
  559. var $directionality;
  560. var $extgstates; // Used for alpha channel - Transparency (Watermark)
  561. var $mgl;
  562. var $mgt;
  563. var $mgr;
  564. var $mgb;
  565. var $tts;
  566. var $ttz;
  567. var $tta;
  568. var $headerDetails;
  569. var $footerDetails;
  570. // Best to alter the below variables using default stylesheet above
  571. var $page_break_after_avoid;
  572. var $margin_bottom_collapse;
  573. var $list_indent;
  574. var $list_align;
  575. var $list_margin_bottom;
  576. var $default_font_size; // in pts
  577. var $original_default_font_size; // used to save default sizes when using table default
  578. var $original_default_font;
  579. var $watermark_font;
  580. var $defaultAlign;
  581. // TABLE
  582. var $defaultTableAlign;
  583. var $tablethead;
  584. var $thead_font_weight;
  585. var $thead_font_style;
  586. var $thead_font_smCaps;
  587. var $thead_valign_default;
  588. var $thead_textalign_default;
  589. var $tabletfoot;
  590. var $tfoot_font_weight;
  591. var $tfoot_font_style;
  592. var $tfoot_font_smCaps;
  593. var $tfoot_valign_default;
  594. var $tfoot_textalign_default;
  595. var $trow_text_rotate;
  596. var $cellPaddingL;
  597. var $cellPaddingR;
  598. var $cellPaddingT;
  599. var $cellPaddingB;
  600. var $table_lineheight;
  601. var $table_border_attr_set;
  602. var $table_border_css_set;
  603. var $shrin_k; // factor with which to shrink tables - used internally - do not change
  604. var $shrink_this_table_to_fit; // 0 or false to disable; value (if set) gives maximum factor to reduce fontsize
  605. var $MarginCorrection; // corrects for OddEven Margins
  606. var $margin_footer;
  607. var $margin_header;
  608. var $tabletheadjustfinished;
  609. var $usingCoreFont;
  610. var $charspacing;
  611. //Private properties FROM FPDF
  612. var $DisplayPreferences;
  613. var $flowingBlockAttr;
  614. var $page; //current page number
  615. var $n; //current object number
  616. var $offsets; //array of object offsets
  617. var $buffer; //buffer holding in-memory PDF
  618. var $pages; //array containing pages
  619. var $state; //current document state
  620. var $compress; //compression flag
  621. var $DefOrientation; //default orientation
  622. var $CurOrientation; //current orientation
  623. var $OrientationChanges; //array indicating orientation changes
  624. var $k; //scale factor (number of points in user unit)
  625. var $fwPt;
  626. var $fhPt; //dimensions of page format in points
  627. var $fw;
  628. var $fh; //dimensions of page format in user unit
  629. var $wPt;
  630. var $hPt; //current dimensions of page in points
  631. var $w;
  632. var $h; //current dimensions of page in user unit
  633. var $lMargin; //left margin
  634. var $tMargin; //top margin
  635. var $rMargin; //right margin
  636. var $bMargin; //page break margin
  637. var $cMarginL; //cell margin Left
  638. var $cMarginR; //cell margin Right
  639. var $cMarginT; //cell margin Left
  640. var $cMarginB; //cell margin Right
  641. var $DeflMargin; //Default left margin
  642. var $DefrMargin; //Default right margin
  643. var $x;
  644. var $y; //current position in user unit for cell positioning
  645. var $lasth; //height of last cell printed
  646. var $LineWidth; //line width in user unit
  647. var $CoreFonts; //array of standard font names
  648. var $fonts; //array of used fonts
  649. var $FontFiles; //array of font files
  650. var $images; //array of used images
  651. var $PageLinks; //array of links in pages
  652. var $links; //array of internal links
  653. var $FontFamily; //current font family
  654. var $FontStyle; //current font style
  655. var $CurrentFont; //current font info
  656. var $FontSizePt; //current font size in points
  657. var $FontSize; //current font size in user unit
  658. var $DrawColor; //commands for drawing color
  659. var $FillColor; //commands for filling color
  660. var $TextColor; //commands for text color
  661. var $ColorFlag; //indicates whether fill and text colors are different
  662. var $autoPageBreak; //automatic page breaking
  663. var $PageBreakTrigger; //threshold used to trigger page breaks
  664. var $InFooter; //flag set when processing footer
  665. var $InHTMLFooter;
  666. var $processingFooter; //flag set when processing footer - added for columns
  667. var $processingHeader; //flag set when processing header - added for columns
  668. var $ZoomMode; //zoom display mode
  669. var $LayoutMode; //layout display mode
  670. var $title; //title
  671. var $subject; //subject
  672. var $author; //author
  673. var $keywords; //keywords
  674. var $creator; //creator
  675. var $aliasNbPg; //alias for total number of pages
  676. var $aliasNbPgGp; //alias for total number of pages in page group
  677. var $aliasNbPgHex;
  678. var $aliasNbPgGpHex;
  679. var $ispre;
  680. var $outerblocktags;
  681. var $innerblocktags;
  682. // **********************************
  683. // **********************************
  684. // **********************************
  685. // **********************************
  686. // **********************************
  687. // **********************************
  688. // **********************************
  689. // **********************************
  690. // **********************************
  691. function mPDF($mode='',$format='A4',$default_font_size=0,$default_font='',$mgl=15,$mgr=15,$mgt=16,$mgb=16,$mgh=9,$mgf=9, $orientation='P') {
  692. /*-- BACKGROUNDS --*/
  693. if (!class_exists('grad', false)) { include(_MPDF_PATH.'classes/grad.php'); }
  694. if (empty($this->grad)) { $this->grad = new grad($this); }
  695. /*-- END BACKGROUNDS --*/
  696. /*-- FORMS --*/
  697. if (!class_exists('form', false)) { include(_MPDF_PATH.'classes/form.php'); }
  698. if (empty($this->form)) { $this->form = new form($this); }
  699. /*-- END FORMS --*/
  700. $this->time0 = microtime(true);
  701. //Some checks
  702. $this->_dochecks();
  703. // Set up Aliases for backwards compatability
  704. $this->UnvalidatedText =& $this->watermarkText;
  705. $this->TopicIsUnvalidated =& $this->showWatermarkText;
  706. $this->AliasNbPg =& $this->aliasNbPg;
  707. $this->AliasNbPgGp =& $this->aliasNbPgGp;
  708. $this->BiDirectional =& $this->biDirectional;
  709. $this->Anchor2Bookmark =& $this->anchor2Bookmark;
  710. $this->KeepColumns =& $this->keepColumns;
  711. $this->useOddEven =& $this->mirrorMargins;
  712. $this->useSubstitutionsMB =& $this->useSubstitutions;
  713. $this->writingToC = false; // mPDF 5.6.38
  714. // mPDF 5.6.01
  715. $this->layers = array();
  716. $this->current_layer = 0;
  717. $this->open_layer_pane = false;
  718. $this->visibility='visible';
  719. //Initialization of properties
  720. $this->spotColors=array();
  721. $this->spotColorIDs = array();
  722. $this->tableBackgrounds = array();
  723. $this->kt_y00 = '';
  724. $this->kt_p00 = '';
  725. $this->iterationCounter = false;
  726. $this->BMPonly = array();
  727. $this->page=0;
  728. $this->n=2;
  729. $this->buffer='';
  730. $this->objectbuffer = array();
  731. $this->pages=array();
  732. $this->OrientationChanges=array();
  733. $this->state=0;
  734. $this->fonts=array();
  735. $this->FontFiles=array();
  736. $this->images=array();
  737. $this->links=array();
  738. $this->InFooter=false;
  739. $this->processingFooter=false;
  740. $this->processingHeader=false;
  741. $this->lasth=0;
  742. $this->FontFamily='';
  743. $this->FontStyle='';
  744. $this->FontSizePt=9;
  745. $this->U=false;
  746. // Small Caps
  747. $this->upperCase = array();
  748. $this->S = false;
  749. $this->smCapsScale = 1;
  750. $this->smCapsStretch = 100;
  751. $this->margBuffer = 0; // mPDF 5.4.04
  752. $this->inMeter = false; // mPDF 5.5.09
  753. $this->decimal_offset = 0;
  754. $this->defTextColor = $this->TextColor = $this->SetTColor($this->ConvertColor(0),true);
  755. $this->defDrawColor = $this->DrawColor = $this->SetDColor($this->ConvertColor(0),true);
  756. $this->defFillColor = $this->FillColor = $this->SetFColor($this->ConvertColor(255),true);
  757. //SVG color names array
  758. //http://www.w3schools.com/css/css_colornames.asp
  759. $this->SVGcolors = array('antiquewhite'=>'#FAEBD7','aqua'=>'#00FFFF','aquamarine'=>'#7FFFD4','beige'=>'#F5F5DC','black'=>'#000000',
  760. 'blue'=>'#0000FF','brown'=>'#A52A2A','cadetblue'=>'#5F9EA0','chocolate'=>'#D2691E','cornflowerblue'=>'#6495ED','crimson'=>'#DC143C',
  761. 'darkblue'=>'#00008B','darkgoldenrod'=>'#B8860B','darkgreen'=>'#006400','darkmagenta'=>'#8B008B','darkorange'=>'#FF8C00',
  762. 'darkred'=>'#8B0000','darkseagreen'=>'#8FBC8F','darkslategray'=>'#2F4F4F','darkviolet'=>'#9400D3','deepskyblue'=>'#00BFFF',
  763. 'dodgerblue'=>'#1E90FF','firebrick'=>'#B22222','forestgreen'=>'#228B22','fuchsia'=>'#FF00FF','gainsboro'=>'#DCDCDC','gold'=>'#FFD700',
  764. 'gray'=>'#808080','green'=>'#008000','greenyellow'=>'#ADFF2F','hotpink'=>'#FF69B4','indigo'=>'#4B0082','khaki'=>'#F0E68C',
  765. 'lavenderblush'=>'#FFF0F5','lemonchiffon'=>'#FFFACD','lightcoral'=>'#F08080','lightgoldenrodyellow'=>'#FAFAD2','lightgreen'=>'#90EE90',
  766. 'lightsalmon'=>'#FFA07A','lightskyblue'=>'#87CEFA','lightslategray'=>'#778899','lightyellow'=>'#FFFFE0','lime'=>'#00FF00','limegreen'=>'#32CD32',
  767. 'magenta'=>'#FF00FF','maroon'=>'#800000','mediumaquamarine'=>'#66CDAA','mediumorchid'=>'#BA55D3','mediumseagreen'=>'#3CB371',
  768. 'mediumspringgreen'=>'#00FA9A','mediumvioletred'=>'#C71585','midnightblue'=>'#191970','mintcream'=>'#F5FFFA','moccasin'=>'#FFE4B5','navy'=>'#000080',
  769. 'olive'=>'#808000','orange'=>'#FFA500','orchid'=>'#DA70D6','palegreen'=>'#98FB98',
  770. 'palevioletred'=>'#D87093','peachpuff'=>'#FFDAB9','pink'=>'#FFC0CB','powderblue'=>'#B0E0E6','purple'=>'#800080',
  771. 'red'=>'#FF0000','royalblue'=>'#4169E1','salmon'=>'#FA8072','seagreen'=>'#2E8B57','sienna'=>'#A0522D','silver'=>'#C0C0C0','skyblue'=>'#87CEEB',
  772. 'slategray'=>'#708090','springgreen'=>'#00FF7F','steelblue'=>'#4682B4','tan'=>'#D2B48C','teal'=>'#008080','thistle'=>'#D8BFD8','turquoise'=>'#40E0D0',
  773. 'violetred'=>'#D02090','white'=>'#FFFFFF','yellow'=>'#FFFF00',
  774. 'aliceblue'=>'#f0f8ff', 'azure'=>'#f0ffff', 'bisque'=>'#ffe4c4', 'blanchedalmond'=>'#ffebcd', 'blueviolet'=>'#8a2be2', 'burlywood'=>'#deb887',
  775. 'chartreuse'=>'#7fff00', 'coral'=>'#ff7f50', 'cornsilk'=>'#fff8dc', 'cyan'=>'#00ffff', 'darkcyan'=>'#008b8b', 'darkgray'=>'#a9a9a9',
  776. 'darkgrey'=>'#a9a9a9', 'darkkhaki'=>'#bdb76b', 'darkolivegreen'=>'#556b2f', 'darkorchid'=>'#9932cc', 'darksalmon'=>'#e9967a',
  777. 'darkslateblue'=>'#483d8b', 'darkslategrey'=>'#2f4f4f', 'darkturquoise'=>'#00ced1', 'deeppink'=>'#ff1493', 'dimgray'=>'#696969',
  778. 'dimgrey'=>'#696969', 'floralwhite'=>'#fffaf0', 'ghostwhite'=>'#f8f8ff', 'goldenrod'=>'#daa520', 'grey'=>'#808080', 'honeydew'=>'#f0fff0',
  779. 'indianred'=>'#cd5c5c', 'ivory'=>'#fffff0', 'lavender'=>'#e6e6fa', 'lawngreen'=>'#7cfc00', 'lightblue'=>'#add8e6', 'lightcyan'=>'#e0ffff',
  780. 'lightgray'=>'#d3d3d3', 'lightgrey'=>'#d3d3d3', 'lightpink'=>'#ffb6c1', 'lightseagreen'=>'#20b2aa', 'lightslategrey'=>'#778899',
  781. 'lightsteelblue'=>'#b0c4de', 'linen'=>'#faf0e6', 'mediumblue'=>'#0000cd', 'mediumpurple'=>'#9370db', 'mediumslateblue'=>'#7b68ee',
  782. 'mediumturquoise'=>'#48d1cc', 'mistyrose'=>'#ffe4e1', 'navajowhite'=>'#ffdead', 'oldlace'=>'#fdf5e6', 'olivedrab'=>'#6b8e23', 'orangered'=>'#ff4500',
  783. 'palegoldenrod'=>'#eee8aa', 'paleturquoise'=>'#afeeee', 'papayawhip'=>'#ffefd5', 'peru'=>'#cd853f', 'plum'=>'#dda0dd', 'rosybrown'=>'#bc8f8f',
  784. 'saddlebrown'=>'#8b4513', 'sandybrown'=>'#f4a460', 'seashell'=>'#fff5ee', 'slateblue'=>'#6a5acd', 'slategrey'=>'#708090', 'snow'=>'#fffafa',
  785. 'tomato'=>'#ff6347', 'violet'=>'#ee82ee', 'wheat'=>'#f5deb3', 'whitesmoke'=>'#f5f5f5', 'yellowgreen'=>'#9acd32');
  786. $this->ColorFlag=false;
  787. $this->extgstates = array();
  788. $this->mb_enc='windows-1252';
  789. $this->directionality='ltr';
  790. $this->defaultAlign = 'L';
  791. $this->defaultTableAlign = 'L';
  792. $this->fixedPosBlockSave = array();
  793. $this->extraFontSubsets = 0;
  794. $this->SHYpatterns = array();
  795. $this->loadedSHYdictionary = false;
  796. $this->SHYdictionary = array();
  797. $this->SHYdictionaryWords = array();
  798. $this->blockContext = 1;
  799. $this->floatDivs = array();
  800. $this->DisplayPreferences='';
  801. $this->patterns = array(); // Tiling patterns used for backgrounds
  802. $this->pageBackgrounds = array();
  803. $this->writingHTMLheader = false; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
  804. $this->writingHTMLfooter = false; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
  805. $this->gradients = array();
  806. $this->kwt_Reference = array();
  807. $this->kwt_BMoutlines = array();
  808. $this->kwt_toc = array();
  809. $this->tbrot_Reference = array();
  810. $this->tbrot_BMoutlines = array();
  811. $this->tbrot_toc = array();
  812. $this->col_Reference = array();
  813. $this->col_BMoutlines = array();
  814. $this->col_toc = array();
  815. $this->graphs = array();
  816. $this->pgsIns = array();
  817. $this->PDFAXwarnings = array();
  818. $this->inlineDisplayOff = false;
  819. $this->kerning = false;
  820. $this->lSpacingCSS = '';
  821. $this->wSpacingCSS = '';
  822. $this->fixedlSpacing = false;
  823. $this->minwSpacing = 0;
  824. $this->baselineC = 0.35; // Baseline for text
  825. $this->noImageFile = str_replace("\\","/",dirname(__FILE__)) . '/includes/no_image.jpg';
  826. $this->subPos = 0;
  827. $this->forceExactLineheight = false;
  828. $this->listOcc = 0;
  829. $this->normalLineheight = 1.3;
  830. // These are intended as configuration variables, and should be set in config.php - which will override these values;
  831. // set here as failsafe as will cause an error if not defined
  832. $this->incrementFPR1 = 10;
  833. $this->incrementFPR2 = 10;
  834. $this->incrementFPR3 = 10;
  835. $this->incrementFPR4 = 10;
  836. $this->fullImageHeight = false;
  837. $this->floatbuffer = array();
  838. $this->floatmargins = array();
  839. $this->autoFontGroups = 0;
  840. $this->formobjects=array(); // array of Form Objects for WMF
  841. $this->InlineProperties=array();
  842. $this->InlineAnnots=array();
  843. $this->ktAnnots=array();
  844. $this->tbrot_Annots=array();
  845. $this->kwt_Annots=array();
  846. $this->columnAnnots=array();
  847. $this->pageDim=array();
  848. $this->breakpoints = array(); // used in columnbuffer
  849. $this->tableLevel=0;
  850. $this->tbctr=array(); // counter for nested tables at each level
  851. $this->page_box = array();
  852. $this->show_marks = ''; // crop or cross marks
  853. $this->kwt = false;
  854. $this->kwt_height = 0;
  855. $this->kwt_y0 = 0;
  856. $this->kwt_x0 = 0;
  857. $this->kwt_buffer = array();
  858. $this->kwt_Links = array();
  859. $this->kwt_moved = false;
  860. $this->kwt_saved = false;
  861. $this->PageNumSubstitutions = array();
  862. $this->base_table_properties=array();
  863. $this->borderstyles = array('inset','groove','outset','ridge','dotted','dashed','solid','double');
  864. $this->tbrot_align = 'C';
  865. $this->pageheaders=array();
  866. $this->pagefooters=array();
  867. $this->pageHTMLheaders=array();
  868. $this->pageHTMLfooters=array();
  869. $this->HTMLheaderPageLinks = array();
  870. $this->HTMLheaderPageAnnots = array();
  871. $this->ktForms = array();
  872. $this->HTMLheaderPageForms = array();
  873. $this->columnForms = array();
  874. $this->tbrotForms = array();
  875. $this->useRC128encryption = false;
  876. $this->uniqid = '';
  877. $this->bufferoutput = false;
  878. $this->encrypted=false; //whether document is protected
  879. $this->BMoutlines=array();
  880. $this->ColActive=0; //Flag indicating that columns are on (the index is being processed)
  881. $this->Reference=array(); //Array containing the references
  882. $this->CurrCol=0; //Current column number
  883. $this->ColL = array(0); // Array of Left pos of columns - absolute - needs Margin correction for Odd-Even
  884. $this->ColR = array(0); // Array of Right pos of columns - absolute pos - needs Margin correction for Odd-Even
  885. $this->ChangeColumn = 0;
  886. $this->columnbuffer = array();
  887. $this->ColDetails = array(); // Keeps track of some column details
  888. $this->columnLinks = array(); // Cross references PageLinks
  889. $this->substitute = array(); // Array of substitution strings e.g. <ttz>112</ttz>
  890. $this->entsearch = array(); // Array of HTML entities (>ASCII 127) to substitute
  891. $this->entsubstitute = array(); // Array of substitution decimal unicode for the Hi entities
  892. $this->lastoptionaltag = '';
  893. $this->charset_in = '';
  894. $this->blk = array();
  895. $this->blklvl = 0;
  896. $this->tts = false;
  897. $this->ttz = false;
  898. $this->tta = false;
  899. $this->ispre=false;
  900. $this->checkSIP = false;
  901. $this->checkSMP = false;
  902. $this->checkCJK = false;
  903. $this->tableCJK = false;
  904. $this->headerDetails=array();
  905. $this->footerDetails=array();
  906. $this->page_break_after_avoid = false;
  907. $this->margin_bottom_collapse = false;
  908. $this->tablethead = 0;
  909. $this->tabletfoot = 0;
  910. $this->table_border_attr_set = 0;
  911. $this->table_border_css_set = 0;
  912. $this->shrin_k = 1.0;
  913. $this->shrink_this_table_to_fit = 0;
  914. $this->MarginCorrection = 0;
  915. $this->tabletheadjustfinished = false;
  916. $this->usingCoreFont = false;
  917. $this->charspacing=0;
  918. $this->autoPageBreak = true;
  919. require(_MPDF_PATH.'config.php'); // config data
  920. $this->_setPageSize($format, $orientation);
  921. $this->DefOrientation=$orientation;
  922. $this->margin_header=$mgh;
  923. $this->margin_footer=$mgf;
  924. $bmargin=$mgb;
  925. $this->DeflMargin = $mgl;
  926. $this->DefrMargin = $mgr;
  927. $this->orig_tMargin = $mgt;
  928. $this->orig_bMargin = $bmargin;
  929. $this->orig_lMargin = $this->DeflMargin;
  930. $this->orig_rMargin = $this->DefrMargin;
  931. $this->orig_hMargin = $this->margin_header;
  932. $this->orig_fMargin = $this->margin_footer;
  933. if ($this->setAutoTopMargin=='pad') { $mgt += $this->margin_header; }
  934. if ($this->setAutoBottomMargin=='pad') { $mgb += $this->margin_footer; }
  935. $this->SetMargins($this->DeflMargin,$this->DefrMargin,$mgt); // sets l r t margin
  936. //Automatic page break
  937. $this->SetAutoPageBreak($this->autoPageBreak,$bmargin); // sets $this->bMargin & PageBreakTrigger
  938. $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
  939. //Interior cell margin (1 mm) ? not used
  940. $this->cMarginL = 1;
  941. $this->cMarginR = 1;
  942. //Line width (0.2 mm)
  943. $this->LineWidth=.567/_MPDFK;
  944. //To make the function Footer() work - replaces {nb} with page number
  945. $this->AliasNbPages();
  946. $this->AliasNbPageGroups();
  947. $this->aliasNbPgHex = '{nbHEXmarker}';
  948. $this->aliasNbPgGpHex = '{nbpgHEXmarker}';
  949. //Enable all tags as default
  950. $this->DisableTags();
  951. //Full width display mode
  952. $this->SetDisplayMode(100); // fullwidth? 'fullpage'
  953. //Compression
  954. $this->SetCompression(true);
  955. //Set default display preferences
  956. $this->SetDisplayPreferences('');
  957. // Font data
  958. require(_MPDF_PATH.'config_fonts.php');
  959. // Available fonts
  960. $this->available_unifonts = array();
  961. foreach ($this->fontdata AS $f => $fs) {
  962. if (isset($fs['R']) && $fs['R']) { $this->available_unifonts[] = $f; }
  963. if (isset($fs['B']) && $fs['B']) { $this->available_unifonts[] = $f.'B'; }
  964. if (isset($fs['I']) && $fs['I']) { $this->available_unifonts[] = $f.'I'; }
  965. if (isset($fs['BI']) && $fs['BI']) { $this->available_unifonts[] = $f.'BI'; }
  966. }
  967. $this->default_available_fonts = $this->available_unifonts;
  968. $optcore = false;
  969. $onlyCoreFonts = false;
  970. if (preg_match('/([\-+])aCJK/i',$mode, $m)) {
  971. preg_replace('/([\-+])aCJK/i','',$mode);
  972. if ($m[1]=='+') { $this->useAdobeCJK = true; }
  973. else { $this->useAdobeCJK = false; }
  974. }
  975. if (strlen($mode)==1) {
  976. if ($mode=='s') { $this->percentSubset = 100; $mode = ''; }
  977. else if ($mode=='c') { $onlyCoreFonts = true; $mode = ''; }
  978. }
  979. else if (substr($mode,-2)=='-s') {
  980. $this->percentSubset = 100;
  981. $mode = substr($mode,0,strlen($mode)-2);
  982. }
  983. else if (substr($mode,-2)=='-c') {
  984. $onlyCoreFonts = true;
  985. $mode = substr($mode,0,strlen($mode)-2);
  986. }
  987. else if (substr($mode,-2)=='-x') {
  988. $optcore = true;
  989. $mode = substr($mode,0,strlen($mode)-2);
  990. }
  991. // Autodetect if mode is a language_country string (en-GB or en_GB or en)
  992. if ((strlen($mode) == 5 && $mode != 'UTF-8') || strlen($mode) == 2) {
  993. list ($coreSuitable,$mpdf_pdf_unifonts) = GetLangOpts($mode, $this->useAdobeCJK);
  994. if ($coreSuitable && $optcore) { $onlyCoreFonts = true; }
  995. if ($mpdf_pdf_unifonts) {
  996. $this->RestrictUnicodeFonts($mpdf_pdf_unifonts);
  997. $this->default_available_fonts = $mpdf_pdf_unifonts;
  998. }
  999. $this->currentLang = $mode;
  1000. $this->default_lang = $mode;
  1001. }
  1002. $this->onlyCoreFonts = $onlyCoreFonts;
  1003. if ($this->onlyCoreFonts) {
  1004. $this->setMBencoding('windows-1252'); // sets $this->mb_enc
  1005. }
  1006. else {
  1007. $this->setMBencoding('UTF-8'); // sets $this->mb_enc
  1008. }
  1009. @mb_regex_encoding('UTF-8'); // required only for mb_ereg... and mb_split functions
  1010. // Adobe CJK fonts
  1011. $this->available_CJK_fonts = array('gb','big5','sjis','uhc','gbB','big5B','sjisB','uhcB','gbI','big5I','sjisI','uhcI',
  1012. 'gbBI','big5BI','sjisBI','uhcBI');
  1013. //Standard fonts
  1014. $this->CoreFonts=array('ccourier'=>'Courier','ccourierB'=>'Courier-Bold','ccourierI'=>'Courier-Oblique','ccourierBI'=>'Courier-BoldOblique',
  1015. 'chelvetica'=>'Helvetica','chelveticaB'=>'Helvetica-Bold','chelveticaI'=>'Helvetica-Oblique','chelveticaBI'=>'Helvetica-BoldOblique',
  1016. 'ctimes'=>'Times-Roman','ctimesB'=>'Times-Bold','ctimesI'=>'Times-Italic','ctimesBI'=>'Times-BoldItalic',
  1017. 'csymbol'=>'Symbol','czapfdingbats'=>'ZapfDingbats');
  1018. $this->fontlist=array("ctimes","ccourier","chelvetica","csymbol","czapfdingbats");
  1019. // Substitutions
  1020. $this->setHiEntitySubstitutions();
  1021. if ($this->onlyCoreFonts) {
  1022. $this->useSubstitutions = true;
  1023. $this->SetSubstitutions();
  1024. }
  1025. else { $this->useSubstitutions = false; }
  1026. /*-- HTML-CSS --*/
  1027. if (!class_exists('cssmgr', false)) { include(_MPDF_PATH .'classes/cssmgr.php'); }
  1028. $this->cssmgr = new cssmgr($this);
  1029. if (file_exists(_MPDF_PATH.'mpdf.css')) {
  1030. $css = file_get_contents(_MPDF_PATH.'mpdf.css');
  1031. $css2 = $this->cssmgr->ReadDefaultCSS($css);
  1032. $this->defaultCSS = $this->cssmgr->array_merge_recursive_unique($this->defaultCSS,$css2);
  1033. }
  1034. /*-- END HTML-CSS --*/
  1035. if ($default_font=='') {
  1036. if ($this->onlyCoreFonts) {
  1037. if (in_array(strtolower($this->defaultCSS['BODY']['FONT-FAMILY']),$this->mono_fonts)) { $default_font = 'ccourier'; }
  1038. else if (in_array(strtolower($this->defaultCSS['BODY']['FONT-FAMILY']),$this->sans_fonts)) { $default_font = 'chelvetica'; }
  1039. else { $default_font = 'ctimes'; }
  1040. }
  1041. else { $default_font = $this->defaultCSS['BODY']['FONT-FAMILY']; }
  1042. }
  1043. if (!$default_font_size) {
  1044. $mmsize = $this->ConvertSize($this->defaultCSS['BODY']['FONT-SIZE']);
  1045. $default_font_size = $mmsize*(_MPDFK);
  1046. }
  1047. if ($default_font) { $this->SetDefaultFont($default_font); }
  1048. if ($default_font_size) { $this->SetDefaultFontSize($default_font_size); }
  1049. $this->SetLineHeight(); // lineheight is in mm
  1050. $this->SetFColor($this->ConvertColor(255));
  1051. $this->HREF='';
  1052. $this->oldy=-1;
  1053. $this->B=0;
  1054. $this->U=false;
  1055. $this->S=false;
  1056. $this->I=0;
  1057. $this->listlvl=0;
  1058. $this->listnum=0;
  1059. $this->listtype='';
  1060. $this->listoccur=array();
  1061. $this->listlist=array();
  1062. $this->listitem=array();
  1063. $this->tdbegin=false;
  1064. $this->table=array();
  1065. $this->cell=array();
  1066. $this->col=-1;
  1067. $this->row=-1;
  1068. $this->cellBorderBuffer = array();
  1069. $this->divbegin=false;
  1070. $this->divalign='';
  1071. $this->divwidth=0;
  1072. $this->divheight=0;
  1073. $this->spanbgcolor=false;
  1074. $this->divrevert=false;
  1075. $this->spanborder=false;
  1076. $this->spanborddet=array();
  1077. $this->blockjustfinished=false;
  1078. $this->listjustfinished=false;
  1079. $this->ignorefollowingspaces = true; //in order to eliminate exceeding left-side spaces
  1080. $this->toupper=false;
  1081. $this->tolower=false;
  1082. $this->capitalize=false;
  1083. $this->dash_on=false;
  1084. $this->dotted_on=false;
  1085. $this->SUP=false;
  1086. $this->SUB=false;
  1087. $this->strike=false;
  1088. $this->textshadow='';
  1089. $this->currentfontfamily='';
  1090. $this->currentfontsize='';
  1091. $this->currentfontstyle='';
  1092. $this->colorarray=array();
  1093. $this->spanbgcolorarray=array();
  1094. $this->textbuffer=array();
  1095. $this->internallink=array();
  1096. $this->basepath = "";
  1097. $this->SetBasePath('');
  1098. $this->textparam = array();
  1099. $this->specialcontent = '';
  1100. $this->selectoption = array();
  1101. /*-- IMPORTS --*/
  1102. $this->tpls = array();
  1103. $this->tpl = 0;
  1104. $this->tplprefix = "/TPL";
  1105. $this->res = array();
  1106. if ($this->enableImports) {
  1107. $this->SetImportUse();
  1108. }
  1109. /*-- END IMPORTS --*/
  1110. if ($this->progressBar) { $this->StartProgressBarOutput($this->progressBar) ; } // *PROGRESS-BAR*
  1111. }
  1112. function _setPageSize($format, &$orientation) {
  1113. //Page format
  1114. if(is_string($format))
  1115. {
  1116. if ($format=='') { $format = 'A4'; }
  1117. $pfo = 'P';
  1118. if(preg_match('/([0-9a-zA-Z]*)-L/i',$format,$m)) { // e.g. A4-L = A4 landscape
  1119. $format=$m[1];
  1120. $pfo='L';
  1121. }
  1122. $format = $this->_getPageFormat($format);
  1123. if (!$format) { $this->Error('Unknown page format: '.$format); }
  1124. else { $orientation = $pfo; }
  1125. $this->fwPt=$format[0];
  1126. $this->fhPt=$format[1];
  1127. }
  1128. else
  1129. {
  1130. if (!$format[0] || !$format[1]) { $this->Error('Invalid page format: '.$format[0].' '.$format[1]); }
  1131. $this->fwPt=$format[0]*_MPDFK;
  1132. $this->fhPt=$format[1]*_MPDFK;
  1133. }
  1134. $this->fw=$this->fwPt/_MPDFK;
  1135. $this->fh=$this->fhPt/_MPDFK;
  1136. //Page orientation
  1137. $orientation=strtolower($orientation);
  1138. if($orientation=='p' or $orientation=='portrait')
  1139. {
  1140. $orientation='P';
  1141. $this->wPt=$this->fwPt;
  1142. $this->hPt=$this->fhPt;
  1143. }
  1144. elseif($orientation=='l' or $orientation=='landscape')
  1145. {
  1146. $orientation='L';
  1147. $this->wPt=$this->fhPt;
  1148. $this->hPt=$this->fwPt;
  1149. }
  1150. else $this->Error('Incorrect orientation: '.$orientation);
  1151. $this->CurOrientation=$orientation;
  1152. $this->w=$this->wPt/_MPDFK;
  1153. $this->h=$this->hPt/_MPDFK;
  1154. }
  1155. function _getPageFormat($format) {
  1156. switch (strtoupper($format)) {
  1157. case '4A0': {$format = array(4767.87,6740.79); break;}
  1158. case '2A0': {$format = array(3370.39,4767.87); break;}
  1159. case 'A0': {$format = array(2383.94,3370.39); break;}
  1160. case 'A1': {$format = array(1683.78,2383.94); break;}
  1161. case 'A2': {$format = array(1190.55,1683.78); break;}
  1162. case 'A3': {$format = array(841.89,1190.55); break;}
  1163. case 'A4': default: {$format = array(595.28,841.89); break;}
  1164. case 'A5': {$format = array(419.53,595.28); break;}
  1165. case 'A6': {$format = array(297.64,419.53); break;}
  1166. case 'A7': {$format = array(209.76,297.64); break;}
  1167. case 'A8': {$format = array(147.40,209.76); break;}
  1168. case 'A9': {$format = array(104.88,147.40); break;}
  1169. case 'A10': {$format = array(73.70,104.88); break;}
  1170. case 'B0': {$format = array(2834.65,4008.19); break;}
  1171. case 'B1': {$format = array(2004.09,2834.65); break;}
  1172. case 'B2': {$format = array(1417.32,2004.09); break;}
  1173. case 'B3': {$format = array(1000.63,1417.32); break;}
  1174. case 'B4': {$format = array(708.66,1000.63); break;}
  1175. case 'B5': {$format = array(498.90,708.66); break;}
  1176. case 'B6': {$format = array(354.33,498.90); break;}
  1177. case 'B7': {$format = array(249.45,354.33); break;}
  1178. case 'B8': {$format = array(175.75,249.45); break;}
  1179. case 'B9': {$format = array(124.72,175.75); break;}
  1180. case 'B10': {$format = array(87.87,124.72); break;}
  1181. case 'C0': {$format = array(2599.37,3676.54); break;}
  1182. case 'C1': {$format = array(1836.85,2599.37); break;}
  1183. case 'C2': {$format = array(1298.27,1836.85); break;}
  1184. case 'C3': {$format = array(918.43,1298.27); break;}
  1185. case 'C4': {$format = array(649.13,918.43); break;}
  1186. case 'C5': {$format = array(459.21,649.13); break;}
  1187. case 'C6': {$format = array(323.15,459.21); break;}
  1188. case 'C7': {$format = array(229.61,323.15); break;}
  1189. case 'C8': {$format = array(161.57,229.61); break;}
  1190. case 'C9': {$format = array(113.39,161.57); break;}
  1191. case 'C10': {$format = array(79.37,113.39); break;}
  1192. case 'RA0': {$format = array(2437.80,3458.27); break;}
  1193. case 'RA1': {$format = array(1729.13,2437.80); break;}
  1194. case 'RA2': {$format = array(1218.90,1729.13); break;}
  1195. case 'RA3': {$format = array(864.57,1218.90); break;}
  1196. case 'RA4': {$format = array(609.45,864.57); break;}
  1197. case 'SRA0': {$format = array(2551.18,3628.35); break;}
  1198. case 'SRA1': {$format = array(1814.17,2551.18); break;}
  1199. case 'SRA2': {$format = array(1275.59,1814.17); break;}
  1200. case 'SRA3': {$format = array(907.09,1275.59); break;}
  1201. case 'SRA4': {$format = array(637.80,907.09); break;}
  1202. case 'LETTER': {$format = array(612.00,792.00); break;}
  1203. case 'LEGAL': {$format = array(612.00,1008.00); break;}
  1204. case 'LEDGER': {$format = array(279.00,432.00); break;}
  1205. case 'TABLOID': {$format = array(279.00,432.00); break;}
  1206. case 'EXECUTIVE': {$format = array(521.86,756.00); break;}
  1207. case 'FOLIO': {$format = array(612.00,936.00); break;}
  1208. case 'B': {$format=array(362.83,561.26 ); break;} // 'B' format paperback size 128x198mm
  1209. case 'A': {$format=array(314.65,504.57 ); break;} // 'A' format paperback size 111x178mm
  1210. case 'DEMY': {$format=array(382.68,612.28 ); break;} // 'Demy' format paperback size 135x216mm
  1211. case 'ROYAL': {$format=array(433.70,663.30 ); break;} // 'Royal' format paperback size 153x234mm
  1212. default: $format = false;
  1213. }
  1214. return $format;
  1215. }
  1216. /*-- PROGRESS-BAR --*/
  1217. function StartProgressBarOutput($mode=1) {
  1218. // must be relative path, or URI (not a file system path)
  1219. if (!defined('_MPDF_URI')) {
  1220. $this->progressBar = false;
  1221. if ($this->debug) { $this->Error("You need to define _MPDF_URI to use the progress bar!"); }
  1222. else return false;
  1223. }
  1224. $this->progressBar = $mode;
  1225. if ($this->progbar_altHTML) {
  1226. echo $this->progbar_altHTML;
  1227. }
  1228. else {
  1229. echo '<html>
  1230. <head>
  1231. <title>mPDF File Progress</title>
  1232. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  1233. <link rel="stylesheet" type="text/css" href="'._MPDF_URI.'progbar.css" />
  1234. </head>
  1235. <body>
  1236. <div class="main">
  1237. <div class="heading">'.$this->progbar_heading.'</div>
  1238. <div class="demo">
  1239. ';
  1240. if ($this->progressBar==2) { echo ' <table width="100%"><tr><td style="width: 50%;">
  1241. <span class="barheading">Writing HTML code</span> <br/>
  1242. <div class="progressBar">
  1243. <div id="element1" class="innerBar">&nbsp;</div>
  1244. </div>
  1245. <span class="code" id="box1"></span>
  1246. </td><td style="width: 50%;">
  1247. <span class="barheading">Autosizing elements</span> <br/>
  1248. <div class="progressBar">
  1249. <div id="element4" class="innerBar">&nbsp;</div>
  1250. </div>
  1251. <span class="code" id="box4"></span>
  1252. <br/><br/>
  1253. <span class="barheading">Writing Tables</span> <br/>
  1254. <div class="progressBar">
  1255. <div id="element7" class="innerBar">&nbsp;</div>
  1256. </div>
  1257. <span class="code" id="box7"></span>
  1258. </td></tr>
  1259. <tr><td><br /><br /></td><td></td></tr>
  1260. <tr><td style="width: 50%;">
  1261. '; }
  1262. echo ' <span class="barheading">Writing PDF file</span> <br/>
  1263. <div class="progressBar">
  1264. <div id="element2" class="innerBar">&nbsp;</div>
  1265. </div>
  1266. <span class="code" id="box2"></span>
  1267. ';
  1268. if ($this->progressBar==2) { echo '
  1269. </td><td style="width: 50%;">
  1270. <span class="barheading">Memory usage</span> <br/>
  1271. <div class="progressBar">
  1272. <div id="element5" class="innerBar">&nbsp;</div>
  1273. </div>
  1274. <span id="box5">0</span> '.ini_get("memory_limit").'<br />
  1275. <br/><br/>
  1276. <span class="barheading">Memory usage (peak)</span> <br/>
  1277. <div class="progressBar">
  1278. <div id="element6" class="innerBar">&nbsp;</div>
  1279. </div>
  1280. <span id="box6">0</span> '.ini_get("memory_limit").'<br />
  1281. </td></tr>
  1282. </table>
  1283. '; }
  1284. echo ' <br/><br/>
  1285. <span id="box3"></span>
  1286. </div>
  1287. ';
  1288. }
  1289. ob_flush();
  1290. flush();
  1291. }
  1292. function UpdateProgressBar($el,$val,$txt='') {
  1293. // $val should be a string - 5 = actual value, +15 = increment
  1294. if ($this->progressBar<2) {
  1295. if ($el>3) { return; }
  1296. else if ($el ==1) { $el = 2; }
  1297. }
  1298. echo '<script type="text/javascript">';
  1299. if ($val) { echo ' document.getElementById(\'element'.$el.'\').style.width=\''.$val.'%\'; '; }
  1300. if ($txt) { echo ' document.getElementById(\'box'.$el.'\').innerHTML=\''.$txt.'\'; '; }
  1301. if ($this->progressBar==2) {
  1302. $m = round(memory_get_usage(true)/1048576);
  1303. $m2 = round(memory_get_peak_usage(true)/1048576);
  1304. $mem = $m * 100 / (ini_get("memory_limit")+0);
  1305. $mem2 = $m2 * 100 / (ini_get("memory_limit")+0);
  1306. echo ' document.getElementById(\'element5\').style.width=\''.$mem.'%\'; ';
  1307. echo ' document.getElementById(\'element6\').style.width=\''.$mem2.'%\'; ';
  1308. echo ' document.getElementById(\'box5\').innerHTML=\''.$m.'MB / \'; ';
  1309. echo ' document.getElementById(\'box6\').innerHTML=\''.$m2.'MB / \'; ';
  1310. }
  1311. echo '</script>'."\n";
  1312. ob_flush();
  1313. flush();
  1314. }
  1315. /*-- END PROGRESS-BAR --*/
  1316. function RestrictUnicodeFonts($res) {
  1317. // $res = array of (Unicode) fonts to restrict to: e.g. norasi|norasiB - language specific
  1318. if (count($res)) { // Leave full list of available fonts if passed blank array
  1319. $this->available_unifonts = $res;
  1320. }
  1321. else { $this->available_unifonts = $this->default_available_fonts; }
  1322. if (count($this->available_unifonts) == 0) { $this->available_unifonts[] = $this->default_available_fonts[0]; }
  1323. $this->available_unifonts = array_values($this->available_unifonts);
  1324. }
  1325. function setMBencoding($enc) {
  1326. if ($this->mb_enc != $enc) {
  1327. $this->mb_enc = $enc;
  1328. mb_internal_encoding($this->mb_enc);
  1329. }
  1330. }
  1331. function SetMargins($left,$right,$top) {
  1332. //Set left, top and right margins
  1333. $this->lMargin=$left;
  1334. $this->rMargin=$right;
  1335. $this->tMargin=$top;
  1336. }
  1337. function ResetMargins() {
  1338. //ReSet left, top margins
  1339. if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P' && $this->CurOrientation=='L') {
  1340. if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
  1341. $this->tMargin=$this->orig_rMargin;
  1342. $this->bMargin=$this->orig_lMargin;
  1343. }
  1344. else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS
  1345. $this->tMargin=$this->orig_lMargin;
  1346. $this->bMargin=$this->orig_rMargin;
  1347. }
  1348. $this->lMargin=$this->DeflMargin;
  1349. $this->rMargin=$this->DefrMargin;
  1350. $this->MarginCorrection = 0;
  1351. $this->PageBreakTrigger=$this->h-$this->bMargin;
  1352. }
  1353. else if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
  1354. $this->lMargin=$this->DefrMargin;
  1355. $this->rMargin=$this->DeflMargin;
  1356. $this->MarginCorrection = $this->DefrMargin-$this->DeflMargin;
  1357. }
  1358. else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS
  1359. $this->lMargin=$this->DeflMargin;
  1360. $this->rMargin=$this->DefrMargin;
  1361. if ($this->mirrorMargins) { $this->MarginCorrection = $this->DeflMargin-$this->DefrMargin; }
  1362. }
  1363. $this->x=$this->lMargin;
  1364. }
  1365. function SetLeftMargin($margin) {
  1366. //Set left margin
  1367. $this->lMargin=$margin;
  1368. if($this->page>0 and $this->x<$margin) $this->x=$margin;
  1369. }
  1370. function SetTopMargin($margin) {
  1371. //Set top margin
  1372. $this->tMargin=$margin;
  1373. }
  1374. function SetRightMargin($margin) {
  1375. //Set right margin
  1376. $this->rMargin=$margin;
  1377. }
  1378. function SetAutoPageBreak($auto,$margin=0) {
  1379. //Set auto page break mode and triggering margin
  1380. $this->autoPageBreak=$auto;
  1381. $this->bMargin=$margin;
  1382. $this->PageBreakTrigger=$this->h-$margin;
  1383. }
  1384. function SetDisplayMode($zoom,$layout='continuous') {
  1385. //Set display mode in viewer
  1386. if($zoom=='fullpage' or $zoom=='fullwidth' or $zoom=='real' or $zoom=='default' or !is_string($zoom))
  1387. $this->ZoomMode=$zoom;
  1388. else
  1389. $this->Error('Incorrect zoom display mode: '.$zoom);
  1390. if($layout=='single' or $layout=='continuous' or $layout=='two' or $layout=='twoleft' or $layout=='tworight' or $layout=='default')
  1391. $this->LayoutMode=$layout;
  1392. else
  1393. $this->Error('Incorrect layout display mode: '.$layout);
  1394. }
  1395. function SetCompression($compress) {
  1396. //Set page compression
  1397. if(function_exists('gzcompress')) $this->compress=$compress;
  1398. else $this->compress=false;
  1399. }
  1400. function SetTitle($title) {
  1401. //Title of document // Arrives as UTF-8
  1402. $this->title = $title;
  1403. }
  1404. function SetSubject($subject) {
  1405. //Subject of document
  1406. $this->subject= $subject;
  1407. }
  1408. function SetAuthor($author) {
  1409. //Author of document
  1410. $this->author= $author;
  1411. }
  1412. function SetKeywords($keywords) {
  1413. //Keywords of document
  1414. $this->keywords= $keywords;
  1415. }
  1416. function SetCreator($creator) {
  1417. //Creator of document
  1418. $this->creator= $creator;
  1419. }
  1420. function SetAnchor2Bookmark($x) {
  1421. $this->anchor2Bookmark = $x;
  1422. }
  1423. function AliasNbPages($alias='{nb}') {
  1424. //Define an alias for total number of pages
  1425. $this->aliasNbPg=$alias;
  1426. }
  1427. function AliasNbPageGroups($alias='{nbpg}') {
  1428. //Define an alias for total number of pages in a group
  1429. $this->aliasNbPgGp=$alias;
  1430. }
  1431. function SetAlpha($alpha, $bm='Normal', $return=false, $mode='B') {
  1432. // alpha: real value from 0 (transparent) to 1 (opaque)
  1433. // bm: blend mode, one of the following:
  1434. // Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn,
  1435. // HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity
  1436. // set alpha for stroking (CA) and non-stroking (ca) operations
  1437. // mode determines F (fill) S (stroke) B (both)
  1438. if (($this->PDFA || $this->PDFX) && $alpha!=1) {
  1439. if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Image opacity must be 100% (Opacity changed to 100%)"; }
  1440. $alpha = 1;
  1441. }
  1442. $a = array('BM'=>'/'.$bm);
  1443. if ($mode=='F' || $mode='B') $a['ca'] = $alpha;
  1444. if ($mode=='S' || $mode='B') $a['CA'] = $alpha;
  1445. $gs = $this->AddExtGState($a);
  1446. if ($return) { return sprintf('/GS%d gs', $gs); }
  1447. else { $this->_out(sprintf('/GS%d gs', $gs)); }
  1448. }
  1449. function AddExtGState($parms) {
  1450. $n = count($this->extgstates);
  1451. // check if graphics state already exists
  1452. for ($i=1; $i<=$n; $i++) {
  1453. if (count($this->extgstates[$i]['parms']) == count($parms)) {
  1454. $same = true;
  1455. foreach($this->extgstates[$i]['parms'] AS $k=>$v) {
  1456. if (!isset($parms[$k]) || $parms[$k] != $v) { $same = false; break; }
  1457. }
  1458. if ($same) { return $i; }
  1459. }
  1460. }
  1461. $n++;
  1462. $this->extgstates[$n]['parms'] = $parms;
  1463. return $n;
  1464. }
  1465. function SetVisibility($v) {
  1466. if (($this->PDFA || $this->PDFX) && $this->visibility!='visible') { $this->PDFAXwarnings[] = "Cannot set visibility to anything other than full when using PDFA or PDFX"; return ''; }
  1467. else if (!$this->PDFA && !$this->PDFX)
  1468. $this->pdf_version='1.5';
  1469. if($this->visibility!='visible') {
  1470. $this->_out('EMC');
  1471. $this->hasOC=intval($this->hasOC ); // mPDF 5.6.01
  1472. }
  1473. if($v=='printonly') {
  1474. $this->_out('/OC /OC1 BDC');
  1475. $this->hasOC=($this->hasOC | 1); // mPDF 5.6.01
  1476. }
  1477. elseif($v=='screenonly') {
  1478. $this->_out('/OC /OC2 BDC');
  1479. $this->hasOC=($this->hasOC | 2); // mPDF 5.6.01
  1480. }
  1481. elseif($v=='hidden') {
  1482. $this->_out('/OC /OC3 BDC');
  1483. $this->hasOC=($this->hasOC | 4); // mPDF 5.6.01
  1484. }
  1485. elseif($v!='visible')
  1486. $this->Error('Incorrect visibility: '.$v);
  1487. $this->visibility=$v;
  1488. }
  1489. function Error($msg) {
  1490. //Fatal error
  1491. header('Content-Type: text/html; charset=utf-8');
  1492. die('<B>mPDF error: </B>'.$msg);
  1493. }
  1494. function Open() {
  1495. //Begin document
  1496. if($this->state==0) $this->_begindoc();
  1497. }
  1498. function Close() {
  1499. if ($this->progressBar) { $this->UpdateProgressBar(2,'2','Closing last page'); } // *PROGRESS-BAR*
  1500. //Terminate document
  1501. if($this->state==3) return;
  1502. if($this->page==0) $this->AddPage($this->CurOrientation);
  1503. if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); } // *TABLES*
  1504. if ($this->tablebuffer) { $this->printtablebuffer(); } // *TABLES*
  1505. /*-- COLUMNS --*/
  1506. if ($this->ColActive) {
  1507. $this->SetColumns(0);
  1508. $this->ColActive = 0;
  1509. if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
  1510. }
  1511. /*-- END COLUMNS --*/
  1512. if (count($this->divbuffer)) { $this->printdivbuffer(); }
  1513. // BODY Backgrounds
  1514. $s = '';
  1515. $s .= $this->PrintBodyBackgrounds();
  1516. $s .= $this->PrintPageBackgrounds();
  1517. $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', "\n".$s."\n".'\\1', $this->pages[$this->page]);
  1518. $this->pageBackgrounds = array();
  1519. if($this->visibility!='visible')
  1520. $this->SetVisibility('visible');
  1521. // mPDF 5.6.01 - LAYERS
  1522. $this->EndLayer();
  1523. if (!$this->tocontents || !$this->tocontents->TOCmark) { //Page footer
  1524. $this->InFooter=true;
  1525. $this->Footer();
  1526. $this->InFooter=false;
  1527. }
  1528. if ($this->tocontents && ($this->tocontents->TOCmark || count($this->tocontents->m_TOC))) { $this->tocontents->insertTOC(); } // *TOC*
  1529. //Close page
  1530. $this->_endpage();
  1531. //Close document
  1532. $this->_enddoc();
  1533. }
  1534. /*-- BACKGROUNDS --*/
  1535. function _resizeBackgroundImage($imw, $imh, $cw, $ch, $resize=0, $repx, $repy, $pba=array(), $size=array()) { // mPDF 5.6.10
  1536. // pba is background positioning area (from CSS background-origin) may not always be set [x,y,w,h]
  1537. // size is from CSS3 background-size - takes precendence over old resize
  1538. // $w - absolute length or % or auto or cover | contain
  1539. // $h - absolute length or % or auto or cover | contain
  1540. // mPDF 5.6.10
  1541. if (isset($pba['w'])) $cw = $pba['w'];
  1542. if (isset($pba['h'])) $ch = $pba['h'];
  1543. $cw = $cw*_MPDFK;
  1544. $ch = $ch*_MPDFK;
  1545. if (empty($size) && !$resize) { return array($imw, $imh, $repx, $repy); }
  1546. // mPDF 5.6.10
  1547. if (isset($size['w']) && $size['w']) {
  1548. if ($size['w']=='contain') {
  1549. // Scale the image, while preserving its intrinsic aspect ratio (if any), to the largest size such that both its width and its height can fit inside the background positioning area.
  1550. // Same as resize==3
  1551. $h = $imh * $cw/$imw;
  1552. $w = $cw;
  1553. if ($h > $ch) {
  1554. $w = $w * $ch/$h;
  1555. $h = $ch;
  1556. }
  1557. }
  1558. else if ($size['w']=='cover') {
  1559. // Scale the image, while preserving its intrinsic aspect ratio (if any), to the smallest size such that both its width and its height can completely cover the background positioning area.
  1560. $h = $imh * $cw/$imw;
  1561. $w = $cw;
  1562. if ($h < $ch) {
  1563. $w = $w * $h/$ch;
  1564. $h = $ch;
  1565. }
  1566. }
  1567. else {
  1568. if (stristr($size['w'] ,'%')) {
  1569. $size['w'] += 0;
  1570. $size['w'] /= 100;
  1571. $size['w'] = ($cw * $size['w']);
  1572. }
  1573. if (stristr($size['h'] ,'%')) {
  1574. $size['h'] += 0;
  1575. $size['h'] /= 100;
  1576. $size['h'] = ($ch * $size['h']);
  1577. }
  1578. if ($size['w']=='auto' && $size['h']=='auto') {
  1579. $w = $imw;
  1580. $h = $imh;
  1581. }
  1582. else if ($size['w']=='auto' && $size['h']!='auto') {
  1583. $w = $imw * $size['h']/$imh;
  1584. $h = $size['h'];
  1585. }
  1586. else if ($size['w']!='auto' && $size['h']=='auto') {
  1587. $h = $imh * $size['w']/$imw;
  1588. $w = $size['w'];
  1589. }
  1590. else {
  1591. $w = $size['w'];
  1592. $h = $size['h'];
  1593. }
  1594. }
  1595. return array($w, $h, $repx, $repy);
  1596. }
  1597. else if ($resize==1 && $imw > $cw) {
  1598. $h = $imh * $cw/$imw;
  1599. return array($cw, $h, $repx, $repy);
  1600. }
  1601. else if ($resize==2 && $imh > $ch) {
  1602. $w = $imw * $ch/$imh;
  1603. return array($w, $ch, $repx, $repy);
  1604. }
  1605. else if ($resize==3) {
  1606. $w = $imw;
  1607. $h = $imh;
  1608. if ($w > $cw) {
  1609. $h = $h * $cw/$w;
  1610. $w = $cw;
  1611. }
  1612. if ($h > $ch) {
  1613. $w = $w * $ch/$h;
  1614. $h = $ch;
  1615. }
  1616. return array($w, $h, $repx, $repy);
  1617. }
  1618. else if ($resize==4) {
  1619. $h = $imh * $cw/$imw;
  1620. return array($cw, $h, $repx, $repy);
  1621. }
  1622. else if ($resize==5) {
  1623. $w = $imw * $ch/$imh;
  1624. return array($w, $ch, $repx, $repy);
  1625. }
  1626. else if ($resize==6) {
  1627. return array($cw, $ch, $repx, $repy);
  1628. }
  1629. return array($imw, $imh, $repx, $repy);
  1630. }
  1631. function SetBackground(&$properties, &$maxwidth) {
  1632. // mPDF 5.6.10 5.6.11
  1633. if (isset($properties['BACKGROUND-ORIGIN']) && ($properties['BACKGROUND-ORIGIN']=='border-box' || $properties['BACKGROUND-ORIGIN']== 'content-box')) { $origin = $properties['BACKGROUND-ORIGIN']; }
  1634. else { $origin = 'padding-box'; }
  1635. // mPDF 5.6.10
  1636. if (isset($properties['BACKGROUND-SIZE'])) {
  1637. if (stristr($properties['BACKGROUND-SIZE'] ,'contain') ) { $bsw = $bsh = 'contain'; }
  1638. else if (stristr($properties['BACKGROUND-SIZE'] ,'cover') ) { $bsw = $bsh = 'cover'; }
  1639. else {
  1640. $bsw = $bsh = 'auto';
  1641. $sz = preg_split('/\s+/',trim($properties['BACKGROUND-SIZE']));
  1642. if (count($sz)==2) { $bsw = $sz[0]; $bsh = $sz[1]; }
  1643. else { $bsw = $sz[0]; }
  1644. if (!stristr($bsw ,'%') && !stristr($bsw ,'auto') ) { $bsw = $this->ConvertSize($bsw ,$maxwidth,$this->FontSize); }
  1645. if (!stristr($bsh ,'%') && !stristr($bsh ,'auto') ) { $bsh = $this->ConvertSize($bsh ,$maxwidth,$this->FontSize); }
  1646. }
  1647. $size = array('w'=>$bsw, 'h'=>$bsh);
  1648. }
  1649. if (preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/',$properties['BACKGROUND-IMAGE'])) {
  1650. return array('gradient'=>$properties['BACKGROUND-IMAGE'], 'origin'=>$origin, 'size'=>$size ); // mPDF 5.6.10
  1651. }
  1652. else {
  1653. $file = $properties['BACKGROUND-IMAGE'];
  1654. $sizesarray = $this->Image($file,0,0,0,0,'','',false, false, false, false, true);
  1655. if (isset($sizesarray['IMAGE_ID'])) {
  1656. $image_id = $sizesarray['IMAGE_ID'];
  1657. $orig_w = $sizesarray['WIDTH']*_MPDFK; // in user units i.e. mm
  1658. $orig_h = $sizesarray['HEIGHT']*_MPDFK; // (using $this->img_dpi)
  1659. if (isset($properties['BACKGROUND-IMAGE-RESOLUTION'])) {
  1660. if (preg_match('/from-image/i', $properties['BACKGROUND-IMAGE-RESOLUTION']) && isset($sizesarray['set-dpi']) && $sizesarray['set-dpi']>0) {
  1661. $orig_w *= $this->img_dpi / $sizesarray['set-dpi'];
  1662. $orig_h *= $this->img_dpi / $sizesarray['set-dpi'];
  1663. }
  1664. else if (preg_match('/(\d+)dpi/i', $properties['BACKGROUND-IMAGE-RESOLUTION'], $m)) {
  1665. $dpi = $m[1];
  1666. if ($dpi > 0) {
  1667. $orig_w *= $this->img_dpi / $dpi;
  1668. $orig_h *= $this->img_dpi / $dpi;
  1669. }
  1670. }
  1671. }
  1672. $x_repeat = true;
  1673. $y_repeat = true;
  1674. if (isset($properties['BACKGROUND-REPEAT'])) {
  1675. if ($properties['BACKGROUND-REPEAT']=='no-repeat' || $properties['BACKGROUND-REPEAT']=='repeat-x') { $y_repeat = false; }
  1676. if ($properties['BACKGROUND-REPEAT']=='no-repeat' || $properties['BACKGROUND-REPEAT']=='repeat-y') { $x_repeat = false; }
  1677. }
  1678. $x_pos = 0;
  1679. $y_pos = 0;
  1680. if (isset($properties['BACKGROUND-POSITION'])) {
  1681. $ppos = preg_split('/\s+/',$properties['BACKGROUND-POSITION']);
  1682. $x_pos = $ppos[0];
  1683. $y_pos = $ppos[1];
  1684. if (!stristr($x_pos ,'%') ) { $x_pos = $this->ConvertSize($x_pos ,$maxwidth,$this->FontSize); }
  1685. if (!stristr($y_pos ,'%') ) { $y_pos = $this->ConvertSize($y_pos ,$maxwidth,$this->FontSize); }
  1686. }
  1687. if (isset($properties['BACKGROUND-IMAGE-RESIZE'])) { $resize = $properties['BACKGROUND-IMAGE-RESIZE']; }
  1688. else { $resize = 0; }
  1689. if (isset($properties['BACKGROUND-IMAGE-OPACITY'])) { $opacity = $properties['BACKGROUND-IMAGE-OPACITY']; }
  1690. else { $opacity = 1; }
  1691. return array('image_id'=>$image_id, 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$x_pos, 'y_pos'=>$y_pos, 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'resize'=>$resize, 'opacity'=>$opacity, 'itype'=>$sizesarray['itype'], 'origin'=>$origin, 'size'=>$size );
  1692. }
  1693. }
  1694. return false;
  1695. }
  1696. /*-- END BACKGROUNDS --*/
  1697. function PrintBodyBackgrounds() {
  1698. $s = '';
  1699. $clx = 0;
  1700. $cly = 0;
  1701. $clw = $this->w;
  1702. $clh = $this->h;
  1703. // If using bleed and trim margins in paged media
  1704. if ($this->pageDim[$this->page]['outer_width_LR'] || $this->pageDim[$this->page]['outer_width_TB']) {
  1705. $clx = $this->pageDim[$this->page]['outer_width_LR'] - $this->pageDim[$this->page]['bleedMargin'];
  1706. $cly = $this->pageDim[$this->page]['outer_width_TB'] - $this->pageDim[$this->page]['bleedMargin'];
  1707. $clw = $this->w - 2*$clx;
  1708. $clh = $this->h - 2*$cly;
  1709. }
  1710. if ($this->bodyBackgroundColor) {
  1711. $s .= 'q ' .$this->SetFColor($this->bodyBackgroundColor, true)."\n";
  1712. if ($this->bodyBackgroundColor{0}==5) { // RGBa
  1713. $s .= $this->SetAlpha(ord($this->bodyBackgroundColor{4})/100, 'Normal', true, 'F')."\n";
  1714. }
  1715. else if ($this->bodyBackgroundColor{0}==6) { // CMYKa
  1716. $s .= $this->SetAlpha(ord($this->bodyBackgroundColor{5})/100, 'Normal', true, 'F')."\n";
  1717. }
  1718. $s .= sprintf('%.3F %.3F %.3F %.3F re f Q', ($clx*_MPDFK), ($cly*_MPDFK),$clw*_MPDFK,$clh*_MPDFK)."\n";
  1719. }
  1720. /*-- BACKGROUNDS --*/
  1721. if ($this->bodyBackgroundGradient) {
  1722. $g = $this->grad->parseBackgroundGradient($this->bodyBackgroundGradient);
  1723. if ($g) {
  1724. $s .= $this->grad->Gradient($clx, $cly, $clw, $clh, (isset($g['gradtype']) ? $g['gradtype'] : null), $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true);
  1725. }
  1726. }
  1727. if ($this->bodyBackgroundImage) {
  1728. if ( $this->bodyBackgroundImage['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $this->bodyBackgroundImage['gradient'])) {
  1729. $g = $this->grad->parseMozGradient( $this->bodyBackgroundImage['gradient']);
  1730. if ($g) {
  1731. $s .= $this->grad->Gradient($clx, $cly, $clw, $clh, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true);
  1732. }
  1733. }
  1734. else if ($this->bodyBackgroundImage['image_id']) { // Background pattern
  1735. $n = count($this->patterns)+1;
  1736. // If using resize, uses TrimBox (not including the bleed)
  1737. list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($this->bodyBackgroundImage['orig_w'], $this->bodyBackgroundImage['orig_h'], $clw, $clh, $this->bodyBackgroundImage['resize'], $this->bodyBackgroundImage['x_repeat'], $this->bodyBackgroundImage['y_repeat']);
  1738. $this->patterns[$n] = array('x'=>$clx, 'y'=>$cly, 'w'=>$clw, 'h'=>$clh, 'pgh'=>$this->h, 'image_id'=>$this->bodyBackgroundImage['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$this->bodyBackgroundImage['x_pos'], 'y_pos'=>$this->bodyBackgroundImage['y_pos'], 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$this->bodyBackgroundImage['itype']);
  1739. if (($this->bodyBackgroundImage['opacity']>0 || $this->bodyBackgroundImage['opacity']==='0') && $this->bodyBackgroundImage['opacity']<1) { $opac = $this->SetAlpha($this->bodyBackgroundImage['opacity'],'Normal',true); }
  1740. else { $opac = ''; }
  1741. $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, ($clx*_MPDFK), ($cly*_MPDFK),$clw*_MPDFK, $clh*_MPDFK) ."\n";
  1742. }
  1743. }
  1744. /*-- END BACKGROUNDS --*/
  1745. return $s;
  1746. }
  1747. function PrintPageBackgrounds($adjustmenty=0) {
  1748. $s = '';
  1749. ksort($this->pageBackgrounds);
  1750. foreach($this->pageBackgrounds AS $bl=>$pbs) {
  1751. foreach ($pbs AS $pb) {
  1752. if ((!isset($pb['image_id']) && !isset($pb['gradient'])) || isset($pb['shadowonly'])) { // Background colour or boxshadow
  1753. // mPDF 5.6.01 - LAYERS
  1754. if($pb['z-index']>0) {
  1755. $this->current_layer = $pb['z-index'];
  1756. $s .= "\n".'/OCBZ-index /ZI'.$pb['z-index'].' BDC'."\n";
  1757. }
  1758. if($pb['visibility']!='visible') {
  1759. if($pb['visibility']=='printonly')
  1760. $s .= '/OC /OC1 BDC'."\n";
  1761. else if($pb['visibility']=='screenonly')
  1762. $s .= '/OC /OC2 BDC'."\n";
  1763. else if($pb['visibility']=='hidden')
  1764. $s .= '/OC /OC3 BDC'."\n";
  1765. }
  1766. // Box shadow
  1767. if (isset($pb['shadow']) && $pb['shadow']) { $s .= $pb['shadow']."\n"; }
  1768. if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
  1769. $s .= 'q '.$this->SetFColor($pb['col'], true)."\n";
  1770. if ($pb['col']{0}==5) { // RGBa
  1771. $s .= $this->SetAlpha(ord($pb['col']{4})/100, 'Normal', true, 'F')."\n";
  1772. }
  1773. else if ($pb['col']{0}==6) { // CMYKa
  1774. $s .= $this->SetAlpha(ord($pb['col']{5})/100, 'Normal', true, 'F')."\n";
  1775. }
  1776. $s .= sprintf('%.3F %.3F %.3F %.3F re f Q',$pb['x']*_MPDFK,($this->h-$pb['y'])*_MPDFK,$pb['w']*_MPDFK,-$pb['h']*_MPDFK)."\n";
  1777. if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
  1778. if($pb['visibility']!='visible')
  1779. $s .= 'EMC'."\n";
  1780. // mPDF 5.6.01 - LAYERS
  1781. if($pb['z-index']>0) {
  1782. $s .= "\n".'EMCBZ-index'."\n";
  1783. $this->current_layer = 0;
  1784. }
  1785. }
  1786. }
  1787. /*-- BACKGROUNDS --*/
  1788. foreach ($pbs AS $pb) {
  1789. // mPDF 5.6.01 - LAYERS
  1790. if ((isset($pb['gradient']) && $pb['gradient']) || (isset($pb['image_id']) && $pb['image_id'])) {
  1791. if($pb['z-index']>0) {
  1792. $this->current_layer = $pb['z-index'];
  1793. $s .= "\n".'/OCGZ-index /ZI'.$pb['z-index'].' BDC'."\n";
  1794. }
  1795. if($pb['visibility']!='visible') {
  1796. if($pb['visibility']=='printonly')
  1797. $s .= '/OC /OC1 BDC'."\n";
  1798. else if($pb['visibility']=='screenonly')
  1799. $s .= '/OC /OC2 BDC'."\n";
  1800. else if($pb['visibility']=='hidden')
  1801. $s .= '/OC /OC3 BDC'."\n";
  1802. }
  1803. }
  1804. if (isset($pb['gradient']) && $pb['gradient']) {
  1805. if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
  1806. $s .= $this->grad->Gradient($pb['x'], $pb['y'], $pb['w'], $pb['h'], $pb['gradtype'], $pb['stops'], $pb['colorspace'], $pb['coords'], $pb['extend'], true);
  1807. if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
  1808. }
  1809. else if (isset($pb['image_id']) && $pb['image_id']) { // Background Image
  1810. $pb['y'] -= $adjustmenty;
  1811. $pb['h'] += $adjustmenty;
  1812. $n = count($this->patterns)+1;
  1813. list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($pb['orig_w'], $pb['orig_h'], $pb['w'], $pb['h'], $pb['resize'], $pb['x_repeat'], $pb['y_repeat'], $pb['bpa'], $pb['size']); // mPDF 5.6.10
  1814. $this->patterns[$n] = array('x'=>$pb['x'], 'y'=>$pb['y'], 'w'=>$pb['w'], 'h'=>$pb['h'], 'pgh'=>$this->h, 'image_id'=>$pb['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$pb['x_pos'], 'y_pos'=>$pb['y_pos'], 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$pb['itype'], 'bpa'=>$pb['bpa']); // mPDF 5.6.10
  1815. $x = $pb['x']*_MPDFK;
  1816. $y = ($this->h - $pb['y'])*_MPDFK;
  1817. $w = $pb['w']*_MPDFK;
  1818. $h = -$pb['h']*_MPDFK;
  1819. if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
  1820. if ($this->writingHTMLfooter || $this->writingHTMLheader) { // Write each (tiles) image rather than use as a pattern
  1821. $iw = $pb['orig_w']/_MPDFK;
  1822. $ih = $pb['orig_h']/_MPDFK;
  1823. $w = $pb['w'];
  1824. $h = $pb['h'];
  1825. $x0 = $pb['x'];
  1826. $y0 = $pb['y'];
  1827. // mPDF 5.6.11
  1828. if (isset($pb['bpa']) && $pb['bpa']) {
  1829. $w = $pb['bpa']['w'];
  1830. $h = $pb['bpa']['h'];
  1831. $x0 = $pb['bpa']['x'];
  1832. $y0 = $pb['bpa']['y'];
  1833. }
  1834. // mPDF 5.6.11
  1835. if (isset($pb['size']['w']) && $pb['size']['w']) {
  1836. $size = $pb['size'];
  1837. if ($size['w']=='contain') {
  1838. // Scale the image, while preserving its intrinsic aspect ratio (if any), to the largest size such that both its width and its height can fit inside the background positioning area.
  1839. // Same as resize==3
  1840. $ih = $ih * $pb['bpa']['w']/$iw;
  1841. $iw = $pb['bpa']['w'];
  1842. if ($ih > $pb['bpa']['h']) {
  1843. $iw = $iw * $pb['bpa']['h']/$ih;
  1844. $ih = $pb['bpa']['h'];
  1845. }
  1846. }
  1847. else if ($size['w']=='cover') {
  1848. // Scale the image, while preserving its intrinsic aspect ratio (if any), to the smallest size such that both its width and its height can completely cover the background positioning area.
  1849. $ih = $ih * $pb['bpa']['w']/$iw;
  1850. $iw = $pb['bpa']['w'];
  1851. if ($ih < $pb['bpa']['h']) {
  1852. $iw = $iw * $ih/$pb['bpa']['h'];
  1853. $ih = $pb['bpa']['h'];
  1854. }
  1855. }
  1856. else {
  1857. if (stristr($size['w'] ,'%')) {
  1858. $size['w'] += 0;
  1859. $size['w'] /= 100;
  1860. $size['w'] = ($pb['bpa']['w'] * $size['w']);
  1861. }
  1862. if (stristr($size['h'] ,'%')) {
  1863. $size['h'] += 0;
  1864. $size['h'] /= 100;
  1865. $size['h'] = ($pb['bpa']['h'] * $size['h']);
  1866. }
  1867. if ($size['w']=='auto' && $size['h']=='auto') {
  1868. $iw = $iw;
  1869. $ih = $ih;
  1870. }
  1871. else if ($size['w']=='auto' && $size['h']!='auto') {
  1872. $iw = $iw * $size['h']/$ih;
  1873. $ih = $size['h'];
  1874. }
  1875. else if ($size['w']!='auto' && $size['h']=='auto') {
  1876. $ih = $ih * $size['w']/$iw;
  1877. $iw = $size['w'];
  1878. }
  1879. else {
  1880. $iw = $size['w'];
  1881. $ih = $size['h'];
  1882. }
  1883. }
  1884. }
  1885. // Number to repeat
  1886. if ($pb['x_repeat']) { $nx = ceil($pb['w']/$iw)+1; } // mPDF 5.6.11
  1887. else { $nx = 1; }
  1888. if ($pb['y_repeat']) { $ny = ceil($pb['h']/$ih)+1; } // mPDF 5.6.11
  1889. else { $ny = 1; }
  1890. $x_pos = $pb['x_pos'];
  1891. if (stristr($x_pos ,'%') ) {
  1892. $x_pos += 0;
  1893. $x_pos /= 100;
  1894. $x_pos = ($pb['bpa']['w'] * $x_pos) - ($iw * $x_pos); // mPDF 5.6.11
  1895. }
  1896. $y_pos = $pb['y_pos'];
  1897. if (stristr($y_pos ,'%') ) {
  1898. $y_pos += 0;
  1899. $y_pos /= 100;
  1900. $y_pos = ($pb['bpa']['h'] * $y_pos) - ($ih * $y_pos); // mPDF 5.6.11
  1901. }
  1902. if ($nx>1) {
  1903. while($x_pos>($pb['x']-$pb['bpa']['x'])) { $x_pos -= $iw; } // mPDF 5.6.11
  1904. }
  1905. if ($ny>1) {
  1906. while($y_pos>($pb['y']-$pb['bpa']['y'])) { $y_pos -= $ih; } // mPDF 5.6.11
  1907. }
  1908. for($xi=0;$xi<$nx;$xi++) {
  1909. for($yi=0;$yi<$ny;$yi++) {
  1910. $x = $x0 + $x_pos + ($iw*$xi);
  1911. $y = $y0 + $y_pos + ($ih*$yi);
  1912. if ($pb['opacity']>0 && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
  1913. else { $opac = ''; }
  1914. $s .= sprintf("q %s %.3F 0 0 %.3F %.3F %.3F cm /I%d Do Q", $opac,$iw*_MPDFK,$ih*_MPDFK,$x*_MPDFK,($this->h-($y+$ih))*_MPDFK,$pb['image_id']) ."\n";
  1915. }
  1916. }
  1917. }
  1918. else {
  1919. if (($pb['opacity']>0 || $pb['opacity']==='0') && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
  1920. else { $opac = ''; }
  1921. $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $x, $y, $w, $h) ."\n";
  1922. }
  1923. if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
  1924. }
  1925. if ((isset($pb['gradient']) && $pb['gradient']) || (isset($pb['image_id']) && $pb['image_id'])) {
  1926. if($pb['visibility']!='visible')
  1927. $s .= 'EMC'."\n";
  1928. // mPDF 5.6.01 - LAYERS
  1929. if($pb['z-index']>0) {
  1930. $s .= "\n".'EMCGZ-index'."\n";
  1931. $this->current_layer = 0;
  1932. }
  1933. }
  1934. }
  1935. /*-- END BACKGROUNDS --*/
  1936. }
  1937. return $s;
  1938. }
  1939. function PrintTableBackgrounds($adjustmenty=0) {
  1940. $s = '';
  1941. /*-- BACKGROUNDS --*/
  1942. ksort($this->tableBackgrounds);
  1943. foreach($this->tableBackgrounds AS $bl=>$pbs) {
  1944. foreach ($pbs AS $pb) {
  1945. if ((!isset($pb['gradient']) || !$pb['gradient']) && (!isset($pb['image_id']) || !$pb['image_id'])) {
  1946. $s .= 'q '.$this->SetFColor($pb['col'], true)."\n";
  1947. if ($pb['col']{0}==5) { // RGBa
  1948. $s .= $this->SetAlpha(ord($pb['col']{4})/100, 'Normal', true, 'F')."\n";
  1949. }
  1950. else if ($pb['col']{0}==6) { // CMYKa
  1951. $s .= $this->SetAlpha(ord($pb['col']{5})/100, 'Normal', true, 'F')."\n";
  1952. }
  1953. $s .= sprintf('%.3F %.3F %.3F %.3F re %s Q',$pb['x']*_MPDFK,($this->h-$pb['y'])*_MPDFK,$pb['w']*_MPDFK,-$pb['h']*_MPDFK,'f')."\n";
  1954. }
  1955. if (isset($pb['gradient']) && $pb['gradient']) {
  1956. if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
  1957. $s .= $this->grad->Gradient($pb['x'], $pb['y'], $pb['w'], $pb['h'], $pb['gradtype'], $pb['stops'], $pb['colorspace'], $pb['coords'], $pb['extend'], true);
  1958. if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
  1959. }
  1960. if (isset($pb['image_id']) && $pb['image_id']) { // Background pattern
  1961. $pb['y'] -= $adjustmenty;
  1962. $pb['h'] += $adjustmenty;
  1963. $n = count($this->patterns)+1;
  1964. list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($pb['orig_w'], $pb['orig_h'], $pb['w'], $pb['h'], $pb['resize'], $pb['x_repeat'], $pb['y_repeat']);
  1965. $this->patterns[$n] = array('x'=>$pb['x'], 'y'=>$pb['y'], 'w'=>$pb['w'], 'h'=>$pb['h'], 'pgh'=>$this->h, 'image_id'=>$pb['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$pb['x_pos'], 'y_pos'=>$pb['y_pos'], 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$pb['itype']);
  1966. $x = $pb['x']*_MPDFK;
  1967. $y = ($this->h - $pb['y'])*_MPDFK;
  1968. $w = $pb['w']*_MPDFK;
  1969. $h = -$pb['h']*_MPDFK;
  1970. if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
  1971. if ($pb['opacity']>0 && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
  1972. else { $opac = ''; }
  1973. $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $x, $y, $w, $h) ."\n";
  1974. if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
  1975. }
  1976. }
  1977. }
  1978. /*-- END BACKGROUNDS --*/
  1979. return $s;
  1980. }
  1981. // mPDF 5.6.01 - LAYERS
  1982. function BeginLayer($id) {
  1983. if($this->current_layer>0) $this->EndLayer();
  1984. if ($id < 1) { return false; }
  1985. if (!isset($this->layers[$id])) {
  1986. $this->layers[$id] = array('name'=>'Layer '.($id) );
  1987. if (($this->PDFA || $this->PDFX)) { $this->PDFAXwarnings[] = "Cannot use layers when using PDFA or PDFX"; return ''; }
  1988. else if (!$this->PDFA && !$this->PDFX) { $this->pdf_version='1.5'; }
  1989. }
  1990. $this->current_layer = $id;
  1991. $this->_out('/OCZ-index /ZI'.$id.' BDC');
  1992. $this->pageoutput[$this->page] = array();
  1993. }
  1994. function EndLayer() {
  1995. if($this->current_layer>0) {
  1996. $this->_out('EMCZ-index');
  1997. $this->current_layer = 0;
  1998. }
  1999. }
  2000. // Depracated - can use AddPage for all
  2001. function AddPages($orientation='',$condition='', $resetpagenum='', $pagenumstyle='', $suppress='',$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='')
  2002. {
  2003. $this->AddPage($orientation,$condition,$resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue,$pagesel,$newformat);
  2004. }
  2005. function AddPageByArray($a) {
  2006. if (!is_array($a)) { $a = array(); }
  2007. $orientation = (isset($a['orientation']) ? $a['orientation'] : '');
  2008. $condition = (isset($a['condition']) ? $a['condition'] : (isset($a['type']) ? $a['type'] : ''));
  2009. $resetpagenum = (isset($a['resetpagenum']) ? $a['resetpagenum'] : '');
  2010. $pagenumstyle = (isset($a['pagenumstyle']) ? $a['pagenumstyle'] : '');
  2011. $suppress = (isset($a['suppress']) ? $a['suppress'] : '');
  2012. $mgl = (isset($a['mgl']) ? $a['mgl'] : (isset($a['margin-left']) ? $a['margin-left'] : ''));
  2013. $mgr = (isset($a['mgr']) ? $a['mgr'] : (isset($a['margin-right']) ? $a['margin-right'] : ''));
  2014. $mgt = (isset($a['mgt']) ? $a['mgt'] : (isset($a['margin-top']) ? $a['margin-top'] : ''));
  2015. $mgb = (isset($a['mgb']) ? $a['mgb'] : (isset($a['margin-bottom']) ? $a['margin-bottom'] : ''));
  2016. $mgh = (isset($a['mgh']) ? $a['mgh'] : (isset($a['margin-header']) ? $a['margin-header'] : ''));
  2017. $mgf = (isset($a['mgf']) ? $a['mgf'] : (isset($a['margin-footer']) ? $a['margin-footer'] : ''));
  2018. $ohname = (isset($a['ohname']) ? $a['ohname'] : (isset($a['odd-header-name']) ? $a['odd-header-name'] : ''));
  2019. $ehname = (isset($a['ehname']) ? $a['ehname'] : (isset($a['even-header-name']) ? $a['even-header-name'] : ''));
  2020. $ofname = (isset($a['ofname']) ? $a['ofname'] : (isset($a['odd-footer-name']) ? $a['odd-footer-name'] : ''));
  2021. $efname = (isset($a['efname']) ? $a['efname'] : (isset($a['even-footer-name']) ? $a['even-footer-name'] : ''));
  2022. $ohvalue = (isset($a['ohvalue']) ? $a['ohvalue'] : (isset($a['odd-header-value']) ? $a['odd-header-value'] : 0));
  2023. $ehvalue = (isset($a['ehvalue']) ? $a['ehvalue'] : (isset($a['even-header-value']) ? $a['even-header-value'] : 0));
  2024. $ofvalue = (isset($a['ofvalue']) ? $a['ofvalue'] : (isset($a['odd-footer-value']) ? $a['odd-footer-value'] : 0));
  2025. $efvalue = (isset($a['efvalue']) ? $a['efvalue'] : (isset($a['even-footer-value']) ? $a['even-footer-value'] : 0));
  2026. $pagesel = (isset($a['pagesel']) ? $a['pagesel'] : (isset($a['pageselector']) ? $a['pageselector'] : ''));
  2027. $newformat = (isset($a['newformat']) ? $a['newformat'] : (isset($a['sheet-size']) ? $a['sheet-size'] : ''));
  2028. $this->AddPage($orientation,$condition,$resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue,$pagesel,$newformat);
  2029. }
  2030. function AddPage($orientation='',$condition='', $resetpagenum='', $pagenumstyle='', $suppress='',$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='')
  2031. {
  2032. /*-- CSS-FLOAT --*/
  2033. // Float DIV
  2034. // Cannot do with columns on, or if any change in page orientation/margins etc.
  2035. // If next page already exists - i.e background /headers and footers already written
  2036. if ($this->state > 0 && $this->page < count($this->pages)) {
  2037. $bak_cml = $this->cMarginL;
  2038. $bak_cmr = $this->cMarginR;
  2039. $bak_dw = $this->divwidth;
  2040. // Paint Div Border if necessary
  2041. if ($this->blklvl > 0) {
  2042. $save_tr = $this->table_rotate; // *TABLES*
  2043. $this->table_rotate = 0; // *TABLES*
  2044. if ($this->y == $this->blk[$this->blklvl]['y0']) { $this->blk[$this->blklvl]['startpage']++; }
  2045. if (($this->y > $this->blk[$this->blklvl]['y0']) || $this->flowingBlockAttr['is_table'] ) { $toplvl = $this->blklvl; }
  2046. else { $toplvl = $this->blklvl-1; }
  2047. $sy = $this->y;
  2048. for ($bl=1;$bl<=$toplvl;$bl++) {
  2049. $this->PaintDivBB('pagebottom',0,$bl);
  2050. }
  2051. $this->y = $sy;
  2052. $this->table_rotate = $save_tr; // *TABLES*
  2053. }
  2054. $s = $this->PrintPageBackgrounds();
  2055. // Writes after the marker so not overwritten later by page background etc.
  2056. $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
  2057. $this->pageBackgrounds = array();
  2058. $family=$this->FontFamily;
  2059. $style=$this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
  2060. $size=$this->FontSizePt;
  2061. $lw=$this->LineWidth;
  2062. $dc=$this->DrawColor;
  2063. $fc=$this->FillColor;
  2064. $tc=$this->TextColor;
  2065. $cf=$this->ColorFlag;
  2066. $this->printfloatbuffer();
  2067. //Move to next page
  2068. $this->page++;
  2069. $this->ResetMargins();
  2070. $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
  2071. $this->x=$this->lMargin;
  2072. $this->y=$this->tMargin;
  2073. $this->FontFamily='';
  2074. $this->_out('2 J');
  2075. $this->LineWidth=$lw;
  2076. $this->_out(sprintf('%.3F w',$lw*_MPDFK));
  2077. if($family) $this->SetFont($family,$style,$size,true,true);
  2078. $this->DrawColor=$dc;
  2079. if($dc!=$this->defDrawColor) $this->_out($dc);
  2080. $this->FillColor=$fc;
  2081. if($fc!=$this->defFillColor) $this->_out($fc);
  2082. $this->TextColor=$tc;
  2083. $this->ColorFlag=$cf;
  2084. for($bl=1;$bl<=$this->blklvl;$bl++) {
  2085. $this->blk[$bl]['y0'] = $this->y;
  2086. // Don't correct more than once for background DIV containing a Float
  2087. if (!isset($this->blk[$bl]['marginCorrected'][$this->page])) { $this->blk[$bl]['x0'] += $this->MarginCorrection; }
  2088. $this->blk[$bl]['marginCorrected'][$this->page] = true;
  2089. }
  2090. $this->cMarginL = $bak_cml;
  2091. $this->cMarginR = $bak_cmr;
  2092. $this->divwidth = $bak_dw;
  2093. return '';
  2094. }
  2095. /*-- END CSS-FLOAT --*/
  2096. //Start a new page
  2097. if($this->state==0) $this->Open();
  2098. $bak_cml = $this->cMarginL;
  2099. $bak_cmr = $this->cMarginR;
  2100. $bak_dw = $this->divwidth;
  2101. $bak_lh = $this->lineheight;
  2102. $orientation = substr(strtoupper($orientation),0,1);
  2103. $condition = strtoupper($condition);
  2104. if ($condition == 'NEXT-EVEN') { // always adds at least one new page to create an Even page
  2105. if (!$this->mirrorMargins) { $condition = ''; }
  2106. else {
  2107. if ($pagesel) { $pbch = $pagesel; $pagesel = ''; } // *CSS-PAGE*
  2108. else { $pbch = false; } // *CSS-PAGE*
  2109. $this->AddPage($this->CurOrientation,'O');
  2110. if ($pbch ) { $pagesel = $pbch; } // *CSS-PAGE*
  2111. $condition = '';
  2112. }
  2113. }
  2114. if ($condition == 'NEXT-ODD') { // always adds at least one new page to create an Odd page
  2115. if (!$this->mirrorMargins) { $condition = ''; }
  2116. else {
  2117. if ($pagesel) { $pbch = $pagesel; $pagesel = ''; } // *CSS-PAGE*
  2118. else { $pbch = false; } // *CSS-PAGE*
  2119. $this->AddPage($this->CurOrientation,'E');
  2120. if ($pbch ) { $pagesel = $pbch; } // *CSS-PAGE*
  2121. $condition = '';
  2122. }
  2123. }
  2124. if ($condition == 'E') { // only adds new page if needed to create an Even page
  2125. if (!$this->mirrorMargins || ($this->page)%2==0) { return false; }
  2126. }
  2127. if ($condition == 'O') { // only adds new page if needed to create an Odd page
  2128. if (!$this->mirrorMargins || ($this->page)%2==1) { return false; }
  2129. }
  2130. if ($resetpagenum || $pagenumstyle || $suppress) {
  2131. $this->PageNumSubstitutions[] = array('from'=>($this->page+1), 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=>$suppress);
  2132. }
  2133. $save_tr = $this->table_rotate; // *TABLES*
  2134. $this->table_rotate = 0; // *TABLES*
  2135. $save_kwt = $this->kwt;
  2136. $this->kwt = 0;
  2137. // mPDF 5.6.01 - LAYERS
  2138. $save_layer = $this->current_layer;
  2139. $save_vis = $this->visibility;
  2140. if($this->visibility!='visible')
  2141. $this->SetVisibility('visible');
  2142. // mPDF 5.6.01 - LAYERS
  2143. $this->EndLayer();
  2144. // Paint Div Border if necessary
  2145. //PAINTS BACKGROUND COLOUR OR BORDERS for DIV - DISABLED FOR COLUMNS (cf. AcceptPageBreak) AT PRESENT in ->PaintDivBB
  2146. if (!$this->ColActive && $this->blklvl > 0) {
  2147. if (isset($this->blk[$this->blklvl]['y0']) && $this->y == $this->blk[$this->blklvl]['y0']) {
  2148. if (isset($this->blk[$this->blklvl]['startpage'])) { $this->blk[$this->blklvl]['startpage']++; }
  2149. else { $this->blk[$this->blklvl]['startpage'] = 1; }
  2150. }
  2151. if ((isset($this->blk[$this->blklvl]['y0']) && $this->y > $this->blk[$this->blklvl]['y0']) || $this->flowingBlockAttr['is_table'] ) { $toplvl = $this->blklvl; }
  2152. else { $toplvl = $this->blklvl-1; }
  2153. $sy = $this->y;
  2154. for ($bl=1;$bl<=$toplvl;$bl++) {
  2155. // mPDF 5.6.01 - LAYERS
  2156. if ($this->blk[$bl]['z-index']>0) {
  2157. $this->BeginLayer($this->blk[$bl]['z-index']);
  2158. }
  2159. if (isset($this->blk[$bl]['visibility']) && $this->blk[$bl]['visibility'] && $this->blk[$bl]['visibility']!='visible') {
  2160. $this->SetVisibility($this->blk[$bl]['visibility']);
  2161. }
  2162. $this->PaintDivBB('pagebottom',0,$bl);
  2163. }
  2164. $this->y = $sy;
  2165. // RESET block y0 and x0 - see below
  2166. }
  2167. if($this->visibility!='visible')
  2168. $this->SetVisibility('visible');
  2169. // mPDF 5.6.01 - LAYERS
  2170. $this->EndLayer();
  2171. // BODY Backgrounds
  2172. if ($this->page > 0) {
  2173. $s = '';
  2174. $s .= $this->PrintBodyBackgrounds();
  2175. $s .= $this->PrintPageBackgrounds();
  2176. $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', "\n".$s."\n".'\\1', $this->pages[$this->page]);
  2177. $this->pageBackgrounds = array();
  2178. }
  2179. $save_kt = $this->keep_block_together;
  2180. $this->keep_block_together = 0;
  2181. $save_cols = false;
  2182. /*-- COLUMNS --*/
  2183. if ($this->ColActive) {
  2184. $save_cols = true;
  2185. $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
  2186. $this->SetColumns(0);
  2187. }
  2188. /*-- END COLUMNS --*/
  2189. $family=$this->FontFamily;
  2190. $style=$this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
  2191. $size=$this->FontSizePt;
  2192. $this->ColumnAdjust = true; // enables column height adjustment for the page
  2193. $lw=$this->LineWidth;
  2194. $dc=$this->DrawColor;
  2195. $fc=$this->FillColor;
  2196. $tc=$this->TextColor;
  2197. $cf=$this->ColorFlag;
  2198. if($this->page>0)
  2199. {
  2200. //Page footer
  2201. $this->InFooter=true;
  2202. $this->Reset();
  2203. $this->pageoutput[$this->page] = array();
  2204. $this->Footer();
  2205. //Close page
  2206. $this->_endpage();
  2207. }
  2208. //Start new page
  2209. $this->_beginpage($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat);
  2210. if ($this->docTemplate) {
  2211. $pagecount = $this->SetSourceFile($this->docTemplate);
  2212. if (($this->page - $this->docTemplateStart) > $pagecount) {
  2213. if ($this->docTemplateContinue) {
  2214. $tplIdx = $this->ImportPage($pagecount);
  2215. $this->UseTemplate($tplIdx);
  2216. }
  2217. }
  2218. else {
  2219. $tplIdx = $this->ImportPage(($this->page - $this->docTemplateStart));
  2220. $this->UseTemplate($tplIdx);
  2221. }
  2222. }
  2223. if ($this->pageTemplate) {
  2224. $this->UseTemplate($this->pageTemplate);
  2225. }
  2226. // Tiling Patterns
  2227. $this->_out('___PAGE___START'.date('jY'));
  2228. $this->_out('___BACKGROUND___PATTERNS'.date('jY'));
  2229. $this->_out('___HEADER___MARKER'.date('jY'));
  2230. $this->pageBackgrounds = array();
  2231. //Set line cap style to square
  2232. $this->SetLineCap(2);
  2233. //Set line width
  2234. $this->LineWidth=$lw;
  2235. $this->_out(sprintf('%.3F w',$lw*_MPDFK));
  2236. //Set font
  2237. if($family) $this->SetFont($family,$style,$size,true,true); // forces write
  2238. //Set colors
  2239. $this->DrawColor=$dc;
  2240. if($dc!=$this->defDrawColor) $this->_out($dc);
  2241. $this->FillColor=$fc;
  2242. if($fc!=$this->defFillColor) $this->_out($fc);
  2243. $this->TextColor=$tc;
  2244. $this->ColorFlag=$cf;
  2245. //Page header
  2246. $this->Header();
  2247. //Restore line width
  2248. if($this->LineWidth!=$lw)
  2249. {
  2250. $this->LineWidth=$lw;
  2251. $this->_out(sprintf('%.3F w',$lw*_MPDFK));
  2252. }
  2253. //Restore font
  2254. if($family) $this->SetFont($family,$style,$size,true,true); // forces write
  2255. //Restore colors
  2256. if($this->DrawColor!=$dc)
  2257. {
  2258. $this->DrawColor=$dc;
  2259. $this->_out($dc);
  2260. }
  2261. if($this->FillColor!=$fc)
  2262. {
  2263. $this->FillColor=$fc;
  2264. $this->_out($fc);
  2265. }
  2266. $this->TextColor=$tc;
  2267. $this->ColorFlag=$cf;
  2268. $this->InFooter=false;
  2269. // mPDF 5.6.01 - LAYERS
  2270. if ($save_layer>0)
  2271. $this->BeginLayer($save_layer);
  2272. if($save_vis!='visible')
  2273. $this->SetVisibility($save_vis);
  2274. /*-- COLUMNS --*/
  2275. if ($save_cols) {
  2276. // Restore columns
  2277. $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
  2278. }
  2279. if ($this->ColActive) { $this->SetCol(0); }
  2280. /*-- END COLUMNS --*/
  2281. //RESET BLOCK BORDER TOP
  2282. if (!$this->ColActive) {
  2283. for($bl=1;$bl<=$this->blklvl;$bl++) {
  2284. $this->blk[$bl]['y0'] = $this->y;
  2285. if (isset($this->blk[$bl]['x0'])) { $this->blk[$bl]['x0'] += $this->MarginCorrection; }
  2286. else { $this->blk[$bl]['x0'] = $this->MarginCorrection; }
  2287. // Added mPDF 3.0 Float DIV
  2288. $this->blk[$bl]['marginCorrected'][$this->page] = true;
  2289. }
  2290. }
  2291. $this->table_rotate = $save_tr; // *TABLES*
  2292. $this->kwt = $save_kwt;
  2293. $this->keep_block_together = $save_kt ;
  2294. $this->cMarginL = $bak_cml;
  2295. $this->cMarginR = $bak_cmr;
  2296. $this->divwidth = $bak_dw;
  2297. $this->lineheight = $bak_lh;
  2298. }
  2299. function PageNo() {
  2300. //Get current page number
  2301. return $this->page;
  2302. }
  2303. function AddSpotColorsFromFile($file) {
  2304. $colors = @file($file) or die("Cannot load spot colors file - ".$file);
  2305. foreach($colors AS $sc) {
  2306. list($name, $c, $m, $y, $k) = preg_split("/\t/",$sc);
  2307. $c = intval($c);
  2308. $m = intval($m);
  2309. $y = intval($y);
  2310. $k = intval($k);
  2311. $this->AddSpotColor($name, $c, $m, $y, $k);
  2312. }
  2313. }
  2314. function AddSpotColor($name, $c, $m, $y, $k) {
  2315. $name = strtoupper(trim($name));
  2316. if(!isset($this->spotColors[$name])) {
  2317. $i=count($this->spotColors)+1;
  2318. $this->spotColors[$name]=array('i'=>$i,'c'=>$c,'m'=>$m,'y'=>$y,'k'=>$k);
  2319. $this->spotColorIDs[$i]=$name;
  2320. }
  2321. }
  2322. function SetColor($col, $type='') {
  2323. $out = '';
  2324. if ($col{0}==3 || $col{0}==5) { // RGB / RGBa
  2325. $out = sprintf('%.3F %.3F %.3F rg',ord($col{1})/255,ord($col{2})/255,ord($col{3})/255);
  2326. }
  2327. else if ($col{0}==1) { // GRAYSCALE
  2328. $out = sprintf('%.3F g',ord($col{1})/255);
  2329. }
  2330. else if ($col{0}==2) { // SPOT COLOR
  2331. $out = sprintf('/CS%d cs %.3F scn',ord($col{1}),ord($col{2})/100);
  2332. }
  2333. else if ($col{0}==4 || $col{0}==6) { // CMYK / CMYKa
  2334. $out = sprintf('%.3F %.3F %.3F %.3F k', ord($col{1})/100, ord($col{2})/100, ord($col{3})/100, ord($col{4})/100);
  2335. }
  2336. if ($type=='Draw') { $out = strtoupper($out); } // e.g. rg => RG
  2337. else if ($type=='CodeOnly') { $out = preg_replace('/\s(rg|g|k)/','',$out); }
  2338. return $out;
  2339. }
  2340. function SetDColor($col, $return=false) {
  2341. $out = $this->SetColor($col, 'Draw');
  2342. if ($return) { return $out; }
  2343. if ($out=='') { return ''; }
  2344. $this->DrawColor = $out;
  2345. if($this->page>0 && ((isset($this->pageoutput[$this->page]['DrawColor']) && $this->pageoutput[$this->page]['DrawColor'] != $this->DrawColor) || !isset($this->pageoutput[$this->page]['DrawColor']) || $this->keep_block_together)) { $this->_out($this->DrawColor); }
  2346. $this->pageoutput[$this->page]['DrawColor'] = $this->DrawColor;
  2347. }
  2348. function SetFColor($col, $return=false) {
  2349. $out = $this->SetColor($col, 'Fill');
  2350. if ($return) { return $out; }
  2351. if ($out=='') { return ''; }
  2352. $this->FillColor = $out;
  2353. $this->ColorFlag = ($out != $this->TextColor);
  2354. if($this->page>0 && ((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']) || $this->keep_block_together)) { $this->_out($this->FillColor); }
  2355. $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
  2356. }
  2357. function SetTColor($col, $return=false) {
  2358. $out = $this->SetColor($col, 'Text');
  2359. if ($return) { return $out; }
  2360. if ($out=='') { return ''; }
  2361. $this->TextColor = $out;
  2362. $this->ColorFlag = ($this->FillColor != $out);
  2363. }
  2364. function SetDrawColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
  2365. //Set color for all stroking operations
  2366. $col = array();
  2367. if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
  2368. else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
  2369. else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
  2370. $out = $this->SetDColor($col, $return);
  2371. return $out;
  2372. }
  2373. function SetFillColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
  2374. //Set color for all filling operations
  2375. $col = array();
  2376. if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
  2377. else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
  2378. else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
  2379. $out = $this->SetFColor($col, $return);
  2380. return $out;
  2381. }
  2382. function SetTextColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
  2383. //Set color for text
  2384. $col = array();
  2385. if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
  2386. else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
  2387. else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
  2388. $out = $this->SetTColor($col, $return);
  2389. return $out;
  2390. }
  2391. function _getCharWidth(&$cw, $u, $isdef=true) {
  2392. if ($u==0) { $w = false; }
  2393. else { $w = (ord($cw[$u*2]) << 8) + ord($cw[$u*2+1]); }
  2394. if ($w == 65535) { return 0; }
  2395. else if ($w) { return $w; }
  2396. else if ($isdef) { return false; }
  2397. else { return 0; }
  2398. }
  2399. function _charDefined(&$cw, $u) {
  2400. if ($u==0) { return false; }
  2401. $w = (ord($cw[$u*2]) << 8) + ord($cw[$u*2+1]);
  2402. if ($w) { return true; }
  2403. else { return false; }
  2404. }
  2405. function GetCharWidthCore($c) {
  2406. //Get width of a single character in the current Core font
  2407. $c = (string)$c;
  2408. $w = 0;
  2409. // Soft Hyphens chr(173)
  2410. if ($c == chr(173) && $this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
  2411. return 0;
  2412. }
  2413. else if ($this->S && isset($this->upperCase[ord($c)])) {
  2414. $charw = $this->CurrentFont['cw'][chr($this->upperCase[ord($c)])];
  2415. if ($charw!==false) {
  2416. $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
  2417. $w+=$charw;
  2418. }
  2419. }
  2420. else if (isset($this->CurrentFont['cw'][$c])) {
  2421. $w += $this->CurrentFont['cw'][$c];
  2422. }
  2423. else if (isset($this->CurrentFont['cw'][ord($c)])) {
  2424. $w += $this->CurrentFont['cw'][ord($c)];
  2425. }
  2426. $w *= ($this->FontSize/ 1000);
  2427. if ($this->minwSpacing || $this->fixedlSpacing) {
  2428. if ($c==' ') $nb_spaces = 1;
  2429. else $nb_spaces = 0;
  2430. $w += $this->fixedlSpacing + ($nb_spaces * $this->minwSpacing);
  2431. }
  2432. return ($w);
  2433. }
  2434. function GetCharWidthNonCore($c, $addSubset=true) {
  2435. //Get width of a single character in the current Non-Core font
  2436. $c = (string)$c;
  2437. $w = 0;
  2438. $unicode = $this->UTF8StringToArray($c, $addSubset);
  2439. $char = $unicode[0];
  2440. /*-- CJK-FONTS --*/
  2441. if ($this->CurrentFont['type'] == 'Type0') { // CJK Adobe fonts
  2442. if ($char == 173) { return 0; } // Soft Hyphens
  2443. elseif (isset($this->CurrentFont['cw'][$char])) { $w+=$this->CurrentFont['cw'][$char]; }
  2444. elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
  2445. else { $w += 500; }
  2446. }
  2447. else {
  2448. /*-- END CJK-FONTS --*/
  2449. if ($char == 173) { return 0; } // Soft Hyphens
  2450. else if ($this->S && isset($this->upperCase[$char])) {
  2451. $charw = $this->_getCharWidth($this->CurrentFont['cw'],$this->upperCase[$char]);
  2452. if ($charw!==false) {
  2453. $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
  2454. $w+=$charw;
  2455. }
  2456. elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
  2457. elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
  2458. else { $w += 500; }
  2459. }
  2460. else {
  2461. $charw = $this->_getCharWidth($this->CurrentFont['cw'],$char);
  2462. if ($charw!==false) { $w+=$charw; }
  2463. elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
  2464. elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
  2465. else { $w += 500; }
  2466. }
  2467. } // *CJK-FONTS*
  2468. $w *= ($this->FontSize/ 1000);
  2469. if ($this->minwSpacing || $this->fixedlSpacing) {
  2470. if ($c==' ') $nb_spaces = 1;
  2471. else $nb_spaces = 0;
  2472. $w += $this->fixedlSpacing + ($nb_spaces * $this->minwSpacing);
  2473. }
  2474. return ($w);
  2475. }
  2476. function GetCharWidth($c, $addSubset=true) {
  2477. if (!$this->usingCoreFont) {
  2478. return $this->GetCharWidthNonCore($c, $addSubset);
  2479. }
  2480. else {
  2481. return $this->GetCharWidthCore($c);
  2482. }
  2483. }
  2484. function GetStringWidth($s, $addSubset=true) {
  2485. //Get width of a string in the current font
  2486. $s = (string)$s;
  2487. $cw = &$this->CurrentFont['cw'];
  2488. $w = 0;
  2489. $kerning = 0;
  2490. $lastchar = 0;
  2491. $nb_carac = 0;
  2492. $nb_spaces = 0;
  2493. // mPDF ITERATION
  2494. if ($this->iterationCounter) $s = preg_replace('/{iteration ([a-zA-Z0-9_]+)}/', '\\1', $s);
  2495. if (!$this->usingCoreFont) {
  2496. $s = str_replace("\xc2\xad",'',$s );
  2497. $unicode = $this->UTF8StringToArray($s, $addSubset);
  2498. if ($this->minwSpacing || $this->fixedlSpacing) {
  2499. $nb_carac = count($unicode);
  2500. $nb_spaces = mb_substr_count($s,' ', $this->mb_enc);
  2501. }
  2502. /*-- CJK-FONTS --*/
  2503. if ($this->CurrentFont['type'] == 'Type0') { // CJK Adobe fonts
  2504. foreach($unicode as $char) {
  2505. if (isset($cw[$char])) { $w+=$cw[$char]; }
  2506. elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
  2507. else { $w += 500; }
  2508. }
  2509. }
  2510. else {
  2511. /*-- END CJK-FONTS --*/
  2512. foreach($unicode as $char) {
  2513. if ($this->S && isset($this->upperCase[$char])) {
  2514. $charw = $this->_getCharWidth($cw,$this->upperCase[$char]);
  2515. if ($charw!==false) {
  2516. $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
  2517. $w+=$charw;
  2518. }
  2519. elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
  2520. elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
  2521. else { $w += 500; }
  2522. }
  2523. else {
  2524. $charw = $this->_getCharWidth($cw,$char);
  2525. if ($charw!==false) { $w+=$charw; }
  2526. elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
  2527. elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
  2528. else { $w += 500; }
  2529. if ($this->kerning && $this->useKerning && $lastchar) {
  2530. if (isset($this->CurrentFont['kerninfo'][$lastchar][$char])) {
  2531. $kerning += $this->CurrentFont['kerninfo'][$lastchar][$char];
  2532. }
  2533. }
  2534. $lastchar = $char;
  2535. }
  2536. }
  2537. } // *CJK-FONTS*
  2538. }
  2539. else {
  2540. if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
  2541. $s = str_replace(chr(173),'',$s );
  2542. }
  2543. $nb_carac = $l = strlen($s);
  2544. if ($this->minwSpacing || $this->fixedlSpacing) {
  2545. $nb_spaces = substr_count($s,' ');
  2546. }
  2547. for($i=0; $i<$l; $i++) {
  2548. if ($this->S && isset($this->upperCase[ord($s[$i])])) {
  2549. $charw = $cw[chr($this->upperCase[ord($s[$i])])];
  2550. if ($charw!==false) {
  2551. $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
  2552. $w+=$charw;
  2553. }
  2554. }
  2555. else if (isset($cw[$s[$i]])) {
  2556. $w += $cw[$s[$i]];
  2557. }
  2558. else if (isset($cw[ord($s[$i])])) {
  2559. $w += $cw[ord($s[$i])];
  2560. }
  2561. if ($this->kerning && $this->useKerning && $i>0) {
  2562. if (isset($this->CurrentFont['kerninfo'][$s[($i-1)]][$s[$i]])) {
  2563. $kerning += $this->CurrentFont['kerninfo'][$s[($i-1)]][$s[$i]];
  2564. }
  2565. }
  2566. }
  2567. }
  2568. unset($cw);
  2569. if ($this->kerning && $this->useKerning) { $w += $kerning; }
  2570. $w *= ($this->FontSize/ 1000);
  2571. $w += (($nb_carac + $nb_spaces) * $this->fixedlSpacing) + ($nb_spaces * $this->minwSpacing);
  2572. return ($w);
  2573. }
  2574. function SetLineWidth($width) {
  2575. //Set line width
  2576. $this->LineWidth=$width;
  2577. $lwout = (sprintf('%.3F w',$width*_MPDFK));
  2578. if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineWidth']) && $this->pageoutput[$this->page]['LineWidth'] != $lwout) || !isset($this->pageoutput[$this->page]['LineWidth']) || $this->keep_block_together)) {
  2579. $this->_out($lwout);
  2580. }
  2581. $this->pageoutput[$this->page]['LineWidth'] = $lwout;
  2582. }
  2583. function Line($x1,$y1,$x2,$y2) {
  2584. //Draw a line
  2585. $this->_out(sprintf('%.3F %.3F m %.3F %.3F l S',$x1*_MPDFK,($this->h-$y1)*_MPDFK,$x2*_MPDFK,($this->h-$y2)*_MPDFK));
  2586. }
  2587. function Arrow($x1,$y1,$x2,$y2,$headsize=3,$fill='B',$angle=25) {
  2588. //F == fill //S == stroke //B == stroke and fill
  2589. // angle = splay of arrowhead - 1 - 89 degrees
  2590. if($fill=='F') $fill='f';
  2591. elseif($fill=='FD' or $fill=='DF' or $fill=='B') $fill='B';
  2592. else $fill='S';
  2593. $a = atan2(($y2-$y1),($x2-$x1));
  2594. $b = $a + deg2rad($angle);
  2595. $c = $a - deg2rad($angle);
  2596. $x3 = $x2 - ($headsize* cos($b));
  2597. $y3 = $this->h-($y2 - ($headsize* sin($b)));
  2598. $x4 = $x2 - ($headsize* cos($c));
  2599. $y4 = $this->h-($y2 - ($headsize* sin($c)));
  2600. $x5 = $x3-($x3-$x4)/2; // mid point of base of arrowhead - to join arrow line to
  2601. $y5 = $y3-($y3-$y4)/2;
  2602. $s = '';
  2603. $s.=sprintf('%.3F %.3F m %.3F %.3F l S',$x1*_MPDFK,($this->h-$y1)*_MPDFK,$x5*_MPDFK,$y5*_MPDFK);
  2604. $this->_out($s);
  2605. $s = '';
  2606. $s.=sprintf('%.3F %.3F m %.3F %.3F l %.3F %.3F l %.3F %.3F l %.3F %.3F l ',$x5*_MPDFK,$y5*_MPDFK,$x3*_MPDFK,$y3*_MPDFK,$x2*_MPDFK,($this->h-$y2)*_MPDFK,$x4*_MPDFK,$y4*_MPDFK,$x5*_MPDFK,$y5*_MPDFK);
  2607. $s.=$fill;
  2608. $this->_out($s);
  2609. }
  2610. function Rect($x,$y,$w,$h,$style='') {
  2611. //Draw a rectangle
  2612. if($style=='F') $op='f';
  2613. elseif($style=='FD' or $style=='DF') $op='B';
  2614. else $op='S';
  2615. $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$h*_MPDFK,$op));
  2616. }
  2617. function AddFont($family,$style='') {
  2618. if(empty($family)) { return; }
  2619. $family = strtolower($family);
  2620. $style=strtoupper($style);
  2621. $style=str_replace('U','',$style);
  2622. if($style=='IB') $style='BI';
  2623. $fontkey = $family.$style;
  2624. // check if the font has been already added
  2625. if(isset($this->fonts[$fontkey])) {
  2626. return;
  2627. }
  2628. /*-- CJK-FONTS --*/
  2629. if (in_array($family,$this->available_CJK_fonts)) {
  2630. if (empty($this->Big5_widths)) { require(_MPDF_PATH . 'includes/CJKdata.php'); }
  2631. $this->AddCJKFont($family); // don't need to add style
  2632. return;
  2633. }
  2634. /*-- END CJK-FONTS --*/
  2635. if ($this->usingCoreFont) { die("mPDF Error - problem with Font management"); }
  2636. $stylekey = $style;
  2637. if (!$style) { $stylekey = 'R'; }
  2638. if (!isset($this->fontdata[$family][$stylekey]) || !$this->fontdata[$family][$stylekey]) {
  2639. die('mPDF Error - Font is not supported - '.$family.' '.$style);
  2640. }
  2641. $name = '';
  2642. $originalsize = 0;
  2643. $sip = false;
  2644. $smp = false;
  2645. $unAGlyphs = false; // mPDF 5.4.05
  2646. $haskerninfo = false;
  2647. $BMPselected = false;
  2648. @include(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php');
  2649. $ttffile = '';
  2650. if (defined('_MPDF_SYSTEM_TTFONTS')) {
  2651. $ttffile = _MPDF_SYSTEM_TTFONTS.$this->fontdata[$family][$stylekey];
  2652. if (!file_exists($ttffile)) { $ttffile = ''; }
  2653. }
  2654. if (!$ttffile) {
  2655. $ttffile = _MPDF_TTFONTPATH.$this->fontdata[$family][$stylekey];
  2656. if (!file_exists($ttffile)) { die("mPDF Error - cannot find TTF TrueType font file - ".$ttffile); }
  2657. }
  2658. $ttfstat = stat($ttffile);
  2659. if (isset($this->fontdata[$family]['TTCfontID'][$stylekey])) { $TTCfontID = $this->fontdata[$family]['TTCfontID'][$stylekey]; }
  2660. else { $TTCfontID = 0; }
  2661. $BMPonly = false;
  2662. if (in_array($family,$this->BMPonly)) { $BMPonly = true; }
  2663. $regenerate = false;
  2664. if ($BMPonly && !$BMPselected) { $regenerate = true; }
  2665. else if (!$BMPonly && $BMPselected) { $regenerate = true; }
  2666. if ($this->useKerning && !$haskerninfo) { $regenerate = true; }
  2667. // mPDF 5.4.05
  2668. if (isset($this->fontdata[$family]['unAGlyphs']) && $this->fontdata[$family]['unAGlyphs'] && !$unAGlyphs) {
  2669. $regenerate = true;
  2670. $unAGlyphs = true;
  2671. }
  2672. else if ((!isset($this->fontdata[$family]['unAGlyphs']) || !$this->fontdata[$family]['unAGlyphs']) && $unAGlyphs) {
  2673. $regenerate = true;
  2674. $unAGlyphs = false;
  2675. }
  2676. if (!isset($name) || $originalsize != $ttfstat['size'] || $regenerate) {
  2677. if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
  2678. $ttf = new TTFontFile();
  2679. $ttf->getMetrics($ttffile, $TTCfontID, $this->debugfonts, $BMPonly, $this->useKerning, $unAGlyphs); // mPDF 5.4.05
  2680. $cw = $ttf->charWidths;
  2681. $kerninfo = $ttf->kerninfo;
  2682. $haskerninfo = true;
  2683. $name = preg_replace('/[ ()]/','',$ttf->fullName);
  2684. $sip = $ttf->sipset;
  2685. $smp = $ttf->smpset;
  2686. $desc= array('Ascent'=>round($ttf->ascent),
  2687. 'Descent'=>round($ttf->descent),
  2688. 'CapHeight'=>round($ttf->capHeight),
  2689. 'Flags'=>$ttf->flags,
  2690. 'FontBBox'=>'['.round($ttf->bbox[0])." ".round($ttf->bbox[1])." ".round($ttf->bbox[2])." ".round($ttf->bbox[3]).']',
  2691. 'ItalicAngle'=>$ttf->italicAngle,
  2692. 'StemV'=>round($ttf->stemV),
  2693. 'MissingWidth'=>round($ttf->defaultWidth));
  2694. $panose = '';
  2695. // mPDF 5.5.19
  2696. if (count($ttf->panose)) {
  2697. $panoseArray = array_merge(array($ttf->sFamilyClass, $ttf->sFamilySubClass), $ttf->panose);
  2698. foreach($panoseArray as $value)
  2699. $panose .= ' '.dechex($value);
  2700. }
  2701. $up = round($ttf->underlinePosition);
  2702. $ut = round($ttf->underlineThickness);
  2703. $originalsize = $ttfstat['size']+0;
  2704. $type = 'TTF';
  2705. //Generate metrics .php file
  2706. $s='<?php'."\n";
  2707. $s.='$name=\''.$name."';\n";
  2708. $s.='$type=\''.$type."';\n";
  2709. $s.='$desc='.var_export($desc,true).";\n";
  2710. $s.='$up='.$up.";\n";
  2711. $s.='$ut='.$ut.";\n";
  2712. $s.='$ttffile=\''.$ttffile."';\n";
  2713. $s.='$TTCfontID=\''.$TTCfontID."';\n";
  2714. $s.='$originalsize='.$originalsize.";\n";
  2715. if ($sip) $s.='$sip=true;'."\n";
  2716. else $s.='$sip=false;'."\n";
  2717. if ($smp) $s.='$smp=true;'."\n";
  2718. else $s.='$smp=false;'."\n";
  2719. if ($BMPonly) $s.='$BMPselected=true;'."\n";
  2720. else $s.='$BMPselected=false;'."\n";
  2721. $s.='$fontkey=\''.$fontkey."';\n";
  2722. $s.='$panose=\''.$panose."';\n";
  2723. if ($this->useKerning) {
  2724. $s.='$kerninfo='.var_export($kerninfo,true).";\n";
  2725. $s.='$haskerninfo=true;'."\n";
  2726. }
  2727. else $s.='$haskerninfo=false;'."\n";
  2728. // mPDF 5.4.05
  2729. if ($this->fontdata[$family]['unAGlyphs']) {
  2730. $s.='$unAGlyphs=true;'."\n";
  2731. }
  2732. else $s.='$unAGlyphs=false;'."\n";
  2733. $s.="?>";
  2734. if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
  2735. $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php',"w");
  2736. fwrite($fh,$s,strlen($s));
  2737. fclose($fh);
  2738. $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat',"wb");
  2739. fwrite($fh,$cw,strlen($cw));
  2740. fclose($fh);
  2741. @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cgm');
  2742. @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.z');
  2743. @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cw127.php');
  2744. @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cw');
  2745. }
  2746. else if ($this->debugfonts) { $this->Error('Cannot write to the font caching directory - '._MPDF_TTFONTDATAPATH); }
  2747. unset($ttf);
  2748. }
  2749. else {
  2750. $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat');
  2751. }
  2752. if (isset($this->fontdata[$family]['indic']) && $this->fontdata[$family]['indic']) { $indic = true; }
  2753. else { $indic = false; }
  2754. if (isset($this->fontdata[$family]['sip-ext']) && $this->fontdata[$family]['sip-ext']) { $sipext = $this->fontdata[$family]['sip-ext']; }
  2755. else { $sipext = ''; }
  2756. $i = count($this->fonts)+$this->extraFontSubsets+1;
  2757. if ($sip || $smp) {
  2758. $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'panose'=>$panose, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subsets'=>array(0=>range(0,127)), 'subsetfontids'=>array($i), 'used'=>false, 'indic'=>$indic, 'sip'=>$sip, 'sipext'=>$sipext, 'smp'=>$smp, 'TTCfontID' => $TTCfontID, 'unAGlyphs' => false); // mPDF 5.4.05
  2759. }
  2760. else {
  2761. $ss = array();
  2762. for ($s=32; $s<128; $s++) { $ss[$s] = $s; }
  2763. $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'panose'=>$panose, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subset'=>$ss, 'used'=>false, 'indic'=>$indic, 'sip'=>$sip, 'sipext'=>$sipext, 'smp'=>$smp, 'TTCfontID' => $TTCfontID, 'unAGlyphs' => $unAGlyphs); // mPDF 5.4.05
  2764. }
  2765. if ($this->useKerning && $haskerninfo) { $this->fonts[$fontkey]['kerninfo'] = $kerninfo; }
  2766. $this->FontFiles[$fontkey]=array('length1'=>$originalsize, 'type'=>"TTF", 'ttffile'=>$ttffile, 'sip'=>$sip, 'smp'=>$smp);
  2767. unset($cw);
  2768. }
  2769. function SetFont($family,$style='',$size=0, $write=true, $forcewrite=false) {
  2770. $family=strtolower($family);
  2771. if (!$this->onlyCoreFonts) {
  2772. if ($family == 'sans' || $family == 'sans-serif') { $family = $this->sans_fonts[0]; }
  2773. if ($family == 'serif') { $family = $this->serif_fonts[0]; }
  2774. if ($family == 'mono' || $family == 'monospace') { $family = $this->mono_fonts[0]; }
  2775. }
  2776. if (isset($this->fonttrans[$family]) && $this->fonttrans[$family]) { $family = $this->fonttrans[$family]; }
  2777. if($family=='') {
  2778. if ($this->FontFamily) { $family=$this->FontFamily; }
  2779. else if ($this->default_font) { $family=$this->default_font; }
  2780. else { $this->Error("No font or default font set!"); }
  2781. }
  2782. $this->ReqFontStyle = $style; // required or requested style - used later for artificial bold/italic
  2783. if (($family == 'csymbol') || ($family == 'czapfdingbats') || ($family == 'ctimes') || ($family == 'ccourier') || ($family == 'chelvetica')) {
  2784. if ($this->PDFA || $this->PDFX) {
  2785. if ($family == 'csymbol' || $family == 'czapfdingbats') {
  2786. $this->Error("Symbol and Zapfdingbats cannot be embedded in mPDF (required for PDFA1-b or PDFX/1-a).");
  2787. }
  2788. if ($family == 'ctimes' || $family == 'ccourier' || $family == 'chelvetica') {
  2789. if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Core Adobe font ".ucfirst($family)." cannot be embedded in mPDF, which is required for PDFA1-b or PDFX/1-a. (Embedded font will be substituted.)"; }
  2790. if ($family == 'chelvetica') { $family = 'sans'; }
  2791. if ($family == 'ctimes') { $family = 'serif'; }
  2792. if ($family == 'ccourier') { $family = 'mono'; }
  2793. }
  2794. $this->usingCoreFont = false;
  2795. }
  2796. else { $this->usingCoreFont = true; }
  2797. if($family=='csymbol' || $family=='czapfdingbats') { $style=''; }
  2798. }
  2799. else { $this->usingCoreFont = false; }
  2800. $this->U=false;
  2801. $this->S=false;
  2802. if ($style) {
  2803. $style=strtoupper($style);
  2804. if(strpos($style,'U')!==false) {
  2805. $this->U=true;
  2806. $style=str_replace('U','',$style);
  2807. }
  2808. if(strpos($style,'S')!==false) {
  2809. $this->S=true;
  2810. // Small Caps
  2811. if (empty($this->upperCase)) { @include(_MPDF_PATH.'includes/upperCase.php'); }
  2812. $style=str_replace('S','',$style);
  2813. }
  2814. if ($style=='IB') $style='BI';
  2815. }
  2816. if ($size==0) $size=$this->FontSizePt;
  2817. $fontkey=$family.$style;
  2818. $stylekey = $style;
  2819. if (!$stylekey) { $stylekey = "R"; }
  2820. if (!$this->onlyCoreFonts && !$this->usingCoreFont) {
  2821. if(!isset($this->fonts[$fontkey]) || count($this->default_available_fonts) != count($this->available_unifonts) ) { // not already added
  2822. /*-- CJK-FONTS --*/
  2823. // CJK fonts
  2824. if (in_array($fontkey,$this->available_CJK_fonts)) {
  2825. if(!isset($this->fonts[$fontkey])) { // already added
  2826. if (empty($this->Big5_widths)) { require(_MPDF_PATH . 'includes/CJKdata.php'); }
  2827. $this->AddCJKFont($family); // don't need to add style
  2828. }
  2829. }
  2830. // Test to see if requested font/style is available - or substitute
  2831. else
  2832. /*-- END CJK-FONTS --*/
  2833. if (!in_array($fontkey,$this->available_unifonts)) {
  2834. // If font[nostyle] exists - set it
  2835. if (in_array($family,$this->available_unifonts)) {
  2836. $style = '';
  2837. }
  2838. // Else if only one font available - set it (assumes if only one font available it will not have a style)
  2839. else if (count($this->available_unifonts) == 1) {
  2840. $family = $this->available_unifonts[0];
  2841. $style = '';
  2842. }
  2843. else {
  2844. $found = 0;
  2845. // else substitute font of similar type
  2846. if (in_array($family,$this->sans_fonts)) {
  2847. $i = array_intersect($this->sans_fonts,$this->available_unifonts);
  2848. if (count($i)) {
  2849. $i = array_values($i);
  2850. // with requested style if possible
  2851. if (!in_array(($i[0].$style),$this->available_unifonts)) {
  2852. $style = '';
  2853. }
  2854. $family = $i[0];
  2855. $found = 1;
  2856. }
  2857. }
  2858. else if (in_array($family,$this->serif_fonts)) {
  2859. $i = array_intersect($this->serif_fonts,$this->available_unifonts);
  2860. if (count($i)) {
  2861. $i = array_values($i);
  2862. // with requested style if possible
  2863. if (!in_array(($i[0].$style),$this->available_unifonts)) {
  2864. $style = '';
  2865. }
  2866. $family = $i[0];
  2867. $found = 1;
  2868. }
  2869. }
  2870. else if (in_array($family,$this->mono_fonts)) {
  2871. $i = array_intersect($this->mono_fonts,$this->available_unifonts);
  2872. if (count($i)) {
  2873. $i = array_values($i);
  2874. // with requested style if possible
  2875. if (!in_array(($i[0].$style),$this->available_unifonts)) {
  2876. $style = '';
  2877. }
  2878. $family = $i[0];
  2879. $found = 1;
  2880. }
  2881. }
  2882. if (!$found) {
  2883. // set first available font
  2884. $fs = $this->available_unifonts[0];
  2885. preg_match('/^([a-z_0-9\-]+)([BI]{0,2})$/',$fs,$fas); // Allow "-"
  2886. // with requested style if possible
  2887. $ws = $fas[1].$style;
  2888. if (in_array($ws,$this->available_unifonts)) {
  2889. $family = $fas[1]; // leave $style as is
  2890. }
  2891. else if (in_array($fas[1],$this->available_unifonts)) {
  2892. // or without style
  2893. $family = $fas[1];
  2894. $style = '';
  2895. }
  2896. else {
  2897. // or with the style specified
  2898. $family = $fas[1];
  2899. $style = $fas[2];
  2900. }
  2901. }
  2902. }
  2903. $fontkey = $family.$style;
  2904. }
  2905. }
  2906. // try to add font (if not already added)
  2907. $this->AddFont($family, $style);
  2908. //Test if font is already selected
  2909. if($this->FontFamily == $family && $this->FontFamily == $this->currentfontfamily && $this->FontStyle == $style && $this->FontStyle == $this->currentfontstyle && $this->FontSizePt == $size && $this->FontSizePt == $this->currentfontsize && !$forcewrite) {
  2910. return $family;
  2911. }
  2912. $fontkey = $family.$style;
  2913. //Select it
  2914. $this->FontFamily = $family;
  2915. $this->FontStyle = $style;
  2916. $this->FontSizePt = $size;
  2917. $this->FontSize = $size / _MPDFK;
  2918. $this->CurrentFont = &$this->fonts[$fontkey];
  2919. if ($write) {
  2920. $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
  2921. if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
  2922. $this->pageoutput[$this->page]['Font'] = $fontout;
  2923. }
  2924. // Added - currentfont (lowercase) used in HTML2PDF
  2925. $this->currentfontfamily=$family;
  2926. $this->currentfontsize=$size;
  2927. $this->currentfontstyle=$style.($this->U ? 'U' : '').($this->S ? 'S' : '');
  2928. $this->setMBencoding('UTF-8');
  2929. }
  2930. else { // if using core fonts
  2931. if ($this->PDFA || $this->PDFX) {
  2932. $this->Error('Core Adobe fonts cannot be embedded in mPDF (required for PDFA1-b or PDFX/1-a) - cannot use option to use core fonts.');
  2933. }
  2934. $this->setMBencoding('windows-1252');
  2935. //Test if font is already selected
  2936. if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size) && !$forcewrite) {
  2937. return $family;
  2938. }
  2939. if (!isset($this->CoreFonts[$fontkey])) {
  2940. if (in_array($family,$this->serif_fonts)) { $family = 'ctimes'; }
  2941. else if (in_array($family,$this->mono_fonts)) { $family = 'ccourier'; }
  2942. else { $family = 'chelvetica'; }
  2943. $this->usingCoreFont = true;
  2944. $fontkey = $family.$style;
  2945. }
  2946. if(!isset($this->fonts[$fontkey])) {
  2947. // STANDARD CORE FONTS
  2948. if (isset($this->CoreFonts[$fontkey])) {
  2949. //Load metric file
  2950. $file=$family;
  2951. if($family=='ctimes' || $family=='chelvetica' || $family=='ccourier') { $file.=strtolower($style); }
  2952. $file.='.php';
  2953. include(_MPDF_PATH.'font/'.$file);
  2954. if(!isset($cw)) { $this->Error('Could not include font metric file'); }
  2955. $i=count($this->fonts)+$this->extraFontSubsets+1;
  2956. $this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw);
  2957. if ($this->useKerning) { $this->fonts[$fontkey]['kerninfo'] = $kerninfo; }
  2958. }
  2959. else {
  2960. die('mPDF error - Font not defined');
  2961. }
  2962. }
  2963. //Test if font is already selected
  2964. if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size) && !$forcewrite) {
  2965. return $family;
  2966. }
  2967. //Select it
  2968. $this->FontFamily=$family;
  2969. $this->FontStyle=$style;
  2970. $this->FontSizePt=$size;
  2971. $this->FontSize=$size/_MPDFK;
  2972. $this->CurrentFont=&$this->fonts[$fontkey];
  2973. if ($write) {
  2974. $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
  2975. if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
  2976. $this->pageoutput[$this->page]['Font'] = $fontout;
  2977. }
  2978. // Added - currentfont (lowercase) used in HTML2PDF
  2979. $this->currentfontfamily=$family;
  2980. $this->currentfontsize=$size;
  2981. $this->currentfontstyle=$style.($this->U ? 'U' : '').($this->S ? 'S' : '');
  2982. }
  2983. return $family;
  2984. }
  2985. function SetFontSize($size,$write=true) {
  2986. //Set font size in points
  2987. if($this->FontSizePt==$size) return;
  2988. $this->FontSizePt=$size;
  2989. $this->FontSize=$size/_MPDFK;
  2990. $this->currentfontsize=$size;
  2991. if ($write) {
  2992. $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
  2993. // Edited mPDF 3.0
  2994. if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
  2995. $this->pageoutput[$this->page]['Font'] = $fontout;
  2996. }
  2997. }
  2998. function AddLink() {
  2999. //Create a new internal link
  3000. $n=count($this->links)+1;
  3001. $this->links[$n]=array(0,0);
  3002. return $n;
  3003. }
  3004. function SetLink($link,$y=0,$page=-1) {
  3005. //Set destination of internal link
  3006. if($y==-1) $y=$this->y;
  3007. if($page==-1) $page=$this->page;
  3008. $this->links[$link]=array($page,$y);
  3009. }
  3010. function Link($x,$y,$w,$h,$link) {
  3011. $l = array($x*_MPDFK,$this->hPt-$y*_MPDFK,$w*_MPDFK,$h*_MPDFK,$link);
  3012. if ($this->keep_block_together) { // Save to array - don't write yet
  3013. $this->ktLinks[$this->page][]= $l;
  3014. return;
  3015. }
  3016. else if ($this->table_rotate) { // *TABLES*
  3017. $this->tbrot_Links[$this->page][]= $l; // *TABLES*
  3018. return; // *TABLES*
  3019. } // *TABLES*
  3020. else if ($this->kwt) {
  3021. $this->kwt_Links[$this->page][]= $l;
  3022. return;
  3023. }
  3024. if ($this->writingHTMLheader || $this->writingHTMLfooter) {
  3025. $this->HTMLheaderPageLinks[]= $l;
  3026. return;
  3027. }
  3028. //Put a link on the page
  3029. $this->PageLinks[$this->page][]= $l;
  3030. // Save cross-reference to Column buffer
  3031. $ref = count($this->PageLinks[$this->page])-1; // *COLUMNS*
  3032. $this->columnLinks[$this->CurrCol][INTVAL($this->x)][INTVAL($this->y)] = $ref; // *COLUMNS*
  3033. }
  3034. function Text($x,$y,$txt) {
  3035. // Output a string
  3036. // Called (internally) by Watermark and _tableWrite [rotated cells]
  3037. // Expects input to be mb_encoded if necessary and RTL reversed
  3038. // ARTIFICIAL BOLD AND ITALIC
  3039. $s = 'q ';
  3040. if ($this->falseBoldWeight && strpos($this->ReqFontStyle,"B") !== false && strpos($this->FontStyle,"B") === false) {
  3041. $s .= '2 Tr 1 J 1 j ';
  3042. $s .= sprintf('%.3F w ',($this->FontSize/130)*_MPDFK*$this->falseBoldWeight);
  3043. $tc = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
  3044. if($this->FillColor!=$tc) { $s .= $tc.' '; } // stroke (outline) = same colour as text(fill)
  3045. }
  3046. if (strpos($this->ReqFontStyle,"I") !== false && strpos($this->FontStyle,"I") === false) {
  3047. $aix = '1 0 0.261799 1 %.3F %.3F Tm';
  3048. }
  3049. else { $aix = '%.3F %.3F Td'; }
  3050. if($this->ColorFlag) $s.=$this->TextColor.' ';
  3051. $this->CurrentFont['used']= true;
  3052. if ($this->CurrentFont['type']=='TTF' && ($this->CurrentFont['sip'] || $this->CurrentFont['smp'])) {
  3053. $txt2 = str_replace(chr(194).chr(160),chr(32),$txt);
  3054. $txt2 = $this->UTF8toSubset($txt2);
  3055. $s.=sprintf('BT '.$aix.' %s Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$txt2);
  3056. }
  3057. else if (!$this->usingCoreFont) {
  3058. $txt2 = str_replace(chr(194).chr(160),chr(32),$txt);
  3059. $this->UTF8StringToArray($txt2); // this is just to add chars to subset list
  3060. if ($this->kerning && $this->useKerning) { $s .= $this->_kern($txt2, '', $aix, $x, $y); }
  3061. else {
  3062. //Convert string to UTF-16BE without BOM
  3063. $txt2= $this->UTF8ToUTF16BE($txt2, false);
  3064. $s.=sprintf('BT '.$aix.' (%s) Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$this->_escape($txt2));
  3065. }
  3066. }
  3067. else {
  3068. $txt2 = str_replace(chr(160),chr(32),$txt);
  3069. if ($this->kerning && $this->useKerning) { $s .= $this->_kern($txt2, '', $aix, $x, $y); }
  3070. else {
  3071. $s.=sprintf('BT '.$aix.' (%s) Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$this->_escape($txt2));
  3072. }
  3073. }
  3074. if($this->U && $txt!='') {
  3075. $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
  3076. if($this->FillColor!=$c) { $s.= ' '.$c.' '; }
  3077. if (isset($this->CurrentFont['up'])) { $up=$this->CurrentFont['up']; }
  3078. else { $up = -100; }
  3079. $adjusty = (-$up/1000* $this->FontSize);
  3080. if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
  3081. else { $ut = 60/1000* $this->FontSize; }
  3082. $olw = $this->LineWidth;
  3083. $s.=' '.(sprintf(' %.3F w',$ut*_MPDFK));
  3084. $s.=' '.$this->_dounderline($x,$y + $adjusty,$txt);
  3085. $s.=' '.(sprintf(' %.3F w',$olw*_MPDFK));
  3086. if($this->FillColor!=$c) { $s.= ' '.$this->FillColor.' '; }
  3087. }
  3088. // STRIKETHROUGH
  3089. if($this->strike && $txt!='') {
  3090. $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
  3091. if($this->FillColor!=$c) { $s.= ' '.$c.' '; }
  3092. //Superscript and Subscript Y coordinate adjustment (now for striked-through texts)
  3093. if (isset($this->CurrentFont['desc']['CapHeight'])) { $ch=$this->CurrentFont['desc']['CapHeight']; }
  3094. else { $ch = 700; }
  3095. $adjusty = (-$ch/1000* $this->FontSize) * 0.35;
  3096. if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
  3097. else { $ut = 60/1000* $this->FontSize; }
  3098. $olw = $this->LineWidth;
  3099. $s.=' '.(sprintf(' %.3F w',$ut*_MPDFK));
  3100. $s.=' '.$this->_dounderline($x,$y+$adjusty,$txt);
  3101. $s.=' '.(sprintf(' %.3F w',$olw*_MPDFK));
  3102. if($this->FillColor!=$c) { $s.= ' '.$this->FillColor.' '; }
  3103. }
  3104. $s .= 'Q';
  3105. $this->_out($s);
  3106. }
  3107. /*-- DIRECTW --*/
  3108. function WriteText($x,$y,$txt) {
  3109. // Output a string using Text() but does encoding and text reversing of RTL
  3110. $txt = $this->purify_utf8_text($txt);
  3111. if ($this->text_input_as_HTML) {
  3112. $txt = $this->all_entities_to_utf8($txt);
  3113. }
  3114. if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
  3115. // DIRECTIONALITY
  3116. if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *RTL*
  3117. $this->magic_reverse_dir($txt, true, $this->directionality); // *RTL*
  3118. // Font-specific ligature substitution for Indic fonts
  3119. if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($txt); // *INDIC*
  3120. $this->Text($x,$y,$txt);
  3121. }
  3122. function WriteCell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='', $currentx=0) {
  3123. //Output a cell using Cell() but does encoding and text reversing of RTL
  3124. $txt = $this->purify_utf8_text($txt);
  3125. if ($this->text_input_as_HTML) {
  3126. $txt = $this->all_entities_to_utf8($txt);
  3127. }
  3128. if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
  3129. // DIRECTIONALITY
  3130. if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *RTL*
  3131. $this->magic_reverse_dir($txt, true, $this->directionality); // *RTL*
  3132. // Font-specific ligature substitution for Indic fonts
  3133. if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($txt); // *INDIC*
  3134. $this->Cell($w,$h,$txt,$border,$ln,$align,$fill,$link, $currentx);
  3135. }
  3136. /*-- END DIRECTW --*/
  3137. function ResetSpacing() {
  3138. if ($this->ws != 0) { $this->_out('BT 0 Tw ET'); }
  3139. $this->ws=0;
  3140. if ($this->charspacing != 0) { $this->_out('BT 0 Tc ET'); }
  3141. $this->charspacing=0;
  3142. }
  3143. function SetSpacing($cs,$ws) {
  3144. if (intval($cs*1000)==0) { $cs = 0; }
  3145. if ($cs) { $this->_out(sprintf('BT %.3F Tc ET',$cs)); }
  3146. else if ($this->charspacing != 0) { $this->_out('BT 0 Tc ET'); }
  3147. $this->charspacing=$cs;
  3148. if (intval($ws*1000)==0) { $ws = 0; }
  3149. if ($ws) { $this->_out(sprintf('BT %.3F Tw ET',$ws)); }
  3150. else if ($this->ws != 0) { $this->_out('BT 0 Tw ET'); }
  3151. $this->ws=$ws;
  3152. }
  3153. // WORD SPACING
  3154. function GetJspacing($nc,$ns,$w,$inclCursive) {
  3155. $ws = 0;
  3156. $charspacing = 0;
  3157. $ww = $this->jSWord;
  3158. $ncx = $nc-1;
  3159. if ($nc == 0) { return array(0,0); }
  3160. else if ($nc==1) { $charspacing = $w; }
  3161. // Only word spacing allowed / possible
  3162. else if ($this->fixedlSpacing !== false || $inclCursive) {
  3163. if ($ns) { $ws = $w / $ns; }
  3164. }
  3165. else if (!$ns) {
  3166. $charspacing = $w / ($ncx );
  3167. if (($this->jSmaxChar > 0) && ($charspacing > $this->jSmaxChar)) {
  3168. $charspacing = $this->jSmaxChar;
  3169. }
  3170. }
  3171. else if ($ns == ($ncx )) {
  3172. $charspacing = $w / $ns;
  3173. }
  3174. else {
  3175. if ($this->usingCoreFont) {
  3176. $cs = ($w * (1 - $this->jSWord)) / ($ncx );
  3177. if (($this->jSmaxChar > 0) && ($cs > $this->jSmaxChar)) {
  3178. $cs = $this->jSmaxChar;
  3179. $ww = 1 - (($cs * ($ncx ))/$w);
  3180. }
  3181. $charspacing = $cs;
  3182. $ws = ($w * ($ww) ) / $ns;
  3183. }
  3184. else {
  3185. $cs = ($w * (1 - $this->jSWord)) / ($ncx -$ns);
  3186. if (($this->jSmaxChar > 0) && ($cs > $this->jSmaxChar)) {
  3187. $cs = $this->jSmaxChar;
  3188. $ww = 1 - (($cs * ($ncx -$ns))/$w);
  3189. }
  3190. $charspacing = $cs;
  3191. $ws = (($w * ($ww) ) / $ns) - $charspacing;
  3192. }
  3193. }
  3194. return array($charspacing,$ws);
  3195. }
  3196. function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='', $currentx=0, $lcpaddingL=0, $lcpaddingR=0, $valign='M', $spanfill=0, $abovefont=0, $belowfont=0, $exactWidth=false) {
  3197. //Output a cell
  3198. // Expects input to be mb_encoded if necessary and RTL reversed
  3199. // NON_BREAKING SPACE
  3200. if ($this->usingCoreFont) {
  3201. $txt = str_replace(chr(160),chr(32),$txt);
  3202. }
  3203. else {
  3204. $txt = str_replace(chr(194).chr(160),chr(32),$txt);
  3205. }
  3206. $oldcolumn = $this->CurrCol;
  3207. // Automatic page break
  3208. // Allows PAGE-BREAK-AFTER = avoid to work
  3209. if (!$this->tableLevel && (($this->y+$this->divheight>$this->PageBreakTrigger) || ($this->y+$h>$this->PageBreakTrigger) ||
  3210. ($this->y+($h*2)>$this->PageBreakTrigger && $this->blk[$this->blklvl]['page_break_after_avoid'])) and !$this->InFooter and $this->AcceptPageBreak()) {
  3211. $x=$this->x;//Current X position
  3212. // WORD SPACING
  3213. $ws=$this->ws;//Word Spacing
  3214. $charspacing=$this->charspacing;//Character Spacing
  3215. $this->ResetSpacing();
  3216. $this->AddPage($this->CurOrientation);
  3217. // Added to correct for OddEven Margins
  3218. $x += $this->MarginCorrection;
  3219. if ($currentx) {
  3220. $currentx += $this->MarginCorrection;
  3221. }
  3222. $this->x=$x;
  3223. // WORD SPACING
  3224. $this->SetSpacing($charspacing,$ws);
  3225. }
  3226. // Test: to put line through centre of cell: $this->Line($this->x,$this->y+($h/2),$this->x+50,$this->y+($h/2));
  3227. /*-- COLUMNS --*/
  3228. // COLS
  3229. // COLUMN CHANGE
  3230. if ($this->CurrCol != $oldcolumn) {
  3231. if ($currentx) {
  3232. $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
  3233. }
  3234. $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
  3235. }
  3236. // COLUMNS Update/overwrite the lowest bottom of printing y value for a column
  3237. if ($this->ColActive) {
  3238. if ($h) { $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$h; }
  3239. else { $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$this->divheight; }
  3240. }
  3241. /*-- END COLUMNS --*/
  3242. // KEEP BLOCK TOGETHER Update/overwrite the lowest bottom of printing y value on first page
  3243. if ($this->keep_block_together) {
  3244. if ($h) { $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$h; }
  3245. // else { $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$this->divheight; }
  3246. }
  3247. if($w==0) $w = $this->w-$this->rMargin-$this->x;
  3248. $s='';
  3249. if($fill==1 && $this->FillColor) {
  3250. if((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']) || $this->keep_block_together) { $s .= $this->FillColor.' '; }
  3251. $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
  3252. }
  3253. $boxtop = $this->y;
  3254. $boxheight = $h;
  3255. $boxbottom = $this->y+$h;
  3256. if($txt!='') {
  3257. // FONT SIZE - this determines the baseline caculation
  3258. if ($this->linemaxfontsize && !$this->processingHeader) { $bfs = $this->linemaxfontsize; }
  3259. else { $bfs = $this->FontSize; }
  3260. //Calculate baseline Superscript and Subscript Y coordinate adjustment
  3261. $bfx = $this->baselineC;
  3262. $baseline = $bfx*$bfs;
  3263. if($this->SUP) { $baseline += ($bfx-1.05)*$this->FontSize; }
  3264. else if($this->SUB) { $baseline += ($bfx + 0.04)*$this->FontSize; }
  3265. else if($this->bullet) { $baseline += ($bfx-0.7)*$this->FontSize; }
  3266. // Vertical align (for Images)
  3267. if ($abovefont || $belowfont) { // from flowing block - valign always M
  3268. $va = $abovefont + (0.5*$bfs);
  3269. }
  3270. else if ($this->lineheight_correction) {
  3271. if ($valign == 'T') { $va = (0.5 * $bfs * $this->lineheight_correction); }
  3272. else if ($valign == 'B') { $va = $h-(0.5 * $bfs * $this->lineheight_correction); }
  3273. else { $va = 0.5*$h; } // Middle
  3274. }
  3275. else {
  3276. if ($valign == 'T') { $va = (0.5 * $bfs * $this->default_lineheight_correction); }
  3277. else if ($valign == 'B') { $va = $h-(0.5 * $bfs * $this->default_lineheight_correction); }
  3278. else { $va = 0.5*$h; } // Middle
  3279. }
  3280. // ONLY SET THESE IF WANT TO CONFINE BORDER +/- FILL TO FIT FONTSIZE - NOT FULL CELL AS IS ORIGINAL FUNCTION
  3281. // spanfill or spanborder are set in FlowingBlock functions
  3282. if ($spanfill || !empty($this->spanborddet) || $link!='') {
  3283. $exth = 0.2; // Add to fontsize to increase height of background / link / border
  3284. $boxtop = $this->y+$baseline+$va-($this->FontSize*(1+$exth/2)*(0.5+$bfx));
  3285. $boxheight = $this->FontSize * (1+$exth);
  3286. $boxbottom = $boxtop + $boxheight;
  3287. }
  3288. }
  3289. $bbw = $tbw = $lbw = $rbw = 0; // Border widths
  3290. if (!empty($this->spanborddet)) {
  3291. if (!isset($this->spanborddet['B'])) { $this->spanborddet['B'] = array('s' => 0, 'style' => '', 'w' => 0); }
  3292. if (!isset($this->spanborddet['T'])) { $this->spanborddet['T'] = array('s' => 0, 'style' => '', 'w' => 0); }
  3293. if (!isset($this->spanborddet['L'])) { $this->spanborddet['L'] = array('s' => 0, 'style' => '', 'w' => 0); }
  3294. if (!isset($this->spanborddet['R'])) { $this->spanborddet['R'] = array('s' => 0, 'style' => '', 'w' => 0); }
  3295. $bbw = $this->spanborddet['B']['w'];
  3296. $tbw = $this->spanborddet['T']['w'];
  3297. $lbw = $this->spanborddet['L']['w'];
  3298. $rbw = $this->spanborddet['R']['w'];
  3299. }
  3300. if($fill==1 || $border==1 || !empty($this->spanborddet)) {
  3301. if (!empty($this->spanborddet)) {
  3302. if ($fill==1) {
  3303. $s.=sprintf('%.3F %.3F %.3F %.3F re f ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($w+$lbw+$rbw)*_MPDFK,(-$boxheight-$tbw-$bbw)*_MPDFK);
  3304. }
  3305. $s.= ' q ';
  3306. $dashon = 3;
  3307. $dashoff = 3.5;
  3308. $dot = 2.5;
  3309. if($tbw) {
  3310. $short = 0;
  3311. if ($this->spanborddet['T']['style'] == 'dashed') {
  3312. $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$tbw*$dashon*_MPDFK,$tbw*$dashoff*_MPDFK);
  3313. }
  3314. else if ($this->spanborddet['T']['style'] == 'dotted') {
  3315. $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$tbw*$dot*_MPDFK,-$tbw/2*_MPDFK);
  3316. $short = $tbw/2;
  3317. }
  3318. else {
  3319. $s.=' 0 j 0 J [] 0 d ';
  3320. }
  3321. $c = $this->SetDColor($this->spanborddet['T']['c'],true);
  3322. if ($this->spanborddet['T']['style'] == 'double') {
  3323. $s.=sprintf(' %s %.3F w ',$c,$tbw/3*_MPDFK);
  3324. $xadj = $xadj2 = 0;
  3325. if ($this->spanborddet['L']['style'] == 'double') { $xadj = $this->spanborddet['L']['w']*2/3; }
  3326. if ($this->spanborddet['R']['style'] == 'double') { $xadj2 = $this->spanborddet['R']['w']*2/3; }
  3327. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw*5/6)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxtop+$tbw*5/6)*_MPDFK);
  3328. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw+$xadj)*_MPDFK,($this->h-$boxtop+$tbw/6)*_MPDFK,($this->x+$w+$rbw-$short-$xadj2)*_MPDFK,($this->h-$boxtop+$tbw/6)*_MPDFK);
  3329. }
  3330. else {
  3331. $s.=sprintf(' %s %.3F w ',$c,$tbw*_MPDFK);
  3332. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxtop+$tbw/2)*_MPDFK);
  3333. }
  3334. }
  3335. if($bbw) {
  3336. $short = 0;
  3337. if ($this->spanborddet['B']['style'] == 'dashed') {
  3338. $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$bbw*$dashon*_MPDFK,$bbw*$dashoff*_MPDFK);
  3339. }
  3340. else if ($this->spanborddet['B']['style'] == 'dotted') {
  3341. $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$bbw*$dot*_MPDFK,-$bbw/2*_MPDFK);
  3342. $short = $bbw/2;
  3343. }
  3344. else {
  3345. $s.=' 0 j 0 J [] 0 d ';
  3346. }
  3347. $c = $this->SetDColor($this->spanborddet['B']['c'],true);
  3348. if ($this->spanborddet['B']['style'] == 'double') {
  3349. $s.=sprintf(' %s %.3F w ',$c,$bbw/3*_MPDFK);
  3350. $xadj = $xadj2 = 0;
  3351. if ($this->spanborddet['L']['style'] == 'double') { $xadj = $this->spanborddet['L']['w']*2/3; }
  3352. if ($this->spanborddet['R']['style'] == 'double') { $xadj2 = $this->spanborddet['R']['w']*2/3; }
  3353. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw+$xadj)*_MPDFK,($this->h-$boxbottom-$bbw/6)*_MPDFK,($this->x+$w+$rbw-$short-$xadj2)*_MPDFK,($this->h-$boxbottom-$bbw/6)*_MPDFK);
  3354. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxbottom-$bbw*5/6)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxbottom-$bbw*5/6)*_MPDFK);
  3355. }
  3356. else {
  3357. $s.=sprintf(' %s %.3F w ',$c,$bbw*_MPDFK);
  3358. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxbottom-$bbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxbottom-$bbw/2)*_MPDFK);
  3359. }
  3360. }
  3361. if($lbw) {
  3362. $short = 0;
  3363. if ($this->spanborddet['L']['style'] == 'dashed') {
  3364. $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$lbw*$dashon*_MPDFK,$lbw*$dashoff*_MPDFK);
  3365. }
  3366. else if ($this->spanborddet['L']['style'] == 'dotted') {
  3367. $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$lbw*$dot*_MPDFK,-$lbw/2*_MPDFK);
  3368. $short = $lbw/2;
  3369. }
  3370. else {
  3371. $s.=' 0 j 0 J [] 0 d ';
  3372. }
  3373. $c = $this->SetDColor($this->spanborddet['L']['c'],true);
  3374. if ($this->spanborddet['L']['style'] == 'double') {
  3375. $s.=sprintf(' %s %.3F w ',$c,$lbw/3*_MPDFK);
  3376. $yadj = $yadj2 = 0;
  3377. if ($this->spanborddet['T']['style'] == 'double') { $yadj = $this->spanborddet['T']['w']*2/3; }
  3378. if ($this->spanborddet['B']['style'] == 'double') { $yadj2 = $this->spanborddet['B']['w']*2/3; }
  3379. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/6)*_MPDFK,($this->h-$boxtop+$tbw-$yadj)*_MPDFK,($this->x-$lbw/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short+$yadj2)*_MPDFK);
  3380. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw*5/6)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x-$lbw*5/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
  3381. }
  3382. else {
  3383. $s.=sprintf(' %s %.3F w ',$c,$lbw*_MPDFK);
  3384. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/2)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x-$lbw/2)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
  3385. }
  3386. }
  3387. if($rbw) {
  3388. $short = 0;
  3389. if ($this->spanborddet['R']['style'] == 'dashed') {
  3390. $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$rbw*$dashon*_MPDFK,$rbw*$dashoff*_MPDFK);
  3391. }
  3392. else if ($this->spanborddet['R']['style'] == 'dotted') {
  3393. $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$rbw*$dot*_MPDFK,-$rbw/2*_MPDFK);
  3394. $short = $rbw/2;
  3395. }
  3396. else {
  3397. $s.=' 0 j 0 J [] 0 d ';
  3398. }
  3399. $c = $this->SetDColor($this->spanborddet['R']['c'],true);
  3400. if ($this->spanborddet['R']['style'] == 'double') {
  3401. $s.=sprintf(' %s %.3F w ',$c,$rbw/3*_MPDFK);
  3402. $yadj = $yadj2 = 0;
  3403. if ($this->spanborddet['T']['style'] == 'double') { $yadj = $this->spanborddet['T']['w']*2/3; }
  3404. if ($this->spanborddet['B']['style'] == 'double') { $yadj2 = $this->spanborddet['B']['w']*2/3; }
  3405. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/6)*_MPDFK,($this->h-$boxtop+$tbw-$yadj)*_MPDFK,($this->x+$w+$rbw/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short+$yadj2)*_MPDFK);
  3406. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw*5/6)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw*5/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
  3407. }
  3408. else {
  3409. $s.=sprintf(' %s %.3F w ',$c,$rbw*_MPDFK);
  3410. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/2)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw/2)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
  3411. }
  3412. }
  3413. $s.= ' Q ';
  3414. }
  3415. else {
  3416. if ($fill==1) $op=($border==1) ? 'B' : 'f';
  3417. else $op='S';
  3418. $s.=sprintf('%.3F %.3F %.3F %.3F re %s ',$this->x*_MPDFK,($this->h-$boxtop)*_MPDFK,$w*_MPDFK,-$boxheight*_MPDFK,$op);
  3419. }
  3420. }
  3421. if(is_string($border)) {
  3422. $x=$this->x;
  3423. $y=$this->y;
  3424. if(is_int(strpos($border,'L')))
  3425. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-$boxtop)*_MPDFK,$x*_MPDFK,($this->h-($boxbottom))*_MPDFK);
  3426. if(is_int(strpos($border,'T')))
  3427. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-$boxtop)*_MPDFK,($x+$w)*_MPDFK,($this->h-$boxtop)*_MPDFK);
  3428. if(is_int(strpos($border,'R')))
  3429. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($x+$w)*_MPDFK,($this->h-$boxtop)*_MPDFK,($x+$w)*_MPDFK,($this->h-($boxbottom))*_MPDFK);
  3430. if(is_int(strpos($border,'B')))
  3431. $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-($boxbottom))*_MPDFK,($x+$w)*_MPDFK,($this->h-($boxbottom))*_MPDFK);
  3432. }
  3433. if($txt!='') {
  3434. if ($exactWidth)
  3435. $stringWidth = $w;
  3436. else
  3437. $stringWidth = $this->GetStringWidth($txt) + ( $this->charspacing * mb_strlen( $txt, $this->mb_enc ) / _MPDFK )
  3438. + ( $this->ws * mb_substr_count( $txt, ' ', $this->mb_enc ) / _MPDFK );
  3439. // Set x OFFSET FOR PRINTING
  3440. if($align=='R') {
  3441. $dx=$w-$this->cMarginR - $stringWidth - $lcpaddingR;
  3442. }
  3443. elseif($align=='C') {
  3444. $dx=(($w - $stringWidth )/2);
  3445. }
  3446. elseif($align=='L' or $align=='J') $dx=$this->cMarginL + $lcpaddingL;
  3447. else $dx = 0;
  3448. if($this->ColorFlag) $s .='q '.$this->TextColor.' ';
  3449. // OUTLINE
  3450. if($this->textparam['outline-s'] && !$this->S) { // mPDF 5.6.07
  3451. $s .=' '.sprintf('%.3F w',$this->LineWidth*_MPDFK).' ';
  3452. $s .=" $this->DrawColor ";
  3453. $s .=" 2 Tr ";
  3454. }
  3455. else if ($this->falseBoldWeight && strpos($this->ReqFontStyle,"B") !== false && strpos($this->FontStyle,"B") === false && !$this->S) { // can't use together with OUTLINE or Small Caps
  3456. $s .= ' 2 Tr 1 J 1 j ';
  3457. $s .= ' '.sprintf('%.3F w',($this->FontSize/130)*_MPDFK*$this->falseBoldWeight).' ';
  3458. $tc = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
  3459. if($this->FillColor!=$tc) { $s .= ' '.$tc.' '; } // stroke (outline) = same colour as text(fill)
  3460. }
  3461. else { $s .=" 0 Tr "; } // mPDF 5.6.07
  3462. if (strpos($this->ReqFontStyle,"I") !== false && strpos($this->FontStyle,"I") === false) { // Artificial italic
  3463. $aix = '1 0 0.261799 1 %.3F %.3F Tm ';
  3464. }
  3465. else { $aix = '%.3F %.3F Td '; }
  3466. // THE TEXT
  3467. $sub = '';
  3468. $this->CurrentFont['used']= true;
  3469. // WORD SPACING
  3470. // IF multibyte - Tw has no effect - need to use alternative method - do word spacing using an adjustment before each space
  3471. if ($this->ws && !$this->usingCoreFont && !$this->CurrentFont['sip'] && !$this->CurrentFont['smp'] && !$this->S) {
  3472. $sub .= ' BT 0 Tw ET ';
  3473. if ($this->kerning && $this->useKerning) { $sub .= $this->_kern($txt, 'MBTw', $aix, ($this->x+$dx), ($this->y+$baseline+$va)); }
  3474. else {
  3475. $space = " ";
  3476. //Convert string to UTF-16BE without BOM
  3477. $space= $this->UTF8ToUTF16BE($space , false);
  3478. $space=$this->_escape($space );
  3479. $sub .=sprintf('BT '.$aix,($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK);
  3480. $t = explode(' ',$txt);
  3481. $sub .=sprintf(' %.3F Tc [',$this->charspacing);
  3482. $numt = count($t);
  3483. for($i=0;$i<$numt;$i++) {
  3484. $tx = $t[$i];
  3485. //Convert string to UTF-16BE without BOM
  3486. $tx = $this->UTF8ToUTF16BE($tx , false);
  3487. $tx = $this->_escape($tx);
  3488. $sub .=sprintf('(%s) ',$tx);
  3489. if (($i+1)<$numt) {
  3490. $adj = -($this->ws)*1000/$this->FontSizePt;
  3491. $sub .=sprintf('%d(%s) ',$adj,$space);
  3492. }
  3493. }
  3494. $sub .='] TJ ';
  3495. $sub .=' ET';
  3496. }
  3497. }
  3498. else {
  3499. $txt2= $txt;
  3500. if ($this->CurrentFont['type']=='TTF' && ($this->CurrentFont['sip'] || $this->CurrentFont['smp'])) {
  3501. if ($this->S) { $sub .= $this->_smallCaps($txt2, 'SIPSMP', $aix, $dx, _MPDFK, $baseline, $va); }
  3502. else {
  3503. $txt2 = $this->UTF8toSubset($txt2);
  3504. $sub .=sprintf('BT '.$aix.' %s Tj ET',($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK,$txt2);
  3505. }
  3506. }
  3507. else {
  3508. if ($this->S) { $sub .= $this->_smallCaps($txt2, '', $aix, $dx, _MPDFK, $baseline, $va); }
  3509. else if ($this->kerning && $this->useKerning) { $sub .= $this->_kern($txt2, '', $aix, ($this->x+$dx), ($this->y+$baseline+$va)); }
  3510. else {
  3511. if (!$this->usingCoreFont) {
  3512. $txt2 = $this->UTF8ToUTF16BE($txt2, false);
  3513. }
  3514. $txt2=$this->_escape($txt2);
  3515. $sub .=sprintf('BT '.$aix.' (%s) Tj ET',($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK,$txt2);
  3516. }
  3517. }
  3518. }
  3519. // UNDERLINE
  3520. if($this->U) {
  3521. $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
  3522. if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
  3523. if (isset($this->CurrentFont['up'])) { $up=$this->CurrentFont['up']; }
  3524. else { $up = -100; }
  3525. $adjusty = (-$up/1000* $this->FontSize);
  3526. if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
  3527. else { $ut = 60/1000* $this->FontSize; }
  3528. $olw = $this->LineWidth;
  3529. $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
  3530. $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$baseline+$va+$adjusty,$txt);
  3531. $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
  3532. if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
  3533. }
  3534. // STRIKETHROUGH
  3535. if($this->strike) {
  3536. $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
  3537. if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
  3538. //Superscript and Subscript Y coordinate adjustment (now for striked-through texts)
  3539. if (isset($this->CurrentFont['desc']['CapHeight'])) { $ch=$this->CurrentFont['desc']['CapHeight']; }
  3540. else { $ch = 700; }
  3541. $adjusty = (-$ch/1000* $this->FontSize) * 0.35;
  3542. if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
  3543. else { $ut = 60/1000* $this->FontSize; }
  3544. $olw = $this->LineWidth;
  3545. $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
  3546. $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$baseline+$va+$adjusty,$txt);
  3547. $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
  3548. if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
  3549. }
  3550. // TEXT SHADOW
  3551. if ($this->textshadow) { // First to process is last in CSS comma separated shadows
  3552. foreach($this->textshadow AS $ts) {
  3553. $s .= ' q ';
  3554. $s .= $this->SetTColor($ts['col'], true)."\n";
  3555. if ($ts['col']{0}==5 && ord($ts['col']{4})<100) { // RGBa
  3556. $s .= $this->SetAlpha(ord($ts['col']{4})/100, 'Normal', true, 'F')."\n";
  3557. }
  3558. else if ($ts['col']{0}==6 && ord($ts['col']{5})<100) { // CMYKa
  3559. $s .= $this->SetAlpha(ord($ts['col']{5})/100, 'Normal', true, 'F')."\n";
  3560. }
  3561. else if ($ts['col']{0}==1 && $ts['col']{2}==1 && ord($ts['col']{3})<100) { // Gray
  3562. $s .= $this->SetAlpha(ord($ts['col']{3})/100, 'Normal', true, 'F')."\n";
  3563. }
  3564. $s .= sprintf(' 1 0 0 1 %.4F %.4F cm', $ts['x']*_MPDFK, -$ts['y']*_MPDFK)."\n";
  3565. $s .= $sub;
  3566. $s .= ' Q ';
  3567. }
  3568. }
  3569. $s .= $sub;
  3570. // COLOR
  3571. if($this->ColorFlag) $s .=' Q';
  3572. // LINK
  3573. if($link!='') {
  3574. $this->Link($this->x,$boxtop,$w,$boxheight,$link);
  3575. }
  3576. }
  3577. if($s) $this->_out($s);
  3578. // WORD SPACING
  3579. if ($this->ws && !$this->usingCoreFont) {
  3580. $this->_out(sprintf('BT %.3F Tc ET',$this->charspacing));
  3581. }
  3582. $this->lasth=$h;
  3583. if( strpos($txt,"\n") !== false) $ln=1; // cell recognizes \n from <BR> tag
  3584. if($ln>0)
  3585. {
  3586. //Go to next line
  3587. $this->y += $h;
  3588. if($ln==1) {
  3589. //Move to next line
  3590. if ($currentx != 0) { $this->x=$currentx; }
  3591. else { $this->x=$this->lMargin; }
  3592. }
  3593. }
  3594. else $this->x+=$w;
  3595. }
  3596. function _kern($txt, $mode, $aix, $x, $y) {
  3597. if ($mode == 'MBTw') { // Multibyte requiring word spacing
  3598. $space = ' ';
  3599. //Convert string to UTF-16BE without BOM
  3600. $space= $this->UTF8ToUTF16BE($space , false);
  3601. $space=$this->_escape($space );
  3602. $s = sprintf(' BT '.$aix,$x*_MPDFK,($this->h-$y)*_MPDFK);
  3603. $t = explode(' ',$txt);
  3604. for($i=0;$i<count($t);$i++) {
  3605. $tx = $t[$i];
  3606. $tj = '(';
  3607. $unicode = $this->UTF8StringToArray($tx);
  3608. for($ti=0;$ti<count($unicode);$ti++) {
  3609. if ($ti > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($ti-1)]][$unicode[$ti]])) {
  3610. $kern = -$this->CurrentFont['kerninfo'][$unicode[($ti-1)]][$unicode[$ti]];
  3611. $tj .= sprintf(')%d(',$kern);
  3612. }
  3613. $tc = code2utf($unicode[$ti]);
  3614. $tc = $this->UTF8ToUTF16BE($tc, false);
  3615. $tj .= $this->_escape($tc);
  3616. }
  3617. $tj .= ')';
  3618. $s.=sprintf(' %.3F Tc [%s] TJ',$this->charspacing,$tj);
  3619. if (($i+1)<count($t)) {
  3620. $s.=sprintf(' %.3F Tc (%s) Tj',$this->ws+$this->charspacing,$space);
  3621. }
  3622. }
  3623. $s.=' ET ';
  3624. }
  3625. else if (!$this->usingCoreFont) {
  3626. $s = '';
  3627. $tj = '(';
  3628. $unicode = $this->UTF8StringToArray($txt);
  3629. for($i=0;$i<count($unicode);$i++) {
  3630. if ($i > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]])) {
  3631. $kern = -$this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]];
  3632. $tj .= sprintf(')%d(',$kern);
  3633. }
  3634. $tx = code2utf($unicode[$i]);
  3635. $tx = $this->UTF8ToUTF16BE($tx, false);
  3636. $tj .= $this->_escape($tx);
  3637. }
  3638. $tj .= ')';
  3639. $s.=sprintf(' BT '.$aix.' [%s] TJ ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$tj);
  3640. }
  3641. else { // CORE Font
  3642. $s = '';
  3643. $tj = '(';
  3644. $l = strlen($txt);
  3645. for($i=0;$i<$l;$i++) {
  3646. if ($i > 0 && isset($this->CurrentFont['kerninfo'][$txt[($i-1)]][$txt[$i]])) {
  3647. $kern = -$this->CurrentFont['kerninfo'][$txt[($i-1)]][$txt[$i]];
  3648. $tj .= sprintf(')%d(',$kern);
  3649. }
  3650. $tj .= $this->_escape($txt[$i]);
  3651. }
  3652. $tj .= ')';
  3653. $s.=sprintf(' BT '.$aix.' [%s] TJ ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$tj);
  3654. }
  3655. return $s;
  3656. }
  3657. function _smallCaps($txt, $mode, $aix, $dx, $k, $baseline, $va) {
  3658. $upp = false;
  3659. $str = array();
  3660. $bits = array();
  3661. if (!$this->usingCoreFont) {
  3662. $unicode = $this->UTF8StringToArray($txt);
  3663. foreach($unicode as $char) {
  3664. if ($this->ws && $char == 32) { // space
  3665. if (count($str)) { $bits[] = array($upp, $str, false); }
  3666. $bits[] = array(false, array(32), true);
  3667. $str = array();
  3668. $upp = false;
  3669. }
  3670. else if (isset($this->upperCase[$char])) {
  3671. if (!$upp) {
  3672. if (count($str)) { $bits[] = array($upp, $str, false); }
  3673. $str = array();
  3674. }
  3675. $str[] = $this->upperCase[$char];
  3676. if ((!isset($this->CurrentFont['sip']) || !$this->CurrentFont['sip']) && (!isset($this->CurrentFont['smp']) || !$this->CurrentFont['smp'])) {
  3677. $this->CurrentFont['subset'][$this->upperCase[$char]] = $this->upperCase[$char];
  3678. }
  3679. $upp = true;
  3680. }
  3681. else {
  3682. if ($upp) {
  3683. if (count($str)) { $bits[] = array($upp, $str, false); }
  3684. $str = array();
  3685. }
  3686. $str[] = $char;
  3687. $upp = false;
  3688. }
  3689. }
  3690. }
  3691. else {
  3692. for($i=0;$i<strlen($txt);$i++) {
  3693. if (isset($this->upperCase[ord($txt[$i])]) && $this->upperCase[ord($txt[$i])] < 256) {
  3694. if (!$upp) {
  3695. if (count($str)) { $bits[] = array($upp, $str, false); }
  3696. $str = array();
  3697. }
  3698. $str[] = $this->upperCase[ord($txt[$i])];
  3699. $upp = true;
  3700. }
  3701. else {
  3702. if ($upp) {
  3703. if (count($str)) { $bits[] = array($upp, $str, false); }
  3704. $str = array();
  3705. }
  3706. $str[] = ord($txt[$i]);
  3707. $upp = false;
  3708. }
  3709. }
  3710. }
  3711. if (count($str)) { $bits[] = array($upp, $str, false); }
  3712. $fid = $this->CurrentFont['i'];
  3713. $s=sprintf(' BT '.$aix,($this->x+$dx)*$k,($this->h-($this->y+$baseline+$va))*$k);
  3714. foreach($bits AS $b) {
  3715. if ($b[0]) { $upp = true; }
  3716. else { $upp = false; }
  3717. $size = count ($b[1]);
  3718. $txt = '';
  3719. for ($i = 0; $i < $size; $i++) {
  3720. $txt .= code2utf($b[1][$i]);
  3721. }
  3722. if ($this->usingCoreFont) {
  3723. $txt = utf8_decode($txt);
  3724. }
  3725. if ($mode == 'SIPSMP') {
  3726. $txt = $this->UTF8toSubset($txt);
  3727. }
  3728. else {
  3729. if (!$this->usingCoreFont) {
  3730. $txt = $this->UTF8ToUTF16BE($txt, false);
  3731. }
  3732. $txt=$this->_escape($txt);
  3733. $txt = '('.$txt.')';
  3734. }
  3735. if ($b[2]) { // space
  3736. $s.=sprintf(' /F%d %.3F Tf %d Tz', $fid, $this->FontSizePt, 100);
  3737. $s.=sprintf(' %.3F Tc', ($this->charspacing+$this->ws));
  3738. $s.=sprintf(' %s Tj', $txt);
  3739. }
  3740. else if ($upp) {
  3741. $s.=sprintf(' /F%d %.3F Tf', $fid, $this->FontSizePt*$this->smCapsScale);
  3742. $s.=sprintf(' %d Tz', $this->smCapsStretch);
  3743. $s.=sprintf(' %.3F Tc', ($this->charspacing*100/$this->smCapsStretch));
  3744. $s.=sprintf(' %s Tj', $txt);
  3745. }
  3746. else {
  3747. $s.=sprintf(' /F%d %.3F Tf %d Tz', $fid, $this->FontSizePt, 100);
  3748. $s.=sprintf(' %.3F Tc', ($this->charspacing));
  3749. $s.=sprintf(' %s Tj', $txt);
  3750. }
  3751. }
  3752. $s.=' ET ';
  3753. return $s;
  3754. }
  3755. function MultiCell($w,$h,$txt,$border=0,$align='',$fill=0,$link='',$directionality='ltr',$encoded=false)
  3756. {
  3757. // Parameter (pre-)encoded - When called internally from ToC or textarea: mb_encoding already done - but not reverse RTL/Indic
  3758. if (!$encoded) {
  3759. $txt = $this->purify_utf8_text($txt);
  3760. if ($this->text_input_as_HTML) {
  3761. $txt = $this->all_entities_to_utf8($txt);
  3762. }
  3763. if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
  3764. // Font-specific ligature substitution for Indic fonts
  3765. else if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) { // *INDIC*
  3766. $this->ConvertIndic($tmp); // *INDIC*
  3767. } // *INDIC*
  3768. if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *RTL*
  3769. }
  3770. if (!$align) { $align = $this->defaultAlign; }
  3771. //Output text with automatic or explicit line breaks
  3772. $cw=&$this->CurrentFont['cw'];
  3773. if($w==0) $w=$this->w-$this->rMargin-$this->x;
  3774. $wmax = ($w - ($this->cMarginL+$this->cMarginR));
  3775. if ($this->usingCoreFont) {
  3776. $s=str_replace("\r",'',$txt);
  3777. $nb=strlen($s);
  3778. while($nb>0 and $s[$nb-1]=="\n") $nb--;
  3779. }
  3780. else {
  3781. $s=str_replace("\r",'',$txt);
  3782. $nb=mb_strlen($s, $this->mb_enc );
  3783. while($nb>0 and mb_substr($s,$nb-1,1,$this->mb_enc )=="\n") $nb--;
  3784. }
  3785. $b=0;
  3786. if($border) {
  3787. if($border==1) {
  3788. $border='LTRB';
  3789. $b='LRT';
  3790. $b2='LR';
  3791. }
  3792. else {
  3793. $b2='';
  3794. if(is_int(strpos($border,'L'))) $b2.='L';
  3795. if(is_int(strpos($border,'R'))) $b2.='R';
  3796. $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
  3797. }
  3798. }
  3799. $sep=-1;
  3800. $i=0;
  3801. $j=0;
  3802. $l=0;
  3803. $ns=0;
  3804. $nl=1;
  3805. if (!$this->usingCoreFont) {
  3806. $checkCursive=false;
  3807. if ($this->biDirectional) { $checkCursive=true; }
  3808. else if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) { $checkCursive=true; } // *INDIC*
  3809. while($i<$nb) {
  3810. //Get next character
  3811. $c = mb_substr($s,$i,1,$this->mb_enc );
  3812. if($c == "\n") {
  3813. //Explicit line break
  3814. // WORD SPACING
  3815. $this->ResetSpacing();
  3816. $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
  3817. // DIRECTIONALITY
  3818. $this->magic_reverse_dir($tmp, true, $directionality); // *RTL*
  3819. $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
  3820. $i++;
  3821. $sep=-1;
  3822. $j=$i;
  3823. $l=0;
  3824. $ns=0;
  3825. $nl++;
  3826. if($border and $nl==2) $b=$b2;
  3827. continue;
  3828. }
  3829. if($c == " ") {
  3830. $sep=$i;
  3831. $ls=$l;
  3832. $ns++;
  3833. }
  3834. $l += $this->GetCharWidthNonCore($c);
  3835. if($l>$wmax) {
  3836. //Automatic line break
  3837. if($sep==-1) { // Only one word
  3838. if($i==$j) $i++;
  3839. // WORD SPACING
  3840. $this->ResetSpacing();
  3841. $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
  3842. // DIRECTIONALITY
  3843. $this->magic_reverse_dir($tmp, true, $directionality); // *RTL*
  3844. $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
  3845. }
  3846. else {
  3847. $tmp = rtrim(mb_substr($s,$j,$sep-$j,$this->mb_enc));
  3848. if($align=='J') {
  3849. //////////////////////////////////////////
  3850. // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
  3851. // WORD SPACING UNICODE
  3852. // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
  3853. $tmp = str_replace(chr(194).chr(160),chr(32),$tmp );
  3854. $len_ligne = $this->GetStringWidth($tmp );
  3855. $nb_carac = mb_strlen( $tmp , $this->mb_enc ) ;
  3856. $nb_spaces = mb_substr_count( $tmp ,' ', $this->mb_enc ) ;
  3857. $inclCursive=false;
  3858. if ($checkCursive) {
  3859. if (preg_match("/([".$this->pregRTLchars."])/u", $tmp)) { $inclCursive = true; } // *RTL*
  3860. if (preg_match("/([".$this->pregHIchars.$this->pregBNchars.$this->pregPAchars."])/u", $tmp)) { $inclCursive = true; } // *INDIC*
  3861. }
  3862. list($charspacing,$ws) = $this->GetJspacing($nb_carac,$nb_spaces,((($wmax) - $len_ligne) * _MPDFK),$inclCursive);
  3863. $this->SetSpacing($charspacing,$ws);
  3864. //////////////////////////////////////////
  3865. }
  3866. // DIRECTIONALITY
  3867. $this->magic_reverse_dir($tmp, true, $directionality); // *RTL*
  3868. $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
  3869. $i=$sep+1;
  3870. }
  3871. $sep=-1;
  3872. $j=$i;
  3873. $l=0;
  3874. $ns=0;
  3875. $nl++;
  3876. if($border and $nl==2) $b=$b2;
  3877. }
  3878. else $i++;
  3879. }
  3880. //Last chunk
  3881. // WORD SPACING
  3882. $this->ResetSpacing();
  3883. }
  3884. else {
  3885. while($i<$nb) {
  3886. //Get next character
  3887. $c=$s[$i];
  3888. if($c == "\n") {
  3889. //Explicit line break
  3890. // WORD SPACING
  3891. $this->ResetSpacing();
  3892. $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link);
  3893. $i++;
  3894. $sep=-1;
  3895. $j=$i;
  3896. $l=0;
  3897. $ns=0;
  3898. $nl++;
  3899. if($border and $nl==2) $b=$b2;
  3900. continue;
  3901. }
  3902. if($c == " ") {
  3903. $sep=$i;
  3904. $ls=$l;
  3905. $ns++;
  3906. }
  3907. $l += $this->GetCharWidthCore($c);
  3908. if($l>$wmax) {
  3909. //Automatic line break
  3910. if($sep==-1) {
  3911. if($i==$j) $i++;
  3912. // WORD SPACING
  3913. $this->ResetSpacing();
  3914. $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link);
  3915. }
  3916. else {
  3917. if($align=='J') {
  3918. $tmp = rtrim(substr($s,$j,$sep-$j));
  3919. //////////////////////////////////////////
  3920. // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
  3921. // WORD SPACING NON_UNICDOE/CJK
  3922. // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
  3923. $tmp = str_replace(chr(160),chr(32),$tmp);
  3924. $len_ligne = $this->GetStringWidth($tmp );
  3925. $nb_carac = strlen( $tmp ) ;
  3926. $nb_spaces = substr_count( $tmp ,' ' ) ;
  3927. list($charspacing,$ws) = $this->GetJspacing($nb_carac,$nb_spaces,((($wmax) - $len_ligne) * _MPDFK),false);
  3928. $this->SetSpacing($charspacing,$ws);
  3929. //////////////////////////////////////////
  3930. }
  3931. $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill,$link);
  3932. $i=$sep+1;
  3933. }
  3934. $sep=-1;
  3935. $j=$i;
  3936. $l=0;
  3937. $ns=0;
  3938. $nl++;
  3939. if($border and $nl==2) $b=$b2;
  3940. }
  3941. else $i++;
  3942. }
  3943. //Last chunk
  3944. // WORD SPACING
  3945. $this->ResetSpacing();
  3946. }
  3947. //Last chunk
  3948. if($border and is_int(strpos($border,'B'))) $b.='B';
  3949. if (!$this->usingCoreFont) {
  3950. $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
  3951. // DIRECTIONALITY
  3952. $this->magic_reverse_dir($tmp, true, $directionality); // *RTL*
  3953. $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
  3954. }
  3955. else { $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link); }
  3956. $this->x=$this->lMargin;
  3957. }
  3958. /*-- DIRECTW --*/
  3959. function Write($h,$txt,$currentx=0,$link='',$directionality='ltr',$align='') {
  3960. if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
  3961. if (empty($this->directw)) { $this->directw = new directw($this); }
  3962. $this->directw->Write($h,$txt,$currentx,$link,$directionality,$align);
  3963. }
  3964. /*-- END DIRECTW --*/
  3965. /*-- HTML-CSS --*/
  3966. function saveInlineProperties() {
  3967. $saved = array();
  3968. $saved[ 'family' ] = $this->FontFamily;
  3969. $saved[ 'style' ] = $this->FontStyle;
  3970. $saved[ 'sizePt' ] = $this->FontSizePt;
  3971. $saved[ 'size' ] = $this->FontSize;
  3972. $saved[ 'HREF' ] = $this->HREF;
  3973. $saved[ 'underline' ] = $this->U;
  3974. $saved[ 'smCaps' ] = $this->S;
  3975. $saved[ 'strike' ] = $this->strike;
  3976. $saved[ 'textshadow' ] = $this->textshadow;
  3977. $saved[ 'SUP' ] = $this->SUP;
  3978. $saved[ 'SUB' ] = $this->SUB;
  3979. $saved[ 'linewidth' ] = $this->LineWidth;
  3980. $saved[ 'drawcolor' ] = $this->DrawColor;
  3981. $saved[ 'textparam' ] = $this->textparam;
  3982. $saved[ 'toupper' ] = $this->toupper;
  3983. $saved[ 'tolower' ] = $this->tolower;
  3984. $saved[ 'capitalize' ] = $this->capitalize;
  3985. $saved[ 'fontkerning' ] = $this->kerning;
  3986. $saved[ 'lSpacingCSS' ] = $this->lSpacingCSS;
  3987. $saved[ 'wSpacingCSS' ] = $this->wSpacingCSS;
  3988. $saved[ 'I' ] = $this->I;
  3989. $saved[ 'B' ] = $this->B;
  3990. $saved[ 'colorarray' ] = $this->colorarray;
  3991. $saved[ 'bgcolorarray' ] = $this->spanbgcolorarray;
  3992. $saved[ 'border' ] = $this->spanborddet;
  3993. $saved[ 'color' ] = $this->TextColor;
  3994. $saved[ 'bgcolor' ] = $this->FillColor;
  3995. $saved[ 'lang' ] = $this->currentLang;
  3996. $saved[ 'display_off' ] = $this->inlineDisplayOff;
  3997. return $saved;
  3998. }
  3999. function restoreInlineProperties( &$saved) {
  4000. $FontFamily = $saved[ 'family' ];
  4001. $this->FontStyle = $saved[ 'style' ];
  4002. $this->FontSizePt = $saved[ 'sizePt' ];
  4003. $this->FontSize = $saved[ 'size' ];
  4004. $this->currentLang = $saved['lang'];
  4005. if ($this->useLang && !$this->usingCoreFont) {
  4006. if ($this->currentLang != $this->default_lang && ((strlen($this->currentLang) == 5 && $this->currentLang != 'UTF-8') || strlen($this->currentLang ) == 2)) {
  4007. list ($coreSuitable,$mpdf_pdf_unifonts) = GetLangOpts($this->currentLang, $this->useAdobeCJK);
  4008. if ($mpdf_pdf_unifonts) { $this->RestrictUnicodeFonts($mpdf_pdf_unifonts); }
  4009. else { $this->RestrictUnicodeFonts($this->default_available_fonts ); }
  4010. }
  4011. else {
  4012. $this->RestrictUnicodeFonts($this->default_available_fonts );
  4013. }
  4014. }
  4015. $this->ColorFlag = ($this->FillColor != $this->TextColor); //Restore ColorFlag as well
  4016. $this->HREF = $saved[ 'HREF' ];
  4017. $this->U = $saved[ 'underline' ];
  4018. $this->S = $saved[ 'smCaps' ];
  4019. $this->strike = $saved[ 'strike' ];
  4020. $this->textshadow = $saved[ 'textshadow' ];
  4021. $this->SUP = $saved[ 'SUP' ];
  4022. $this->SUB = $saved[ 'SUB' ];
  4023. $this->LineWidth = $saved[ 'linewidth' ];
  4024. $this->DrawColor = $saved[ 'drawcolor' ];
  4025. $this->textparam = $saved[ 'textparam' ];
  4026. $this->inlineDisplayOff = $saved['display_off'];
  4027. $this->toupper = $saved[ 'toupper' ];
  4028. $this->tolower = $saved[ 'tolower' ];
  4029. $this->capitalize = $saved[ 'capitalize' ];
  4030. $this->kerning = $saved[ 'fontkerning' ];
  4031. $this->lSpacingCSS = $saved[ 'lSpacingCSS' ];
  4032. if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
  4033. $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
  4034. }
  4035. else { $this->fixedlSpacing = false; }
  4036. $this->wSpacingCSS = $saved[ 'wSpacingCSS' ];
  4037. if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
  4038. $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
  4039. }
  4040. else { $this->minwSpacing = 0; }
  4041. $this->SetFont($FontFamily, $saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ],false);
  4042. $this->currentfontstyle = $saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : '');
  4043. $this->currentfontsize = $saved[ 'sizePt' ];
  4044. $this->SetStylesArray(array('S'=>$this->S, 'U'=>$this->U, 'B'=>$saved[ 'B' ], 'I'=>$saved[ 'I' ]));
  4045. $this->TextColor = $saved[ 'color' ];
  4046. $this->FillColor = $saved[ 'bgcolor' ];
  4047. $this->colorarray = $saved[ 'colorarray' ];
  4048. $cor = $saved[ 'colorarray' ];
  4049. if ($cor) $this->SetTColor($cor);
  4050. $this->spanbgcolorarray = $saved[ 'bgcolorarray' ];
  4051. $cor = $saved[ 'bgcolorarray' ];
  4052. if ($cor) $this->SetFColor($cor);
  4053. $this->spanborddet = $saved[ 'border' ];
  4054. }
  4055. // Used when ColActive for tables - updated to return first block with background fill OR borders
  4056. function GetFirstBlockFill() {
  4057. // Returns the first blocklevel that uses a bgcolor fill
  4058. $startfill = 0;
  4059. for ($i=1;$i<=$this->blklvl;$i++) {
  4060. if ($this->blk[$i]['bgcolor'] || $this->blk[$i]['border_left']['w'] || $this->blk[$i]['border_right']['w'] || $this->blk[$i]['border_top']['w'] || $this->blk[$i]['border_bottom']['w'] ) {
  4061. $startfill = $i;
  4062. break;
  4063. }
  4064. }
  4065. return $startfill;
  4066. }
  4067. function SetBlockFill($blvl) {
  4068. if ($this->blk[$blvl]['bgcolor']) {
  4069. $this->SetFColor($this->blk[$blvl]['bgcolorarray']);
  4070. return 1;
  4071. }
  4072. else {
  4073. $this->SetFColor($this->ConvertColor(255));
  4074. return 0;
  4075. }
  4076. }
  4077. //-------------------------FLOWING BLOCK------------------------------------//
  4078. //The following functions were originally written by Damon Kohler //
  4079. //--------------------------------------------------------------------------//
  4080. function saveFont() {
  4081. $saved = array();
  4082. $saved[ 'family' ] = $this->FontFamily;
  4083. $saved[ 'style' ] = $this->FontStyle;
  4084. $saved[ 'sizePt' ] = $this->FontSizePt;
  4085. $saved[ 'size' ] = $this->FontSize;
  4086. $saved[ 'curr' ] = &$this->CurrentFont;
  4087. $saved[ 'color' ] = $this->TextColor;
  4088. $saved[ 'spanbgcolor' ] = $this->spanbgcolor;
  4089. $saved[ 'spanbgcolorarray' ] = $this->spanbgcolorarray;
  4090. $saved[ 'bord' ] = $this->spanborder;
  4091. $saved[ 'border' ] = $this->spanborddet;
  4092. $saved[ 'HREF' ] = $this->HREF;
  4093. $saved[ 'underline' ] = $this->U;
  4094. $saved[ 'smCaps' ] = $this->S;
  4095. $saved[ 'strike' ] = $this->strike;
  4096. $saved[ 'textshadow' ] = $this->textshadow;
  4097. $saved[ 'SUP' ] = $this->SUP;
  4098. $saved[ 'SUB' ] = $this->SUB;
  4099. $saved[ 'linewidth' ] = $this->LineWidth;
  4100. $saved[ 'drawcolor' ] = $this->DrawColor;
  4101. $saved[ 'textparam' ] = $this->textparam;
  4102. $saved[ 'ReqFontStyle' ] = $this->ReqFontStyle;
  4103. $saved[ 'fontkerning' ] = $this->kerning;
  4104. $saved[ 'fixedlSpacing' ] = $this->fixedlSpacing;
  4105. $saved[ 'minwSpacing' ] = $this->minwSpacing;
  4106. return $saved;
  4107. }
  4108. function restoreFont( &$saved, $write=true) {
  4109. if (!isset($saved) || empty($saved)) return;
  4110. $this->FontFamily = $saved[ 'family' ];
  4111. $this->FontStyle = $saved[ 'style' ];
  4112. $this->FontSizePt = $saved[ 'sizePt' ];
  4113. $this->FontSize = $saved[ 'size' ];
  4114. $this->CurrentFont = &$saved[ 'curr' ];
  4115. $this->TextColor = $saved[ 'color' ];
  4116. $this->spanbgcolor = $saved[ 'spanbgcolor' ];
  4117. $this->spanbgcolorarray = $saved[ 'spanbgcolorarray' ];
  4118. $this->spanborder = $saved[ 'bord' ];
  4119. $this->spanborddet = $saved[ 'border' ];
  4120. $this->ColorFlag = ($this->FillColor != $this->TextColor); //Restore ColorFlag as well
  4121. $this->HREF = $saved[ 'HREF' ];
  4122. $this->U = $saved[ 'underline' ];
  4123. $this->S = $saved[ 'smCaps' ];
  4124. $this->kerning = $saved[ 'fontkerning' ];
  4125. $this->fixedlSpacing = $saved[ 'fixedlSpacing' ];
  4126. $this->minwSpacing = $saved[ 'minwSpacing' ];
  4127. $this->strike = $saved[ 'strike' ];
  4128. $this->textshadow = $saved[ 'textshadow' ];
  4129. $this->SUP = $saved[ 'SUP' ];
  4130. $this->SUB = $saved[ 'SUB' ];
  4131. $this->LineWidth = $saved[ 'linewidth' ];
  4132. $this->DrawColor = $saved[ 'drawcolor' ];
  4133. $this->textparam = $saved[ 'textparam' ];
  4134. if ($write) {
  4135. $this->SetFont($saved[ 'family' ],$saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ],true,true); // force output
  4136. $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
  4137. if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
  4138. $this->pageoutput[$this->page]['Font'] = $fontout;
  4139. }
  4140. else
  4141. $this->SetFont($saved[ 'family' ],$saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ]);
  4142. $this->ReqFontStyle = $saved[ 'ReqFontStyle' ];
  4143. }
  4144. function newFlowingBlock( $w, $h, $a = '', $is_table = false, $is_list = false, $blockstate = 0, $newblock=true, $blockdir='ltr')
  4145. {
  4146. if (!$a) {
  4147. if ($blockdir=='rtl') { $a = 'R'; }
  4148. else { $a = 'L'; }
  4149. }
  4150. $this->flowingBlockAttr[ 'width' ] = ($w * _MPDFK);
  4151. // line height in user units
  4152. $this->flowingBlockAttr[ 'is_table' ] = $is_table;
  4153. $this->flowingBlockAttr[ 'is_list' ] = $is_list;
  4154. $this->flowingBlockAttr[ 'height' ] = $h;
  4155. $this->flowingBlockAttr[ 'lineCount' ] = 0;
  4156. $this->flowingBlockAttr[ 'align' ] = $a;
  4157. $this->flowingBlockAttr[ 'font' ] = array();
  4158. $this->flowingBlockAttr[ 'content' ] = array();
  4159. $this->flowingBlockAttr[ 'contentB' ] = array();
  4160. $this->flowingBlockAttr[ 'contentWidth' ] = 0;
  4161. $this->flowingBlockAttr[ 'blockstate' ] = $blockstate;
  4162. $this->flowingBlockAttr[ 'newblock' ] = $newblock;
  4163. $this->flowingBlockAttr[ 'valign' ] = 'M';
  4164. $this->flowingBlockAttr['blockdir'] = $blockdir;
  4165. }
  4166. function finishFlowingBlock($endofblock=false, $next='') {
  4167. $currentx = $this->x;
  4168. //prints out the last chunk
  4169. $is_table = $this->flowingBlockAttr[ 'is_table' ];
  4170. $is_list = $this->flowingBlockAttr[ 'is_list' ];
  4171. $maxWidth =& $this->flowingBlockAttr[ 'width' ];
  4172. $lineHeight =& $this->flowingBlockAttr[ 'height' ];
  4173. $align =& $this->flowingBlockAttr[ 'align' ];
  4174. $content =& $this->flowingBlockAttr[ 'content' ];
  4175. $contentB =& $this->flowingBlockAttr[ 'contentB' ];
  4176. $font =& $this->flowingBlockAttr[ 'font' ];
  4177. $contentWidth =& $this->flowingBlockAttr[ 'contentWidth' ];
  4178. $lineCount =& $this->flowingBlockAttr[ 'lineCount' ];
  4179. $valign =& $this->flowingBlockAttr[ 'valign' ];
  4180. $blockstate = $this->flowingBlockAttr[ 'blockstate' ];
  4181. $newblock = $this->flowingBlockAttr[ 'newblock' ];
  4182. $blockdir = $this->flowingBlockAttr['blockdir'];
  4183. // *********** BLOCK BACKGROUND COLOR *****************//
  4184. if ($this->blk[$this->blklvl]['bgcolor'] && !$is_table) {
  4185. $fill = 0;
  4186. }
  4187. else {
  4188. $this->SetFColor($this->ConvertColor(255));
  4189. $fill = 0;
  4190. }
  4191. $hanger = ''; // mPDF 5.6.40
  4192. // Always right trim!
  4193. // Right trim content and adjust width if need to justify (later)
  4194. if (isset($content[count($content)-1]) && preg_match('/[ ]+$/',$content[count($content)-1], $m)) {
  4195. $strip = strlen($m[0]);
  4196. $content[count($content)-1] = substr($content[count($content)-1],0,(strlen($content[count($content)-1])-$strip));
  4197. $this->restoreFont( $font[ count($content)-1 ],false );
  4198. $contentWidth -= $this->GetStringWidth($m[0]) * _MPDFK;
  4199. }
  4200. // the amount of space taken up so far in user units
  4201. $usedWidth = 0;
  4202. // COLS
  4203. $oldcolumn = $this->CurrCol;
  4204. if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  4205. // Print out each chunk
  4206. /*-- TABLES --*/
  4207. if ($is_table) {
  4208. $ipaddingL = 0;
  4209. $ipaddingR = 0;
  4210. $paddingL = 0;
  4211. $paddingR = 0;
  4212. }
  4213. else {
  4214. /*-- END TABLES --*/
  4215. $ipaddingL = $this->blk[$this->blklvl]['padding_left'];
  4216. $ipaddingR = $this->blk[$this->blklvl]['padding_right'];
  4217. $paddingL = ($ipaddingL * _MPDFK);
  4218. $paddingR = ($ipaddingR * _MPDFK);
  4219. $this->cMarginL = $this->blk[$this->blklvl]['border_left']['w'];
  4220. $this->cMarginR = $this->blk[$this->blklvl]['border_right']['w'];
  4221. // Added mPDF 3.0 Float DIV
  4222. $fpaddingR = 0;
  4223. $fpaddingL = 0;
  4224. /*-- CSS-FLOAT --*/
  4225. if (count($this->floatDivs)) {
  4226. list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
  4227. if ($r_exists) { $fpaddingR = $r_width; }
  4228. if ($l_exists) { $fpaddingL = $l_width; }
  4229. }
  4230. /*-- END CSS-FLOAT --*/
  4231. $usey = $this->y + 0.002;
  4232. if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
  4233. $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
  4234. }
  4235. /*-- CSS-IMAGE-FLOAT --*/
  4236. // If float exists at this level
  4237. if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
  4238. if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
  4239. /*-- END CSS-IMAGE-FLOAT --*/
  4240. } // *TABLES*
  4241. // Set Current lineheight (correction factor)
  4242. $lhfixed = false;
  4243. /*-- LISTS --*/
  4244. if ($is_list) {
  4245. if (preg_match('/([0-9.,]+)mm/',$this->list_lineheight[$this->listlvl][$this->listOcc],$am)) {
  4246. $lhfixed = true;
  4247. $def_fontsize = $this->InlineProperties['LISTITEM'][$this->listlvl][$this->listOcc][$this->listnum]['size'];
  4248. $this->lineheight_correction = $am[1] / $def_fontsize ;
  4249. }
  4250. else {
  4251. $this->lineheight_correction = $this->list_lineheight[$this->listlvl][$this->listOcc];
  4252. }
  4253. }
  4254. else
  4255. /*-- END LISTS --*/
  4256. /*-- TABLES --*/
  4257. if ($is_table) {
  4258. if (preg_match('/([0-9.,]+)mm/',$this->table_lineheight,$am)) {
  4259. $lhfixed = true;
  4260. $def_fontsize = $this->FontSize; // needs to be default font-size for block ****
  4261. $this->lineheight_correction = $lineHeight / $def_fontsize ;
  4262. }
  4263. else {
  4264. $this->lineheight_correction = $this->table_lineheight;
  4265. }
  4266. }
  4267. else
  4268. /*-- END TABLES --*/
  4269. if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
  4270. if (preg_match('/([0-9.,]+)mm/',$this->blk[$this->blklvl]['line_height'],$am)) {
  4271. $lhfixed = true;
  4272. $def_fontsize = $this->blk[$this->blklvl]['InlineProperties']['size']; // needs to be default font-size for block ****
  4273. $this->lineheight_correction = $am[1] / $def_fontsize ;
  4274. }
  4275. else {
  4276. $this->lineheight_correction = $this->blk[$this->blklvl]['line_height'];
  4277. }
  4278. }
  4279. else {
  4280. $this->lineheight_correction = $this->normalLineheight;
  4281. }
  4282. // correct lineheight to maximum fontsize
  4283. if ($lhfixed) { $maxlineHeight = $this->lineheight; }
  4284. else { $maxlineHeight = 0; }
  4285. $this->forceExactLineheight = true;
  4286. $maxfontsize = 0;
  4287. // While we're at it, check if contains cursive text
  4288. $checkCursive=false;
  4289. if ($this->biDirectional) { $checkCursive=true; } // *RTL*
  4290. foreach ( $content as $k => $chunk )
  4291. {
  4292. $this->restoreFont( $font[ $k ],false );
  4293. if (!isset($this->objectbuffer[$k])) {
  4294. // Soft Hyphens chr(173)
  4295. if (!$this->usingCoreFont) {
  4296. $content[$k] = $chunk = str_replace("\xc2\xad",'',$chunk );
  4297. if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) { $checkCursive=true; } // *INDIC*
  4298. }
  4299. else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
  4300. $content[$k] = $chunk = str_replace(chr(173),'',$chunk );
  4301. }
  4302. // Special case of sub/sup carried over on its own to last line
  4303. if (($this->SUB || $this->SUP) && count($content)==1) { $actfs = $this->FontSize*100/55; } // 55% is font change for sub/sup
  4304. else { $actfs = $this->FontSize; }
  4305. if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
  4306. if ($lhfixed && ($actfs > $def_fontsize || ($actfs > ($lineHeight * $this->lineheight_correction) && $is_list))) {
  4307. $this->forceExactLineheight = false;
  4308. }
  4309. $maxfontsize = max($maxfontsize,$actfs);
  4310. }
  4311. }
  4312. if(isset($font[count($font)-1])) {
  4313. $lastfontreqstyle = $font[count($font)-1]['ReqFontStyle'];
  4314. $lastfontstyle = $font[count($font)-1]['style'];
  4315. }
  4316. else {
  4317. $lastfontreqstyle=null;
  4318. $lastfontstyle=null;
  4319. }
  4320. if ($blockdir == 'ltr' && strpos($lastfontreqstyle,"I") !== false && strpos($lastfontstyle,"I") === false) { // Artificial italic
  4321. $lastitalic = $this->FontSize*0.15*_MPDFK;
  4322. }
  4323. else { $lastitalic = 0; }
  4324. /*-- LISTS --*/
  4325. if ($is_list && is_array($this->bulletarray) && count($this->bulletarray)) {
  4326. $actfs = $this->bulletarray['fontsize'];
  4327. if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
  4328. if ($lhfixed && $actfs > $def_fontsize) { $this->forceExactLineheight = false; }
  4329. $maxfontsize = max($maxfontsize,$actfs);
  4330. }
  4331. /*-- END LISTS --*/
  4332. // when every text item checked i.e. $maxfontsize is set properly
  4333. $af = 0; // Above font
  4334. $bf = 0; // Below font
  4335. $mta = 0; // Maximum top-aligned
  4336. $mba = 0; // Maximum bottom-aligned
  4337. foreach ( $content as $k => $chunk )
  4338. {
  4339. if (isset($this->objectbuffer[$k])) {
  4340. $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
  4341. $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
  4342. if ($lhfixed && $oh > $def_fontsize) { $this->forceExactLineheight = false; }
  4343. if ($va == 'BS') { // (BASELINE default)
  4344. $af = max($af, ($oh - ($maxfontsize * (0.5 + $this->baselineC))));
  4345. }
  4346. else if ($va == 'M') {
  4347. $af = max($af, ($oh - $maxfontsize)/2);
  4348. $bf = max($bf, ($oh - $maxfontsize)/2);
  4349. }
  4350. else if ($va == 'TT') {
  4351. $bf = max($bf, ($oh - $maxfontsize));
  4352. }
  4353. else if ($va == 'TB') {
  4354. $af = max($af, ($oh - $maxfontsize));
  4355. }
  4356. else if ($va == 'T') {
  4357. $mta = max($mta, $oh);
  4358. }
  4359. else if ($va == 'B') {
  4360. $mba = max($mba, $oh);
  4361. }
  4362. }
  4363. }
  4364. if ((!$lhfixed || !$this->forceExactLineheight) && ($af > (($maxlineHeight - $maxfontsize)/2) || $bf > (($maxlineHeight - $maxfontsize)/2))) {
  4365. $maxlineHeight = $maxfontsize + $af + $bf;
  4366. }
  4367. else if (!$lhfixed) { $af = $bf = ($maxlineHeight - $maxfontsize)/2; }
  4368. if ($mta > $maxlineHeight) {
  4369. $bf += ($mta - $maxlineHeight);
  4370. $maxlineHeight = $mta;
  4371. }
  4372. if ($mba > $maxlineHeight) {
  4373. $af += ($mba - $maxlineHeight);
  4374. $maxlineHeight = $mba;
  4375. }
  4376. $lineHeight = $maxlineHeight;
  4377. // If NOT images, and maxfontsize NOT > lineHeight - this value determines text baseline positioning
  4378. if ($lhfixed && $af==0 && $bf==0 && $maxfontsize<=($def_fontsize * $this->lineheight_correction * 0.8 )) {
  4379. $this->linemaxfontsize = $def_fontsize;
  4380. }
  4381. else { $this->linemaxfontsize = $maxfontsize; }
  4382. // Get PAGEBREAK TO TEST for height including the bottom border/padding
  4383. $check_h = max($this->divheight,$lineHeight);
  4384. // This fixes a proven bug...
  4385. if ($endofblock && $newblock && $blockstate==0 && !$content) { $check_h = 0; }
  4386. // but ? needs to fix potentially more widespread...
  4387. // if (!$content) { $check_h = 0; }
  4388. if ($this->blklvl > 0 && !$is_table) {
  4389. if ($endofblock && $blockstate > 1) {
  4390. if ($this->blk[$this->blklvl]['page_break_after_avoid']) { $check_h += $lineHeight; }
  4391. $check_h += ($this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']);
  4392. }
  4393. // mPDF 5.4.03
  4394. if (($newblock && ($blockstate==1 || $blockstate==3) && $lineCount == 0) || ($endofblock && $blockstate ==3 && $lineCount == 0)) {
  4395. $check_h += ($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['border_top']['w']);
  4396. }
  4397. }
  4398. // Force PAGE break if column height cannot take check-height
  4399. if ($this->ColActive && $check_h > ($this->PageBreakTrigger - $this->y0)) {
  4400. $this->SetCol($this->NbCol-1);
  4401. }
  4402. // mPDF 5.4.04
  4403. // Avoid just border/background-color moved on to next page
  4404. if ($endofblock && $blockstate > 1 && !$content) { $buff = $this->margBuffer; }
  4405. else { $buff = 0; }
  4406. // PAGEBREAK
  4407. // mPDF 5.4.04
  4408. if(!$is_table && ($this->y+$check_h) > ($this->PageBreakTrigger + $buff) and !$this->InFooter and $this->AcceptPageBreak()) {
  4409. $bak_x=$this->x;//Current X position
  4410. // WORD SPACING
  4411. $ws=$this->ws;//Word Spacing
  4412. $charspacing=$this->charspacing;//Character Spacing
  4413. $this->ResetSpacing();
  4414. $this->AddPage($this->CurOrientation);
  4415. $this->x=$bak_x;
  4416. // Added to correct for OddEven Margins
  4417. $currentx += $this->MarginCorrection;
  4418. $this->x += $this->MarginCorrection;
  4419. // WORD SPACING
  4420. $this->SetSpacing($charspacing,$ws);
  4421. }
  4422. if ($this->keep_block_together && !$is_table && $this->kt_p00 < $this->page && ($this->y+$check_h) > $this->kt_y00) {
  4423. $this->printdivbuffer();
  4424. $this->keep_block_together = 0;
  4425. }
  4426. /*-- COLUMNS --*/
  4427. // COLS
  4428. // COLUMN CHANGE
  4429. if ($this->CurrCol != $oldcolumn) {
  4430. $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
  4431. $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
  4432. $oldcolumn = $this->CurrCol;
  4433. }
  4434. if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; }
  4435. /*-- END COLUMNS --*/
  4436. // TOP MARGIN
  4437. if ($newblock && ($blockstate==1 || $blockstate==3) && ($this->blk[$this->blklvl]['margin_top']) && $lineCount == 0 && !$is_table && !$is_list) {
  4438. $this->DivLn($this->blk[$this->blklvl]['margin_top'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
  4439. if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  4440. }
  4441. if ($newblock && ($blockstate==1 || $blockstate==3) && $lineCount == 0 && !$is_table && !$is_list) {
  4442. $this->blk[$this->blklvl]['y0'] = $this->y;
  4443. $this->blk[$this->blklvl]['startpage'] = $this->page;
  4444. if ($this->blk[$this->blklvl]['float']) { $this->blk[$this->blklvl]['float_start_y'] = $this->y; } // mPDF 5.6.63
  4445. if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  4446. }
  4447. // ADDED for Paragraph_indent
  4448. $WidthCorrection = 0;
  4449. if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align != 'C')) {
  4450. $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
  4451. $WidthCorrection = ($ti*_MPDFK);
  4452. }
  4453. // PADDING and BORDER spacing/fill
  4454. if (($newblock) && ($blockstate==1 || $blockstate==3) && (($this->blk[$this->blklvl]['padding_top']) || ($this->blk[$this->blklvl]['border_top'])) && ($lineCount == 0) && (!$is_table) && (!$is_list)) {
  4455. // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
  4456. $this->DivLn($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'],-3,true,false,1);
  4457. if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  4458. $this->x = $currentx;
  4459. }
  4460. // Added mPDF 3.0 Float DIV
  4461. $fpaddingR = 0;
  4462. $fpaddingL = 0;
  4463. /*-- CSS-FLOAT --*/
  4464. if (count($this->floatDivs)) {
  4465. list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
  4466. if ($r_exists) { $fpaddingR = $r_width; }
  4467. if ($l_exists) { $fpaddingL = $l_width; }
  4468. }
  4469. /*-- END CSS-FLOAT --*/
  4470. $usey = $this->y + 0.002;
  4471. if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
  4472. $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
  4473. }
  4474. /*-- CSS-IMAGE-FLOAT --*/
  4475. // If float exists at this level
  4476. if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
  4477. if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
  4478. /*-- END CSS-IMAGE-FLOAT --*/
  4479. if ($content) {
  4480. // In FinishFlowing Block no lines are justified as it is always last line
  4481. // but if CJKorphan has allowed content width to go over max width, use J charspacing to compress line
  4482. // JUSTIFICATION J - NOT!
  4483. $nb_carac = 0;
  4484. $nb_spaces = 0;
  4485. $jcharspacing = 0;
  4486. $jws = 0;
  4487. $inclCursive=false;
  4488. $dottab = false; // mPDF 5.6.19
  4489. foreach ( $content as $k => $chunk ) {
  4490. if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
  4491. if ($this->usingCoreFont) {
  4492. $chunk = str_replace(chr(160),chr(32),$chunk );
  4493. }
  4494. else {
  4495. $chunk = str_replace(chr(194).chr(160),chr(32),$chunk );
  4496. }
  4497. $nb_carac += mb_strlen( $chunk, $this->mb_enc );
  4498. $nb_spaces += mb_substr_count( $chunk,' ', $this->mb_enc );
  4499. if ($checkCursive) {
  4500. if (preg_match("/([".$this->pregRTLchars."])/u", $chunk)) { $inclCursive = true; } // *RTL*
  4501. if (preg_match("/([".$this->pregHIchars.$this->pregBNchars.$this->pregPAchars."])/u", $chunk)) { $inclCursive = true; } // *INDIC*
  4502. }
  4503. }
  4504. else if ($this->objectbuffer[$k]['type']=='dottab') { $dottab = $this->objectbuffer[$k]['outdent']; } // mPDF 5.6.19
  4505. }
  4506. // if it's justified, we need to find the char/word spacing (or if orphans have allowed length of line to go over the maxwidth)
  4507. // If "orphans" in fact is just a final space - ignore this
  4508. // mPDF 5.6.40
  4509. $lastchar = mb_substr($content[(count($content)-1)],mb_strlen($content[(count($content)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
  4510. if (preg_match("/[".$this->CJKoverflow."]/u", $lastchar)) { $CJKoverflow = true; }
  4511. else {$CJKoverflow = false; }
  4512. if ((((($contentWidth + $lastitalic) > $maxWidth) && ($content[count($content)-1] != ' ') ) ||
  4513. (!$endofblock && $align=='J' && ($next=='image' || $next=='select' || $next=='input' || $next=='textarea' || ($next=='br' && $this->justifyB4br)))) && !($CJKoverflow && $this->allowCJKoverflow) ) { // mPDF 5.6.40
  4514. // WORD SPACING
  4515. list($jcharspacing,$jws) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$contentWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive);
  4516. }
  4517. /*-- CJK-FONTS --*/
  4518. // mPDF 5.6.40
  4519. else if ($this->checkCJK && $align=='J' && $CJKoverflow && $this->allowCJKoverflow && $this->CJKforceend) {
  4520. // force-end overhang
  4521. $hanger = mb_substr($content[count($content)-1],mb_strlen($content[count($content)-1],$this->mb_enc)-1,1,$this->mb_enc );
  4522. if (preg_match("/[".$this->CJKoverflow."]/u", $hanger)) {
  4523. $content[count($content)-1] = mb_substr($content[count($content)-1],0,mb_strlen($content[count($content)-1],$this->mb_enc)-1,$this->mb_enc );
  4524. $this->restoreFont( $font[ count($content)-1 ],false );
  4525. $contentWidth -= $this->GetStringWidth($hanger) * _MPDFK;
  4526. $nb_carac -= 1;
  4527. list($jcharspacing,$jws) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$contentWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive);
  4528. }
  4529. }
  4530. /*-- END CJK-FONTS --*/
  4531. // Check if will fit at word/char spacing of previous line - if so continue it
  4532. // but only allow a maximum of $this->jSmaxWordLast and $this->jSmaxCharLast
  4533. else if ($contentWidth < ($maxWidth - $lastitalic-$WidthCorrection - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK))) && !$this->fixedlSpacing) {
  4534. if ($this->ws > $this->jSmaxWordLast) {
  4535. $jws = $this->jSmaxWordLast;
  4536. }
  4537. if ($this->charspacing > $this->jSmaxCharLast) {
  4538. $jcharspacing = $this->jSmaxCharLast;
  4539. }
  4540. $check = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) - ( $jcharspacing * $nb_carac) - ( $jws * $nb_spaces);
  4541. if ($check <= 0) {
  4542. $jcharspacing = 0;
  4543. $jws = 0;
  4544. }
  4545. }
  4546. $empty = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
  4547. $empty -= ($jcharspacing * $nb_carac);
  4548. $empty -= ($jws * $nb_spaces);
  4549. $empty /= _MPDFK;
  4550. if (!$is_table) {
  4551. $this->maxPosR = max($this->maxPosR , ($this->w - $this->rMargin - $this->blk[$this->blklvl]['outer_right_margin'] - $empty));
  4552. $this->maxPosL = min($this->maxPosL , ($this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $empty));
  4553. }
  4554. $arraysize = count($content);
  4555. $margins = ($this->cMarginL+$this->cMarginR) + ($ipaddingL+$ipaddingR + $fpaddingR + $fpaddingR );
  4556. if (!$is_table) { $this->DivLn($lineHeight,$this->blklvl,false); } // false -> don't advance y
  4557. // DIRECTIONALITY RTL
  4558. $all_rtl = false;
  4559. $contains_rtl = false;
  4560. /*-- RTL --*/
  4561. if ($blockdir == 'rtl' || $this->biDirectional) {
  4562. $all_rtl = true;
  4563. foreach ( $content as $k => $chunk ) {
  4564. $reversed = $this->magic_reverse_dir($chunk, false, $blockdir);
  4565. if ($reversed > 0) { $contains_rtl = true; }
  4566. if ($reversed < 2) { $all_rtl = false; }
  4567. $content[$k] = $chunk;
  4568. }
  4569. if (($blockdir =='rtl' && $contains_rtl) || $all_rtl) {
  4570. $content = array_reverse($content,false);
  4571. $contentB = array_reverse($contentB,false);
  4572. }
  4573. }
  4574. /*-- END RTL --*/
  4575. $this->x = $currentx + $this->cMarginL + $ipaddingL + $fpaddingL;
  4576. if ($dottab !== false && $blockdir=='rtl') { $this->x -= $dottab; } // mPDF 5.6.19
  4577. else if ($align == 'R') { $this->x += $empty; }
  4578. else if ($align == 'J' && $blockdir == 'rtl') { $this->x += $empty; }
  4579. else if ($align == 'C') { $this->x += ($empty / 2); }
  4580. // Paragraph INDENT
  4581. $WidthCorrection = 0;
  4582. if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align !='C')) {
  4583. $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
  4584. $this->x += $ti;
  4585. }
  4586. foreach ( $content as $k => $chunk )
  4587. {
  4588. // FOR IMAGES
  4589. if ((($blockdir == 'rtl') && ($contains_rtl )) || $all_rtl ) { $dirk = $arraysize-1 - $k; } else { $dirk = $k; }
  4590. $va = 'M'; // default for text
  4591. if (isset($this->objectbuffer[$dirk]) && $this->objectbuffer[$dirk]) {
  4592. $xadj = $this->x - $this->objectbuffer[$dirk]['OUTER-X'];
  4593. $this->objectbuffer[$dirk]['OUTER-X'] += $xadj;
  4594. $this->objectbuffer[$dirk]['BORDER-X'] += $xadj;
  4595. $this->objectbuffer[$dirk]['INNER-X'] += $xadj;
  4596. $va = $this->objectbuffer[$dirk]['vertical-align'];
  4597. $yadj = $this->y - $this->objectbuffer[$dirk]['OUTER-Y'];
  4598. if ($va == 'BS') {
  4599. $yadj += $af + ($this->linemaxfontsize * (0.5 + $this->baselineC)) - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
  4600. }
  4601. else if ($va == 'M' || $va == '') {
  4602. $yadj += $af + ($this->linemaxfontsize /2) - ($this->objectbuffer[$dirk]['OUTER-HEIGHT']/2);
  4603. }
  4604. else if ($va == 'TB') {
  4605. $yadj += $af + $this->linemaxfontsize - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
  4606. }
  4607. else if ($va == 'TT') {
  4608. $yadj += $af;
  4609. }
  4610. else if ($va == 'B') {
  4611. $yadj += $af + $this->linemaxfontsize + $bf - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
  4612. }
  4613. else if ($va == 'T') {
  4614. $yadj += 0;
  4615. }
  4616. $this->objectbuffer[$dirk]['OUTER-Y'] += $yadj;
  4617. $this->objectbuffer[$dirk]['BORDER-Y'] += $yadj;
  4618. $this->objectbuffer[$dirk]['INNER-Y'] += $yadj;
  4619. }
  4620. // DIRECTIONALITY RTL
  4621. if ((($blockdir == 'rtl') && ($contains_rtl )) || $all_rtl ) { $this->restoreFont( $font[ $arraysize-1 - $k ] ); }
  4622. else { $this->restoreFont( $font[ $k ] ); }
  4623. // mPDF 5.6.13 Decimal alignment - set in _tableWrite
  4624. if ($is_table && substr($align,0,1)=='D' && $k==0 ) {
  4625. $dp = $this->decimal_align[substr($align,0,2)];
  4626. $s = preg_split('/'.preg_quote($dp,'/').'/', $content[0], 2); // ? needs to be /u if not core
  4627. $s0 = $this->GetStringWidth($s[0], false);
  4628. $this->x += ($this->decimal_offset - $s0);
  4629. }
  4630. $this->SetSpacing(($this->fixedlSpacing*_MPDFK)+$jcharspacing,($this->fixedlSpacing+$this->minwSpacing)*_MPDFK+$jws);
  4631. $this->fixedlSpacing = false;
  4632. $this->minwSpacing = 0;
  4633. // mPDF 5.6.26
  4634. $save_vis = $this->visibility;
  4635. if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->textparam['visibility'] != $this->visibility) {
  4636. $this->SetVisibility($this->textparam['visibility']);
  4637. }
  4638. // *********** SPAN BACKGROUND COLOR ***************** //
  4639. if (isset($this->spanbgcolor) && $this->spanbgcolor) {
  4640. $cor = $this->spanbgcolorarray;
  4641. $this->SetFColor($cor);
  4642. $save_fill = $fill; $spanfill = 1; $fill = 1;
  4643. }
  4644. if (!empty($this->spanborddet)) {
  4645. if (strpos($contentB[$k],'L')!==false && isset($this->spanborddet['L'])) $this->x += $this->spanborddet['L']['w'];
  4646. if (strpos($contentB[$k],'L')===false) $this->spanborddet['L']['s'] = $this->spanborddet['L']['w'] = 0;
  4647. if (strpos($contentB[$k],'R')===false) $this->spanborddet['R']['s'] = $this->spanborddet['R']['w'] = 0;
  4648. }
  4649. // WORD SPACING
  4650. $stringWidth = $this->GetStringWidth($chunk ) + ( $this->charspacing * mb_strlen($chunk,$this->mb_enc ) / _MPDFK )
  4651. + ( $this->ws * mb_substr_count($chunk,' ',$this->mb_enc ) / _MPDFK );
  4652. if (isset($this->objectbuffer[$dirk])) {
  4653. if ($this->objectbuffer[$dirk]['type']=='dottab') {
  4654. $this->objectbuffer[$dirk]['OUTER-WIDTH'] +=$empty;
  4655. $this->objectbuffer[$dirk]['OUTER-WIDTH'] +=$this->objectbuffer[$dirk]['outdent']; // mPDF 5.6.19
  4656. }
  4657. $stringWidth = $this->objectbuffer[$dirk]['OUTER-WIDTH'];
  4658. }
  4659. if ($stringWidth==0) { $stringWidth = 0.000001; }
  4660. if ($k == $arraysize-1) {
  4661. // mPDF 5.6.40
  4662. if ($this->checkCJK && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) {
  4663. // force-end overhang
  4664. $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
  4665. $this->Cell( $this->GetStringWidth($hanger), $lineHeight, $hanger, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
  4666. }
  4667. else {
  4668. $this->Cell( $stringWidth, $lineHeight, $chunk, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
  4669. }
  4670. }
  4671. else $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, 0, 0,0,'M', $fill, $af, $bf, true );//first or middle part
  4672. if (!empty($this->spanborddet)) {
  4673. if (strpos($contentB[$k],'R')!==false && $k != $arraysize-1) $this->x += $this->spanborddet['R']['w'];
  4674. }
  4675. // *********** SPAN BACKGROUND COLOR OFF - RESET BLOCK BGCOLOR ***************** //
  4676. if (isset($spanfill) && $spanfill) {
  4677. $fill = $save_fill; $spanfill = 0;
  4678. if ($fill) { $this->SetFColor($bcor); }
  4679. }
  4680. // mPDF 5.6.26
  4681. if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->visibility != $save_vis) {
  4682. $this->SetVisibility($save_vis);
  4683. }
  4684. }
  4685. $this->printobjectbuffer($is_table, $blockdir);
  4686. $this->objectbuffer = array();
  4687. $this->ResetSpacing();
  4688. /*-- LISTS --*/
  4689. // LIST BULLETS/NUMBERS
  4690. if ($is_list && is_array($this->bulletarray) && ($lineCount == 0) ) {
  4691. $savedFont = $this->saveFont();
  4692. $bull = $this->bulletarray;
  4693. if (isset($bull['level']) && isset($bull['occur']) && isset($this->InlineProperties['LIST'][$bull['level']][$bull['occur']])) {
  4694. $this->restoreInlineProperties($this->InlineProperties['LIST'][$bull['level']][$bull['occur']]);
  4695. }
  4696. if (isset($bull['level']) && isset($bull['occur']) && isset($bull['num']) && isset($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) && $this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) { $this->restoreInlineProperties($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]); }
  4697. if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
  4698. $this->bullet = true;
  4699. $this->SetFont('czapfdingbats','',$this->FontSizePt/2.5);
  4700. }
  4701. else { $this->SetFont($this->FontFamily,$this->FontStyle,$this->FontSizePt,true,true); } // force output
  4702. //Output bullet
  4703. $this->x = $currentx;
  4704. if (isset($bull['x'])) { $this->x += $bull['x']; }
  4705. $this->y -= $lineHeight;
  4706. if (isset($bull['col']) && $bull['col']) { $this->SetTColor($bull['col']); } // mPDF 5.6.67
  4707. if (isset($bull['txt'])) { $this->Cell($bull['w'], $lineHeight,$bull['txt'],'','',$bull['align'],0,'',0,-$this->cMarginL, -$this->cMarginR ); }
  4708. if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
  4709. $this->bullet = false;
  4710. }
  4711. $this->x = $currentx; // Reset
  4712. $this->y += $lineHeight;
  4713. if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  4714. $this->restoreFont( $savedFont );
  4715. // $font = array( $savedFont );
  4716. $this->bulletarray = array(); // prevents repeat of bullet/number if <li>....<br />.....</li>
  4717. }
  4718. /*-- END LISTS --*/
  4719. } // END IF CONTENT
  4720. /*-- CSS-IMAGE-FLOAT --*/
  4721. // Update values if set to skipline
  4722. if ($this->floatmargins) { $this->_advanceFloatMargins(); }
  4723. if ($endofblock && $blockstate>1) {
  4724. // If float exists at this level
  4725. if (isset($this->floatmargins['R']['y1'])) { $fry1 = $this->floatmargins['R']['y1']; }
  4726. else { $fry1 = 0; }
  4727. if (isset($this->floatmargins['L']['y1'])) { $fly1 = $this->floatmargins['L']['y1']; }
  4728. else { $fly1 = 0; }
  4729. if ($this->y < $fry1 || $this->y < $fly1) {
  4730. $drop = max($fry1,$fly1) - $this->y;
  4731. $this->DivLn($drop);
  4732. $this->x = $currentx;
  4733. }
  4734. }
  4735. /*-- END CSS-IMAGE-FLOAT --*/
  4736. // PADDING and BORDER spacing/fill
  4737. if ($endofblock && ($blockstate > 1) && ($this->blk[$this->blklvl]['padding_bottom'] || $this->blk[$this->blklvl]['border_bottom'] || $this->blk[$this->blklvl]['css_set_height']) && (!$is_table) && (!$is_list)) {
  4738. // If CSS height set, extend bottom - if on same page as block started, and CSS HEIGHT > actual height,
  4739. // and does not force pagebreak
  4740. $extra = 0;
  4741. if ($this->blk[$this->blklvl]['css_set_height'] && $this->blk[$this->blklvl]['startpage']==$this->page) {
  4742. // predicted height
  4743. $h1 = ($this->y-$this->blk[$this->blklvl]['y0']) + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'];
  4744. if ($h1 < ($this->blk[$this->blklvl]['css_set_height']+$this->blk[$this->blklvl]['padding_bottom']+$this->blk[$this->blklvl]['padding_top'])) { $extra = ($this->blk[$this->blklvl]['css_set_height']+$this->blk[$this->blklvl]['padding_bottom']+$this->blk[$this->blklvl]['padding_top']) - $h1; }
  4745. if($this->y + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $extra > $this->PageBreakTrigger) {
  4746. $extra = $this->PageBreakTrigger - ($this->y + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']);
  4747. }
  4748. }
  4749. // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
  4750. $this->DivLn($this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $extra,-3,true,false,2);
  4751. $this->x = $currentx;
  4752. if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  4753. }
  4754. // SET Bottom y1 of block (used for painting borders)
  4755. if (($endofblock) && ($blockstate > 1) && (!$is_table) && (!$is_list)) {
  4756. $this->blk[$this->blklvl]['y1'] = $this->y;
  4757. }
  4758. // BOTTOM MARGIN
  4759. if (($endofblock) && ($blockstate > 1) && ($this->blk[$this->blklvl]['margin_bottom']) && (!$is_table) && (!$is_list)) {
  4760. if($this->y+$this->blk[$this->blklvl]['margin_bottom'] < $this->PageBreakTrigger and !$this->InFooter) {
  4761. $this->DivLn($this->blk[$this->blklvl]['margin_bottom'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
  4762. if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  4763. }
  4764. }
  4765. // Reset lineheight
  4766. $lineHeight = $this->divheight;
  4767. }
  4768. function printobjectbuffer($is_table=false, $blockdir=false) {
  4769. if (!$blockdir) { $blockdir = $this->directionality; }
  4770. if ($is_table && $this->shrin_k > 1) { $k = $this->shrin_k; }
  4771. else { $k = 1; }
  4772. $save_y = $this->y;
  4773. $save_x = $this->x;
  4774. $save_currentfontfamily = $this->FontFamily;
  4775. $save_currentfontsize = $this->FontSizePt;
  4776. $save_currentfontstyle = $this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
  4777. if ($blockdir == 'rtl') { $rtlalign = 'R'; } else { $rtlalign = 'L'; }
  4778. foreach ($this->objectbuffer AS $ib => $objattr) {
  4779. if ($objattr['type'] == 'bookmark' || $objattr['type'] == 'indexentry' || $objattr['type'] == 'toc') {
  4780. $x = $objattr['OUTER-X'];
  4781. $y = $objattr['OUTER-Y'];
  4782. $this->y = $y - $this->FontSize/2;
  4783. $this->x = $x;
  4784. if ($objattr['type'] == 'bookmark' ) { $this->Bookmark($objattr['CONTENT'],$objattr['bklevel'] ,$y - $this->FontSize); } // *BOOKMARKS*
  4785. if ($objattr['type'] == 'indexentry') { $this->IndexEntry($objattr['CONTENT']); } // *INDEX*
  4786. if ($objattr['type'] == 'toc') { $this->TOC_Entry($objattr['CONTENT'], $objattr['toclevel'], $objattr['toc_id']); } // *TOC*
  4787. }
  4788. /*-- ANNOTATIONS --*/
  4789. else if ($objattr['type'] == 'annot') {
  4790. if ($objattr['POS-X']) { $x = $objattr['POS-X']; }
  4791. else if ($this->annotMargin<>0) { $x = -$objattr['OUTER-X']; }
  4792. else { $x = $objattr['OUTER-X']; }
  4793. if ($objattr['POS-Y']) { $y = $objattr['POS-Y']; }
  4794. else { $y = $objattr['OUTER-Y'] - $this->FontSize/2; }
  4795. // Create a dummy entry in the _out/columnBuffer with position sensitive data,
  4796. // linking $y-1 in the Columnbuffer with entry in $this->columnAnnots
  4797. // and when columns are split in length will not break annotation from current line
  4798. $this->y = $y-1;
  4799. $this->x = $x-1;
  4800. $this->Line($x-1,$y-1,$x-1,$y-1);
  4801. $this->Annotation($objattr['CONTENT'], $x , $y , $objattr['ICON'], $objattr['AUTHOR'], $objattr['SUBJECT'], $objattr['OPACITY'], $objattr['COLOR'], $objattr['POPUP'], $objattr['FILE']);
  4802. }
  4803. /*-- END ANNOTATIONS --*/
  4804. else {
  4805. $y = $objattr['OUTER-Y'];
  4806. $x = $objattr['OUTER-X'];
  4807. $w = $objattr['OUTER-WIDTH'];
  4808. $h = $objattr['OUTER-HEIGHT'];
  4809. if (isset($objattr['text'])) { $texto = $objattr['text']; }
  4810. $this->y = $y;
  4811. $this->x = $x;
  4812. if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],'',$objattr['fontsize'] ); }
  4813. }
  4814. // HR
  4815. if ($objattr['type'] == 'hr') {
  4816. $this->SetDColor($objattr['color']);
  4817. switch($objattr['align']) {
  4818. case 'C':
  4819. $empty = $objattr['OUTER-WIDTH'] - $objattr['INNER-WIDTH'];
  4820. $empty /= 2;
  4821. $x += $empty;
  4822. break;
  4823. case 'R':
  4824. $empty = $objattr['OUTER-WIDTH'] - $objattr['INNER-WIDTH'];
  4825. $x += $empty;
  4826. break;
  4827. }
  4828. $oldlinewidth = $this->LineWidth;
  4829. $this->SetLineWidth($objattr['linewidth']/$k );
  4830. $this->y += ($objattr['linewidth']/2) + $objattr['margin_top']/$k;
  4831. $this->Line($x,$this->y,$x+$objattr['INNER-WIDTH'],$this->y);
  4832. $this->SetLineWidth($oldlinewidth);
  4833. $this->SetDColor($this->ConvertColor(0));
  4834. }
  4835. // IMAGE
  4836. if ($objattr['type'] == 'image') {
  4837. // mPDF 5.6.01 - LAYERS
  4838. if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->currentlayer==0) {
  4839. $this->BeginLayer($objattr['z-index']);
  4840. }
  4841. if(isset($objattr['visibility']) && $objattr['visibility']!='visible' && $objattr['visibility']) {
  4842. $this->SetVisibility($objattr['visibility']);
  4843. }
  4844. if (isset($objattr['opacity'])) { $this->SetAlpha($objattr['opacity']); }
  4845. $rotate = 0;
  4846. $obiw = $objattr['INNER-WIDTH'];
  4847. $obih = $objattr['INNER-HEIGHT'];
  4848. $sx = $objattr['INNER-WIDTH']*_MPDFK / $objattr['orig_w'];
  4849. $sy = abs($objattr['INNER-HEIGHT'])*_MPDFK / abs($objattr['orig_h']);
  4850. $sx = ($objattr['INNER-WIDTH']*_MPDFK / $objattr['orig_w']);
  4851. $sy = ($objattr['INNER-HEIGHT']*_MPDFK / $objattr['orig_h']);
  4852. if (isset($objattr['ROTATE'])) { $rotate = $objattr['ROTATE']; }
  4853. if ($rotate==90) {
  4854. // Clockwise
  4855. $obiw = $objattr['INNER-HEIGHT'];
  4856. $obih = $objattr['INNER-WIDTH'];
  4857. $tr = $this->transformTranslate(0, -$objattr['INNER-WIDTH'], true) ;
  4858. $tr .= ' '. $this->transformRotate(90, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-WIDTH'] ),true) ;
  4859. $sx = $obiw*_MPDFK / $objattr['orig_h'];
  4860. $sy = $obih*_MPDFK / $objattr['orig_w'];
  4861. }
  4862. else if ($rotate==-90 || $rotate==270) {
  4863. // AntiClockwise
  4864. $obiw = $objattr['INNER-HEIGHT'];
  4865. $obih = $objattr['INNER-WIDTH'];
  4866. $tr = $this->transformTranslate($objattr['INNER-WIDTH'], ($objattr['INNER-HEIGHT']-$objattr['INNER-WIDTH']), true) ;
  4867. $tr .= ' '. $this->transformRotate(-90, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-WIDTH'] ),true) ;
  4868. $sx = $obiw*_MPDFK / $objattr['orig_h'];
  4869. $sy = $obih*_MPDFK / $objattr['orig_w'];
  4870. }
  4871. else if ($rotate==180) {
  4872. // Mirror
  4873. $tr = $this->transformTranslate($objattr['INNER-WIDTH'], -$objattr['INNER-HEIGHT'], true) ;
  4874. $tr .= ' '. $this->transformRotate(180, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-HEIGHT'] ),true) ;
  4875. }
  4876. else { $tr = ''; }
  4877. $tr = trim($tr);
  4878. if ($tr) { $tr .= ' '; }
  4879. $gradmask = '';
  4880. /*-- BACKGROUNDS --*/
  4881. if (isset($objattr['GRADIENT-MASK'])) {
  4882. $g = $this->grad->parseMozGradient( $objattr['GRADIENT-MASK'] );
  4883. if ($g) {
  4884. $dummy = $this->grad->Gradient($objattr['INNER-X'], $objattr['INNER-Y'], $obiw, $obih, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true, true);
  4885. $gradmask = '/TGS'.count($this->gradients).' gs ';
  4886. // $this->_out("q ".$tr.$this->grad->Gradient($objattr['INNER-X'], $objattr['INNER-Y'], $obiw, $obih, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true)." Q");
  4887. }
  4888. }
  4889. /*-- END BACKGROUNDS --*/
  4890. /*-- IMAGES-WMF --*/
  4891. if (isset($objattr['itype']) && $objattr['itype']=='wmf') {
  4892. $outstring = sprintf('q '.$tr.'%.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, -$sy, $objattr['INNER-X']*_MPDFK-$sx*$objattr['wmf_x'], (($this->h-$objattr['INNER-Y'])*_MPDFK)+$sy*$objattr['wmf_y'], $objattr['ID']);
  4893. }
  4894. else
  4895. /*-- END IMAGES-WMF --*/
  4896. if (isset($objattr['itype']) && $objattr['itype']=='svg') {
  4897. $outstring = sprintf('q '.$tr.'%.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, -$sy, $objattr['INNER-X']*_MPDFK-$sx*$objattr['wmf_x'], (($this->h-$objattr['INNER-Y'])*_MPDFK)+$sy*$objattr['wmf_y'], $objattr['ID']);
  4898. }
  4899. else {
  4900. $outstring = sprintf("q ".$tr."%.3F 0 0 %.3F %.3F %.3F cm ".$gradmask."/I%d Do Q",$obiw*_MPDFK, $obih*_MPDFK, $objattr['INNER-X'] *_MPDFK, ($this->h-($objattr['INNER-Y'] +$obih ))*_MPDFK,$objattr['ID'] );
  4901. }
  4902. $this->_out($outstring);
  4903. // LINK
  4904. if (isset($objattr['link'])) $this->Link($objattr['INNER-X'],$objattr['INNER-Y'],$objattr['INNER-WIDTH'],$objattr['INNER-HEIGHT'],$objattr['link']);
  4905. if (isset($objattr['opacity'])) { $this->SetAlpha(1); }
  4906. if ((isset($objattr['border_top']) && $objattr['border_top']>0) || (isset($objattr['border_left']) && $objattr['border_left']>0) || (isset($objattr['border_right']) && $objattr['border_right']>0) || (isset($objattr['border_bottom']) && $objattr['border_bottom']>0)) { $this->PaintImgBorder($objattr,$is_table); }
  4907. if(isset($objattr['visibility']) && $objattr['visibility']!='visible' && $objattr['visibility']) {
  4908. $this->SetVisibility('visible');
  4909. }
  4910. // mPDF 5.6.01 - LAYERS
  4911. if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->currentlayer==0) {
  4912. $this->EndLayer();
  4913. }
  4914. }
  4915. /*-- BARCODES --*/
  4916. // BARCODE
  4917. if ($objattr['type'] == 'barcode') {
  4918. $bgcol = $this->ConvertColor(255);
  4919. if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
  4920. $bgcol = $objattr['bgcolor'];
  4921. }
  4922. $col = $this->ConvertColor(0);
  4923. if (isset($objattr['color']) && $objattr['color']) {
  4924. $col = $objattr['color'];
  4925. }
  4926. $this->SetFColor($bgcol);
  4927. $this->Rect($objattr['BORDER-X'], $objattr['BORDER-Y'], $objattr['BORDER-WIDTH'], $objattr['BORDER-HEIGHT'], 'F');
  4928. $this->SetFColor($this->ConvertColor(255));
  4929. if (isset($objattr['BORDER-WIDTH'])) { $this->PaintImgBorder($objattr,$is_table); }
  4930. if ($objattr['btype'] == 'EAN13' || $objattr['btype'] == 'ISBN' || $objattr['btype'] == 'ISSN' || $objattr['btype'] == 'UPCA' || $objattr['btype'] == 'UPCE' || $objattr['btype'] == 'EAN8') {
  4931. $this->WriteBarcode($objattr['code'], $objattr['showtext'], $objattr['INNER-X'], $objattr['INNER-Y'], $objattr['bsize'], 0, 0, 0, 0, 0, $objattr['bheight'], $bgcol, $col, $objattr['btype'], $objattr['bsupp'], $objattr['bsupp_code'], $k);
  4932. }
  4933. // QR-code
  4934. else if ($objattr['btype']=='QR') {
  4935. if (!class_exists('QRcode', false)) {
  4936. include(_MPDF_PATH.'qrcode/qrcode.class.php');
  4937. }
  4938. $this->qrcode = new QRcode($objattr['code'], $objattr['errorlevel']);
  4939. $this->qrcode->displayFPDF($this, $objattr['INNER-X'], $objattr['INNER-Y'], $objattr['bsize']*25, array(255,255,255), array(0,0,0));
  4940. }
  4941. else {
  4942. $this->WriteBarcode2($objattr['code'], $objattr['INNER-X'], $objattr['INNER-Y'], $objattr['bsize'], $objattr['bheight'], $bgcol, $col, $objattr['btype'], $objattr['pr_ratio'], $k);
  4943. }
  4944. }
  4945. /*-- END BARCODES --*/
  4946. // TEXT CIRCLE
  4947. if ($objattr['type'] == 'textcircle') {
  4948. $bgcol = ''; // mPDF 5.5.14
  4949. if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
  4950. $bgcol = $objattr['bgcolor'];
  4951. }
  4952. $col = $this->ConvertColor(0);
  4953. if (isset($objattr['color']) && $objattr['color']) {
  4954. $col = $objattr['color'];
  4955. }
  4956. $this->SetTColor($col);
  4957. $this->SetFColor($bgcol);
  4958. if ($bgcol) $this->Rect($objattr['BORDER-X'], $objattr['BORDER-Y'], $objattr['BORDER-WIDTH'], $objattr['BORDER-HEIGHT'], 'F'); // mPDF 5.5.14
  4959. $this->SetFColor($this->ConvertColor(255));
  4960. if (isset($objattr['BORDER-WIDTH'])) { $this->PaintImgBorder($objattr,$is_table); }
  4961. if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
  4962. if (empty($this->directw)) { $this->directw = new directw($this); }
  4963. $save_lmfs = $this->linemaxfontsize;
  4964. $this->linemaxfontsize = 0;
  4965. if (isset($objattr['top-text'])) {
  4966. $this->directw->CircularText($objattr['INNER-X']+$objattr['INNER-WIDTH']/2, $objattr['INNER-Y']+$objattr['INNER-HEIGHT']/2, $objattr['r']/$k, $objattr['top-text'], 'top', $objattr['fontfamily'], $objattr['fontsize']/$k, $objattr['fontstyle'], $objattr['space-width'], $objattr['char-width'], $objattr['divider']); // mPDF 5.5.23
  4967. }
  4968. if (isset($objattr['bottom-text'])) {
  4969. $this->directw->CircularText($objattr['INNER-X']+$objattr['INNER-WIDTH']/2, $objattr['INNER-Y']+$objattr['INNER-HEIGHT']/2, $objattr['r']/$k, $objattr['bottom-text'], 'bottom', $objattr['fontfamily'], $objattr['fontsize']/$k, $objattr['fontstyle'], $objattr['space-width'], $objattr['char-width'], $objattr['divider']); // mPDF 5.5.23
  4970. }
  4971. $this->linemaxfontsize = $save_lmfs;
  4972. }
  4973. $this->ResetSpacing();
  4974. // DOT-TAB
  4975. if ($objattr['type'] == 'dottab') {
  4976. // mPDF 5.6.19
  4977. if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],'',$objattr['fontsize'] ); }
  4978. $sp = $this->GetStringWidth(' ');
  4979. $nb=floor(($w-2*$sp)/$this->GetStringWidth('.'));
  4980. if ($nb>0) { $dots=' '.str_repeat('.',$nb).' '; }
  4981. else { $dots=' '; }
  4982. $col = $this->ConvertColor(0);
  4983. if (isset($objattr['colorarray']) && ($objattr['colorarray'])) { // mPDF 5.6.19
  4984. $col = $objattr['colorarray'];
  4985. }
  4986. $this->SetTColor($col);
  4987. $save_dh = $this->divheight; // mPDF 5.6.19
  4988. $save_sbd = $this->spanborddet;
  4989. $save_u = $this->U;
  4990. $save_s = $this->strike;
  4991. $this->spanborddet = '';
  4992. $this->divheight = 0; // mPDF 5.6.19
  4993. $this->U = false;
  4994. $this->strike = false;
  4995. $this->Cell($w,$h,$dots,0,0,'C');
  4996. $this->spanborddet = $save_sbd;
  4997. $this->U = $save_u;
  4998. $this->strike = $save_s;
  4999. $this->divheight = $save_dh; // mPDF 5.6.19
  5000. // mPDF 5.0
  5001. $this->SetTColor($this->ConvertColor(0));
  5002. }
  5003. /*-- FORMS --*/
  5004. // TEXT/PASSWORD INPUT
  5005. if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'TEXT' || $objattr['subtype'] == 'PASSWORD')) {
  5006. $this->form->print_ob_text($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
  5007. }
  5008. // TEXTAREA
  5009. if ($objattr['type'] == 'textarea') {
  5010. $this->form->print_ob_textarea($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
  5011. }
  5012. // SELECT
  5013. if ($objattr['type'] == 'select') {
  5014. $this->form->print_ob_select($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
  5015. }
  5016. // INPUT/BUTTON as IMAGE
  5017. if ($objattr['type'] == 'input' && $objattr['subtype'] == 'IMAGE') {
  5018. $this->form->print_ob_imageinput($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
  5019. }
  5020. // BUTTON
  5021. if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'SUBMIT' || $objattr['subtype'] == 'RESET' || $objattr['subtype'] == 'BUTTON')) {
  5022. $this->form->print_ob_button($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
  5023. }
  5024. // CHECKBOX
  5025. if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'CHECKBOX')) {
  5026. $this->form->print_ob_checkbox($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir,$x,$y);
  5027. }
  5028. // RADIO
  5029. if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'RADIO')) {
  5030. $this->form->print_ob_radio($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir,$x,$y);
  5031. }
  5032. /*-- END FORMS --*/
  5033. }
  5034. $this->SetFont($save_currentfontfamily,$save_currentfontstyle,$save_currentfontsize);
  5035. $this->y = $save_y;
  5036. $this->x = $save_x;
  5037. unset($content);
  5038. }
  5039. function WriteFlowingBlock( $s)
  5040. {
  5041. $currentx = $this->x;
  5042. $is_table = $this->flowingBlockAttr[ 'is_table' ];
  5043. $is_list = $this->flowingBlockAttr[ 'is_list' ];
  5044. // width of all the content so far in points
  5045. $contentWidth =& $this->flowingBlockAttr[ 'contentWidth' ];
  5046. // cell width in points
  5047. $maxWidth =& $this->flowingBlockAttr[ 'width' ];
  5048. $lineCount =& $this->flowingBlockAttr[ 'lineCount' ];
  5049. // line height in user units
  5050. $lineHeight =& $this->flowingBlockAttr[ 'height' ];
  5051. $align =& $this->flowingBlockAttr[ 'align' ];
  5052. $content =& $this->flowingBlockAttr[ 'content' ];
  5053. $contentB =& $this->flowingBlockAttr[ 'contentB' ];
  5054. $font =& $this->flowingBlockAttr[ 'font' ];
  5055. $valign =& $this->flowingBlockAttr[ 'valign' ];
  5056. $blockstate = $this->flowingBlockAttr[ 'blockstate' ];
  5057. $newblock = $this->flowingBlockAttr[ 'newblock' ];
  5058. $blockdir = $this->flowingBlockAttr['blockdir'];
  5059. // *********** BLOCK BACKGROUND COLOR ***************** //
  5060. if ($this->blk[$this->blklvl]['bgcolor'] && !$is_table) {
  5061. $fill = 0;
  5062. }
  5063. else {
  5064. $this->SetFColor($this->ConvertColor(255));
  5065. $fill = 0;
  5066. }
  5067. $font[] = $this->saveFont();
  5068. $content[] = '';
  5069. $contentB[] = '';
  5070. $currContent =& $content[ count( $content ) - 1 ];
  5071. // where the line should be cutoff if it is to be justified
  5072. $cutoffWidth = $contentWidth;
  5073. $CJKoverflow = false;
  5074. $hanger = ''; // mPDF 5.6.40
  5075. // COLS
  5076. $oldcolumn = $this->CurrCol;
  5077. if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  5078. /*-- TABLES --*/
  5079. if ($is_table) {
  5080. $ipaddingL = 0;
  5081. $ipaddingR = 0;
  5082. $paddingL = 0;
  5083. $paddingR = 0;
  5084. $cpaddingadjustL = 0;
  5085. $cpaddingadjustR = 0;
  5086. // Added mPDF 3.0
  5087. $fpaddingR = 0;
  5088. $fpaddingL = 0;
  5089. }
  5090. else {
  5091. /*-- END TABLES --*/
  5092. $ipaddingL = $this->blk[$this->blklvl]['padding_left'];
  5093. $ipaddingR = $this->blk[$this->blklvl]['padding_right'];
  5094. $paddingL = ($ipaddingL * _MPDFK);
  5095. $paddingR = ($ipaddingR * _MPDFK);
  5096. $this->cMarginL = $this->blk[$this->blklvl]['border_left']['w'];
  5097. $cpaddingadjustL = -$this->cMarginL;
  5098. $this->cMarginR = $this->blk[$this->blklvl]['border_right']['w'];
  5099. $cpaddingadjustR = -$this->cMarginR;
  5100. // Added mPDF 3.0 Float DIV
  5101. $fpaddingR = 0;
  5102. $fpaddingL = 0;
  5103. /*-- CSS-FLOAT --*/
  5104. if (count($this->floatDivs)) {
  5105. list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
  5106. if ($r_exists) { $fpaddingR = $r_width; }
  5107. if ($l_exists) { $fpaddingL = $l_width; }
  5108. }
  5109. /*-- END CSS-FLOAT --*/
  5110. $usey = $this->y + 0.002;
  5111. if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
  5112. $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
  5113. }
  5114. /*-- CSS-IMAGE-FLOAT --*/
  5115. // If float exists at this level
  5116. if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
  5117. if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
  5118. /*-- END CSS-IMAGE-FLOAT --*/
  5119. } // *TABLES*
  5120. //OBJECTS - IMAGES & FORM Elements (NB has already skipped line/page if required - in printbuffer)
  5121. if (substr($s,0,3) == "\xbb\xa4\xac") { //identifier has been identified!
  5122. $objattr = $this->_getObjAttr($s);
  5123. $h_corr = 0;
  5124. if ($is_table) { // *TABLES*
  5125. $maximumW = ($maxWidth/_MPDFK) - ($this->cellPaddingL + $this->cMarginL + $this->cellPaddingR + $this->cMarginR); // *TABLES*
  5126. } // *TABLES*
  5127. else { // *TABLES*
  5128. if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) && (!$is_table)) { $h_corr = $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w']; }
  5129. $maximumW = ($maxWidth/_MPDFK) - ($this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_right'] + $this->blk[$this->blklvl]['border_right']['w'] + $fpaddingL + $fpaddingR );
  5130. } // *TABLES*
  5131. $objattr = $this->inlineObject($objattr['type'],$this->lMargin + $fpaddingL + ($contentWidth/_MPDFK),($this->y + $h_corr), $objattr, $this->lMargin,($contentWidth/_MPDFK),$maximumW,$lineHeight,true,$is_table);
  5132. // SET LINEHEIGHT for this line ================ RESET AT END
  5133. $lineHeight = MAX($lineHeight,$objattr['OUTER-HEIGHT']);
  5134. $this->objectbuffer[count($content)-1] = $objattr;
  5135. // if (isset($objattr['vertical-align'])) { $valign = $objattr['vertical-align']; }
  5136. // else { $valign = ''; }
  5137. $contentWidth += ($objattr['OUTER-WIDTH'] * _MPDFK);
  5138. return;
  5139. }
  5140. $lbw = $rbw = 0; // Border widths
  5141. if (!empty($this->spanborddet)) {
  5142. if (isset($this->spanborddet['L'])) $lbw = $this->spanborddet['L']['w'];
  5143. if (isset($this->spanborddet['R'])) $rbw = $this->spanborddet['R']['w'];
  5144. }
  5145. if ($this->usingCoreFont) {
  5146. $tmp = strlen( $s );
  5147. }
  5148. else {
  5149. $tmp = mb_strlen( $s, $this->mb_enc );
  5150. }
  5151. // for every character in the string
  5152. for ( $i = 0; $i < $tmp; $i++ ) {
  5153. // extract the current character
  5154. // get the width of the character in points
  5155. if ($this->usingCoreFont) {
  5156. $c = $s[$i];
  5157. // Soft Hyphens chr(173)
  5158. $cw = ($this->GetCharWidthCore($c) * _MPDFK);
  5159. if ($this->kerning && $this->useKerning && $i > 0) {
  5160. if (isset($this->CurrentFont['kerninfo'][$s[($i-1)]][$c])) {
  5161. $cw += ($this->CurrentFont['kerninfo'][$s[($i-1)]][$c] * $this->FontSizePt / 1000 );
  5162. }
  5163. }
  5164. }
  5165. else {
  5166. $c = mb_substr($s,$i,1,$this->mb_enc );
  5167. $cw = ($this->GetCharWidthNonCore($c, false) * _MPDFK);
  5168. if ($this->kerning && $this->useKerning && $i > 0) {
  5169. $lastc = mb_substr($s,($i-1),1,$this->mb_enc );
  5170. $ulastc = $this->UTF8StringToArray($lastc, false);
  5171. $uc = $this->UTF8StringToArray($c, false);
  5172. if (isset($this->CurrentFont['kerninfo'][$ulastc[0]][$uc[0]])) {
  5173. $cw += ($this->CurrentFont['kerninfo'][$ulastc[0]][$uc[0]] * $this->FontSizePt / 1000 );
  5174. }
  5175. }
  5176. }
  5177. if ($i==0) {
  5178. $cw += $lbw*_MPDFK;
  5179. $contentB[(count($contentB)-1)] .= 'L';
  5180. }
  5181. if ($i==($tmp-1)) {
  5182. $cw += $rbw*_MPDFK;
  5183. $contentB[(count($contentB)-1)] .= 'R';
  5184. }
  5185. // mPDF 5.6.45
  5186. if ($c==' ') {
  5187. $currContent .= $c;
  5188. $cutoffWidth = $contentWidth;
  5189. $contentWidth += $cw;
  5190. continue;
  5191. }
  5192. // ADDED for Paragraph_indent
  5193. $WidthCorrection = 0;
  5194. if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align != 'C')) {
  5195. $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
  5196. $WidthCorrection = ($ti*_MPDFK);
  5197. }
  5198. // Added mPDF 3.0 Float DIV
  5199. $fpaddingR = 0;
  5200. $fpaddingL = 0;
  5201. /*-- CSS-FLOAT --*/
  5202. if (count($this->floatDivs)) {
  5203. list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
  5204. if ($r_exists) { $fpaddingR = $r_width; }
  5205. if ($l_exists) { $fpaddingL = $l_width; }
  5206. }
  5207. /*-- END CSS-FLOAT --*/
  5208. $usey = $this->y + 0.002;
  5209. if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
  5210. $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
  5211. }
  5212. /*-- CSS-IMAGE-FLOAT --*/
  5213. // If float exists at this level
  5214. if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
  5215. if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
  5216. /*-- END CSS-IMAGE-FLOAT --*/
  5217. // try adding another char
  5218. if (( $contentWidth + $cw > $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) + 0.001)) {// 0.001 is to correct for deviations converting mm=>pts
  5219. // it won't fit, output what we already have
  5220. $lineCount++;
  5221. // contains any content that didn't make it into this print
  5222. $savedContent = '';
  5223. $savedContentB = '';
  5224. $savedFont = array();
  5225. $savedObj = array();
  5226. // mPDF 5.6.20
  5227. $savedPreContent = array();
  5228. $savedPreContentB = array();
  5229. $savedPreFont = array();
  5230. // cut off and save any partial words at the end of the string
  5231. $words = explode( ' ', $currContent );
  5232. ///////////////////
  5233. // HYPHENATION
  5234. $currWord = $words[count($words)-1] ;
  5235. $success = false;
  5236. // mPDF 5.6.21 Hard Hyphens -
  5237. $hardsuccess = false;
  5238. if ($this->textparam['hyphens'] != 2 && preg_match("/\-/",$currWord)) {
  5239. $rem = $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
  5240. list($hardsuccess,$pre,$post,$prelength) = $this->hardHyphenate($currWord, (($rem-$cutoffWidth)/_MPDFK -$this->GetCharWidth("-", false)) );
  5241. if ($hardsuccess) {
  5242. $already = array_pop( $words );
  5243. $forward = mb_substr($already,$prelength+1,mb_strlen($already, $this->mb_enc), $this->mb_enc);
  5244. $words[] = $pre.'-';
  5245. $words[] = $forward;
  5246. $currContent = mb_substr($currContent,0,mb_strlen($currContent, $this->mb_enc)+1-mb_strlen($post, $this->mb_enc), $this->mb_enc) . '-';
  5247. }
  5248. }
  5249. /*-- HYPHENATION --*/
  5250. // Soft Hyphens chr(173)
  5251. else if ($this->textparam['hyphens'] != 2 && (!$this->usingCoreFont && preg_match("/\xc2\xad/",$currWord)) || ($this->usingCoreFont && preg_match("/".chr(173)."/",$currWord) && ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats')) ) { // mPDF 5.6.06
  5252. $rem = $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
  5253. list($success,$pre,$post,$prelength) = $this->softHyphenate($currWord, (($rem-$cutoffWidth)/_MPDFK -$this->GetCharWidth(" ", false)) );
  5254. }
  5255. if (!$success && !$hardsuccess && $this->textparam['hyphens'] == 1 ) { // mPDF 5.6.06 // mPDF 5.6.21
  5256. // Look ahead to get current word
  5257. for($ac = $i; $ac<(mb_strlen($s)-1); $ac++) {
  5258. $addc = mb_substr($s,$ac,1,$this->mb_enc );
  5259. if ($addc == ' ') { break; }
  5260. $currWord .= $addc;
  5261. }
  5262. $rem = $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
  5263. list($success,$pre,$post,$prelength) = $this->hyphenateWord($currWord, (($rem-$cutoffWidth)/_MPDFK -$this->GetCharWidth(" ", false)) );
  5264. }
  5265. if ($success) {
  5266. $already = array_pop( $words );
  5267. $forward = mb_substr($already,$prelength,mb_strlen($already, $this->mb_enc), $this->mb_enc);
  5268. $words[] = $pre.'-';
  5269. $words[] = $forward;
  5270. $currContent = mb_substr($currContent,0,mb_strlen($currContent, $this->mb_enc)+1-mb_strlen($post, $this->mb_enc), $this->mb_enc) . '-';
  5271. }
  5272. /*-- END HYPHENATION --*/
  5273. // mPDF 5.6.13 Decimal alignment (cancel if wraps to > 1 line)
  5274. if ($is_table && substr($align,0,1)=='D' ) { $align=substr($align,2,1); }
  5275. /*-- CJK-FONTS --*/
  5276. // mPDF 5.6.42
  5277. if ($this->checkCJK) {
  5278. $lastchar = mb_substr($words[(count($words)-1)],mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
  5279. }
  5280. // Next character is suitable to add as overhanging or squeezed punctuation
  5281. if ($this->checkCJK && preg_match("/[".$this->CJKoverflow."]/u", $c) && $this->allowCJKorphans && !$CJKoverflow) {
  5282. // add character onto this line
  5283. $currContent .= $c;
  5284. $cutoffWidth = $contentWidth;
  5285. $contentWidth += $cw;
  5286. $CJKoverflow = true;
  5287. continue;
  5288. }
  5289. // Last character that fits is not allowed to end a line - move lastchar(s) to start of next line
  5290. else if ($this->checkCJK && preg_match("/[".$this->CJKleading."]/u", $lastchar)) {
  5291. //move lastchar(s) to next line
  5292. $m0 = $lastchar;
  5293. $m1 = $c;
  5294. while(preg_match("/[".$this->CJKleading."]/u", $m0) && mb_strlen($words[(count($words)-1)], $this->mb_enc)>2) {
  5295. // trim last letter off word[0]
  5296. $words[(count($words)-1)] = mb_substr($words[(count($words)-1)],0,mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, $this->mb_enc);
  5297. // and add it to savedContent for next line
  5298. $savedContent = $m0.$savedContent;
  5299. $m1 = $lastchar;
  5300. $lastchar = mb_substr($words[(count($words)-1)],mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
  5301. $m0 = $lastchar;
  5302. }
  5303. $lastContent = '';
  5304. for ( $w = 0; $w < count( $words ) ; $w++) { $lastContent .= $words[ $w ]." "; }
  5305. $savedFont = $this->saveFont();
  5306. // replace the current content with the cropped version
  5307. $currContent = rtrim( $lastContent );
  5308. }
  5309. // Next character is not allowed to start a new line
  5310. else if ($this->checkCJK && preg_match("/[".$this->CJKfollowing."]/u", $c)) {
  5311. // try squeezing another character(s) onto this line = Oikomi
  5312. if ($this->allowCJKorphans && !$CJKoverflow) { // mPDF 5.6.40
  5313. $lookahead = mb_substr($s,$i+1,1,$this->mb_enc );
  5314. //if lookahead is not another following char
  5315. if (!$lookahead || ($lookahead && !preg_match("/[".$this->CJKfollowing."]/u", $lookahead))) {
  5316. $currContent .= $c;
  5317. $cutoffWidth = $contentWidth;
  5318. $contentWidth += $cw;
  5319. if ($this->allowCJKoverflow && preg_match("/[".$this->CJKoverflow."]/u", $c)) { $CJKoverflow = true; }
  5320. continue;
  5321. }
  5322. }
  5323. // or move lastchar(s) to next line to keep $c company = Oidashi
  5324. $m0 = $lastchar;
  5325. $m1 = $c;
  5326. while(preg_match("/[".$this->CJKfollowing."]/u", $m1) && mb_strlen($words[(count($words)-1)], $this->mb_enc)>2) {
  5327. // trim last letter off word[0]
  5328. $words[(count($words)-1)] = mb_substr($words[(count($words)-1)],0,mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, $this->mb_enc);
  5329. // and add it to savedContent for next line
  5330. $savedContent = $m0.$savedContent;
  5331. $m1 = $lastchar;
  5332. $lastchar = mb_substr($words[(count($words)-1)],mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
  5333. $m0 = $lastchar;
  5334. }
  5335. $lastContent = '';
  5336. for ( $w = 0; $w < count( $words ) ; $w++) { $lastContent .= $words[ $w ]." "; }
  5337. $savedFont = $this->saveFont();
  5338. // replace the current content with the cropped version
  5339. $currContent = rtrim( $lastContent );
  5340. }
  5341. // mPDF 5.6.42
  5342. else if ($this->checkCJK && preg_match("/([".$this->pregCJKchars."]+[0-9\x{ff10}-\x{ff19}]+$)/u", $words[0])) {
  5343. $lookahead = mb_substr($s,$i,16,$this->mb_enc );
  5344. //and if lookahead starts with a few numerals
  5345. if ($lookahead && (preg_match("/^([0-9\x{ff10}-\x{ff19}]+[".$this->pregCJKchars."]+)/u", $lookahead) || preg_match("/^([0-9\x{ff10}-\x{ff19}]+$)/u", $lookahead)) ) {
  5346. // or move lastchar(s) to next line to keep numerals together
  5347. $m0 = $lastchar;
  5348. while(preg_match("/[0-9\x{ff10}-\x{ff19}]/u", $m0) && mb_strlen($words[(count($words)-1)], $this->mb_enc)>2) {
  5349. // trim last letter off word[0]
  5350. $words[(count($words)-1)] = mb_substr($words[(count($words)-1)],0,mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, $this->mb_enc);
  5351. // and add it to savedContent for next line
  5352. $savedContent = $m0.$savedContent;
  5353. $lastchar = mb_substr($words[(count($words)-1)],mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
  5354. $m0 = $lastchar;
  5355. }
  5356. }
  5357. $lastContent = '';
  5358. for ( $w = 0; $w < count( $words ) ; $w++) { $lastContent .= $words[ $w ]." "; }
  5359. $savedFont = $this->saveFont();
  5360. // replace the current content with the cropped version
  5361. $currContent = rtrim( $lastContent );
  5362. }
  5363. else
  5364. /*-- END CJK-FONTS --*/
  5365. // if it looks like we didn't finish any words for this chunk
  5366. if ( count( $words ) == 1 ) {
  5367. // TO correct for error when word too wide for page - but only when one long word from left to right margin
  5368. if (count($content) == 1 && $currContent != ' ') {
  5369. $lastchar = mb_substr($words[0],mb_strlen($words[0], $this->mb_enc)-1, 1, $this->mb_enc);
  5370. $lastContent = $words[0];
  5371. $savedFont = $this->saveFont();
  5372. // replace the current content with the cropped version
  5373. $currContent = rtrim( $lastContent );
  5374. }
  5375. // mPDF 5.6.20
  5376. else if ( count($content)>1
  5377. && (!isset($this->objectbuffer[(count($content)-1)]) && !isset($this->objectbuffer[(count($content)-2)]))
  5378. && substr($content[count($content)-2],-1,1) != ' '
  5379. && substr($currContent,0,1) != ' '
  5380. ) {
  5381. // Go back to find a space in a previous chunk of content
  5382. $found = false;
  5383. for ($ix=count($content)-1;$ix>=0;$ix--) {
  5384. // mPDF 5.6.29
  5385. if ($this->usingCoreFont && preg_match('/[ '.chr(173).']/',$content[$ix],$m)) { $match = $m[0]; $found = $ix; break; }
  5386. else if (!$this->usingCoreFont) {
  5387. if (preg_match('/[ ]/',$content[$ix])) { $match = ' '; $found = $ix; break; }
  5388. else if (preg_match('/[\x{00AD}]/u',$content[$ix])) {
  5389. // even though it is UTF-8 replace it temporarily with chr(173)
  5390. $content[$ix] = preg_replace('/[\x{00AD}]/u',chr(173),$content[$ix]);
  5391. $match = chr(173); $found = $ix; break;
  5392. }
  5393. }
  5394. }
  5395. if ($found !== false) {
  5396. $charpos = strrpos($content[$found],$match); // mPDF 5.6.29
  5397. for ($ix=count($content)-1;$ix>$found;$ix--) {
  5398. // save and crop off any subsequent chunks
  5399. $savedPreContent[] = array_pop($content);
  5400. $savedPreContentB[] = array_pop($contentB);
  5401. $savedPreFont[] = array_pop($font);
  5402. }
  5403. if (substr($content[count($content)-1],$charpos+1,strlen($content[count($content)-1])-1) != '') {
  5404. $savedPreContent[] = substr($content[count($content)-1],$charpos+1,strlen($content[count($content)-1])-1);
  5405. $savedPreContentB[] = preg_replace('/L/','',$contentB[count($content)-1]); // ???
  5406. $savedPreFont[] = $font[count($content)-1];
  5407. }
  5408. $savedContent = '';
  5409. $savedContentB = '';
  5410. $savedFont = array();
  5411. $currContent =& $content[ count( $content ) - 1 ];
  5412. $currContent = substr($currContent,0,$charpos);
  5413. if ($match == chr(173)) { $currContent .= '-'; } // mPDF 5.6.29
  5414. if (strpos($contentB[(count($contentB)-1)],'R')!==false) { // ???
  5415. $contentB[count($content)-1] = preg_replace('/R/','',$contentB[count($content)-1]); // ???
  5416. }
  5417. $currContent = rtrim( $currContent );
  5418. }
  5419. else {
  5420. $savedContent = array_pop( $content );
  5421. $savedContentB = array_pop($contentB);
  5422. $savedFont = array_pop( $font );
  5423. $currContent =& $content[ count( $content ) - 1 ];
  5424. $currContent = rtrim( $currContent );
  5425. }
  5426. }
  5427. else {
  5428. // save and crop off the content currently on the stack
  5429. $savedContent = array_pop( $content );
  5430. $savedContentB = array_pop($contentB); // mPDF 5.6.20
  5431. $savedFont = array_pop( $font );
  5432. // trim any trailing spaces off the last bit of content
  5433. $currContent =& $content[ count( $content ) - 1 ];
  5434. $currContent = rtrim( $currContent );
  5435. }
  5436. }
  5437. else { // otherwise, we need to find which bit to cut off
  5438. $lastContent = '';
  5439. for ( $w = 0; $w < count( $words ) - 1; $w++) { $lastContent .= $words[ $w ]." "; }
  5440. $savedContent = $words[ count( $words ) - 1 ];
  5441. $savedFont = $this->saveFont();
  5442. // replace the current content with the cropped version
  5443. $currContent = rtrim( $lastContent );
  5444. }
  5445. // CJK - strip CJK space at end of line
  5446. // &#x3000; = \xe3\x80\x80 = CJK space
  5447. if ($this->checkCJK) { $currContent = preg_replace("/\xe3\x80\x80$/",'',$currContent) ; } // *CJK-FONTS*
  5448. if (isset($this->objectbuffer[(count($content)-1)]) && $this->objectbuffer[(count($content)-1)]['type']=='dottab') {
  5449. $savedObj = array_pop( $this->objectbuffer );
  5450. $contentWidth -= ($this->objectbuffer[(count($content)-1)]['OUTER-WIDTH'] * _MPDFK);
  5451. }
  5452. // Set Current lineheight (correction factor)
  5453. $lhfixed = false;
  5454. /*-- LISTS --*/
  5455. if ($is_list) {
  5456. if (preg_match('/([0-9.,]+)mm/',$this->list_lineheight[$this->listlvl][$this->listOcc],$am)) {
  5457. $lhfixed = true;
  5458. $def_fontsize = $this->InlineProperties['LISTITEM'][$this->listlvl][$this->listOcc][$this->listnum]['size'];
  5459. $this->lineheight_correction = $am[1] / $def_fontsize ;
  5460. }
  5461. else {
  5462. $this->lineheight_correction = $this->list_lineheight[$this->listlvl][$this->listOcc];
  5463. }
  5464. }
  5465. else
  5466. /*-- END LISTS --*/
  5467. /*-- TABLES --*/
  5468. if ($is_table) {
  5469. if (preg_match('/([0-9.,]+)mm/',$this->table_lineheight,$am)) {
  5470. $lhfixed = true;
  5471. $def_fontsize = $this->FontSize; // needs to be default font-size for block ****
  5472. $this->lineheight_correction = $lineHeight / $def_fontsize ;
  5473. }
  5474. else {
  5475. $this->lineheight_correction = $this->table_lineheight;
  5476. }
  5477. }
  5478. else
  5479. /*-- END TABLES --*/
  5480. if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
  5481. if (preg_match('/([0-9.,]+)mm/',$this->blk[$this->blklvl]['line_height'],$am)) {
  5482. $lhfixed = true;
  5483. $def_fontsize = $this->blk[$this->blklvl]['InlineProperties']['size']; // needs to be default font-size for block ****
  5484. $this->lineheight_correction = $am[1] / $def_fontsize ;
  5485. }
  5486. else {
  5487. $this->lineheight_correction = $this->blk[$this->blklvl]['line_height'];
  5488. }
  5489. }
  5490. else {
  5491. $this->lineheight_correction = $this->normalLineheight;
  5492. }
  5493. // update $contentWidth and $cutoffWidth since they changed with cropping
  5494. // Also correct lineheight to maximum fontsize (not for tables)
  5495. $contentWidth = 0;
  5496. // correct lineheight to maximum fontsize
  5497. if ($lhfixed) { $maxlineHeight = $this->lineheight; }
  5498. else { $maxlineHeight = 0; }
  5499. $this->forceExactLineheight = true;
  5500. $maxfontsize = 0;
  5501. // While we're at it, check for cursive text
  5502. $checkCursive=false;
  5503. if ($this->biDirectional) { $checkCursive=true; } // *RTL*
  5504. foreach ( $content as $k => $chunk )
  5505. {
  5506. $this->restoreFont( $font[ $k ]);
  5507. if (!isset($this->objectbuffer[$k])) {
  5508. // mPDF 5.6.40
  5509. if ($this->checkCJK && $k == count($content)-1 && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $this->CJKforceend) {
  5510. // force-end overhang
  5511. $hanger = mb_substr($chunk,mb_strlen($chunk,$this->mb_enc)-1,1,$this->mb_enc );
  5512. $content[$k] = $chunk = mb_substr($chunk,0,mb_strlen($chunk,$this->mb_enc)-1,$this->mb_enc );
  5513. }
  5514. if (!$this->usingCoreFont) {
  5515. $content[$k] = $chunk = str_replace("\xc2\xad",'',$chunk );
  5516. if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) { $checkCursive=true; } // *INDIC*
  5517. }
  5518. // Soft Hyphens chr(173)
  5519. else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
  5520. $content[$k] = $chunk = str_replace(chr(173),'',$chunk );
  5521. }
  5522. $contentWidth += $this->GetStringWidth( $chunk ) * _MPDFK;
  5523. if (!empty($this->spanborddet)) {
  5524. if (strpos($contentB[$k],'L')!==false) $contentWidth += $this->spanborddet['L']['w'] * _MPDFK;
  5525. if (strpos($contentB[$k],'R')!==false) $contentWidth += $this->spanborddet['R']['w'] * _MPDFK;
  5526. }
  5527. if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$this->FontSize * $this->lineheight_correction ); }
  5528. if ($lhfixed && ($this->FontSize > $def_fontsize || ($this->FontSize > ($lineHeight * $this->lineheight_correction) && $is_list))) {
  5529. $this->forceExactLineheight = false;
  5530. }
  5531. $maxfontsize = max($maxfontsize,$this->FontSize);
  5532. }
  5533. }
  5534. $lastfontreqstyle = $font[count($font)-1]['ReqFontStyle'];
  5535. $lastfontstyle = $font[count($font)-1]['style'];
  5536. if ($blockdir == 'ltr' && strpos($lastfontreqstyle,"I") !== false && strpos($lastfontstyle,"I") === false) { // Artificial italic
  5537. $lastitalic = $this->FontSize*0.15*_MPDFK;
  5538. }
  5539. else { $lastitalic = 0; }
  5540. /*-- LISTS --*/
  5541. if ($is_list && is_array($this->bulletarray) && $this->bulletarray) {
  5542. $actfs = $this->bulletarray['fontsize'];
  5543. if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
  5544. if ($lhfixed && $actfs > $def_fontsize) { $this->forceExactLineheight = false; }
  5545. $maxfontsize = max($maxfontsize,$actfs);
  5546. }
  5547. /*-- END LISTS --*/
  5548. // when every text item checked i.e. $maxfontsize is set properly
  5549. $af = 0; // Above font
  5550. $bf = 0; // Below font
  5551. $mta = 0; // Maximum top-aligned
  5552. $mba = 0; // Maximum bottom-aligned
  5553. foreach ( $content as $k => $chunk ) {
  5554. if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]) {
  5555. $contentWidth += $this->objectbuffer[$k]['OUTER-WIDTH'] * _MPDFK;
  5556. $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
  5557. $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
  5558. if ($lhfixed && $oh > $def_fontsize) { $this->forceExactLineheight = false; }
  5559. if ($va == 'BS') { // (BASELINE default)
  5560. $af = max($af, ($oh - ($maxfontsize * (0.5 + $this->baselineC))));
  5561. }
  5562. else if ($va == 'M') {
  5563. $af = max($af, ($oh - $maxfontsize)/2);
  5564. $bf = max($bf, ($oh - $maxfontsize)/2);
  5565. }
  5566. else if ($va == 'TT') {
  5567. $bf = max($bf, ($oh - $maxfontsize));
  5568. }
  5569. else if ($va == 'TB') {
  5570. $af = max($af, ($oh - $maxfontsize));
  5571. }
  5572. else if ($va == 'T') {
  5573. $mta = max($mta, $oh);
  5574. }
  5575. else if ($va == 'B') {
  5576. $mba = max($mba, $oh);
  5577. }
  5578. }
  5579. }
  5580. if ((!$lhfixed || !$this->forceExactLineheight) && ($af > (($maxlineHeight - $maxfontsize)/2) || $bf > (($maxlineHeight - $maxfontsize)/2))) {
  5581. $maxlineHeight = $maxfontsize + $af + $bf;
  5582. }
  5583. else if (!$lhfixed) { $af = $bf = ($maxlineHeight - $maxfontsize)/2; }
  5584. if ($mta > $maxlineHeight) {
  5585. $bf += ($mta - $maxlineHeight);
  5586. $maxlineHeight = $mta;
  5587. }
  5588. if ($mba > $maxlineHeight) {
  5589. $af += ($mba - $maxlineHeight);
  5590. $maxlineHeight = $mba;
  5591. }
  5592. $lineHeight = $maxlineHeight;
  5593. $cutoffWidth = $contentWidth;
  5594. // If NOT images, and maxfontsize NOT > lineHeight - this value determines text baseline positioning
  5595. if ($lhfixed && $af==0 && $bf==0 && $maxfontsize<=($def_fontsize * $this->lineheight_correction * 0.8 )) {
  5596. $this->linemaxfontsize = $def_fontsize;
  5597. }
  5598. else { $this->linemaxfontsize = $maxfontsize; }
  5599. $inclCursive=false;
  5600. foreach ( $content as $k => $chunk ) {
  5601. if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
  5602. if ($this->usingCoreFont) {
  5603. $content[$k] = str_replace(chr(160),chr(32),$chunk );
  5604. }
  5605. else {
  5606. $content[$k] = str_replace(chr(194).chr(160),chr(32),$chunk );
  5607. if ($checkCursive) {
  5608. if (preg_match("/([".$this->pregRTLchars."])/u", $chunk)) { $inclCursive = true; } // *RTL*
  5609. if (preg_match("/([".$this->pregHIchars.$this->pregBNchars.$this->pregPAchars."])/u", $chunk)) { $inclCursive = true; } // *INDIC*
  5610. }
  5611. }
  5612. }
  5613. }
  5614. // JUSTIFICATION J
  5615. $jcharspacing = 0;
  5616. $jws = 0;
  5617. $nb_carac = 0;
  5618. $nb_spaces = 0;
  5619. // if it's justified, we need to find the char/word spacing (or if orphans have allowed length of line to go over the maxwidth)
  5620. if ( ($align == 'J' && !$CJKoverflow) || (($cutoffWidth + $lastitalic > $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) + 0.001) && (!$CJKoverflow || ($CJKoverflow && !$this->allowCJKoverflow))) || $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) { // 0.001 is to correct for deviations converting mm=>pts // mPDF 5.6.40
  5621. // JUSTIFY J (Use character spacing)
  5622. // WORD SPACING
  5623. foreach ( $content as $k => $chunk ) {
  5624. if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
  5625. $nb_carac += mb_strlen( $chunk, $this->mb_enc ) ;
  5626. $nb_spaces += mb_substr_count( $chunk,' ', $this->mb_enc ) ;
  5627. }
  5628. }
  5629. list($jcharspacing,$jws) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$cutoffWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive);
  5630. }
  5631. // WORD SPACING
  5632. $empty = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
  5633. $empty -= ($jcharspacing * $nb_carac);
  5634. $empty -= ($jws * $nb_spaces);
  5635. $empty /= _MPDFK;
  5636. $b = ''; //do not use borders
  5637. // Get PAGEBREAK TO TEST for height including the top border/padding
  5638. $check_h = max($this->divheight,$lineHeight);
  5639. if (($newblock) && ($blockstate==1 || $blockstate==3) && ($this->blklvl > 0) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
  5640. $check_h += ($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['border_top']['w']);
  5641. }
  5642. if ($this->ColActive && $check_h > ($this->PageBreakTrigger - $this->y0)) {
  5643. $this->SetCol($this->NbCol-1);
  5644. }
  5645. // PAGEBREAK
  5646. // 'If' below used in order to fix "first-line of other page with justify on" bug
  5647. if(!$is_table && ($this->y+$check_h) > $this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) {
  5648. $bak_x=$this->x;//Current X position
  5649. // WORD SPACING
  5650. $ws=$this->ws;//Word Spacing
  5651. $charspacing=$this->charspacing;//Character Spacing
  5652. $this->ResetSpacing();
  5653. $this->AddPage($this->CurOrientation);
  5654. $this->x = $bak_x;
  5655. // Added to correct for OddEven Margins
  5656. $currentx += $this->MarginCorrection;
  5657. $this->x += $this->MarginCorrection;
  5658. // WORD SPACING
  5659. $this->SetSpacing($charspacing,$ws);
  5660. }
  5661. if ($this->keep_block_together && !$is_table && $this->kt_p00 < $this->page && ($this->y+$check_h) > $this->kt_y00) {
  5662. $this->printdivbuffer();
  5663. $this->keep_block_together = 0;
  5664. }
  5665. /*-- COLUMNS --*/
  5666. // COLS
  5667. // COLUMN CHANGE
  5668. if ($this->CurrCol != $oldcolumn) {
  5669. $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
  5670. $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
  5671. $oldcolumn = $this->CurrCol;
  5672. }
  5673. if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  5674. /*-- END COLUMNS --*/
  5675. // TOP MARGIN
  5676. if (($newblock) && ($blockstate==1 || $blockstate==3) && ($this->blk[$this->blklvl]['margin_top']) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
  5677. $this->DivLn($this->blk[$this->blklvl]['margin_top'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
  5678. if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  5679. }
  5680. // Update y0 for top of block (used to paint border)
  5681. if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
  5682. $this->blk[$this->blklvl]['y0'] = $this->y;
  5683. $this->blk[$this->blklvl]['startpage'] = $this->page;
  5684. if ($this->blk[$this->blklvl]['float']) { $this->blk[$this->blklvl]['float_start_y'] = $this->y; } // mPDF 5.6.63
  5685. }
  5686. // TOP PADDING and BORDER spacing/fill
  5687. if (($newblock) && ($blockstate==1 || $blockstate==3) && (($this->blk[$this->blklvl]['padding_top']) || ($this->blk[$this->blklvl]['border_top'])) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
  5688. // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
  5689. $this->DivLn($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'],-3,true,false,1);
  5690. if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  5691. }
  5692. $arraysize = count($content);
  5693. $margins = ($this->cMarginL+$this->cMarginR) + ($ipaddingL+$ipaddingR + $fpaddingR + $fpaddingR );
  5694. // PAINT BACKGROUND FOR THIS LINE
  5695. if (!$is_table) { $this->DivLn($lineHeight,$this->blklvl,false); } // false -> don't advance y
  5696. $this->x = $currentx + $this->cMarginL + $ipaddingL + $fpaddingL ;
  5697. if ($align == 'R') { $this->x += $empty; }
  5698. else if ($align == 'C') { $this->x += ($empty / 2); }
  5699. // Paragraph INDENT
  5700. if (isset($this->blk[$this->blklvl]['text_indent']) && ($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 1) && (!$is_table) && ($blockdir !='rtl') && ($align !='C')) {
  5701. $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
  5702. $this->x += $ti;
  5703. }
  5704. // DIRECTIONALITY RTL
  5705. $all_rtl = false;
  5706. $contains_rtl = false;
  5707. /*-- RTL --*/
  5708. if ($blockdir == 'rtl' || $this->biDirectional) {
  5709. $all_rtl = true;
  5710. foreach ( $content as $k => $chunk ) {
  5711. $reversed = $this->magic_reverse_dir($chunk, false, $blockdir);
  5712. if ($reversed > 0) { $contains_rtl = true; }
  5713. if ($reversed < 2) { $all_rtl = false; }
  5714. $content[$k] = $chunk;
  5715. }
  5716. if (($blockdir =='rtl' && $contains_rtl) || $all_rtl) {
  5717. $content = array_reverse($content,false);
  5718. $contentB = array_reverse($contentB,false);
  5719. }
  5720. }
  5721. /*-- END RTL --*/
  5722. foreach ( $content as $k => $chunk ) {
  5723. // FOR IMAGES - UPDATE POSITION
  5724. if (($blockdir =='rtl' && $contains_rtl) || $all_rtl) { $dirk = $arraysize-1 - $k ; } else { $dirk = $k; }
  5725. $va = 'M'; // default for text
  5726. if (isset($this->objectbuffer[$dirk]) && $this->objectbuffer[$dirk]) {
  5727. $xadj = $this->x - $this->objectbuffer[$dirk]['OUTER-X'] ;
  5728. $this->objectbuffer[$dirk]['OUTER-X'] += $xadj;
  5729. $this->objectbuffer[$dirk]['BORDER-X'] += $xadj;
  5730. $this->objectbuffer[$dirk]['INNER-X'] += $xadj;
  5731. $va = $this->objectbuffer[$dirk]['vertical-align'];
  5732. $yadj = $this->y - $this->objectbuffer[$dirk]['OUTER-Y'];
  5733. if ($va == 'BS') {
  5734. $yadj += $af + ($this->linemaxfontsize * (0.5 + $this->baselineC)) - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
  5735. }
  5736. else if ($va == 'M' || $va == '') {
  5737. $yadj += $af + ($this->linemaxfontsize /2) - ($this->objectbuffer[$dirk]['OUTER-HEIGHT']/2);
  5738. }
  5739. else if ($va == 'TB') {
  5740. $yadj += $af + $this->linemaxfontsize - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
  5741. }
  5742. else if ($va == 'TT') {
  5743. $yadj += $af;
  5744. }
  5745. else if ($va == 'B') {
  5746. $yadj += $af + $this->linemaxfontsize + $bf - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
  5747. }
  5748. else if ($va == 'T') {
  5749. $yadj += 0;
  5750. }
  5751. $this->objectbuffer[$dirk]['OUTER-Y'] += $yadj;
  5752. $this->objectbuffer[$dirk]['BORDER-Y'] += $yadj;
  5753. $this->objectbuffer[$dirk]['INNER-Y'] += $yadj;
  5754. }
  5755. // DIRECTIONALITY RTL
  5756. if ((($blockdir == 'rtl') && ($contains_rtl )) || ($all_rtl )) { $this->restoreFont($font[$arraysize-1 - $k]); }
  5757. else { $this->restoreFont( $font[ $k ] ); }
  5758. $this->SetSpacing(($this->fixedlSpacing*_MPDFK)+$jcharspacing,($this->fixedlSpacing+$this->minwSpacing)*_MPDFK+$jws);
  5759. // Now unset these values so they don't influence GetStringwidth below or in fn. Cell
  5760. $this->fixedlSpacing = false;
  5761. $this->minwSpacing = 0;
  5762. // mPDF 5.6.26
  5763. $save_vis = $this->visibility;
  5764. if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->textparam['visibility'] != $this->visibility) {
  5765. $this->SetVisibility($this->textparam['visibility']);
  5766. }
  5767. // *********** SPAN BACKGROUND COLOR ***************** //
  5768. if ($this->spanbgcolor) {
  5769. $cor = $this->spanbgcolorarray;
  5770. $this->SetFColor($cor);
  5771. $save_fill = $fill; $spanfill = 1; $fill = 1;
  5772. }
  5773. if (!empty($this->spanborddet)) {
  5774. if (strpos($contentB[$k],'L')!==false) $this->x += $this->spanborddet['L']['w'];
  5775. if (strpos($contentB[$k],'L')===false) $this->spanborddet['L']['s'] = $this->spanborddet['L']['w'] = 0;
  5776. if (strpos($contentB[$k],'R')===false) $this->spanborddet['R']['s'] = $this->spanborddet['R']['w'] = 0;
  5777. }
  5778. // WORD SPACING
  5779. $stringWidth = $this->GetStringWidth($chunk );
  5780. $stringWidth += ( $this->charspacing * mb_strlen($chunk,$this->mb_enc ) / _MPDFK );
  5781. $stringWidth += ( $this->ws * mb_substr_count($chunk,' ',$this->mb_enc ) / _MPDFK );
  5782. if (isset($this->objectbuffer[$dirk])) { $stringWidth = $this->objectbuffer[$dirk]['OUTER-WIDTH']; }
  5783. if ($stringWidth==0) { $stringWidth = 0.000001; }
  5784. if ($k == $arraysize-1) {
  5785. $stringWidth -= ( $this->charspacing / _MPDFK );
  5786. // mPDF 5.6.40
  5787. if ($this->checkCJK && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) {
  5788. // force-end overhang
  5789. $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
  5790. $this->Cell( $this->GetStringWidth($hanger), $lineHeight, $hanger, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
  5791. }
  5792. else {
  5793. $this->Cell( $stringWidth, $lineHeight, $chunk, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true ); //mono-style line or last part (skips line)
  5794. }
  5795. }
  5796. else $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, 0, 0,0,'M', $fill, $af, $bf, true );//first or middle part
  5797. if (!empty($this->spanborddet)) {
  5798. if (strpos($contentB[$k],'R')!==false && $k != $arraysize-1) $this->x += $this->spanborddet['R']['w'];
  5799. }
  5800. // *********** SPAN BACKGROUND COLOR OFF - RESET BLOCK BGCOLOR ***************** //
  5801. if (isset($spanfill) && $spanfill) {
  5802. $fill = $save_fill; $spanfill = 0;
  5803. if ($fill) { $this->SetFColor($bcor); }
  5804. }
  5805. // mPDF 5.6.26
  5806. if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->visibility != $save_vis) {
  5807. $this->SetVisibility($save_vis);
  5808. }
  5809. }
  5810. if (!$is_table) {
  5811. $this->maxPosR = max($this->maxPosR , ($this->w - $this->rMargin - $this->blk[$this->blklvl]['outer_right_margin']));
  5812. $this->maxPosL = min($this->maxPosL , ($this->lMargin + $this->blk[$this->blklvl]['outer_left_margin']));
  5813. }
  5814. // move on to the next line, reset variables, tack on saved content and current char
  5815. $this->printobjectbuffer($is_table, $blockdir);
  5816. $this->objectbuffer = array();
  5817. /*-- LISTS --*/
  5818. // LIST BULLETS/NUMBERS
  5819. if ($is_list && is_array($this->bulletarray) && ($lineCount == 1) ) {
  5820. $this->ResetSpacing();
  5821. $bull = $this->bulletarray;
  5822. if (isset($bull['level']) && isset($bull['occur']) && isset($this->InlineProperties['LIST'][$bull['level']][$bull['occur']])) {
  5823. $this->restoreInlineProperties($this->InlineProperties['LIST'][$bull['level']][$bull['occur']]);
  5824. }
  5825. if (isset($bull['level']) && isset($bull['occur']) && isset($bull['num']) && isset($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) && $this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) { $this->restoreInlineProperties($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]); }
  5826. if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
  5827. $this->bullet = true;
  5828. $this->SetFont('czapfdingbats','',$this->FontSizePt/2.5);
  5829. }
  5830. else { $this->SetFont($this->FontFamily,$this->FontStyle,$this->FontSizePt,true,true); } // force output
  5831. //Output bullet
  5832. $this->x = $currentx;
  5833. if (isset($bull['x'])) { $this->x += $bull['x']; }
  5834. $this->y -= $lineHeight;
  5835. if (isset($bull['col']) && $bull['col']) { $this->SetTColor($bull['col']); } // mPDF 5.6.67
  5836. if (isset($bull['txt'])) { $this->Cell($bull['w'], $lineHeight,$bull['txt'],'','',$bull['align'],0,'',0,-$this->cMarginL, -$this->cMarginR ); }
  5837. if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
  5838. $this->bullet = false;
  5839. }
  5840. $this->x = $currentx; // Reset
  5841. $this->y += $lineHeight;
  5842. if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
  5843. $this->bulletarray = array(); // prevents repeat of bullet/number if <li>....<br />.....</li>
  5844. }
  5845. /*-- END LISTS --*/
  5846. /*-- CSS-IMAGE-FLOAT --*/
  5847. // Update values if set to skipline
  5848. if ($this->floatmargins) { $this->_advanceFloatMargins(); }
  5849. /*-- END CSS-IMAGE-FLOAT --*/
  5850. // Reset lineheight
  5851. $lineHeight = $this->divheight;
  5852. $valign = 'M';
  5853. $font = array();
  5854. $content = array();
  5855. $contentB = array();
  5856. $contentWidth = 0;
  5857. if (!empty($savedObj)) {
  5858. $this->objectbuffer[] = $savedObj;
  5859. $font[] = $savedFont;
  5860. $content[] = '';
  5861. $contentB[] = '';
  5862. $contentWidth += $savedObj['OUTER-WIDTH'] * _MPDFK;
  5863. }
  5864. // mPDF 5.6.20
  5865. if (count($savedPreContent) > 0) {
  5866. for($ix=count($savedPreContent)-1;$ix>=0;$ix--) {
  5867. $font[] = $savedPreFont[$ix];
  5868. $content[] = $savedPreContent[$ix];
  5869. $contentB[] = $savedPreContentB[$ix];
  5870. $this->restoreFont( $savedPreFont[$ix] );
  5871. $lbw = $rbw = 0; // Border widths
  5872. if (!empty($this->spanborddet)) {
  5873. $lbw = $this->spanborddet['L']['w'];
  5874. $rbw = $this->spanborddet['R']['w'];
  5875. }
  5876. if ($ix>0) {
  5877. $contentWidth += $this->GetStringWidth( $savedPreContent[$ix] ) * _MPDFK;
  5878. if (strpos($savedPreContentB[$ix],'L')!==false) $contentWidth += $lbw;
  5879. if (strpos($savedPreContentB[$ix],'R')!==false) $contentWidth += $rbw;
  5880. }
  5881. }
  5882. $savedPreContent = array();
  5883. $savedPreContentB = array();
  5884. $savedPreFont = array();
  5885. $content[ (count($content)-1) ] .= $c;
  5886. }
  5887. else {
  5888. $font[] = $savedFont;
  5889. $content[] = $savedContent . $c;
  5890. $contentB[] = $savedContentB ;
  5891. }
  5892. $currContent =& $content[ (count($content)-1) ];
  5893. // CJK - strip CJK space at end of line
  5894. // &#x3000; = \xe3\x80\x80 = CJK space
  5895. if ($this->checkCJK && $currContent == "\xe3\x80\x80") { $currContent = '' ; } // *CJK-FONTS*
  5896. $this->restoreFont( $savedFont );
  5897. $lbw = $rbw = 0; // Border widths
  5898. if (!empty($this->spanborddet)) {
  5899. $lbw = $this->spanborddet['L']['w'];
  5900. $rbw = $this->spanborddet['R']['w'];
  5901. }
  5902. $contentWidth += $this->GetStringWidth( $currContent ) * _MPDFK;
  5903. if (strpos($savedContentB,'L')!==false) $contentWidth += $lbw;
  5904. $cutoffWidth = $contentWidth;
  5905. $CJKoverflow = false;
  5906. $hanger = ''; // mPDF 5.6.40
  5907. }
  5908. // another character will fit, so add it on
  5909. else {
  5910. $contentWidth += $cw;
  5911. $currContent .= $c;
  5912. }
  5913. }
  5914. unset($content);
  5915. unset($contentB);
  5916. }
  5917. //----------------------END OF FLOWING BLOCK------------------------------------//
  5918. /*-- CSS-IMAGE-FLOAT --*/
  5919. // Update values if set to skipline
  5920. function _advanceFloatMargins() {
  5921. // Update floatmargins - L
  5922. if (isset($this->floatmargins['L']) && $this->floatmargins['L']['skipline'] && $this->floatmargins['L']['y0'] != $this->y) {
  5923. $yadj = $this->y - $this->floatmargins['L']['y0'];
  5924. $this->floatmargins['L']['y0'] = $this->y;
  5925. $this->floatmargins['L']['y1'] += $yadj;
  5926. // Update objattr in floatbuffer
  5927. if ($this->floatbuffer[$this->floatmargins['L']['id']]['border_left']['w']) {
  5928. $this->floatbuffer[$this->floatmargins['L']['id']]['BORDER-Y'] += $yadj;
  5929. }
  5930. $this->floatbuffer[$this->floatmargins['L']['id']]['INNER-Y'] += $yadj;
  5931. $this->floatbuffer[$this->floatmargins['L']['id']]['OUTER-Y'] += $yadj;
  5932. // Unset values
  5933. $this->floatbuffer[$this->floatmargins['L']['id']]['skipline'] = false;
  5934. $this->floatmargins['L']['skipline'] = false;
  5935. $this->floatmargins['L']['id'] = '';
  5936. }
  5937. // Update floatmargins - R
  5938. if (isset($this->floatmargins['R']) && $this->floatmargins['R']['skipline'] && $this->floatmargins['R']['y0'] != $this->y) {
  5939. $yadj = $this->y - $this->floatmargins['R']['y0'];
  5940. $this->floatmargins['R']['y0'] = $this->y;
  5941. $this->floatmargins['R']['y1'] += $yadj;
  5942. // Update objattr in floatbuffer
  5943. if ($this->floatbuffer[$this->floatmargins['R']['id']]['border_left']['w']) {
  5944. $this->floatbuffer[$this->floatmargins['R']['id']]['BORDER-Y'] += $yadj;
  5945. }
  5946. $this->floatbuffer[$this->floatmargins['R']['id']]['INNER-Y'] += $yadj;
  5947. $this->floatbuffer[$this->floatmargins['R']['id']]['OUTER-Y'] += $yadj;
  5948. // Unset values
  5949. $this->floatbuffer[$this->floatmargins['R']['id']]['skipline'] = false;
  5950. $this->floatmargins['R']['skipline'] = false;
  5951. $this->floatmargins['R']['id'] = '';
  5952. }
  5953. }
  5954. /*-- END CSS-IMAGE-FLOAT --*/
  5955. ////////////////////////////////////////////////////////////////////////////////
  5956. // ADDED forcewrap - to call from inline OBJECT functions to breakwords if necessary in cell
  5957. ////////////////////////////////////////////////////////////////////////////////
  5958. function WordWrap(&$text, $maxwidth, $forcewrap = 0) {
  5959. $biggestword=0;
  5960. $toonarrow=false;
  5961. $text = trim($text);
  5962. if ($text==='') return 0;
  5963. $space = $this->GetCharWidth(' ',false);
  5964. $lines = explode("\n", $text);
  5965. $text = '';
  5966. $count = 0;
  5967. foreach ($lines as $line) {
  5968. $words = explode(' ', $line);
  5969. $width = 0;
  5970. foreach ($words as $word) {
  5971. $word = trim($word);
  5972. $wordwidth = $this->GetStringWidth($word);
  5973. //Warn user that maxwidth is insufficient
  5974. if ($wordwidth > $maxwidth + 0.0001) {
  5975. if ($wordwidth > $biggestword) { $biggestword = $wordwidth; }
  5976. $toonarrow=true;
  5977. // ADDED
  5978. if ($forcewrap) {
  5979. while($wordwidth > $maxwidth) {
  5980. $chw = 0; // check width
  5981. for ( $i = 0; $i < mb_strlen($word, $this->mb_enc ); $i++ ) {
  5982. $chw = $this->GetStringWidth(mb_substr($word,0,$i+1,$this->mb_enc ));
  5983. if ($chw > $maxwidth ) {
  5984. if ($text) {
  5985. $text = rtrim($text)."\n".mb_substr($word,0,$i,$this->mb_enc );
  5986. $count++;
  5987. }
  5988. else {
  5989. $text = mb_substr($word,0,$i,$this->mb_enc );
  5990. }
  5991. $word = mb_substr($word,$i,mb_strlen($word, $this->mb_enc )-$i,$this->mb_enc );
  5992. $wordwidth = $this->GetStringWidth($word);
  5993. $width = $maxwidth;
  5994. break;
  5995. }
  5996. }
  5997. }
  5998. }
  5999. }
  6000. if ($width + $wordwidth < $maxwidth - 0.0001) {
  6001. $width += $wordwidth + $space;
  6002. $text .= $word.' ';
  6003. }
  6004. else {
  6005. $width = $wordwidth + $space;
  6006. $text = rtrim($text)."\n".$word.' ';
  6007. $count++;
  6008. }
  6009. }
  6010. $text .= "\n";
  6011. $count++;
  6012. }
  6013. $text = rtrim($text);
  6014. //Return -(wordsize) if word is bigger than maxwidth
  6015. // ADDED
  6016. if ($forcewrap) { return $count; }
  6017. if (($toonarrow) && ($this->table_error_report)) {
  6018. $this->Error("Word is too long to fit in table - ".$this->table_error_report_param);
  6019. }
  6020. if ($toonarrow) return -$biggestword;
  6021. else return $count;
  6022. }
  6023. /*-- END HTML-CSS --*/
  6024. function _SetTextRendering($mode) {
  6025. if (!(($mode == 0) || ($mode == 1) || ($mode == 2)))
  6026. $this->Error("Text rendering mode should be 0, 1 or 2 (value : $mode)");
  6027. $tr = ($mode.' Tr');
  6028. if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
  6029. $this->pageoutput[$this->page]['TextRendering'] = $tr;
  6030. }
  6031. function SetTextOutline($params=array()) { // mPDF 5.6.07
  6032. if (isset($params['outline-s']) && $params['outline-s'])
  6033. {
  6034. $this->SetLineWidth($params['outline-WIDTH']);
  6035. $this->SetDColor($params['outline-COLOR']);
  6036. $tr = ('2 Tr');
  6037. if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
  6038. $this->pageoutput[$this->page]['TextRendering'] = $tr;
  6039. }
  6040. else //Now resets all values
  6041. {
  6042. $this->SetLineWidth(0.2);
  6043. $this->SetDColor($this->ConvertColor(0));
  6044. $this->_SetTextRendering(0);
  6045. $tr = ('0 Tr');
  6046. if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
  6047. $this->pageoutput[$this->page]['TextRendering'] = $tr;
  6048. }
  6049. }
  6050. function Image($file,$x,$y,$w=0,$h=0,$type='',$link='',$paint=true, $constrain=true, $watermark=false, $shownoimg=true, $allowvector=true) {
  6051. $orig_srcpath = $file;
  6052. $this->GetFullPath($file);
  6053. $info=$this->_getImage($file, true, $allowvector, $orig_srcpath );
  6054. if(!$info && $paint) {
  6055. $info = $this->_getImage($this->noImageFile);
  6056. if ($info) {
  6057. $file = $this->noImageFile;
  6058. $w = ($info['w'] * (25.4/$this->dpi)); // 14 x 16px
  6059. $h = ($info['h'] * (25.4/$this->dpi)); // 14 x 16px
  6060. }
  6061. }
  6062. if(!$info) return false;
  6063. //Automatic width and height calculation if needed
  6064. if($w==0 and $h==0) {
  6065. /*-- IMAGES-WMF --*/
  6066. if ($info['type']=='wmf') {
  6067. // WMF units are twips (1/20pt)
  6068. // divide by 20 to get points
  6069. // divide by k to get user units
  6070. $w = abs($info['w'])/(20*_MPDFK);
  6071. $h = abs($info['h']) / (20*_MPDFK);
  6072. }
  6073. else
  6074. /*-- END IMAGES-WMF --*/
  6075. if ($info['type']=='svg') {
  6076. // returned SVG units are pts
  6077. // divide by k to get user units (mm)
  6078. $w = abs($info['w'])/_MPDFK;
  6079. $h = abs($info['h']) /_MPDFK;
  6080. }
  6081. else {
  6082. //Put image at default image dpi
  6083. $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
  6084. $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
  6085. }
  6086. }
  6087. if($w==0) $w=abs($h*$info['w']/$info['h']);
  6088. if($h==0) $h=abs($w*$info['h']/$info['w']);
  6089. /*-- WATERMARK --*/
  6090. if ($watermark) {
  6091. $maxw = $this->w;
  6092. $maxh = $this->h;
  6093. // Size = D PF or array
  6094. if (is_array($this->watermark_size)) {
  6095. $w = $this->watermark_size[0];
  6096. $h = $this->watermark_size[1];
  6097. }
  6098. else if (!is_string($this->watermark_size)) {
  6099. $maxw -= $this->watermark_size*2;
  6100. $maxh -= $this->watermark_size*2;
  6101. $w = $maxw;
  6102. $h=abs($w*$info['h']/$info['w']);
  6103. if ($h > $maxh ) {
  6104. $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
  6105. }
  6106. }
  6107. else if ($this->watermark_size == 'F') {
  6108. if ($this->ColActive) { $maxw = $this->w - ($this->DeflMargin + $this->DefrMargin); }
  6109. else { $maxw = $this->pgwidth; }
  6110. $maxh = $this->h - ($this->tMargin + $this->bMargin);
  6111. $w = $maxw;
  6112. $h=abs($w*$info['h']/$info['w']);
  6113. if ($h > $maxh ) {
  6114. $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
  6115. }
  6116. }
  6117. else if ($this->watermark_size == 'P') { // Default P
  6118. $w = $maxw;
  6119. $h=abs($w*$info['h']/$info['w']);
  6120. if ($h > $maxh ) {
  6121. $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
  6122. }
  6123. }
  6124. // Automatically resize to maximum dimensions of page if too large
  6125. if ($w > $maxw) {
  6126. $w = $maxw;
  6127. $h=abs($w*$info['h']/$info['w']);
  6128. }
  6129. if ($h > $maxh ) {
  6130. $h = $maxh ;
  6131. $w=abs($h*$info['w']/$info['h']);
  6132. }
  6133. // Position
  6134. if (is_array($this->watermark_pos)) {
  6135. $x = $this->watermark_pos[0];
  6136. $y = $this->watermark_pos[1];
  6137. }
  6138. else if ($this->watermark_pos == 'F') { // centred on printable area
  6139. if ($this->ColActive) { // *COLUMNS*
  6140. if (($this->mirrorMargins) && (($this->page)%2==0)) { $xadj = $this->DeflMargin-$this->DefrMargin; } // *COLUMNS*
  6141. else { $xadj = 0; } // *COLUMNS*
  6142. $x = ($this->DeflMargin - $xadj + ($this->w - ($this->DeflMargin + $this->DefrMargin))/2) - ($w/2); // *COLUMNS*
  6143. } // *COLUMNS*
  6144. else { // *COLUMNS*
  6145. $x = ($this->lMargin + ($this->pgwidth)/2) - ($w/2);
  6146. } // *COLUMNS*
  6147. $y = ($this->tMargin + ($this->h - ($this->tMargin + $this->bMargin))/2) - ($h/2);
  6148. }
  6149. else { // default P - centred on whole page
  6150. $x = ($this->w/2) - ($w/2);
  6151. $y = ($this->h/2) - ($h/2);
  6152. }
  6153. /*-- IMAGES-WMF --*/
  6154. if ($info['type']=='wmf') {
  6155. $sx = $w*_MPDFK / $info['w'];
  6156. $sy = -$h*_MPDFK / $info['h'];
  6157. $outstring = sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, $sy, $x*_MPDFK-$sx*$info['x'], (($this->h-$y)*_MPDFK)-$sy*$info['y'], $info['i']);
  6158. }
  6159. else
  6160. /*-- END IMAGES-WMF --*/
  6161. if ($info['type']=='svg') {
  6162. $sx = $w*_MPDFK / $info['w'];
  6163. $sy = -$h*_MPDFK / $info['h'];
  6164. $outstring = sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, $sy, $x*_MPDFK-$sx*$info['x'], (($this->h-$y)*_MPDFK)-$sy*$info['y'], $info['i']);
  6165. }
  6166. else {
  6167. $outstring = sprintf("q %.3F 0 0 %.3F %.3F %.3F cm /I%d Do Q",$w*_MPDFK,$h*_MPDFK,$x*_MPDFK,($this->h-($y+$h))*_MPDFK,$info['i']);
  6168. }
  6169. if ($this->watermarkImgBehind) {
  6170. $outstring = $this->watermarkImgAlpha . "\n" . $outstring . "\n" . $this->SetAlpha(1, 'Normal', true) . "\n";
  6171. $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', "\n".$outstring."\n".'\\1', $this->pages[$this->page]);
  6172. }
  6173. else { $this->_out($outstring); }
  6174. return 0;
  6175. } // end of IF watermark
  6176. /*-- END WATERMARK --*/
  6177. if ($constrain) {
  6178. // Automatically resize to maximum dimensions of page if too large
  6179. if (isset($this->blk[$this->blklvl]['inner_width']) && $this->blk[$this->blklvl]['inner_width']) { $maxw = $this->blk[$this->blklvl]['inner_width']; }
  6180. else { $maxw = $this->pgwidth; }
  6181. if ($w > $maxw) {
  6182. $w = $maxw;
  6183. $h=abs($w*$info['h']/$info['w']);
  6184. }
  6185. if ($h > $this->h - ($this->tMargin + $this->bMargin + 1)) { // see below - +10 to avoid drawing too close to border of page
  6186. $h = $this->h - ($this->tMargin + $this->bMargin + 1) ;
  6187. if ($this->fullImageHeight) { $h = $this->fullImageHeight; }
  6188. $w=abs($h*$info['w']/$info['h']);
  6189. }
  6190. //Avoid drawing out of the paper(exceeding width limits).
  6191. //if ( ($x + $w) > $this->fw ) {
  6192. if ( ($x + $w) > $this->w ) {
  6193. $x = $this->lMargin;
  6194. $y += 5;
  6195. }
  6196. $changedpage = false;
  6197. $oldcolumn = $this->CurrCol;
  6198. //Avoid drawing out of the page.
  6199. if($y+$h>$this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) {
  6200. $this->AddPage($this->CurOrientation);
  6201. // Added to correct for OddEven Margins
  6202. $x=$x +$this->MarginCorrection;
  6203. $y = $tMargin + $this->margin_header;
  6204. $changedpage = true;
  6205. }
  6206. /*-- COLUMNS --*/
  6207. // COLS
  6208. // COLUMN CHANGE
  6209. if ($this->CurrCol != $oldcolumn) {
  6210. $y = $this->y0;
  6211. $x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
  6212. $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
  6213. }
  6214. /*-- END COLUMNS --*/
  6215. } // end of IF constrain
  6216. /*-- IMAGES-WMF --*/
  6217. if ($info['type']=='wmf') {
  6218. $sx = $w*_MPDFK / $info['w'];
  6219. $sy = -$h*_MPDFK / $info['h'];
  6220. $outstring = sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, $sy, $x*_MPDFK-$sx*$info['x'], (($this->h-$y)*_MPDFK)-$sy*$info['y'], $info['i']);
  6221. }
  6222. else
  6223. /*-- END IMAGES-WMF --*/
  6224. if ($info['type']=='svg') {
  6225. $sx = $w*_MPDFK / $info['w'];
  6226. $sy = -$h*_MPDFK / $info['h'];
  6227. $outstring = sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, $sy, $x*_MPDFK-$sx*$info['x'], (($this->h-$y)*_MPDFK)-$sy*$info['y'], $info['i']);
  6228. }
  6229. else {
  6230. $outstring = sprintf("q %.3F 0 0 %.3F %.3F %.3F cm /I%d Do Q",$w*_MPDFK,$h*_MPDFK,$x*_MPDFK,($this->h-($y+$h))*_MPDFK,$info['i']);
  6231. }
  6232. if($paint) {
  6233. $this->_out($outstring);
  6234. if($link) $this->Link($x,$y,$w,$h,$link);
  6235. // Avoid writing text on top of the image. // THIS WAS OUTSIDE THE if ($paint) bit!!!!!!!!!!!!!!!!
  6236. $this->y = $y + $h;
  6237. }
  6238. //Return width-height array
  6239. $sizesarray['WIDTH'] = $w;
  6240. $sizesarray['HEIGHT'] = $h;
  6241. $sizesarray['X'] = $x; //Position before painting image
  6242. $sizesarray['Y'] = $y; //Position before painting image
  6243. $sizesarray['OUTPUT'] = $outstring;
  6244. $sizesarray['IMAGE_ID'] = $info['i'];
  6245. $sizesarray['itype'] = $info['type'];
  6246. $sizesarray['set-dpi'] = $info['set-dpi'];
  6247. return $sizesarray;
  6248. }
  6249. //=============================================================
  6250. //=============================================================
  6251. //=============================================================
  6252. //=============================================================
  6253. //=============================================================
  6254. /*-- HTML-CSS --*/
  6255. function _getObjAttr($t) {
  6256. $c = explode("\xbb\xa4\xac",$t,2);
  6257. $c = explode(",",$c[1],2);
  6258. foreach($c as $v) {
  6259. $v = explode("=",$v,2);
  6260. $sp[$v[0]] = $v[1];
  6261. }
  6262. return (unserialize($sp['objattr']));
  6263. }
  6264. function inlineObject($type,$x,$y,$objattr,$Lmargin,$widthUsed,$maxWidth,$lineHeight,$paint=false,$is_table=false)
  6265. {
  6266. if ($is_table) { $k = $this->shrin_k; } else { $k = 1; }
  6267. // NB $x is only used when paint=true
  6268. // Lmargin not used
  6269. $w = 0;
  6270. if (isset($objattr['width'])) { $w = $objattr['width']/$k; }
  6271. $h = 0;
  6272. if (isset($objattr['height'])) { $h = abs($objattr['height']/$k); }
  6273. $widthLeft = $maxWidth - $widthUsed;
  6274. $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 10) ;
  6275. if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
  6276. // For Images
  6277. if (isset($objattr['border_left'])) {
  6278. $extraWidth = ($objattr['border_left']['w'] + $objattr['border_right']['w'] + $objattr['margin_left']+ $objattr['margin_right'])/$k;
  6279. $extraHeight = ($objattr['border_top']['w'] + $objattr['border_bottom']['w'] + $objattr['margin_top']+ $objattr['margin_bottom'])/$k;
  6280. if ($type == 'image' || $type == 'barcode' || $type == 'textcircle') {
  6281. $extraWidth += ($objattr['padding_left'] + $objattr['padding_right'])/$k;
  6282. $extraHeight += ($objattr['padding_top'] + $objattr['padding_bottom'])/$k;
  6283. }
  6284. }
  6285. if (!isset($objattr['vertical-align'])) { $objattr['vertical-align'] = 'M'; }
  6286. if ($type == 'image' || (isset($objattr['subtype']) && $objattr['subtype'] == 'IMAGE')) {
  6287. if (isset($objattr['itype']) && ($objattr['itype'] == 'wmf' || $objattr['itype'] == 'svg')) {
  6288. $file = $objattr['file'];
  6289. $info=$this->formobjects[$file];
  6290. }
  6291. else if (isset($objattr['file'])) {
  6292. $file = $objattr['file'];
  6293. $info=$this->images[$file];
  6294. }
  6295. }
  6296. if ($type == 'annot' || $type == 'bookmark' || $type == 'indexentry' || $type == 'toc') {
  6297. $w = 0.00001;
  6298. $h = 0.00001;
  6299. }
  6300. // TEST whether need to skipline
  6301. if (!$paint) {
  6302. if ($type == 'hr') { // always force new line
  6303. if (($y + $h + $lineHeight > $this->PageBreakTrigger) && !$this->InFooter && !$is_table) { return array(-2, $w ,$h ); } // New page + new line
  6304. else { return array(1, $w ,$h ); } // new line
  6305. }
  6306. else {
  6307. if ($widthUsed > 0 && $w > $widthLeft && (!$is_table || $type != 'image')) { // New line needed
  6308. if (($y + $h + $lineHeight > $this->PageBreakTrigger) && !$this->InFooter) { return array(-2,$w ,$h ); } // New page + new line
  6309. return array(1,$w ,$h ); // new line
  6310. }
  6311. else if ($widthUsed > 0 && $w > $widthLeft && $is_table) { // New line needed in TABLE
  6312. return array(1,$w ,$h ); // new line
  6313. }
  6314. // Will fit on line but NEW PAGE REQUIRED
  6315. else if (($y + $h > $this->PageBreakTrigger) && !$this->InFooter && !$is_table) { return array(-1,$w ,$h ); }
  6316. else { return array(0,$w ,$h ); }
  6317. }
  6318. }
  6319. if ($type == 'annot' || $type == 'bookmark' || $type == 'indexentry' || $type == 'toc') {
  6320. $w = 0.00001;
  6321. $h = 0.00001;
  6322. $objattr['BORDER-WIDTH'] = 0;
  6323. $objattr['BORDER-HEIGHT'] = 0;
  6324. $objattr['BORDER-X'] = $x;
  6325. $objattr['BORDER-Y'] = $y;
  6326. $objattr['INNER-WIDTH'] = 0;
  6327. $objattr['INNER-HEIGHT'] = 0;
  6328. $objattr['INNER-X'] = $x;
  6329. $objattr['INNER-Y'] = $y;
  6330. }
  6331. if ($type == 'image') {
  6332. // Automatically resize to width remaining
  6333. if ($w > $widthLeft && !$is_table) {
  6334. $w = $widthLeft ;
  6335. $h=abs($w*$info['h']/$info['w']);
  6336. }
  6337. $img_w = $w - $extraWidth ;
  6338. $img_h = $h - $extraHeight ;
  6339. $objattr['BORDER-WIDTH'] = $img_w + $objattr['padding_left']/$k + $objattr['padding_right']/$k + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
  6340. $objattr['BORDER-HEIGHT'] = $img_h + $objattr['padding_top']/$k + $objattr['padding_bottom']/$k + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
  6341. $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
  6342. $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
  6343. $objattr['INNER-WIDTH'] = $img_w;
  6344. $objattr['INNER-HEIGHT'] = $img_h;
  6345. $objattr['INNER-X'] = $x + $objattr['padding_left']/$k + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
  6346. $objattr['INNER-Y'] = $y + $objattr['padding_top']/$k + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
  6347. $objattr['ID'] = $info['i'];
  6348. }
  6349. if ($type == 'input' && $objattr['subtype'] == 'IMAGE') {
  6350. $img_w = $w - $extraWidth ;
  6351. $img_h = $h - $extraHeight ;
  6352. $objattr['BORDER-WIDTH'] = $img_w + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
  6353. $objattr['BORDER-HEIGHT'] = $img_h + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
  6354. $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
  6355. $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
  6356. $objattr['INNER-WIDTH'] = $img_w;
  6357. $objattr['INNER-HEIGHT'] = $img_h;
  6358. $objattr['INNER-X'] = $x + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
  6359. $objattr['INNER-Y'] = $y + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
  6360. $objattr['ID'] = $info['i'];
  6361. }
  6362. if ($type == 'barcode' || $type == 'textcircle') {
  6363. $b_w = $w - $extraWidth ;
  6364. $b_h = $h - $extraHeight ;
  6365. $objattr['BORDER-WIDTH'] = $b_w + $objattr['padding_left']/$k + $objattr['padding_right']/$k + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
  6366. $objattr['BORDER-HEIGHT'] = $b_h + $objattr['padding_top']/$k + $objattr['padding_bottom']/$k + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
  6367. $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
  6368. $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
  6369. $objattr['INNER-X'] = $x + $objattr['padding_left']/$k + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
  6370. $objattr['INNER-Y'] = $y + $objattr['padding_top']/$k + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
  6371. $objattr['INNER-WIDTH'] = $b_w;
  6372. $objattr['INNER-HEIGHT'] = $b_h;
  6373. }
  6374. if ($type == 'textarea') {
  6375. // Automatically resize to width remaining
  6376. if ($w > $widthLeft && !$is_table) {
  6377. $w = $widthLeft ;
  6378. }
  6379. if (($y + $h > $this->PageBreakTrigger) && !$this->InFooter) {
  6380. $h=$this->h - $y - $this->bMargin;
  6381. }
  6382. }
  6383. if ($type == 'hr') {
  6384. if ($is_table) {
  6385. $objattr['INNER-WIDTH'] = $maxWidth * $objattr['W-PERCENT']/100;
  6386. $objattr['width'] = $objattr['INNER-WIDTH'];
  6387. $w = $maxWidth;
  6388. }
  6389. else {
  6390. if ($w>$maxWidth) { $w = $maxWidth; }
  6391. $objattr['INNER-WIDTH'] = $w;
  6392. $w = $maxWidth;
  6393. }
  6394. }
  6395. if (($type == 'select') || ($type == 'input' && ($objattr['subtype'] == 'TEXT' || $objattr['subtype'] == 'PASSWORD'))) {
  6396. // Automatically resize to width remaining
  6397. if ($w > $widthLeft && !$is_table) {
  6398. $w = $widthLeft;
  6399. }
  6400. }
  6401. if ($type == 'textarea' || $type == 'select' || $type == 'input') {
  6402. if (isset($objattr['fontsize'])) $objattr['fontsize'] /= $k;
  6403. if (isset($objattr['linewidth'])) $objattr['linewidth'] /= $k;
  6404. }
  6405. if (!isset($objattr['BORDER-Y'])) { $objattr['BORDER-Y'] = 0; }
  6406. if (!isset($objattr['BORDER-X'])) { $objattr['BORDER-X'] = 0; }
  6407. if (!isset($objattr['INNER-Y'])) { $objattr['INNER-Y'] = 0; }
  6408. if (!isset($objattr['INNER-X'])) { $objattr['INNER-X'] = 0; }
  6409. //Return width-height array
  6410. $objattr['OUTER-WIDTH'] = $w;
  6411. $objattr['OUTER-HEIGHT'] = $h;
  6412. $objattr['OUTER-X'] = $x;
  6413. $objattr['OUTER-Y'] = $y;
  6414. return $objattr;
  6415. }
  6416. /*-- END HTML-CSS --*/
  6417. //=============================================================
  6418. //=============================================================
  6419. //=============================================================
  6420. //=============================================================
  6421. //=============================================================
  6422. function SetLineJoin($mode=0)
  6423. {
  6424. $s=sprintf('%d j',$mode);
  6425. if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineJoin']) && $this->pageoutput[$this->page]['LineJoin'] != $s) || !isset($this->pageoutput[$this->page]['LineJoin']) || $this->keep_block_together)) { $this->_out($s); }
  6426. $this->pageoutput[$this->page]['LineJoin'] = $s;
  6427. }
  6428. function SetLineCap($mode=2) {
  6429. $s=sprintf('%d J',$mode);
  6430. if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineCap']) && $this->pageoutput[$this->page]['LineCap'] != $s) || !isset($this->pageoutput[$this->page]['LineCap']) || $this->keep_block_together)) { $this->_out($s); }
  6431. $this->pageoutput[$this->page]['LineCap'] = $s;
  6432. }
  6433. function SetDash($black=false,$white=false)
  6434. {
  6435. if($black and $white) $s=sprintf('[%.3F %.3F] 0 d',$black*_MPDFK,$white*_MPDFK);
  6436. else $s='[] 0 d';
  6437. if($this->page>0 && ((isset($this->pageoutput[$this->page]['Dash']) && $this->pageoutput[$this->page]['Dash'] != $s) || !isset($this->pageoutput[$this->page]['Dash']) || $this->keep_block_together)) { $this->_out($s); }
  6438. $this->pageoutput[$this->page]['Dash'] = $s;
  6439. }
  6440. function SetDisplayPreferences($preferences) {
  6441. // String containing any or none of /HideMenubar/HideToolbar/HideWindowUI/DisplayDocTitle/CenterWindow/FitWindow
  6442. $this->DisplayPreferences .= $preferences;
  6443. }
  6444. function Ln($h='',$collapsible=0)
  6445. {
  6446. // Added collapsible to allow collapsible top-margin on new page
  6447. //Line feed; default value is last cell height
  6448. $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
  6449. if ($collapsible && ($this->y==$this->tMargin) && (!$this->ColActive)) { $h = 0; }
  6450. if(is_string($h)) $this->y+=$this->lasth;
  6451. else $this->y+=$h;
  6452. }
  6453. /*-- HTML-CSS --*/
  6454. // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
  6455. function DivLn($h,$level=-3,$move_y=true,$collapsible=false,$state=0) {
  6456. // this->x is returned as it was
  6457. // adds lines (y) where DIV bgcolors are filled in
  6458. // allows .00001 as nominal height used for bookmarks/annotations etc.
  6459. if ($collapsible && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->tMargin)) && (!$this->ColActive)) { return; }
  6460. if ($collapsible && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->y0)) && ($this->ColActive) && $this->CurrCol == 0) { return; } // *COLUMNS*
  6461. // Still use this method if columns or page-break-inside: avoid, as it allows repositioning later
  6462. // otherwise, now uses PaintDivBB()
  6463. if (!$this->ColActive && !$this->keep_block_together && !$this->kwt) {
  6464. if ($move_y && !$this->ColActive) { $this->y += $h; }
  6465. return;
  6466. }
  6467. if ($level == -3) { $level = $this->blklvl; }
  6468. $firstblockfill = $this->GetFirstBlockFill();
  6469. if ($firstblockfill && $this->blklvl > 0 && $this->blklvl >= $firstblockfill) {
  6470. $last_x = 0;
  6471. $last_w = 0;
  6472. $last_fc = $this->FillColor;
  6473. $bak_x = $this->x;
  6474. $bak_h = $this->divheight;
  6475. $this->divheight = 0; // Temporarily turn off divheight - as Cell() uses it to check for PageBreak
  6476. for ($blvl=$firstblockfill;$blvl<=$level;$blvl++) {
  6477. $this->SetBlockFill($blvl);
  6478. $this->x = $this->lMargin + $this->blk[$blvl]['outer_left_margin'];
  6479. if ($last_x != $this->lMargin + $this->blk[$blvl]['outer_left_margin'] || $last_w != $this->blk[$blvl]['width'] || $last_fc != $this->FillColor || $this->blk[$blvl]['border_top']['s'] || $this->blk[$blvl]['border_bottom']['s'] || $this->blk[$blvl]['border_left']['s'] || $this->blk[$blvl]['border_right']['s']) { // mPDF 5.6.55
  6480. $x = $this->x;
  6481. $this->Cell( ($this->blk[$blvl]['width']), $h, '', '', 0, '', 1);
  6482. if (!$this->keep_block_together && !$this->writingHTMLheader && !$this->writingHTMLfooter) {
  6483. $this->x = $x;
  6484. // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
  6485. if ($blvl == $this->blklvl) { $this->PaintDivLnBorder($state,$blvl,$h); }
  6486. else { $this->PaintDivLnBorder(0,$blvl,$h); }
  6487. }
  6488. }
  6489. $last_x = $this->lMargin + $this->blk[$blvl]['outer_left_margin'];
  6490. $last_w = $this->blk[$blvl]['width'];
  6491. $last_fc = $this->FillColor;
  6492. }
  6493. // Reset current block fill
  6494. if (isset($this->blk[$this->blklvl]['bgcolorarray'])) {
  6495. $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
  6496. $this->SetFColor($bcor);
  6497. }
  6498. $this->x = $bak_x;
  6499. $this->divheight = $bak_h;
  6500. }
  6501. if ($move_y) { $this->y += $h; }
  6502. }
  6503. /*-- END HTML-CSS --*/
  6504. function SetX($x)
  6505. {
  6506. //Set x position
  6507. if($x >= 0) $this->x=$x;
  6508. else $this->x = $this->w + $x;
  6509. }
  6510. function SetY($y)
  6511. {
  6512. //Set y position and reset x
  6513. $this->x=$this->lMargin;
  6514. if($y>=0)
  6515. $this->y=$y;
  6516. else
  6517. $this->y=$this->h+$y;
  6518. }
  6519. function SetXY($x,$y)
  6520. {
  6521. //Set x and y positions
  6522. $this->SetY($y);
  6523. $this->SetX($x);
  6524. }
  6525. function Output($name='',$dest='')
  6526. {
  6527. //Output PDF to some destination
  6528. if ($this->showStats) {
  6529. echo '<div>Generated in '.sprintf('%.2F',(microtime(true) - $this->time0)).' seconds</div>';
  6530. }
  6531. //Finish document if necessary
  6532. if ($this->progressBar) { $this->UpdateProgressBar(1,'100','Finished'); } // *PROGRESS-BAR*
  6533. if($this->state < 3) $this->Close();
  6534. if ($this->progressBar) { $this->UpdateProgressBar(2,'100','Finished'); } // *PROGRESS-BAR*
  6535. // fn. error_get_last is only in PHP>=5.2
  6536. if ($this->debug && function_exists('error_get_last') && error_get_last()) {
  6537. $e = error_get_last();
  6538. if (($e['type'] < 2048 && $e['type'] != 8) || (intval($e['type']) & intval(ini_get("error_reporting")))) {
  6539. echo "<p>Error message detected - PDF file generation aborted.</p>";
  6540. echo $e['message'].'<br />';
  6541. echo 'File: '.$e['file'].'<br />';
  6542. echo 'Line: '.$e['line'].'<br />';
  6543. exit;
  6544. }
  6545. }
  6546. if (($this->PDFA || $this->PDFX) && $this->encrypted) { $this->Error("PDFA1-b or PDFX/1-a does not permit encryption of documents."); }
  6547. if (count($this->PDFAXwarnings) && (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto))) {
  6548. if ($this->PDFA) {
  6549. echo '<div>WARNING - This file could not be generated as it stands as a PDFA1-b compliant file.</div>';
  6550. echo '<div>These issues can be automatically fixed by mPDF using <i>$mpdf-&gt;PDFAauto=true;</i></div>';
  6551. echo '<div>Action that mPDF will take to automatically force PDFA1-b compliance are shown in brackets.</div>';
  6552. }
  6553. else {
  6554. echo '<div>WARNING - This file could not be generated as it stands as a PDFX/1-a compliant file.</div>';
  6555. echo '<div>These issues can be automatically fixed by mPDF using <i>$mpdf-&gt;PDFXauto=true;</i></div>';
  6556. echo '<div>Action that mPDF will take to automatically force PDFX/1-a compliance are shown in brackets.</div>';
  6557. }
  6558. echo '<div>Warning(s) generated:</div><ul>';
  6559. $this->PDFAXwarnings = array_unique($this->PDFAXwarnings);
  6560. foreach($this->PDFAXwarnings AS $w) {
  6561. echo '<li>'.$w.'</li>';
  6562. }
  6563. echo '</ul>';
  6564. exit;
  6565. }
  6566. if ($this->showStats) {
  6567. echo '<div>Compiled in '.sprintf('%.2F',(microtime(true) - $this->time0)).' seconds (total)</div>';
  6568. echo '<div>Peak Memory usage '.number_format((memory_get_peak_usage(true)/(1024*1024)),2).' MB</div>';
  6569. echo '<div>PDF file size '.number_format((strlen($this->buffer)/1024)).' kB</div>';
  6570. echo '<div>Number of fonts '.count($this->fonts).'</div>';
  6571. exit;
  6572. }
  6573. if(is_bool($dest)) $dest=$dest ? 'D' : 'F';
  6574. $dest=strtoupper($dest);
  6575. if($dest=='') {
  6576. if($name=='') {
  6577. $name='mpdf.pdf';
  6578. $dest='I';
  6579. }
  6580. else { $dest='F'; }
  6581. }
  6582. /*-- PROGRESS-BAR --*/
  6583. if ($this->progressBar && ($dest=='D' || $dest=='I')) {
  6584. if($name=='') { $name='mpdf.pdf'; }
  6585. $tempfile = '_tempPDF'.RAND(1,10000);
  6586. //Save to local file
  6587. $f=fopen(_MPDF_TEMP_PATH.$tempfile.'.pdf','wb');
  6588. if(!$f) $this->Error('Unable to create temporary output file: '.$tempfile.'.pdf');
  6589. fwrite($f,$this->buffer,strlen($this->buffer));
  6590. fclose($f);
  6591. $this->UpdateProgressBar(3,'','Finished');
  6592. echo '<script type="text/javascript">
  6593. var form = document.createElement("form");
  6594. form.setAttribute("method", "post");
  6595. form.setAttribute("action", "'._MPDF_URI.'includes/out.php");
  6596. var hiddenField = document.createElement("input");
  6597. hiddenField.setAttribute("type", "hidden");
  6598. hiddenField.setAttribute("name", "filename");
  6599. hiddenField.setAttribute("value", "'.$tempfile.'");
  6600. form.appendChild(hiddenField);
  6601. var hiddenField = document.createElement("input");
  6602. hiddenField.setAttribute("type", "hidden");
  6603. hiddenField.setAttribute("name", "dest");
  6604. hiddenField.setAttribute("value", "'.$dest.'");
  6605. form.appendChild(hiddenField);
  6606. var hiddenField = document.createElement("input");
  6607. hiddenField.setAttribute("type", "hidden");
  6608. hiddenField.setAttribute("name", "opname");
  6609. hiddenField.setAttribute("value", "'.$name.'");
  6610. form.appendChild(hiddenField);
  6611. var hiddenField = document.createElement("input");
  6612. hiddenField.setAttribute("type", "hidden");
  6613. hiddenField.setAttribute("name", "path");
  6614. hiddenField.setAttribute("value", "'.urlencode(_MPDF_TEMP_PATH).'");
  6615. form.appendChild(hiddenField);
  6616. document.body.appendChild(form);
  6617. form.submit();
  6618. </script>
  6619. </div>
  6620. </body>
  6621. </html>';
  6622. exit;
  6623. }
  6624. else {
  6625. if ($this->progressBar) { $this->UpdateProgressBar(3,'','Finished'); }
  6626. /*-- END PROGRESS-BAR --*/
  6627. switch($dest) {
  6628. case 'I':
  6629. if ($this->debug && !$this->allow_output_buffering && ob_get_contents()) { echo "<p>Output has already been sent from the script - PDF file generation aborted.</p>"; exit; }
  6630. //Send to standard output
  6631. if(PHP_SAPI!='cli') {
  6632. //We send to a browser
  6633. header('Content-Type: application/pdf');
  6634. if(headers_sent())
  6635. $this->Error('Some data has already been output to browser, can\'t send PDF file');
  6636. if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
  6637. // don't use length if server using compression
  6638. header('Content-Length: '.strlen($this->buffer));
  6639. }
  6640. header('Content-disposition: inline; filename="'.$name.'"');
  6641. header('Cache-Control: public, must-revalidate, max-age=0');
  6642. header('Pragma: public');
  6643. header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
  6644. header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
  6645. }
  6646. echo $this->buffer;
  6647. break;
  6648. case 'D':
  6649. //Download file
  6650. header('Content-Description: File Transfer');
  6651. if (headers_sent())
  6652. $this->Error('Some data has already been output to browser, can\'t send PDF file');
  6653. header('Content-Transfer-Encoding: binary');
  6654. header('Cache-Control: public, must-revalidate, max-age=0');
  6655. header('Pragma: public');
  6656. header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
  6657. header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
  6658. header('Content-Type: application/force-download');
  6659. header('Content-Type: application/octet-stream', false);
  6660. header('Content-Type: application/download', false);
  6661. header('Content-Type: application/pdf', false);
  6662. if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
  6663. // don't use length if server using compression
  6664. header('Content-Length: '.strlen($this->buffer));
  6665. }
  6666. header('Content-disposition: attachment; filename="'.$name.'"');
  6667. echo $this->buffer;
  6668. break;
  6669. case 'F':
  6670. //Save to local file
  6671. $f=fopen($name,'wb');
  6672. if(!$f) $this->Error('Unable to create output file: '.$name);
  6673. fwrite($f,$this->buffer,strlen($this->buffer));
  6674. fclose($f);
  6675. break;
  6676. case 'S':
  6677. //Return as a string
  6678. return $this->buffer;
  6679. default:
  6680. $this->Error('Incorrect output destination: '.$dest);
  6681. }
  6682. } // *PROGRESS-BAR*
  6683. //======================================================================================================
  6684. // DELETE OLD TMP FILES - Housekeeping
  6685. // Delete any files in tmp/ directory that are >1 hrs old
  6686. $interval = 3600;
  6687. if ($handle = opendir(preg_replace('/\/$/','',_MPDF_TEMP_PATH))) {
  6688. while (false !== ($file = readdir($handle))) {
  6689. if (!is_dir($file) && ((filemtime(_MPDF_TEMP_PATH.$file)+$interval) < time()) && ($file != "..") && ($file != ".")) { // mPDF 5.4.19
  6690. unlink(_MPDF_TEMP_PATH.$file);
  6691. }
  6692. }
  6693. closedir($handle);
  6694. }
  6695. //==============================================================================================================
  6696. return '';
  6697. }
  6698. // *****************************************************************************
  6699. // *
  6700. // Protected methods *
  6701. // *
  6702. // *****************************************************************************
  6703. function _dochecks()
  6704. {
  6705. //Check for locale-related bug
  6706. if(1.1==1)
  6707. $this->Error('Don\'t alter the locale before including mPDF');
  6708. //Check for decimal separator
  6709. if(sprintf('%.1f',1.0)!='1.0')
  6710. setlocale(LC_NUMERIC,'C');
  6711. // mPDF 5.4.11
  6712. $mqr=ini_get("magic_quotes_runtime");
  6713. if ($mqr) { $this->Error('mPDF requires magic_quotes_runtime to be turned off e.g. by using ini_set("magic_quotes_runtime", 0);'); }
  6714. }
  6715. function _begindoc()
  6716. {
  6717. //Start document
  6718. $this->state=1;
  6719. $this->_out('%PDF-'.$this->pdf_version);
  6720. $this->_out('%'.chr(226).chr(227).chr(207).chr(211)); // 4 chars > 128 to show binary file
  6721. }
  6722. /*-- HTMLHEADERS-FOOTERS --*/
  6723. function _puthtmlheaders() {
  6724. $this->state=2;
  6725. $nb=$this->page;
  6726. for($n=1;$n<=$nb;$n++) {
  6727. if ($this->mirrorMargins && $n%2==0) { $OE = 'E'; } // EVEN
  6728. else { $OE = 'O'; }
  6729. $this->page = $n;
  6730. if (isset($this->saveHTMLHeader[$n][$OE])) {
  6731. $html = $this->saveHTMLHeader[$n][$OE]['html'];
  6732. $this->lMargin = $this->saveHTMLHeader[$n][$OE]['ml'];
  6733. $this->rMargin = $this->saveHTMLHeader[$n][$OE]['mr'];
  6734. $this->tMargin = $this->saveHTMLHeader[$n][$OE]['mh'];
  6735. $this->bMargin = $this->saveHTMLHeader[$n][$OE]['mf'];
  6736. $this->margin_header = $this->saveHTMLHeader[$n][$OE]['mh'];
  6737. $this->margin_footer = $this->saveHTMLHeader[$n][$OE]['mf'];
  6738. $this->w = $this->saveHTMLHeader[$n][$OE]['pw'];
  6739. $this->h = $this->saveHTMLHeader[$n][$OE]['ph'];
  6740. $rotate = (isset($this->saveHTMLHeader[$n][$OE]['rotate']) ? $this->saveHTMLHeader[$n][$OE]['rotate'] : null);
  6741. $this->Reset();
  6742. $this->pageoutput[$n] = array();
  6743. $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
  6744. $this->x = $this->lMargin;
  6745. $this->y = $this->margin_header;
  6746. // mPDF 5.6.47
  6747. $pn = $this->docPageNum($n);
  6748. if ($pn)
  6749. $pnstr = $this->pagenumPrefix.$pn.$this->pagenumSuffix;
  6750. else { $pnstr = ''; }
  6751. $html = str_replace('{PAGENO}',$pnstr,$html);
  6752. $pnt = $this->docPageNumTotal($n);
  6753. if ($pnt)
  6754. $pntstr = $this->nbpgPrefix.$pnt.$this->nbpgSuffix;
  6755. else { $pntstr = ''; }
  6756. $html = str_replace($this->aliasNbPgGp,$pntstr,$html ); // {nbpg}
  6757. $html = str_replace($this->aliasNbPg,$nb,$html ); // {nb}
  6758. $html = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$html );
  6759. $this->HTMLheaderPageLinks = array();
  6760. $this->HTMLheaderPageAnnots = array();
  6761. $this->HTMLheaderPageForms = array();
  6762. $this->pageBackgrounds = array();
  6763. $this->writingHTMLheader = true;
  6764. $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
  6765. $this->writingHTMLheader = false;
  6766. $this->Reset();
  6767. $this->pageoutput[$n] = array();
  6768. $s = $this->PrintPageBackgrounds();
  6769. $this->headerbuffer = $s . $this->headerbuffer;
  6770. $os = '';
  6771. if ($rotate) {
  6772. $os .= sprintf('q 0 -1 1 0 0 %.3F cm ',($this->w*_MPDFK));
  6773. }
  6774. $os .= $this->headerbuffer ;
  6775. if ($rotate) {
  6776. $os .= ' Q' . "\n";
  6777. }
  6778. // Writes over the page background but behind any other output on page
  6779. $os = preg_replace('/\\\\/','\\\\\\\\',$os);
  6780. $this->pages[$n] = preg_replace('/(___HEADER___MARKER'.date('jY').')/', "\n".$os."\n".'\\1', $this->pages[$n]);
  6781. $lks = $this->HTMLheaderPageLinks;
  6782. foreach($lks AS $lk) {
  6783. if ($rotate) {
  6784. $lw = $lk[2];
  6785. $lh = $lk[3];
  6786. $lk[2] = $lh;
  6787. $lk[3] = $lw; // swap width and height
  6788. $ax = $lk[0]/_MPDFK;
  6789. $ay = $lk[1]/_MPDFK;
  6790. $bx = $ay-($lh/_MPDFK);
  6791. $by = $this->w-$ax;
  6792. $lk[0] = $bx*_MPDFK;
  6793. $lk[1] = ($this->h-$by)*_MPDFK - $lw;
  6794. }
  6795. $this->PageLinks[$n][]=$lk;
  6796. }
  6797. /*-- FORMS --*/
  6798. foreach($this->HTMLheaderPageForms AS $f) {
  6799. $this->form->forms[$f['n']] = $f;
  6800. }
  6801. /*-- END FORMS --*/
  6802. }
  6803. if (isset($this->saveHTMLFooter[$n][$OE])) {
  6804. $html = $this->saveHTMLFooter[$this->page][$OE]['html'];
  6805. $this->lMargin = $this->saveHTMLFooter[$n][$OE]['ml'];
  6806. $this->rMargin = $this->saveHTMLFooter[$n][$OE]['mr'];
  6807. $this->tMargin = $this->saveHTMLFooter[$n][$OE]['mh'];
  6808. $this->bMargin = $this->saveHTMLFooter[$n][$OE]['mf'];
  6809. $this->margin_header = $this->saveHTMLFooter[$n][$OE]['mh'];
  6810. $this->margin_footer = $this->saveHTMLFooter[$n][$OE]['mf'];
  6811. $this->w = $this->saveHTMLFooter[$n][$OE]['pw'];
  6812. $this->h = $this->saveHTMLFooter[$n][$OE]['ph'];
  6813. $rotate = (isset($this->saveHTMLFooter[$n][$OE]['rotate']) ? $this->saveHTMLFooter[$n][$OE]['rotate'] : null);
  6814. $this->Reset();
  6815. $this->pageoutput[$n] = array();
  6816. $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
  6817. $this->x = $this->lMargin;
  6818. $top_y = $this->y = $this->h - $this->margin_footer;
  6819. // if bottom-margin==0, corrects to avoid division by zero
  6820. if ($this->y == $this->h) { $top_y = $this->y = ($this->h - 0.1); }
  6821. // mPDF 5.6.47
  6822. $pn = $this->docPageNum($n);
  6823. if ($pn)
  6824. $pnstr = $this->pagenumPrefix.$pn.$this->pagenumSuffix;
  6825. else { $pnstr = ''; }
  6826. $html = str_replace('{PAGENO}',$pnstr,$html);
  6827. $pnt = $this->docPageNumTotal($n);
  6828. if ($pnt)
  6829. $pntstr = $this->nbpgPrefix.$pnt.$this->nbpgSuffix;
  6830. else { $pntstr = ''; }
  6831. $html = str_replace($this->aliasNbPgGp,$pntstr,$html ); // {nbpg}
  6832. $html = str_replace($this->aliasNbPg,$nb,$html ); // {nb}
  6833. $html = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$html );
  6834. $this->HTMLheaderPageLinks = array();
  6835. $this->HTMLheaderPageAnnots = array();
  6836. $this->HTMLheaderPageForms = array();
  6837. $this->pageBackgrounds = array();
  6838. $this->writingHTMLfooter = true;
  6839. $this->InFooter = true;
  6840. $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
  6841. $this->writingHTMLfooter = false;
  6842. $this->InFooter = false;
  6843. $this->Reset();
  6844. $this->pageoutput[$n] = array();
  6845. $fheight = $this->y - $top_y;
  6846. $adj = -$fheight;
  6847. $s = $this->PrintPageBackgrounds(-$adj);
  6848. $this->headerbuffer = $s . $this->headerbuffer;
  6849. $os = '';
  6850. $os .= $this->StartTransform(true)."\n";
  6851. if ($rotate) {
  6852. $os .= sprintf('q 0 -1 1 0 0 %.3F cm ',($this->w*_MPDFK));
  6853. }
  6854. $os .= $this->transformTranslate(0, $adj, true)."\n";
  6855. $os .= $this->headerbuffer ;
  6856. if ($rotate) {
  6857. $os .= ' Q' . "\n";
  6858. }
  6859. $os .= $this->StopTransform(true)."\n";
  6860. // Writes over the page background but behind any other output on page
  6861. $os = preg_replace('/\\\\/','\\\\\\\\',$os);
  6862. $this->pages[$n] = preg_replace('/(___HEADER___MARKER'.date('jY').')/', "\n".$os."\n".'\\1', $this->pages[$n]);
  6863. $lks = $this->HTMLheaderPageLinks;
  6864. foreach($lks AS $lk) {
  6865. $lk[1] -= $adj*_MPDFK;
  6866. if ($rotate) {
  6867. $lw = $lk[2];
  6868. $lh = $lk[3];
  6869. $lk[2] = $lh;
  6870. $lk[3] = $lw; // swap width and height
  6871. $ax = $lk[0]/_MPDFK;
  6872. $ay = $lk[1]/_MPDFK;
  6873. $bx = $ay-($lh/_MPDFK);
  6874. $by = $this->w-$ax;
  6875. $lk[0] = $bx*_MPDFK;
  6876. $lk[1] = ($this->h-$by)*_MPDFK - $lw;
  6877. }
  6878. $this->PageLinks[$n][]=$lk;
  6879. }
  6880. /*-- FORMS --*/
  6881. foreach($this->HTMLheaderPageForms AS $f) {
  6882. $f['y'] += $adj;
  6883. $this->form->forms[$f['n']] = $f;
  6884. }
  6885. /*-- END FORMS --*/
  6886. }
  6887. }
  6888. $this->page=$nb;
  6889. $this->state=1;
  6890. }
  6891. /*-- END HTMLHEADERS-FOOTERS --*/
  6892. function _putpages()
  6893. {
  6894. $nb=$this->page;
  6895. $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
  6896. if($this->DefOrientation=='P') {
  6897. $defwPt=$this->fwPt;
  6898. $defhPt=$this->fhPt;
  6899. }
  6900. else {
  6901. $defwPt=$this->fhPt;
  6902. $defhPt=$this->fwPt;
  6903. }
  6904. $annotid=(3+2*$nb);
  6905. // Active Forms
  6906. $totaladdnum = 0;
  6907. for($n=1;$n<=$nb;$n++) {
  6908. if (isset($this->PageLinks[$n])) { $totaladdnum += count($this->PageLinks[$n]); }
  6909. /*-- ANNOTATIONS --*/
  6910. if (isset($this->PageAnnots[$n])) {
  6911. foreach ($this->PageAnnots[$n] as $k => $pl) {
  6912. if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) { $totaladdnum += 2 ; }
  6913. else { $totaladdnum++; }
  6914. }
  6915. }
  6916. /*-- END ANNOTATIONS --*/
  6917. /*-- FORMS --*/
  6918. if ( count($this->form->forms) > 0 ) {
  6919. $this->form->countPageForms($n, $totaladdnum);
  6920. }
  6921. /*-- END FORMS --*/
  6922. }
  6923. /*-- FORMS --*/
  6924. // Make a note in the radio button group of the obj_id it will have
  6925. $ctr = 0;
  6926. if (count($this->form->form_radio_groups)) {
  6927. foreach($this->form->form_radio_groups AS $name=>$frg) {
  6928. $this->form->form_radio_groups[$name]['obj_id'] = $annotid + $totaladdnum + $ctr;
  6929. $ctr++;
  6930. }
  6931. }
  6932. /*-- END FORMS --*/
  6933. // Select unused fonts (usually default font)
  6934. $unused = array();
  6935. foreach($this->fonts as $fk=>$font) {
  6936. if (!$font['used'] && ($font['type']=='TTF')) {
  6937. $unused[] = $fk;
  6938. }
  6939. }
  6940. for($n=1;$n<=$nb;$n++)
  6941. {
  6942. $thispage = $this->pages[$n];
  6943. // unset($this->pages[$n]); // mPDF 5.6.47
  6944. if(isset($this->OrientationChanges[$n])) {
  6945. $hPt=$this->pageDim[$n]['w']*_MPDFK;
  6946. $wPt=$this->pageDim[$n]['h']*_MPDFK;
  6947. $owidthPt_LR = $this->pageDim[$n]['outer_width_TB']*_MPDFK;
  6948. $owidthPt_TB = $this->pageDim[$n]['outer_width_LR']*_MPDFK;
  6949. }
  6950. else {
  6951. $wPt=$this->pageDim[$n]['w']*_MPDFK;
  6952. $hPt=$this->pageDim[$n]['h']*_MPDFK;
  6953. $owidthPt_LR = $this->pageDim[$n]['outer_width_LR']*_MPDFK;
  6954. $owidthPt_TB = $this->pageDim[$n]['outer_width_TB']*_MPDFK;
  6955. }
  6956. // Remove references to unused fonts (usually default font)
  6957. foreach($unused as $fk) {
  6958. if ($this->fonts[$fk]['sip'] || $this->fonts[$fk]['smp']) {
  6959. foreach($this->fonts[$fk]['subsetfontids'] AS $k => $fid) {
  6960. $thispage = preg_replace('/\s\/F'.$fid.' \d[\d.]* Tf\s/is',' ',$thispage);
  6961. }
  6962. }
  6963. else {
  6964. $thispage = preg_replace('/\s\/F'.$this->fonts[$fk]['i'].' \d[\d.]* Tf\s/is',' ',$thispage);
  6965. }
  6966. }
  6967. //Replace number of pages
  6968. if(!empty($this->aliasNbPg)) {
  6969. if (!$this->onlyCoreFonts) { $s1 = $this->UTF8ToUTF16BE($this->aliasNbPg, false); }
  6970. $s2 = $this->aliasNbPg;
  6971. if (!$this->onlyCoreFonts) { $r1 = $this->UTF8ToUTF16BE($nb, false); }
  6972. $r2 = $nb;
  6973. if (preg_match_all('/{mpdfheadernbpg (C|R) ff=(\S*) fs=(\S*) fz=(.*?)}/',$thispage,$m)) {
  6974. for($hi=0;$hi<count($m[0]);$hi++) {
  6975. $pos = $m[1][$hi];
  6976. $hff = $m[2][$hi];
  6977. $hfst = $m[3][$hi];
  6978. $hfsz = $m[4][$hi];
  6979. $this->SetFont($hff,$hfst,$hfsz, false);
  6980. $x1 = $this->GetStringWidth($this->aliasNbPg);
  6981. $x2 = $this->GetStringWidth($nb);
  6982. $xadj = $x1 - $x2;
  6983. if ($pos=='C') { $xadj /= 2; }
  6984. $rep = sprintf(' q 1 0 0 1 %.3F 0 cm ', $xadj*_MPDFK);
  6985. $thispage = str_replace($m[0][$hi], $rep, $thispage);
  6986. }
  6987. }
  6988. if (!$this->onlyCoreFonts) { $thispage=str_replace($s1,$r1,$thispage); }
  6989. $thispage=str_replace($s2,$r2,$thispage);
  6990. // And now for any SMP/SIP fonts subset using <HH> format
  6991. $r = '';
  6992. $nstr = "$nb";
  6993. for($i=0;$i<strlen($nstr);$i++) {
  6994. $r .= sprintf("%02s", strtoupper(dechex(intval($nstr[$i])+48)));
  6995. }
  6996. $thispage=str_replace($this->aliasNbPgHex,$r,$thispage);
  6997. }
  6998. //Replace number of pages in group
  6999. if(!empty($this->aliasNbPgGp)) {
  7000. if (!$this->onlyCoreFonts) { $s1 = $this->UTF8ToUTF16BE($this->aliasNbPgGp, false); }
  7001. $s2 = $this->aliasNbPgGp;
  7002. $nbt = $this->docPageNumTotal($n);
  7003. if (!$this->onlyCoreFonts) { $r1 = $this->UTF8ToUTF16BE($nbt, false); }
  7004. $r2 = $nbt;
  7005. if (preg_match_all('/{mpdfheadernbpggp (C|R) ff=(\S*) fs=(\S*) fz=(.*?)}/',$thispage,$m)) {
  7006. for($hi=0;$hi<count($m[0]);$hi++) {
  7007. $pos = $m[1][$hi];
  7008. $hff = $m[2][$hi];
  7009. $hfst = $m[3][$hi];
  7010. $hfsz = $m[4][$hi];
  7011. $this->SetFont($hff,$hfst,$hfsz, false);
  7012. $x1 = $this->GetStringWidth($this->aliasNbPgGp);
  7013. $x2 = $this->GetStringWidth($nbt);
  7014. $xadj = $x1 - $x2;
  7015. if ($pos=='C') { $xadj /= 2; }
  7016. $rep = sprintf(' q 1 0 0 1 %.3F 0 cm ', $xadj*_MPDFK);
  7017. $thispage = str_replace($m[0][$hi], $rep, $thispage);
  7018. }
  7019. }
  7020. if (!$this->onlyCoreFonts) { $thispage=str_replace($s1,$r1,$thispage); }
  7021. $thispage=str_replace($s2,$r2,$thispage);
  7022. // And now for any SMP/SIP fonts subset using <HH> format
  7023. $r = '';
  7024. $nstr = "$nbt";
  7025. for($i=0;$i<strlen($nstr);$i++) {
  7026. $r .= sprintf("%02s", strtoupper(dechex(intval($nstr[$i])+48)));
  7027. }
  7028. $thispage=str_replace($this->aliasNbPgGpHex,$r,$thispage);
  7029. }
  7030. $thispage = preg_replace('/(\s*___BACKGROUND___PATTERNS'.date('jY').'\s*)/', " ", $thispage);
  7031. $thispage = preg_replace('/(\s*___HEADER___MARKER'.date('jY').'\s*)/', " ", $thispage);
  7032. $thispage = preg_replace('/(\s*___PAGE___START'.date('jY').'\s*)/', " ", $thispage);
  7033. $thispage = preg_replace('/(\s*___TABLE___BACKGROUNDS'.date('jY').'\s*)/', " ", $thispage);
  7034. //Page
  7035. $this->_newobj();
  7036. $this->_out('<</Type /Page');
  7037. $this->_out('/Parent 1 0 R');
  7038. if(isset($this->OrientationChanges[$n])) {
  7039. $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$hPt,$wPt));
  7040. //If BleedBox is defined, it must be larger than the TrimBox, but smaller than the MediaBox
  7041. $bleedMargin = $this->pageDim[$n]['bleedMargin']*_MPDFK;
  7042. if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
  7043. $x0 = $owidthPt_TB-$bleedMargin;
  7044. $y0 = $owidthPt_LR-$bleedMargin;
  7045. $x1 = $hPt-$owidthPt_TB+$bleedMargin;
  7046. $y1 = $wPt-$owidthPt_LR+$bleedMargin;
  7047. $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
  7048. }
  7049. $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_TB, $owidthPt_LR, ($hPt-$owidthPt_TB), ($wPt-$owidthPt_LR)));
  7050. if (isset($this->OrientationChanges[$n]) && $this->displayDefaultOrientation) {
  7051. if ($this->DefOrientation=='P') { $this->_out('/Rotate 270'); }
  7052. else { $this->_out('/Rotate 90'); }
  7053. }
  7054. }
  7055. //else if($wPt != $defwPt || $hPt != $defhPt) {
  7056. else {
  7057. $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$wPt,$hPt));
  7058. $bleedMargin = $this->pageDim[$n]['bleedMargin']*_MPDFK;
  7059. if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
  7060. $x0 = $owidthPt_LR-$bleedMargin;
  7061. $y0 = $owidthPt_TB-$bleedMargin;
  7062. $x1 = $wPt-$owidthPt_LR+$bleedMargin;
  7063. $y1 = $hPt-$owidthPt_TB+$bleedMargin;
  7064. $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
  7065. }
  7066. $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_LR, $owidthPt_TB, ($wPt-$owidthPt_LR), ($hPt-$owidthPt_TB)));
  7067. }
  7068. $this->_out('/Resources 2 0 R');
  7069. // Important to keep in RGB colorSpace when using transparency
  7070. if (!$this->PDFA && !$this->PDFX) {
  7071. if ($this->restrictColorSpace == 3)
  7072. $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceCMYK >> ');
  7073. else if ($this->restrictColorSpace == 1)
  7074. $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceGray >> ');
  7075. else
  7076. $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceRGB >> ');
  7077. }
  7078. $annotsnum = 0;
  7079. if (isset($this->PageLinks[$n])) { $annotsnum += count($this->PageLinks[$n]); }
  7080. /*-- ANNOTATIONS --*/
  7081. if (isset($this->PageAnnots[$n])) {
  7082. foreach ($this->PageAnnots[$n] as $k => $pl) {
  7083. if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) { $annotsnum += 2 ; }
  7084. else { $annotsnum++; }
  7085. $this->PageAnnots[$n][$k]['pageobj'] = $this->n;
  7086. }
  7087. }
  7088. /*-- END ANNOTATIONS --*/
  7089. /*-- FORMS --*/
  7090. // Active Forms
  7091. $formsnum = 0;
  7092. if ( count($this->form->forms) > 0 ) {
  7093. foreach( $this->form->forms as $val ) {
  7094. if ( $val['page'] == $n )
  7095. $formsnum++;
  7096. }
  7097. }
  7098. /*-- END FORMS --*/
  7099. if ($annotsnum || $formsnum) {
  7100. $s = '/Annots [ ';
  7101. for($i=0;$i<$annotsnum;$i++) {
  7102. $s .= ($annotid + $i) . ' 0 R ';
  7103. }
  7104. $annotid += $annotsnum;
  7105. /*-- FORMS --*/
  7106. if ( count($this->form->forms) > 0 ) {
  7107. $this->form->addFormIds($n, $s, $annotid);
  7108. }
  7109. /*-- END FORMS --*/
  7110. $s .= '] ';
  7111. $this->_out($s);
  7112. }
  7113. $this->_out('/Contents '.($this->n+1).' 0 R>>');
  7114. $this->_out('endobj');
  7115. //Page content
  7116. $this->_newobj();
  7117. $p=($this->compress) ? gzcompress($thispage) : $thispage;
  7118. $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
  7119. $this->_putstream($p);
  7120. $this->_out('endobj');
  7121. }
  7122. $this->_putannots($n);
  7123. //Pages root
  7124. $this->offsets[1]=strlen($this->buffer);
  7125. $this->_out('1 0 obj');
  7126. $this->_out('<</Type /Pages');
  7127. $kids='/Kids [';
  7128. for($i=0;$i<$nb;$i++)
  7129. $kids.=(3+2*$i).' 0 R ';
  7130. $this->_out($kids.']');
  7131. $this->_out('/Count '.$nb);
  7132. $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$defwPt,$defhPt));
  7133. $this->_out('>>');
  7134. $this->_out('endobj');
  7135. }
  7136. function _putannots($n) {
  7137. $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
  7138. $nb=$this->page;
  7139. for($n=1;$n<=$nb;$n++)
  7140. {
  7141. $annotobjs = array();
  7142. if(isset($this->PageLinks[$n]) || isset($this->PageAnnots[$n]) || count($this->form->forms) > 0 ) {
  7143. $wPt=$this->pageDim[$n]['w']*_MPDFK;
  7144. $hPt=$this->pageDim[$n]['h']*_MPDFK;
  7145. //Links
  7146. if(isset($this->PageLinks[$n])) {
  7147. foreach($this->PageLinks[$n] as $key => $pl) {
  7148. $this->_newobj();
  7149. $annot='';
  7150. $rect=sprintf('%.3F %.3F %.3F %.3F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
  7151. $annot .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.']';
  7152. $annot .= ' /Contents '.$this->_UTF16BEtextstring($pl[4]);
  7153. $annot .= ' /NM '.$this->_textstring(sprintf('%04u-%04u', $n, $key));
  7154. $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
  7155. $annot .= ' /Border [0 0 0]';
  7156. // Use this (instead of /Border) to specify border around link
  7157. // $annot .= ' /BS <</W 1'; // Width on points; 0 = no line
  7158. // $annot .= ' /S /D'; // style - [S]olid, [D]ashed, [B]eveled, [I]nset, [U]nderline
  7159. // $annot .= ' /D [3 2]'; // Dash array - if dashed
  7160. // $annot .= ' >>';
  7161. // $annot .= ' /C [1 0 0]'; // Color RGB
  7162. if ($this->PDFA || $this->PDFX) { $annot .= ' /F 28'; }
  7163. if (strpos($pl[4],'@')===0) {
  7164. $p=substr($pl[4],1);
  7165. // $h=isset($this->OrientationChanges[$p]) ? $wPt : $hPt;
  7166. $htarg=$this->pageDim[$p]['h']*_MPDFK;
  7167. $annot.=sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>',1+2*$p,$htarg);
  7168. }
  7169. else if(is_string($pl[4])) {
  7170. $annot .= ' /A <</S /URI /URI '.$this->_textstring($pl[4]).'>> >>';
  7171. }
  7172. else {
  7173. $l=$this->links[$pl[4]];
  7174. // may not be set if #link points to non-existent target
  7175. if (isset($this->pageDim[$l[0]]['h'])) { $htarg=$this->pageDim[$l[0]]['h']*_MPDFK; }
  7176. else { $htarg=$this->h*_MPDFK; } // doesn't really matter
  7177. $annot.=sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>',1+2*$l[0],$htarg-$l[1]*_MPDFK);
  7178. }
  7179. $this->_out($annot);
  7180. $this->_out('endobj');
  7181. }
  7182. }
  7183. /*-- ANNOTATIONS --*/
  7184. if(isset($this->PageAnnots[$n])) {
  7185. foreach ($this->PageAnnots[$n] as $key => $pl) {
  7186. if ($pl['opt']['file']) { $FileAttachment=true; }
  7187. else { $FileAttachment=false; }
  7188. $this->_newobj();
  7189. $annot='';
  7190. $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER);
  7191. $x = $pl['x'];
  7192. if ($this->annotMargin <> 0 || $x==0 || $x<0) { // Odd page
  7193. $x = ($wPt/_MPDFK) - $this->annotMargin;
  7194. }
  7195. $w = $h = 0;
  7196. $a = $x * _MPDFK;
  7197. $b = $hPt - ($pl['y'] * _MPDFK);
  7198. $annot .= '<</Type /Annot ';
  7199. if ($FileAttachment) {
  7200. $annot .= '/Subtype /FileAttachment';
  7201. // Need to set a size for FileAttachment icons
  7202. if ($pl['opt']['icon']=='Paperclip') { $w=8.235; $h=20; } // 7,17
  7203. else if ($pl['opt']['icon']=='Tag') { $w=20; $h=16; }
  7204. else if ($pl['opt']['icon']=='Graph') { $w=20; $h=20; }
  7205. else { $w=14; $h=20; } // PushPin
  7206. $f = $pl['opt']['file'];
  7207. $f = preg_replace('/^.*\//', '', $f);
  7208. $f = preg_replace('/[^a-zA-Z0-9._]/', '', $f);
  7209. $annot .= '/FS <</Type /Filespec /F ('.$f.')';
  7210. $annot .= '/EF <</F '.($this->n+1).' 0 R>>';
  7211. $annot .= '>>';
  7212. }
  7213. else {
  7214. $annot .= '/Subtype /Text';
  7215. }
  7216. $rect = sprintf('%.3F %.3F %.3F %.3F', $a, $b-$h, $a+$w, $b);
  7217. $annot .= '/Rect ['.$rect.']';
  7218. // contents = description of file in free text
  7219. $annot .= ' /Contents '.$this->_UTF16BEtextstring($pl['txt']);
  7220. $annot .= ' /NM '.$this->_textstring(sprintf('%04u-%04u', $n, (2000 + $key)));
  7221. $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
  7222. $annot .= ' /CreationDate '.$this->_textstring('D:'.date('YmdHis'));
  7223. $annot .= ' /Border [0 0 0]';
  7224. if ($this->PDFA || $this->PDFX) {
  7225. $annot .= ' /F 28';
  7226. $annot .= ' /CA 1';
  7227. }
  7228. else if ($pl['opt']['ca']>0) { $annot .= ' /CA '.$pl['opt']['ca']; }
  7229. $annotcolor = ' /C [';
  7230. if (isset($pl['opt']['c']) AND $pl['opt']['c']) {
  7231. $col = $pl['opt']['c'];
  7232. if ($col{0}==3 || $col{0}==5) { $annotcolor .= sprintf("%.3F %.3F %.3F", ord($col{1})/255,ord($col{2})/255,ord($col{3})/255); }
  7233. else if ($col{0}==1) { $annotcolor .= sprintf("%.3F", ord($col{1})/255); }
  7234. else if ($col{0}==4 || $col{0}==6) { $annotcolor .= sprintf("%.3F %.3F %.3F %.3F", ord($col{1})/100,ord($col{2})/100,ord($col{3})/100,ord($col{4})/100); }
  7235. else { $annotcolor .= '1 1 0'; }
  7236. }
  7237. else { $annotcolor .= '1 1 0'; }
  7238. $annotcolor .= ']';
  7239. $annot .= $annotcolor;
  7240. // Usually Author
  7241. // Use as Title for fileattachment
  7242. if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) {
  7243. $annot .= ' /T '.$this->_UTF16BEtextstring($pl['opt']['t']);
  7244. }
  7245. if ($FileAttachment) {
  7246. $iconsapp = array('Paperclip', 'Graph', 'PushPin', 'Tag');
  7247. }
  7248. else { $iconsapp = array('Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph'); }
  7249. if (isset($pl['opt']['icon']) AND in_array($pl['opt']['icon'], $iconsapp)) {
  7250. $annot .= ' /Name /'.$pl['opt']['icon'];
  7251. }
  7252. else if ($FileAttachment) { $annot .= ' /Name /PushPin'; }
  7253. else { $annot .= ' /Name /Note'; }
  7254. if (!$FileAttachment) {
  7255. // /Subj is PDF 1.5 spec.
  7256. if (isset($pl['opt']['subj']) && !$this->PDFA && !$this->PDFX) {
  7257. $annot .= ' /Subj '.$this->_UTF16BEtextstring($pl['opt']['subj']);
  7258. }
  7259. if (!empty($pl['opt']['popup'])) {
  7260. $annot .= ' /Open true';
  7261. $annot .= ' /Popup '.($this->n+1).' 0 R';
  7262. }
  7263. else { $annot .= ' /Open false'; }
  7264. }
  7265. $annot .= ' /P '.$pl['pageobj'].' 0 R';
  7266. $annot .= '>>';
  7267. $this->_out($annot);
  7268. $this->_out('endobj');
  7269. if ($FileAttachment) {
  7270. $file = @file_get_contents($pl['opt']['file']) or die('mPDF Error: Cannot access file attachment - '.$pl['opt']['file']);
  7271. $filestream = gzcompress($file);
  7272. $this->_newobj();
  7273. $this->_out('<</Type /EmbeddedFile');
  7274. $this->_out('/Length '.strlen($filestream));
  7275. $this->_out('/Filter /FlateDecode');
  7276. $this->_out('>>');
  7277. $this->_putstream($filestream);
  7278. $this->_out('endobj');
  7279. }
  7280. else if (!empty($pl['opt']['popup'])) {
  7281. $this->_newobj();
  7282. $annot='';
  7283. if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][0])) { $x = $pl['opt']['popup'][0] * _MPDFK; }
  7284. else { $x = $pl['x'] * _MPDFK; }
  7285. if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][1])) { $y = $hPt - ($pl['opt']['popup'][1] * _MPDFK); }
  7286. else { $y = $hPt - ($pl['y'] * _MPDFK); }
  7287. if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][2])) { $w = $pl['opt']['popup'][2] * _MPDFK; }
  7288. else { $w = 180; }
  7289. if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][3])) { $h = $pl['opt']['popup'][3] * _MPDFK; }
  7290. else { $h = 120; }
  7291. $rect = sprintf('%.3F %.3F %.3F %.3F', $x, $y-$h, $x+$w, $y);
  7292. $annot .= '<</Type /Annot /Subtype /Popup /Rect ['.$rect.']';
  7293. $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
  7294. if ($this->PDFA || $this->PDFX) { $annot .= ' /F 28'; }
  7295. $annot .= ' /Parent '.($this->n-1).' 0 R';
  7296. $annot .= '>>';
  7297. $this->_out($annot);
  7298. $this->_out('endobj');
  7299. }
  7300. }
  7301. }
  7302. /*-- END ANNOTATIONS --*/
  7303. /*-- FORMS --*/
  7304. // Active Forms
  7305. if ( count($this->form->forms) > 0 ) {
  7306. $this->form->_putFormItems($n, $hPt);
  7307. }
  7308. /*-- END FORMS --*/
  7309. }
  7310. }
  7311. /*-- FORMS --*/
  7312. // Active Forms - Radio Button Group entries
  7313. // Output Radio Button Group form entries (radio_on_obj_id already determined)
  7314. if (count($this->form->form_radio_groups)) {
  7315. $this->form->_putRadioItems($n);
  7316. }
  7317. /*-- END FORMS --*/
  7318. }
  7319. /*-- ANNOTATIONS --*/
  7320. function Annotation($text, $x=0, $y=0, $icon='Note', $author='', $subject='', $opacity=0, $colarray=false, $popup='', $file='') {
  7321. if (is_array($colarray) && count($colarray)==3) { $colarray = $this->ConvertColor('rgb('.$colarray[0].','.$colarray[1].','.$colarray[2].')'); }
  7322. if ($colarray === false) { $colarray = $this->ConvertColor('yellow'); }
  7323. if ($x==0) { $x = $this->x; }
  7324. if ($y==0) { $y = $this->y; }
  7325. $page = $this->page;
  7326. if ($page < 1) { // Document has not been started - assume it's for first page
  7327. $page = 1;
  7328. if ($x==0) { $x = $this->lMargin; }
  7329. if ($y==0) { $y = $this->tMargin; }
  7330. }
  7331. if ($this->PDFA || $this->PDFX) {
  7332. if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Annotation markers cannot be semi-transparent in PDFA1-b or PDFX/1-a, so they may make underlying text unreadable. (Annotation markers moved to right margin)"; }
  7333. $x = ($this->w) - $this->rMargin*0.66;
  7334. }
  7335. if (!$this->annotMargin) { $y -= $this->FontSize / 2; }
  7336. if (!$opacity && $this->annotMargin) { $opacity = 1; }
  7337. else if (!$opacity) { $opacity = $this->annotOpacity; }
  7338. $an = array('txt' => $text, 'x' => $x, 'y' => $y, 'opt' => array('Icon'=>$icon, 'T'=>$author, 'Subj'=>$subject, 'C'=>$colarray, 'CA'=>$opacity, 'popup'=>$popup, 'file'=>$file));
  7339. if ($this->keep_block_together) { // Save to array - don't write yet
  7340. $this->ktAnnots[$this->page][]= $an;
  7341. return;
  7342. }
  7343. else if ($this->table_rotate) {
  7344. $this->tbrot_Annots[$this->page][]= $an;
  7345. return;
  7346. }
  7347. else if ($this->kwt) {
  7348. $this->kwt_Annots[$this->page][]= $an;
  7349. return;
  7350. }
  7351. // mPDF 5.0
  7352. if ($this->writingHTMLheader || $this->writingHTMLfooter) {
  7353. $this->HTMLheaderPageAnnots[]= $an;
  7354. return;
  7355. }
  7356. //Put an Annotation on the page
  7357. $this->PageAnnots[$page][] = $an;
  7358. /*-- COLUMNS --*/
  7359. // Save cross-reference to Column buffer
  7360. $ref = count($this->PageAnnots[$this->page])-1;
  7361. $this->columnAnnots[$this->CurrCol][INTVAL($this->x)][INTVAL($this->y)] = $ref;
  7362. /*-- END COLUMNS --*/
  7363. }
  7364. /*-- END ANNOTATIONS --*/
  7365. function _putfonts() {
  7366. $nf=$this->n;
  7367. foreach($this->FontFiles as $fontkey=>$info) {
  7368. // TrueType embedded
  7369. if (isset($info['type']) && $info['type']=='TTF' && !$info['sip'] && !$info['smp']) {
  7370. $used = true;
  7371. $asSubset = false;
  7372. foreach($this->fonts AS $k=>$f) {
  7373. if ($f['fontkey'] == $fontkey && $f['type']=='TTF') {
  7374. $used = $f['used'];
  7375. if ($used) {
  7376. $nChars = (ord($f['cw'][0]) << 8) + ord($f['cw'][1]);
  7377. $usage = intval(count($f['subset'])*100 / $nChars);
  7378. $fsize = $info['length1'];
  7379. // Always subset the very large TTF files
  7380. if ($fsize > ($this->maxTTFFilesize *1024)) { $asSubset = true; }
  7381. else if ($usage < $this->percentSubset) { $asSubset = true; }
  7382. }
  7383. if ($f['unAGlyphs']) $aaSubset = true; // mPDF 5.4.05
  7384. if ($this->PDFA || $this->PDFX) $asSubset = false;
  7385. $this->fonts[$k]['asSubset'] = $asSubset;
  7386. break;
  7387. }
  7388. }
  7389. if ($used && !$asSubset) {
  7390. //Font file embedding
  7391. $this->_newobj();
  7392. $this->FontFiles[$fontkey]['n']=$this->n;
  7393. $font='';
  7394. $originalsize = $info['length1'];
  7395. if ($this->repackageTTF || $this->fonts[$fontkey]['TTCfontID']>0) {
  7396. // First see if there is a cached compressed file
  7397. if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z')) {
  7398. $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z','rb');
  7399. if(!$f) { $this->Error('Font file .ps.z not found'); }
  7400. while(!feof($f)) { $font .= fread($f, 2048); }
  7401. fclose($f);
  7402. include(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php'); // sets $originalsize (of repackaged font)
  7403. }
  7404. else {
  7405. if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
  7406. $ttf = new TTFontFile();
  7407. $font = $ttf->repackageTTF($this->FontFiles[$fontkey]['ttffile'], $this->fonts[$fontkey]['TTCfontID'], $this->debugfonts, $this->fonts[$fontkey]['unAGlyphs']); // mPDF 5.4.05
  7408. $originalsize = strlen($font);
  7409. $font = gzcompress($font);
  7410. unset($ttf);
  7411. if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
  7412. $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z',"wb");
  7413. fwrite($fh,$font,strlen($font));
  7414. fclose($fh);
  7415. $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php',"wb");
  7416. $len = "<?php \n";
  7417. $len.='$originalsize='.$originalsize.";\n";
  7418. $len.="?>";
  7419. fwrite($fh,$len,strlen($len));
  7420. fclose($fh);
  7421. }
  7422. }
  7423. }
  7424. else {
  7425. // First see if there is a cached compressed file
  7426. if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.z')) {
  7427. $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z','rb');
  7428. if(!$f) { $this->Error('Font file not found'); }
  7429. while(!feof($f)) { $font .= fread($f, 2048); }
  7430. fclose($f);
  7431. }
  7432. else {
  7433. $f=fopen($this->FontFiles[$fontkey]['ttffile'],'rb');
  7434. if(!$f) { $this->Error('Font file not found'); }
  7435. while(!feof($f)) { $font .= fread($f, 2048); }
  7436. fclose($f);
  7437. $font = gzcompress($font);
  7438. if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
  7439. $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z',"wb");
  7440. fwrite($fh,$font,strlen($font));
  7441. fclose($fh);
  7442. }
  7443. }
  7444. }
  7445. $this->_out('<</Length '.strlen($font));
  7446. $this->_out('/Filter /FlateDecode');
  7447. $this->_out('/Length1 '.$originalsize);
  7448. $this->_out('>>');
  7449. $this->_putstream($font);
  7450. $this->_out('endobj');
  7451. }
  7452. }
  7453. }
  7454. $nfonts = count($this->fonts);
  7455. $fctr = 1;
  7456. foreach($this->fonts as $k=>$font) {
  7457. //Font objects
  7458. $type=$font['type'];
  7459. $name=$font['name'];
  7460. if ((!isset($font['used']) || !$font['used']) && $type=='TTF') { continue; }
  7461. if ($this->progressBar) { $this->UpdateProgressBar(2,intval($fctr*100/$nfonts),'Writing Fonts'); $fctr++; } // *PROGRESS-BAR*
  7462. if (isset($font['asSubset'])) { $asSubset = $font['asSubset']; }
  7463. else { $asSubset = ''; }
  7464. /*-- CJK-FONTS --*/
  7465. if($type=='Type0') { // = Adobe CJK Fonts
  7466. $this->fonts[$k]['n']=$this->n+1;
  7467. $this->_newobj();
  7468. $this->_out('<</Type /Font');
  7469. $this->_putType0($font);
  7470. }
  7471. else
  7472. /*-- END CJK-FONTS --*/
  7473. if($type=='core') {
  7474. //Standard font
  7475. $this->fonts[$k]['n']=$this->n+1;
  7476. if ($this->PDFA || $this->PDFX) { $this->Error('Core fonts are not allowed in PDF/A1-b or PDFX/1-a files (Times, Helvetica, Courier etc.)'); }
  7477. $this->_newobj();
  7478. $this->_out('<</Type /Font');
  7479. $this->_out('/BaseFont /'.$name);
  7480. $this->_out('/Subtype /Type1');
  7481. if($name!='Symbol' && $name!='ZapfDingbats') {
  7482. $this->_out('/Encoding /WinAnsiEncoding');
  7483. }
  7484. $this->_out('>>');
  7485. $this->_out('endobj');
  7486. }
  7487. // TrueType embedded SUBSETS for SIP (CJK extB containing Supplementary Ideographic Plane 2)
  7488. // Or Unicode Plane 1 - Supplementary Multilingual Plane
  7489. else if ($type=='TTF' && ($font['sip'] || $font['smp'])) {
  7490. if (!$font['used']) { continue; }
  7491. $ssfaid="AA";
  7492. if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
  7493. $ttf = new TTFontFile();
  7494. for($sfid=0;$sfid<count($font['subsetfontids']);$sfid++) {
  7495. $this->fonts[$k]['n'][$sfid]=$this->n+1; // NB an array for subset
  7496. $subsetname = 'MPDF'.$ssfaid.'+'.$font['name'];
  7497. $ssfaid++;
  7498. $subset = $font['subsets'][$sfid];
  7499. unset($subset[0]);
  7500. $ttfontstream = $ttf->makeSubsetSIP($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts);
  7501. $ttfontsize = strlen($ttfontstream);
  7502. $fontstream = gzcompress($ttfontstream);
  7503. $widthstring = '';
  7504. $toUnistring = '';
  7505. foreach($font['subsets'][$sfid] AS $cp=>$u) {
  7506. $w = $this->_getCharWidth($font['cw'], $u);
  7507. if ($w !== false) {
  7508. $widthstring .= $w.' ';
  7509. }
  7510. else {
  7511. $widthstring .= round($ttf->defaultWidth).' ';
  7512. }
  7513. if ($u > 65535) {
  7514. $utf8 = chr(($u>>18)+240).chr((($u>>12)&63)+128).chr((($u>>6)&63)+128) .chr(($u&63)+128);
  7515. $utf16 = mb_convert_encoding($utf8, 'UTF-16BE', 'UTF-8');
  7516. $l1 = ord($utf16[0]);
  7517. $h1 = ord($utf16[1]);
  7518. $l2 = ord($utf16[2]);
  7519. $h2 = ord($utf16[3]);
  7520. $toUnistring .= sprintf("<%02s> <%02s%02s%02s%02s>\n", strtoupper(dechex($cp)), strtoupper(dechex($l1)), strtoupper(dechex($h1)), strtoupper(dechex($l2)), strtoupper(dechex($h2)));
  7521. }
  7522. else {
  7523. $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u)));
  7524. }
  7525. }
  7526. //Additional Type1 or TrueType font
  7527. $this->_newobj();
  7528. $this->_out('<</Type /Font');
  7529. $this->_out('/BaseFont /'.$subsetname);
  7530. $this->_out('/Subtype /TrueType');
  7531. $this->_out('/FirstChar 0 /LastChar '.(count($font['subsets'][$sfid])-1));
  7532. $this->_out('/Widths '.($this->n+1).' 0 R');
  7533. $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
  7534. $this->_out('/ToUnicode '.($this->n + 3).' 0 R');
  7535. $this->_out('>>');
  7536. $this->_out('endobj');
  7537. //Widths
  7538. $this->_newobj();
  7539. $this->_out('['.$widthstring.']');
  7540. $this->_out('endobj');
  7541. //Descriptor
  7542. $this->_newobj();
  7543. $s='<</Type /FontDescriptor /FontName /'.$subsetname."\n";
  7544. foreach($font['desc'] as $kd=>$v) {
  7545. if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
  7546. $s.=' /'.$kd.' '.$v."\n";
  7547. }
  7548. $s.='/FontFile2 '.($this->n + 2).' 0 R';
  7549. $this->_out($s.'>>');
  7550. $this->_out('endobj');
  7551. // ToUnicode
  7552. $this->_newobj();
  7553. $toUni = "/CIDInit /ProcSet findresource begin\n";
  7554. $toUni .= "12 dict begin\n";
  7555. $toUni .= "begincmap\n";
  7556. $toUni .= "/CIDSystemInfo\n";
  7557. $toUni .= "<</Registry (Adobe)\n";
  7558. $toUni .= "/Ordering (UCS)\n";
  7559. $toUni .= "/Supplement 0\n";
  7560. $toUni .= ">> def\n";
  7561. $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
  7562. $toUni .= "/CMapType 2 def\n";
  7563. $toUni .= "1 begincodespacerange\n";
  7564. $toUni .= "<00> <FF>\n";
  7565. $toUni .= "endcodespacerange\n";
  7566. $toUni .= count($font['subsets'][$sfid])." beginbfchar\n";
  7567. $toUni .= $toUnistring;
  7568. $toUni .= "endbfchar\n";
  7569. $toUni .= "endcmap\n";
  7570. $toUni .= "CMapName currentdict /CMap defineresource pop\n";
  7571. $toUni .= "end\n";
  7572. $toUni .= "end\n";
  7573. $this->_out('<</Length '.(strlen($toUni)).'>>');
  7574. $this->_putstream($toUni);
  7575. $this->_out('endobj');
  7576. //Font file
  7577. $this->_newobj();
  7578. $this->_out('<</Length '.strlen($fontstream));
  7579. $this->_out('/Filter /FlateDecode');
  7580. $this->_out('/Length1 '.$ttfontsize);
  7581. $this->_out('>>');
  7582. $this->_putstream($fontstream);
  7583. $this->_out('endobj');
  7584. } // foreach subset
  7585. unset($ttf);
  7586. }
  7587. // TrueType embedded SUBSETS or FULL
  7588. else if ($type=='TTF') {
  7589. $this->fonts[$k]['n']=$this->n+1;
  7590. if ($asSubset ) {
  7591. $ssfaid="A";
  7592. if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
  7593. $ttf = new TTFontFile();
  7594. $fontname = 'MPDFA'.$ssfaid.'+'.$font['name'];
  7595. $subset = $font['subset'];
  7596. unset($subset[0]);
  7597. $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts, $font['unAGlyphs']); // mPDF 5.4.05
  7598. $ttfontsize = strlen($ttfontstream);
  7599. $fontstream = gzcompress($ttfontstream);
  7600. $codeToGlyph = $ttf->codeToGlyph;
  7601. unset($codeToGlyph[0]);
  7602. }
  7603. else { $fontname = $font['name']; }
  7604. // Type0 Font
  7605. // A composite font - a font composed of other fonts, organized hierarchically
  7606. $this->_newobj();
  7607. $this->_out('<</Type /Font');
  7608. $this->_out('/Subtype /Type0');
  7609. $this->_out('/BaseFont /'.$fontname.'');
  7610. $this->_out('/Encoding /Identity-H');
  7611. $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
  7612. $this->_out('/ToUnicode '.($this->n + 2).' 0 R');
  7613. $this->_out('>>');
  7614. $this->_out('endobj');
  7615. // CIDFontType2
  7616. // A CIDFont whose glyph descriptions are based on TrueType font technology
  7617. $this->_newobj();
  7618. $this->_out('<</Type /Font');
  7619. $this->_out('/Subtype /CIDFontType2');
  7620. $this->_out('/BaseFont /'.$fontname.'');
  7621. $this->_out('/CIDSystemInfo '.($this->n + 2).' 0 R');
  7622. $this->_out('/FontDescriptor '.($this->n + 3).' 0 R');
  7623. if (isset($font['desc']['MissingWidth'])){
  7624. $this->_out('/DW '.$font['desc']['MissingWidth'].'');
  7625. }
  7626. if (!$asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw')) {
  7627. $w = '';
  7628. $w=file_get_contents(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw');
  7629. $this->_out($w);
  7630. }
  7631. else {
  7632. $this->_putTTfontwidths($font, $asSubset, $ttf->maxUni);
  7633. }
  7634. $this->_out('/CIDToGIDMap '.($this->n + 4).' 0 R');
  7635. $this->_out('>>');
  7636. $this->_out('endobj');
  7637. // ToUnicode
  7638. $this->_newobj();
  7639. $toUni = "/CIDInit /ProcSet findresource begin\n";
  7640. $toUni .= "12 dict begin\n";
  7641. $toUni .= "begincmap\n";
  7642. $toUni .= "/CIDSystemInfo\n";
  7643. $toUni .= "<</Registry (Adobe)\n";
  7644. $toUni .= "/Ordering (UCS)\n";
  7645. $toUni .= "/Supplement 0\n";
  7646. $toUni .= ">> def\n";
  7647. $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
  7648. $toUni .= "/CMapType 2 def\n";
  7649. $toUni .= "1 begincodespacerange\n";
  7650. $toUni .= "<0000> <FFFF>\n";
  7651. $toUni .= "endcodespacerange\n";
  7652. $toUni .= "1 beginbfrange\n";
  7653. $toUni .= "<0000> <FFFF> <0000>\n";
  7654. $toUni .= "endbfrange\n";
  7655. $toUni .= "endcmap\n";
  7656. $toUni .= "CMapName currentdict /CMap defineresource pop\n";
  7657. $toUni .= "end\n";
  7658. $toUni .= "end\n";
  7659. $this->_out('<</Length '.(strlen($toUni)).'>>');
  7660. $this->_putstream($toUni);
  7661. $this->_out('endobj');
  7662. // CIDSystemInfo dictionary
  7663. $this->_newobj();
  7664. $this->_out('<</Registry (Adobe)');
  7665. $this->_out('/Ordering (UCS)');
  7666. $this->_out('/Supplement 0');
  7667. $this->_out('>>');
  7668. $this->_out('endobj');
  7669. // Font descriptor
  7670. $this->_newobj();
  7671. $this->_out('<</Type /FontDescriptor');
  7672. $this->_out('/FontName /'.$fontname);
  7673. foreach($font['desc'] as $kd=>$v) {
  7674. if ($asSubset && $kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
  7675. $this->_out(' /'.$kd.' '.$v);
  7676. }
  7677. if ($font['panose']) {
  7678. $this->_out(' /Style << /Panose <'.$font['panose'].'> >>');
  7679. }
  7680. if ($asSubset ) {
  7681. $this->_out('/FontFile2 '.($this->n + 2).' 0 R');
  7682. }
  7683. else if ($font['fontkey']) {
  7684. // obj ID of a stream containing a TrueType font program
  7685. $this->_out('/FontFile2 '.$this->FontFiles[$font['fontkey']]['n'].' 0 R');
  7686. }
  7687. $this->_out('>>');
  7688. $this->_out('endobj');
  7689. // Embed CIDToGIDMap
  7690. // A specification of the mapping from CIDs to glyph indices
  7691. if ($asSubset ) {
  7692. $cidtogidmap = '';
  7693. $cidtogidmap = str_pad('', 256*256*2, "\x00");
  7694. foreach($codeToGlyph as $cc=>$glyph) {
  7695. $cidtogidmap[$cc*2] = chr($glyph >> 8);
  7696. $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF);
  7697. }
  7698. $cidtogidmap = gzcompress($cidtogidmap);
  7699. }
  7700. else {
  7701. // First see if there is a cached CIDToGIDMapfile
  7702. $cidtogidmap = '';
  7703. if (file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm')) {
  7704. $f=fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm','rb');
  7705. while(!feof($f)) { $cidtogidmap .= fread($f, 2048); }
  7706. fclose($f);
  7707. }
  7708. else {
  7709. if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
  7710. $ttf = new TTFontFile();
  7711. $charToGlyph = $ttf->getCTG($font['ttffile'], $font['TTCfontID'], $this->debugfonts, $font['unAGlyphs']); // mPDF 5.4.05
  7712. $cidtogidmap = str_pad('', 256*256*2, "\x00");
  7713. foreach($charToGlyph as $cc=>$glyph) {
  7714. $cidtogidmap[$cc*2] = chr($glyph >> 8);
  7715. $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF);
  7716. }
  7717. unset($ttf);
  7718. $cidtogidmap = gzcompress($cidtogidmap);
  7719. if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
  7720. $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm',"wb");
  7721. fwrite($fh,$cidtogidmap,strlen($cidtogidmap));
  7722. fclose($fh);
  7723. }
  7724. }
  7725. }
  7726. $this->_newobj();
  7727. $this->_out('<</Length '.strlen($cidtogidmap).'');
  7728. $this->_out('/Filter /FlateDecode');
  7729. $this->_out('>>');
  7730. $this->_putstream($cidtogidmap);
  7731. $this->_out('endobj');
  7732. //Font file
  7733. if ($asSubset ) {
  7734. $this->_newobj();
  7735. $this->_out('<</Length '.strlen($fontstream));
  7736. $this->_out('/Filter /FlateDecode');
  7737. $this->_out('/Length1 '.$ttfontsize);
  7738. $this->_out('>>');
  7739. $this->_putstream($fontstream);
  7740. $this->_out('endobj');
  7741. unset($ttf);
  7742. }
  7743. }
  7744. else { $this->Error('Unsupported font type: '.$type.' ('.$name.')'); }
  7745. }
  7746. }
  7747. function _putTTfontwidths(&$font, $asSubset, $maxUni) {
  7748. if ($asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php')) {
  7749. include(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php') ;
  7750. $startcid = 128;
  7751. }
  7752. else {
  7753. $rangeid = 0;
  7754. $range = array();
  7755. $prevcid = -2;
  7756. $prevwidth = -1;
  7757. $interval = false;
  7758. $startcid = 1;
  7759. }
  7760. if ($asSubset) { $cwlen = $maxUni + 1; }
  7761. else { $cwlen = (strlen($font['cw'])/2); }
  7762. // for each character
  7763. for ($cid=$startcid; $cid<$cwlen; $cid++) {
  7764. if ($cid==128 && $asSubset && (!file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php'))) {
  7765. if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
  7766. $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php',"wb");
  7767. $cw127='<?php'."\n";
  7768. $cw127.='$rangeid='.$rangeid.";\n";
  7769. $cw127.='$prevcid='.$prevcid.";\n";
  7770. $cw127.='$prevwidth='.$prevwidth.";\n";
  7771. if ($interval) { $cw127.='$interval=true'.";\n"; }
  7772. else { $cw127.='$interval=false'.";\n"; }
  7773. $cw127.='$range='.var_export($range,true).";\n";
  7774. $cw127.="?>";
  7775. fwrite($fh,$cw127,strlen($cw127));
  7776. fclose($fh);
  7777. }
  7778. }
  7779. if ($font['cw'][$cid*2] == "\00" && $font['cw'][$cid*2+1] == "\00") { continue; }
  7780. $width = (ord($font['cw'][$cid*2]) << 8) + ord($font['cw'][$cid*2+1]);
  7781. if ($width == 65535) { $width = 0; }
  7782. if ($asSubset && $cid > 255 && (!isset($font['subset'][$cid]) || !$font['subset'][$cid])) {
  7783. continue;
  7784. }
  7785. if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
  7786. if ($cid == ($prevcid + 1)) {
  7787. // consecutive CID
  7788. if ($width == $prevwidth) {
  7789. if ($width == $range[$rangeid][0]) {
  7790. $range[$rangeid][] = $width;
  7791. } else {
  7792. array_pop($range[$rangeid]);
  7793. // new range
  7794. $rangeid = $prevcid;
  7795. $range[$rangeid] = array();
  7796. $range[$rangeid][] = $prevwidth;
  7797. $range[$rangeid][] = $width;
  7798. }
  7799. $interval = true;
  7800. $range[$rangeid]['interval'] = true;
  7801. } else {
  7802. if ($interval) {
  7803. // new range
  7804. $rangeid = $cid;
  7805. $range[$rangeid] = array();
  7806. $range[$rangeid][] = $width;
  7807. } else {
  7808. $range[$rangeid][] = $width;
  7809. }
  7810. $interval = false;
  7811. }
  7812. } else {
  7813. // new range
  7814. $rangeid = $cid;
  7815. $range[$rangeid] = array();
  7816. $range[$rangeid][] = $width;
  7817. $interval = false;
  7818. }
  7819. $prevcid = $cid;
  7820. $prevwidth = $width;
  7821. }
  7822. }
  7823. $w = $this->_putfontranges($range);
  7824. $this->_out($w);
  7825. if (!$asSubset) {
  7826. if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
  7827. $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw',"wb");
  7828. fwrite($fh,$w,strlen($w));
  7829. fclose($fh);
  7830. }
  7831. }
  7832. }
  7833. function _putfontranges(&$range) {
  7834. // optimize ranges
  7835. $prevk = -1;
  7836. $nextk = -1;
  7837. $prevint = false;
  7838. foreach ($range as $k => $ws) {
  7839. $cws = count($ws);
  7840. if (($k == $nextk) AND (!$prevint) AND ((!isset($ws['interval'])) OR ($cws < 4))) {
  7841. if (isset($range[$k]['interval'])) {
  7842. unset($range[$k]['interval']);
  7843. }
  7844. $range[$prevk] = array_merge($range[$prevk], $range[$k]);
  7845. unset($range[$k]);
  7846. } else {
  7847. $prevk = $k;
  7848. }
  7849. $nextk = $k + $cws;
  7850. if (isset($ws['interval'])) {
  7851. if ($cws > 3) {
  7852. $prevint = true;
  7853. } else {
  7854. $prevint = false;
  7855. }
  7856. unset($range[$k]['interval']);
  7857. --$nextk;
  7858. } else {
  7859. $prevint = false;
  7860. }
  7861. }
  7862. // output data
  7863. $w = '';
  7864. foreach ($range as $k => $ws) {
  7865. if (count(array_count_values($ws)) == 1) {
  7866. // interval mode is more compact
  7867. $w .= ' '.$k.' '.($k + count($ws) - 1).' '.$ws[0];
  7868. } else {
  7869. // range mode
  7870. $w .= ' '.$k.' [ '.implode(' ', $ws).' ]' . "\n";
  7871. }
  7872. }
  7873. return '/W ['.$w.' ]';
  7874. }
  7875. function _putfontwidths(&$font, $cidoffset=0) {
  7876. ksort($font['cw']);
  7877. unset($font['cw'][65535]);
  7878. $rangeid = 0;
  7879. $range = array();
  7880. $prevcid = -2;
  7881. $prevwidth = -1;
  7882. $interval = false;
  7883. // for each character
  7884. foreach ($font['cw'] as $cid => $width) {
  7885. $cid -= $cidoffset;
  7886. if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
  7887. if ($cid == ($prevcid + 1)) {
  7888. // consecutive CID
  7889. if ($width == $prevwidth) {
  7890. if ($width == $range[$rangeid][0]) {
  7891. $range[$rangeid][] = $width;
  7892. } else {
  7893. array_pop($range[$rangeid]);
  7894. // new range
  7895. $rangeid = $prevcid;
  7896. $range[$rangeid] = array();
  7897. $range[$rangeid][] = $prevwidth;
  7898. $range[$rangeid][] = $width;
  7899. }
  7900. $interval = true;
  7901. $range[$rangeid]['interval'] = true;
  7902. } else {
  7903. if ($interval) {
  7904. // new range
  7905. $rangeid = $cid;
  7906. $range[$rangeid] = array();
  7907. $range[$rangeid][] = $width;
  7908. } else {
  7909. $range[$rangeid][] = $width;
  7910. }
  7911. $interval = false;
  7912. }
  7913. } else {
  7914. // new range
  7915. $rangeid = $cid;
  7916. $range[$rangeid] = array();
  7917. $range[$rangeid][] = $width;
  7918. $interval = false;
  7919. }
  7920. $prevcid = $cid;
  7921. $prevwidth = $width;
  7922. }
  7923. }
  7924. $this->_out($this->_putfontranges($range));
  7925. }
  7926. /*-- CJK-FONTS --*/
  7927. // from class PDF_Chinese CJK EXTENSIONS
  7928. function _putType0(&$font)
  7929. {
  7930. //Type0
  7931. $this->_out('/Subtype /Type0');
  7932. $this->_out('/BaseFont /'.$font['name'].'-'.$font['CMap']);
  7933. $this->_out('/Encoding /'.$font['CMap']);
  7934. $this->_out('/DescendantFonts ['.($this->n+1).' 0 R]');
  7935. $this->_out('>>');
  7936. $this->_out('endobj');
  7937. //CIDFont
  7938. $this->_newobj();
  7939. $this->_out('<</Type /Font');
  7940. $this->_out('/Subtype /CIDFontType0');
  7941. $this->_out('/BaseFont /'.$font['name']);
  7942. $cidinfo = '/Registry '.$this->_textstring('Adobe');
  7943. $cidinfo .= ' /Ordering '.$this->_textstring($font['registry']['ordering']);
  7944. $cidinfo .= ' /Supplement '.$font['registry']['supplement'];
  7945. $this->_out('/CIDSystemInfo <<'.$cidinfo.'>>');
  7946. $this->_out('/FontDescriptor '.($this->n+1).' 0 R');
  7947. if (isset($font['MissingWidth'])){
  7948. $this->_out('/DW '.$font['MissingWidth'].'');
  7949. }
  7950. $this->_putfontwidths($font, 31);
  7951. $this->_out('>>');
  7952. $this->_out('endobj');
  7953. //Font descriptor
  7954. $this->_newobj();
  7955. $s = '<</Type /FontDescriptor /FontName /'.$font['name'];
  7956. foreach ($font['desc'] as $k => $v) {
  7957. if ($k != 'Style') {
  7958. $s .= ' /'.$k.' '.$v.'';
  7959. }
  7960. }
  7961. $this->_out($s.'>>');
  7962. $this->_out('endobj');
  7963. }
  7964. /*-- END CJK-FONTS --*/
  7965. function _putimages()
  7966. {
  7967. $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
  7968. reset($this->images);
  7969. while(list($file,$info)=each($this->images)) {
  7970. $this->_newobj();
  7971. $this->images[$file]['n']=$this->n;
  7972. $this->_out('<</Type /XObject');
  7973. $this->_out('/Subtype /Image');
  7974. $this->_out('/Width '.$info['w']);
  7975. $this->_out('/Height '.$info['h']);
  7976. if (isset($info['masked'])) {
  7977. $this->_out('/SMask '.($this->n - 1).' 0 R');
  7978. }
  7979. if($info['cs']=='Indexed') {
  7980. if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3)) { $this->Error("PDFA1-b and PDFX/1-a files do not permit using mixed colour space (".$file.")."); }
  7981. $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
  7982. }
  7983. else {
  7984. $this->_out('/ColorSpace /'.$info['cs']);
  7985. if($info['cs']=='DeviceCMYK') {
  7986. if ($this->PDFA && $this->restrictColorSpace!=3) { $this->Error("PDFA1-b does not permit Images using mixed colour space (".$file.")."); }
  7987. if($info['type']=='jpg') { $this->_out('/Decode [1 0 1 0 1 0 1 0]'); }
  7988. }
  7989. else if ($info['cs']=='DeviceRGB' && ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3))) { $this->Error("PDFA1-b and PDFX/1-a files do not permit using mixed colour space (".$file.")."); }
  7990. }
  7991. $this->_out('/BitsPerComponent '.$info['bpc']);
  7992. if (isset($info['f']) && $info['f']) { $this->_out('/Filter /'.$info['f']); }
  7993. if(isset($info['parms'])) { $this->_out($info['parms']); }
  7994. if(isset($info['trns']) and is_array($info['trns'])) {
  7995. $trns='';
  7996. for($i=0;$i<count($info['trns']);$i++)
  7997. $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
  7998. $this->_out('/Mask ['.$trns.']');
  7999. }
  8000. $this->_out('/Length '.strlen($info['data']).'>>');
  8001. $this->_putstream($info['data']);
  8002. unset($this->images[$file]['data']);
  8003. $this->_out('endobj');
  8004. //Palette
  8005. if($info['cs']=='Indexed') {
  8006. $this->_newobj();
  8007. $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
  8008. $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
  8009. $this->_putstream($pal);
  8010. $this->_out('endobj');
  8011. }
  8012. }
  8013. }
  8014. function _putinfo()
  8015. {
  8016. $this->_out('/Producer '.$this->_UTF16BEtextstring('mPDF '.mPDF_VERSION));
  8017. if(!empty($this->title))
  8018. $this->_out('/Title '.$this->_UTF16BEtextstring($this->title));
  8019. if(!empty($this->subject))
  8020. $this->_out('/Subject '.$this->_UTF16BEtextstring($this->subject));
  8021. if(!empty($this->author))
  8022. $this->_out('/Author '.$this->_UTF16BEtextstring($this->author));
  8023. if(!empty($this->keywords))
  8024. $this->_out('/Keywords '.$this->_UTF16BEtextstring($this->keywords));
  8025. if(!empty($this->creator))
  8026. $this->_out('/Creator '.$this->_UTF16BEtextstring($this->creator));
  8027. $z = date('O'); // +0200
  8028. $offset = substr($z,0,3)."'".substr($z,3,2)."'";
  8029. $this->_out('/CreationDate '.$this->_textstring(date('YmdHis').$offset));
  8030. $this->_out('/ModDate '.$this->_textstring(date('YmdHis').$offset));
  8031. if ($this->PDFX) {
  8032. $this->_out('/Trapped/False');
  8033. $this->_out('/GTS_PDFXVersion(PDF/X-1a:2003)');
  8034. }
  8035. }
  8036. function _putmetadata() {
  8037. $this->_newobj();
  8038. $this->MetadataRoot = $this->n;
  8039. $Producer = 'mPDF '.mPDF_VERSION;
  8040. $z = date('O'); // +0200
  8041. $offset = substr($z,0,3).':'.substr($z,3,2);
  8042. $CreationDate = date('Y-m-d\TH:i:s').$offset; // 2006-03-10T10:47:26-05:00 2006-06-19T09:05:17Z
  8043. $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff),
  8044. mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
  8045. mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) );
  8046. $m = '<?xpacket begin="'.chr(239).chr(187).chr(191).'" id="W5M0MpCehiHzreSzNTczkc9d"?>'."\n"; // begin = FEFF BOM
  8047. $m .= ' <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="3.1-701">'."\n";
  8048. $m .= ' <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">'."\n";
  8049. $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">'."\n";
  8050. $m .= ' <pdf:Producer>'.$Producer.'</pdf:Producer>'."\n";
  8051. if(!empty($this->keywords)) { $m .= ' <pdf:Keywords>'.$this->keywords.'</pdf:Keywords>'."\n"; }
  8052. $m .= ' </rdf:Description>'."\n";
  8053. $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:xmp="http://ns.adobe.com/xap/1.0/">'."\n";
  8054. $m .= ' <xmp:CreateDate>'.$CreationDate.'</xmp:CreateDate>'."\n";
  8055. $m .= ' <xmp:ModifyDate>'.$CreationDate.'</xmp:ModifyDate>'."\n";
  8056. $m .= ' <xmp:MetadataDate>'.$CreationDate.'</xmp:MetadataDate>'."\n";
  8057. if(!empty($this->creator)) { $m .= ' <xmp:CreatorTool>'.$this->creator.'</xmp:CreatorTool>'."\n"; }
  8058. $m .= ' </rdf:Description>'."\n";
  8059. // DC elements
  8060. $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:dc="http://purl.org/dc/elements/1.1/">'."\n";
  8061. $m .= ' <dc:format>application/pdf</dc:format>'."\n";
  8062. if(!empty($this->title)) {
  8063. $m .= ' <dc:title>
  8064. <rdf:Alt>
  8065. <rdf:li xml:lang="x-default">'.$this->title.'</rdf:li>
  8066. </rdf:Alt>
  8067. </dc:title>'."\n";
  8068. }
  8069. if(!empty($this->keywords)) {
  8070. $m .= ' <dc:subject>
  8071. <rdf:Bag>
  8072. <rdf:li>'.$this->keywords.'</rdf:li>
  8073. </rdf:Bag>
  8074. </dc:subject>'."\n";
  8075. }
  8076. if(!empty($this->subject)) {
  8077. $m .= ' <dc:description>
  8078. <rdf:Alt>
  8079. <rdf:li xml:lang="x-default">'.$this->subject.'</rdf:li>
  8080. </rdf:Alt>
  8081. </dc:description>'."\n";
  8082. }
  8083. if(!empty($this->author)) {
  8084. $m .= ' <dc:creator>
  8085. <rdf:Seq>
  8086. <rdf:li>'.$this->author.'</rdf:li>
  8087. </rdf:Seq>
  8088. </dc:creator>'."\n";
  8089. }
  8090. $m .= ' </rdf:Description>'."\n";
  8091. // This bit is specific to PDFX-1a
  8092. if ($this->PDFX) {
  8093. $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/" pdfx:Apag_PDFX_Checkup="1.3" pdfx:GTS_PDFXConformance="PDF/X-1a:2003" pdfx:GTS_PDFXVersion="PDF/X-1:2003"/>'."\n";
  8094. }
  8095. // This bit is specific to PDFA-1b
  8096. else if ($this->PDFA) {
  8097. $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" >'."\n";
  8098. $m .= ' <pdfaid:part>1</pdfaid:part>'."\n";
  8099. $m .= ' <pdfaid:conformance>B</pdfaid:conformance>'."\n";
  8100. $m .= ' <pdfaid:amd>2005</pdfaid:amd>'."\n";
  8101. $m .= ' </rdf:Description>'."\n";
  8102. }
  8103. $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">'."\n";
  8104. $m .= ' <xmpMM:DocumentID>uuid:'.$uuid.'</xmpMM:DocumentID>'."\n";
  8105. $m .= ' </rdf:Description>'."\n";
  8106. $m .= ' </rdf:RDF>'."\n";
  8107. $m .= ' </x:xmpmeta>'."\n";
  8108. $m .= str_repeat(str_repeat(' ',100)."\n",20); // 2-4kB whitespace padding required
  8109. $m .= '<?xpacket end="w"?>'; // "r" read only
  8110. $this->_out('<</Type/Metadata/Subtype/XML/Length '.strlen($m).'>>');
  8111. $this->_putstream($m);
  8112. $this->_out('endobj');
  8113. }
  8114. function _putoutputintent() {
  8115. $this->_newobj();
  8116. $this->OutputIntentRoot = $this->n;
  8117. $this->_out('<</Type /OutputIntent');
  8118. if ($this->PDFA) {
  8119. $this->_out('/S /GTS_PDFA1');
  8120. if ($this->ICCProfile) {
  8121. $this->_out('/Info ('.preg_replace('/_/',' ',$this->ICCProfile).')');
  8122. $this->_out('/OutputConditionIdentifier (Custom)');
  8123. $this->_out('/OutputCondition ()');
  8124. }
  8125. else {
  8126. $this->_out('/Info (sRGB IEC61966-2.1)');
  8127. $this->_out('/OutputConditionIdentifier (sRGB IEC61966-2.1)');
  8128. $this->_out('/OutputCondition ()');
  8129. }
  8130. $this->_out('/DestOutputProfile '.($this->n+1).' 0 R');
  8131. }
  8132. else if ($this->PDFX) { // always a CMYK profile
  8133. $this->_out('/S /GTS_PDFX');
  8134. if ($this->ICCProfile) {
  8135. $this->_out('/Info ('.preg_replace('/_/',' ',$this->ICCProfile).')');
  8136. $this->_out('/OutputConditionIdentifier (Custom)');
  8137. $this->_out('/OutputCondition ()');
  8138. $this->_out('/DestOutputProfile '.($this->n+1).' 0 R');
  8139. }
  8140. else {
  8141. $this->_out('/Info (CGATS TR 001)');
  8142. $this->_out('/OutputConditionIdentifier (CGATS TR 001)');
  8143. $this->_out('/OutputCondition (CGATS TR 001 (SWOP))');
  8144. $this->_out('/RegistryName (http://www.color.org)');
  8145. }
  8146. }
  8147. $this->_out('>>');
  8148. $this->_out('endobj');
  8149. if ($this->PDFX && !$this->ICCProfile) { return; } // no ICCProfile embedded
  8150. $this->_newobj();
  8151. if ($this->ICCProfile)
  8152. $s = file_get_contents(_MPDF_PATH.'iccprofiles/'.$this->ICCProfile.'.icc');
  8153. else
  8154. $s = file_get_contents(_MPDF_PATH.'iccprofiles/sRGB_IEC61966-2-1.icc');
  8155. if ($this->compress) { $s = gzcompress($s); }
  8156. $this->_out('<<');
  8157. if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace == 3)) { $this->_out('/N 4'); }
  8158. else { $this->_out('/N 3'); }
  8159. if ($this->compress)
  8160. $this->_out('/Filter /FlateDecode ');
  8161. $this->_out('/Length '.strlen($s).'>>');
  8162. $this->_putstream($s);
  8163. $this->_out('endobj');
  8164. }
  8165. function _putcatalog() {
  8166. $this->_out('/Type /Catalog');
  8167. $this->_out('/Pages 1 0 R');
  8168. if($this->ZoomMode=='fullpage') $this->_out('/OpenAction [3 0 R /Fit]');
  8169. elseif($this->ZoomMode=='fullwidth') $this->_out('/OpenAction [3 0 R /FitH null]');
  8170. elseif($this->ZoomMode=='real') $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
  8171. elseif(!is_string($this->ZoomMode)) $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
  8172. else $this->_out('/OpenAction [3 0 R /XYZ null null null]');
  8173. if($this->LayoutMode=='single') $this->_out('/PageLayout /SinglePage');
  8174. elseif($this->LayoutMode=='continuous') $this->_out('/PageLayout /OneColumn');
  8175. elseif($this->LayoutMode=='twoleft') $this->_out('/PageLayout /TwoColumnLeft');
  8176. elseif($this->LayoutMode=='tworight') $this->_out('/PageLayout /TwoColumnRight');
  8177. elseif($this->LayoutMode=='two') {
  8178. if ($this->mirrorMargins) { $this->_out('/PageLayout /TwoColumnRight'); }
  8179. else { $this->_out('/PageLayout /TwoColumnLeft'); }
  8180. }
  8181. /*-- BOOKMARKS --*/
  8182. if(count($this->BMoutlines)>0) {
  8183. $this->_out('/Outlines '.$this->OutlineRoot.' 0 R');
  8184. $this->_out('/PageMode /UseOutlines');
  8185. }
  8186. /*-- END BOOKMARKS --*/
  8187. if(is_int(strpos($this->DisplayPreferences,'FullScreen'))) $this->_out('/PageMode /FullScreen');
  8188. // Metadata
  8189. if ($this->PDFA || $this->PDFX) {
  8190. $this->_out('/Metadata '.$this->MetadataRoot.' 0 R');
  8191. }
  8192. // OutputIntents
  8193. if ($this->PDFA || $this->PDFX || $this->ICCProfile) {
  8194. $this->_out('/OutputIntents ['.$this->OutputIntentRoot.' 0 R]');
  8195. }
  8196. /*-- FORMS --*/
  8197. if (count($this->form->forms)>0) {
  8198. $this->form->_putFormsCatalog();
  8199. }
  8200. /*-- END FORMS --*/
  8201. if ( isset($this->js) ) {
  8202. $this->_out('/Names << /JavaScript '.($this->n_js).' 0 R >> ');
  8203. }
  8204. if($this->DisplayPreferences || $this->directionality == 'rtl' || $this->mirrorMargins) {
  8205. $this->_out('/ViewerPreferences<<');
  8206. if(is_int(strpos($this->DisplayPreferences,'HideMenubar'))) $this->_out('/HideMenubar true');
  8207. if(is_int(strpos($this->DisplayPreferences,'HideToolbar'))) $this->_out('/HideToolbar true');
  8208. if(is_int(strpos($this->DisplayPreferences,'HideWindowUI'))) $this->_out('/HideWindowUI true');
  8209. if(is_int(strpos($this->DisplayPreferences,'DisplayDocTitle'))) $this->_out('/DisplayDocTitle true');
  8210. if(is_int(strpos($this->DisplayPreferences,'CenterWindow'))) $this->_out('/CenterWindow true');
  8211. if(is_int(strpos($this->DisplayPreferences,'FitWindow'))) $this->_out('/FitWindow true');
  8212. // /PrintScaling is PDF 1.6 spec.
  8213. if(is_int(strpos($this->DisplayPreferences,'NoPrintScaling')) && !$this->PDFA && !$this->PDFX)
  8214. $this->_out('/PrintScaling /None');
  8215. if($this->directionality == 'rtl') $this->_out('/Direction /R2L');
  8216. // /Duplex is PDF 1.7 spec.
  8217. if($this->mirrorMargins && !$this->PDFA && !$this->PDFX) {
  8218. // if ($this->DefOrientation=='P') $this->_out('/Duplex /DuplexFlipShortEdge');
  8219. $this->_out('/Duplex /DuplexFlipLongEdge'); // PDF v1.7+
  8220. }
  8221. $this->_out('>>');
  8222. }
  8223. // mPDF 5.6.01
  8224. if($this->open_layer_pane && ($this->hasOC || count($this->layers)))
  8225. $this->_out('/PageMode /UseOC');
  8226. // mPDF 5.6.01
  8227. if ($this->hasOC || count($this->layers)) {
  8228. $p = $v = $h = $l = $loff = $lall = $as = ''; // mPDF 5.6.28
  8229. if ($this->hasOC) {
  8230. if (($this->hasOC & 1) == 1) $p=$this->n_ocg_print.' 0 R';
  8231. if (($this->hasOC & 2) == 2) $v=$this->n_ocg_view.' 0 R';
  8232. if (($this->hasOC & 4) == 4) $h=$this->n_ocg_hidden.' 0 R';
  8233. $as="<</Event /Print /OCGs [$p $v $h] /Category [/Print]>> <</Event /View /OCGs [$p $v $h] /Category [/View]>>";
  8234. }
  8235. if(count($this->layers)) {
  8236. foreach($this->layers as $k=>$layer) { // mPDF 5.6.28
  8237. if (strtolower($this->layerDetails[$k]['state'])=='hidden') { $loff .= $layer['n'].' 0 R '; }
  8238. else { $l .= $layer['n'].' 0 R '; }
  8239. $lall .= $layer['n'].' 0 R ';
  8240. }
  8241. }
  8242. $this->_out("/OCProperties <</OCGs [$p $v $h $lall] /D <</ON [$p $l] /OFF [$v $h $loff] "); // mPDF 5.6.28
  8243. $this->_out("/Order [$v $p $h $lall] "); // mPDF 5.6.28
  8244. if ($as) $this->_out("/AS [$as] ");
  8245. $this->_out(">>>>");
  8246. }
  8247. }
  8248. // Inactive function left for backwards compatability
  8249. function SetUserRights($enable=true, $annots="", $form="", $signature="") {
  8250. // Does nothing
  8251. }
  8252. function _enddoc() {
  8253. if ($this->progressBar) { $this->UpdateProgressBar(2,'10','Writing Headers & Footers'); } // *PROGRESS-BAR*
  8254. $this->_puthtmlheaders(); // *HTMLHEADERS-FOOTERS*
  8255. if ($this->progressBar) { $this->UpdateProgressBar(2,'20','Writing Pages'); } // *PROGRESS-BAR*
  8256. // Remove references to unused fonts (usually default font)
  8257. foreach($this->fonts as $fk=>$font) {
  8258. if (!$font['used'] && ($font['type']=='TTF')) {
  8259. if ($font['sip'] || $font['smp']) {
  8260. foreach($font['subsetfontids'] AS $k => $fid) {
  8261. foreach($this->pages AS $pn=>$page) {
  8262. $this->pages[$pn] = preg_replace('/\s\/F'.$fid.' \d[\d.]* Tf\s/is',' ',$this->pages[$pn]);
  8263. }
  8264. }
  8265. }
  8266. else {
  8267. foreach($this->pages AS $pn=>$page) {
  8268. $this->pages[$pn] = preg_replace('/\s\/F'.$font['i'].' \d[\d.]* Tf\s/is',' ',$this->pages[$pn]);
  8269. }
  8270. }
  8271. }
  8272. }
  8273. // mPDF 5.6.01 - LAYERS
  8274. if (count($this->layers)) {
  8275. foreach($this->pages AS $pn=>$page) {
  8276. preg_match_all('/\/OCZ-index \/ZI(\d+) BDC(.*?)(EMCZ)-index/is',$this->pages[$pn],$m1);
  8277. preg_match_all('/\/OCBZ-index \/ZI(\d+) BDC(.*?)(EMCBZ)-index/is',$this->pages[$pn],$m2);
  8278. preg_match_all('/\/OCGZ-index \/ZI(\d+) BDC(.*?)(EMCGZ)-index/is',$this->pages[$pn],$m3);
  8279. $m = array();
  8280. for ($i=0;$i<4;$i++) {
  8281. $m[$i] = array_merge($m1[$i],$m2[$i],$m3[$i]);
  8282. }
  8283. if (count($m[0])) {
  8284. $sortarr = array();
  8285. for($i=0;$i<count($m[0]);$i++) {
  8286. $key = $m[1][$i]*2;
  8287. if ($m[3][$i]=='EMCZ') $key +=2; // background first then gradient then normal
  8288. else if ($m[3][$i]=='EMCGZ') $key +=1;
  8289. $sortarr[$i] = $key;
  8290. }
  8291. asort($sortarr);
  8292. foreach($sortarr AS $i=>$k) {
  8293. $this->pages[$pn] = str_replace($m[0][$i],'',$this->pages[$pn] );
  8294. $this->pages[$pn] .= "\n".$m[0][$i]."\n";
  8295. }
  8296. $this->pages[$pn] = preg_replace('/\/OC[BG]{0,1}Z-index \/ZI(\d+) BDC/is','/OC /ZI\\1 BDC ',$this->pages[$pn]);
  8297. $this->pages[$pn] = preg_replace('/EMC[BG]{0,1}Z-index/is','EMC',$this->pages[$pn]);
  8298. }
  8299. }
  8300. }
  8301. $this->_putpages();
  8302. if ($this->progressBar) { $this->UpdateProgressBar(2,'30','Writing document resources'); } // *PROGRESS-BAR*
  8303. $this->_putresources();
  8304. //Info
  8305. $this->_newobj();
  8306. $this->InfoRoot = $this->n;
  8307. $this->_out('<<');
  8308. if ($this->progressBar) { $this->UpdateProgressBar(2,'80','Writing document info'); } // *PROGRESS-BAR*
  8309. $this->_putinfo();
  8310. $this->_out('>>');
  8311. $this->_out('endobj');
  8312. // METADATA
  8313. if ($this->PDFA || $this->PDFX) { $this->_putmetadata(); }
  8314. // OUTPUTINTENT
  8315. if ($this->PDFA || $this->PDFX || $this->ICCProfile) { $this->_putoutputintent(); }
  8316. //Catalog
  8317. $this->_newobj();
  8318. $this->_out('<<');
  8319. if ($this->progressBar) { $this->UpdateProgressBar(2,'90','Writing document catalog'); } // *PROGRESS-BAR*
  8320. $this->_putcatalog();
  8321. $this->_out('>>');
  8322. $this->_out('endobj');
  8323. //Cross-ref
  8324. $o=strlen($this->buffer);
  8325. $this->_out('xref');
  8326. $this->_out('0 '.($this->n+1));
  8327. $this->_out('0000000000 65535 f ');
  8328. for($i=1; $i <= $this->n ; $i++)
  8329. $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
  8330. //Trailer
  8331. $this->_out('trailer');
  8332. $this->_out('<<');
  8333. $this->_puttrailer();
  8334. $this->_out('>>');
  8335. $this->_out('startxref');
  8336. $this->_out($o);
  8337. $this->buffer .= '%%EOF';
  8338. $this->state=3;
  8339. /*-- IMPORTS --*/
  8340. if ($this->enableImports && count($this->parsers) > 0) {
  8341. foreach ($this->parsers as $k => $_){
  8342. $this->parsers[$k]->closeFile();
  8343. $this->parsers[$k] = null;
  8344. unset($this->parsers[$k]);
  8345. }
  8346. }
  8347. /*-- END IMPORTS --*/
  8348. }
  8349. function _beginpage($orientation,$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='') {
  8350. if (!($pagesel && $this->page==1 && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->tMargin)))) {
  8351. $this->page++;
  8352. $this->pages[$this->page]='';
  8353. }
  8354. $this->state=2;
  8355. $resetHTMLHeadersrequired = false;
  8356. if ($newformat) { $this->_setPageSize($newformat, $orientation); }
  8357. /*-- CSS-PAGE --*/
  8358. // Paged media (page-box)
  8359. if ($pagesel || (isset($this->page_box['using']) && $this->page_box['using'])) {
  8360. if ($pagesel || $this->page==1) { $first = true; }
  8361. else { $first = false; }
  8362. if ($this->mirrorMargins && ($this->page % 2==0)) { $oddEven = 'E'; }
  8363. else { $oddEven = 'O'; }
  8364. if ($pagesel) { $psel = $pagesel; }
  8365. else if ($this->page_box['current']) { $psel = $this->page_box['current']; }
  8366. else { $psel = ''; }
  8367. list($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS($psel, $first, $oddEven);
  8368. if ($this->mirrorMargins && ($this->page % 2==0)) {
  8369. if ($hname) { $ehvalue = 1; $ehname = $hname; } else { $ehvalue = -1; }
  8370. if ($fname) { $efvalue = 1; $efname = $fname; } else { $efvalue = -1; }
  8371. }
  8372. else {
  8373. if ($hname) { $ohvalue = 1; $ohname = $hname; } else { $ohvalue = -1; }
  8374. if ($fname) { $ofvalue = 1; $ofname = $fname; } else { $ofvalue = -1; }
  8375. }
  8376. if ($resetpagenum || $pagenumstyle || $suppress) {
  8377. $this->PageNumSubstitutions[] = array('from'=>($this->page), 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=>$suppress);
  8378. }
  8379. // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
  8380. $this->show_marks = $marks;
  8381. // Background color
  8382. if (isset($bg['BACKGROUND-COLOR'])) {
  8383. $cor = $this->ConvertColor($bg['BACKGROUND-COLOR']);
  8384. if ($cor) {
  8385. $this->bodyBackgroundColor = $cor;
  8386. }
  8387. }
  8388. else { $this->bodyBackgroundColor = false; }
  8389. /*-- BACKGROUNDS --*/
  8390. if (isset($bg['BACKGROUND-GRADIENT'])) {
  8391. $this->bodyBackgroundGradient = $bg['BACKGROUND-GRADIENT'];
  8392. }
  8393. else { $this->bodyBackgroundGradient = false; }
  8394. // Tiling Patterns
  8395. if (isset($bg['BACKGROUND-IMAGE']) && $bg['BACKGROUND-IMAGE']) {
  8396. $ret = $this->SetBackground($bg, $this->pgwidth);
  8397. if ($ret) { $this->bodyBackgroundImage = $ret; }
  8398. }
  8399. else { $this->bodyBackgroundImage = false; }
  8400. /*-- END BACKGROUNDS --*/
  8401. $this->page_box['current'] = $psel;
  8402. $this->page_box['using'] = true;
  8403. }
  8404. /*-- END CSS-PAGE --*/
  8405. //Page orientation
  8406. if(!$orientation)
  8407. $orientation=$this->DefOrientation;
  8408. else {
  8409. $orientation=strtoupper(substr($orientation,0,1));
  8410. if($orientation!=$this->DefOrientation)
  8411. $this->OrientationChanges[$this->page]=true;
  8412. }
  8413. if($orientation!=$this->CurOrientation || $newformat) {
  8414. //Change orientation
  8415. if($orientation=='P') {
  8416. $this->wPt=$this->fwPt;
  8417. $this->hPt=$this->fhPt;
  8418. $this->w=$this->fw;
  8419. $this->h=$this->fh;
  8420. if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P') {
  8421. $this->tMargin = $this->orig_tMargin;
  8422. $this->bMargin = $this->orig_bMargin;
  8423. $this->DeflMargin = $this->orig_lMargin;
  8424. $this->DefrMargin = $this->orig_rMargin;
  8425. $this->margin_header = $this->orig_hMargin;
  8426. $this->margin_footer = $this->orig_fMargin;
  8427. }
  8428. else { $resetHTMLHeadersrequired = true; } // *HTMLHEADERS-FOOTERS*
  8429. }
  8430. else {
  8431. $this->wPt=$this->fhPt;
  8432. $this->hPt=$this->fwPt;
  8433. $this->w=$this->fh;
  8434. $this->h=$this->fw;
  8435. if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P') {
  8436. $this->tMargin = $this->orig_lMargin;
  8437. $this->bMargin = $this->orig_rMargin;
  8438. $this->DeflMargin = $this->orig_bMargin;
  8439. $this->DefrMargin = $this->orig_tMargin;
  8440. $this->margin_header = $this->orig_hMargin;
  8441. $this->margin_footer = $this->orig_fMargin;
  8442. }
  8443. else { $resetHTMLHeadersrequired = true; } // *HTMLHEADERS-FOOTERS*
  8444. }
  8445. $this->CurOrientation=$orientation;
  8446. $this->ResetMargins();
  8447. $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
  8448. $this->PageBreakTrigger=$this->h-$this->bMargin;
  8449. }
  8450. $this->pageDim[$this->page]['w']=$this->w ;
  8451. $this->pageDim[$this->page]['h']=$this->h ;
  8452. $this->pageDim[$this->page]['outer_width_LR'] = isset($this->page_box['outer_width_LR']) ? $this->page_box['outer_width_LR'] : 0;
  8453. $this->pageDim[$this->page]['outer_width_TB'] = isset($this->page_box['outer_width_TB']) ? $this->page_box['outer_width_TB'] : 0;
  8454. if (!isset($this->page_box['outer_width_LR']) && !isset($this->page_box['outer_width_TB'])) {
  8455. $this->pageDim[$this->page]['bleedMargin'] = 0;
  8456. }
  8457. else if ($this->bleedMargin <= $this->page_box['outer_width_LR'] && $this->bleedMargin <= $this->page_box['outer_width_TB']) {
  8458. $this->pageDim[$this->page]['bleedMargin'] = $this->bleedMargin;
  8459. }
  8460. else {
  8461. $this->pageDim[$this->page]['bleedMargin'] = min($this->page_box['outer_width_LR'], $this->page_box['outer_width_TB'])-0.01;
  8462. }
  8463. // If Page Margins are re-defined
  8464. // strlen()>0 is used to pick up (integer) 0, (string) '0', or set value
  8465. if ((strlen($mgl)>0 && $this->DeflMargin != $mgl) || (strlen($mgr)>0 && $this->DefrMargin != $mgr) || (strlen($mgt)>0 && $this->tMargin != $mgt) || (strlen($mgb)>0 && $this->bMargin != $mgb) || (strlen($mgh)>0 && $this->margin_header!=$mgh) || (strlen($mgf)>0 && $this->margin_footer!=$mgf)) {
  8466. if (strlen($mgl)>0) $this->DeflMargin = $mgl;
  8467. if (strlen($mgr)>0) $this->DefrMargin = $mgr;
  8468. if (strlen($mgt)>0) $this->tMargin = $mgt;
  8469. if (strlen($mgb)>0) $this->bMargin = $mgb;
  8470. if (strlen($mgh)>0) $this->margin_header=$mgh;
  8471. if (strlen($mgf)>0) $this->margin_footer=$mgf;
  8472. $this->ResetMargins();
  8473. $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
  8474. $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
  8475. $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
  8476. }
  8477. $this->ResetMargins();
  8478. $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
  8479. $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
  8480. // Reset column top margin
  8481. $this->y0 = $this->tMargin;
  8482. $this->x=$this->lMargin;
  8483. $this->y=$this->tMargin;
  8484. $this->FontFamily='';
  8485. // HEADERS AND FOOTERS
  8486. if ($ohvalue<0 || strtoupper($ohvalue)=='OFF') {
  8487. $this->HTMLHeader = '';
  8488. $this->headerDetails['odd'] = array();
  8489. $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
  8490. }
  8491. else if ($ohname && $ohvalue>0) {
  8492. /*-- HTMLHEADERS-FOOTERS --*/
  8493. if (preg_match('/^html_(.*)$/i',$ohname,$n)) {
  8494. if (isset($this->pageHTMLheaders[$n[1]])) { $this->HTMLHeader = $this->pageHTMLheaders[$n[1]]; }
  8495. else { $this->HTMLHeader = ''; }
  8496. $this->headerDetails['odd'] = array();
  8497. $resetHTMLHeadersrequired = true;
  8498. }
  8499. else {
  8500. /*-- END HTMLHEADERS-FOOTERS --*/
  8501. if (isset($this->pageheaders[$ohname])) { $this->headerDetails['odd'] = $this->pageheaders[$ohname]; }
  8502. else if ($ohname!='_default') { $this->headerDetails['odd'] = array(); }
  8503. $this->HTMLHeader = '';
  8504. /*-- HTMLHEADERS-FOOTERS --*/
  8505. $resetHTMLHeadersrequired = false;
  8506. }
  8507. /*-- END HTMLHEADERS-FOOTERS --*/
  8508. }
  8509. if ($ehvalue<0 || strtoupper($ehvalue)=='OFF') {
  8510. $this->HTMLHeaderE = '';
  8511. $this->headerDetails['even'] = array();
  8512. $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
  8513. }
  8514. else if ($ehname && $ehvalue>0) {
  8515. /*-- HTMLHEADERS-FOOTERS --*/
  8516. if (preg_match('/^html_(.*)$/i',$ehname,$n)) {
  8517. if (isset($this->pageHTMLheaders[$n[1]])) { $this->HTMLHeaderE = $this->pageHTMLheaders[$n[1]]; }
  8518. else { $this->HTMLHeaderE = ''; }
  8519. $this->headerDetails['even'] = array();
  8520. $resetHTMLHeadersrequired = true;
  8521. }
  8522. else {
  8523. /*-- END HTMLHEADERS-FOOTERS --*/
  8524. if (isset($this->pageheaders[$ehname])) { $this->headerDetails['even'] = $this->pageheaders[$ehname]; }
  8525. else if ($ehname!='_default') { $this->headerDetails['even'] = array(); }
  8526. $this->HTMLHeaderE = '';
  8527. /*-- HTMLHEADERS-FOOTERS --*/
  8528. $resetHTMLHeadersrequired = false;
  8529. }
  8530. /*-- END HTMLHEADERS-FOOTERS --*/
  8531. }
  8532. if ($ofvalue<0 || strtoupper($ofvalue)=='OFF') {
  8533. $this->HTMLFooter = '';
  8534. $this->footerDetails['odd'] = array();
  8535. $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
  8536. }
  8537. else if ($ofname && $ofvalue>0) {
  8538. /*-- HTMLHEADERS-FOOTERS --*/
  8539. if (preg_match('/^html_(.*)$/i',$ofname,$n)) {
  8540. if (isset($this->pageHTMLfooters[$n[1]])) { $this->HTMLFooter = $this->pageHTMLfooters[$n[1]]; }
  8541. else { $this->HTMLFooter = ''; }
  8542. $this->footerDetails['odd'] = array();
  8543. $resetHTMLHeadersrequired = true;
  8544. }
  8545. else {
  8546. /*-- END HTMLHEADERS-FOOTERS --*/
  8547. if (isset($this->pagefooters[$ofname])) { $this->footerDetails['odd'] = $this->pagefooters[$ofname]; }
  8548. else if ($ofname!='_default') { $this->footerDetails['odd'] = array(); }
  8549. $this->HTMLFooter = '';
  8550. /*-- HTMLHEADERS-FOOTERS --*/
  8551. $resetHTMLHeadersrequired = true;
  8552. }
  8553. /*-- END HTMLHEADERS-FOOTERS --*/
  8554. }
  8555. if ($efvalue<0 || strtoupper($efvalue)=='OFF') {
  8556. $this->HTMLFooterE = '';
  8557. $this->footerDetails['even'] = array();
  8558. $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
  8559. }
  8560. else if ($efname && $efvalue>0) {
  8561. /*-- HTMLHEADERS-FOOTERS --*/
  8562. if (preg_match('/^html_(.*)$/i',$efname,$n)) {
  8563. if (isset($this->pageHTMLfooters[$n[1]])) { $this->HTMLFooterE = $this->pageHTMLfooters[$n[1]]; }
  8564. else { $this->HTMLFooterE = ''; }
  8565. $this->footerDetails['even'] = array();
  8566. $resetHTMLHeadersrequired = true;
  8567. }
  8568. else {
  8569. /*-- END HTMLHEADERS-FOOTERS --*/
  8570. if (isset($this->pagefooters[$efname])) { $this->footerDetails['even'] = $this->pagefooters[$efname]; }
  8571. else if ($efname!='_default') { $this->footerDetails['even'] = array(); }
  8572. $this->HTMLFooterE = '';
  8573. /*-- HTMLHEADERS-FOOTERS --*/
  8574. $resetHTMLHeadersrequired = true;
  8575. }
  8576. /*-- END HTMLHEADERS-FOOTERS --*/
  8577. }
  8578. /*-- HTMLHEADERS-FOOTERS --*/
  8579. if ($resetHTMLHeadersrequired) {
  8580. $this->SetHTMLHeader($this->HTMLHeader );
  8581. $this->SetHTMLHeader($this->HTMLHeaderE ,'E');
  8582. $this->SetHTMLFooter($this->HTMLFooter );
  8583. $this->SetHTMLFooter($this->HTMLFooterE ,'E');
  8584. }
  8585. /*-- END HTMLHEADERS-FOOTERS --*/
  8586. if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
  8587. $this->_setAutoHeaderHeight($this->headerDetails['even'], $this->HTMLHeaderE);
  8588. $this->_setAutoFooterHeight($this->footerDetails['even'], $this->HTMLFooterE);
  8589. }
  8590. else { // ODD or DEFAULT
  8591. $this->_setAutoHeaderHeight($this->headerDetails['odd'], $this->HTMLHeader);
  8592. $this->_setAutoFooterHeight($this->footerDetails['odd'], $this->HTMLFooter);
  8593. }
  8594. // Reset column top margin
  8595. $this->y0 = $this->tMargin;
  8596. $this->x=$this->lMargin;
  8597. $this->y=$this->tMargin;
  8598. }
  8599. function _setAutoHeaderHeight(&$det, &$htmlh) {
  8600. if ($this->setAutoTopMargin=='pad') {
  8601. if ($htmlh['h']) { $h = $htmlh['h']; }
  8602. else if ($det) { $h = $this->_getHFHeight($det,'H'); }
  8603. else { $h = 0; }
  8604. $this->tMargin = $this->margin_header + $h + $this->orig_tMargin;
  8605. }
  8606. else if ($this->setAutoTopMargin=='stretch') {
  8607. if ($htmlh['h']) { $h = $htmlh['h']; }
  8608. else if ($det) { $h = $this->_getHFHeight($det,'H'); }
  8609. else { $h = 0; }
  8610. $this->tMargin = max($this->orig_tMargin, $this->margin_header + $h + $this->autoMarginPadding);
  8611. }
  8612. }
  8613. function _setAutoFooterHeight(&$det, &$htmlf) {
  8614. if ($this->setAutoBottomMargin=='pad') {
  8615. if ($htmlf['h']) { $h = $htmlf['h']; }
  8616. else if ($det) { $h = $this->_getHFHeight($det,'F'); }
  8617. else { $h = 0; }
  8618. $this->bMargin = $this->margin_footer + $h + $this->orig_bMargin;
  8619. $this->PageBreakTrigger=$this->h-$this->bMargin ;
  8620. }
  8621. else if ($this->setAutoBottomMargin=='stretch') {
  8622. if ($htmlf['h']) { $h = $htmlf['h']; }
  8623. else if ($det) { $h = $this->_getHFHeight($det,'F'); }
  8624. else { $h = 0; }
  8625. $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $h + $this->autoMarginPadding);
  8626. $this->PageBreakTrigger=$this->h-$this->bMargin ;
  8627. }
  8628. }
  8629. function _getHFHeight(&$det,$end) {
  8630. $h = 0;
  8631. if(count($det)) {
  8632. foreach(array('L','C','R') AS $pos) {
  8633. if (isset($det[$pos]['content']) && $det[$pos]['content']) {
  8634. if (isset($det[$pos]['font-size']) && $det[$pos]['font-size']) { $hfsz = $det[$pos]['font-size']; }
  8635. else { $hfsz = $this->default_font_size; }
  8636. $h = max($h,$hfsz/_MPDFK);
  8637. }
  8638. }
  8639. if ($det['line'] && $end=='H') { $h += $h/_MPDFK*$this->header_line_spacing; }
  8640. else if ($det['line'] && $end=='F') { $h += $h/_MPDFK*$this->footer_line_spacing; }
  8641. }
  8642. return $h;
  8643. }
  8644. function _endpage() {
  8645. /*-- CSS-IMAGE-FLOAT --*/
  8646. $this->printfloatbuffer();
  8647. /*-- END CSS-IMAGE-FLOAT --*/
  8648. if($this->visibility!='visible')
  8649. $this->SetVisibility('visible');
  8650. $this->EndLayer(); // mPDF 5.6.01
  8651. //End of page contents
  8652. $this->state=1;
  8653. }
  8654. function _newobj($obj_id=false,$onlynewobj=false) {
  8655. if (!$obj_id) {
  8656. $obj_id = ++$this->n;
  8657. }
  8658. //Begin a new object
  8659. if (!$onlynewobj) {
  8660. $this->offsets[$obj_id] = strlen($this->buffer);
  8661. $this->_out($obj_id.' 0 obj');
  8662. $this->_current_obj_id = $obj_id; // for later use with encryption
  8663. }
  8664. }
  8665. function _dounderline($x,$y,$txt) {
  8666. // Now print line exactly where $y secifies - called from Text() and Cell() - adjust position there
  8667. // WORD SPACING
  8668. $w =($this->GetStringWidth($txt)*_MPDFK) + ($this->charspacing * mb_strlen( $txt, $this->mb_enc ))
  8669. + ( $this->ws * mb_substr_count( $txt, ' ', $this->mb_enc ));
  8670. //Draw a line
  8671. return sprintf('%.3F %.3F m %.3F %.3F l S',$x*_MPDFK,($this->h-$y)*_MPDFK,($x*_MPDFK)+$w,($this->h-$y)*_MPDFK);
  8672. }
  8673. function _imageError($file, $firsttime, $msg) {
  8674. // Save re-trying image URL's which have already failed
  8675. $this->failedimages[$file] = true;
  8676. if ($firsttime && ($this->showImageErrors || $this->debug)) {
  8677. $this->Error("IMAGE Error (".$file."): ".$msg);
  8678. }
  8679. return false;
  8680. }
  8681. function _getImage(&$file, $firsttime=true, $allowvector=true, $orig_srcpath=false) {
  8682. // firsttime i.e. whether to add to this->images - use false when calling iteratively
  8683. // Image Data passed directly as var:varname
  8684. if (preg_match('/var:\s*(.*)/',$file, $v)) {
  8685. $data = $this->$v[1];
  8686. $file = md5($data);
  8687. }
  8688. // mPDF 5.5.13
  8689. if (preg_match('/data:image\/(gif|jpeg|png);base64,(.*)/',$file, $v)) {
  8690. $type = $v[1];
  8691. $data = base64_decode($v[2]);
  8692. $file = md5($data);
  8693. }
  8694. // mPDF 5.6.02
  8695. if ($firsttime && $file && substr($file,0,5)!='data:') { $file = urlencode_part($file); }
  8696. if ($firsttime && $orig_srcpath && substr($orig_srcpath,0,5)!='data:') { $orig_srcpath = urlencode_part($orig_srcpath); }
  8697. $ppUx = 0;
  8698. if ($orig_srcpath && isset($this->images[$orig_srcpath])) { $file=$orig_srcpath; return $this->images[$orig_srcpath]; }
  8699. if (isset($this->images[$file])) { return $this->images[$file]; }
  8700. else if ($orig_srcpath && isset($this->formobjects[$orig_srcpath])) { $file=$orig_srcpath; return $this->formobjects[$file]; }
  8701. else if (isset($this->formobjects[$file])) { return $this->formobjects[$file]; }
  8702. // Save re-trying image URL's which have already failed
  8703. else if ($firsttime && isset($this->failedimages[$file])) { return $this->_imageError($file, $firsttime, ''); }
  8704. if (empty($data)) {
  8705. $type = '';
  8706. $data = '';
  8707. if ($orig_srcpath && $this->basepathIsLocal && $check = @fopen($orig_srcpath,"rb")) {
  8708. fclose($check);
  8709. $file=$orig_srcpath;
  8710. $data = file_get_contents($file);
  8711. $type = $this->_imageTypeFromString($data);
  8712. }
  8713. if (!$data && $check = @fopen($file,"rb")) {
  8714. fclose($check);
  8715. $data = file_get_contents($file);
  8716. $type = $this->_imageTypeFromString($data);
  8717. }
  8718. if ((!$data || !$type) && !ini_get('allow_url_fopen') ) { // only worth trying if remote file and !ini_get('allow_url_fopen')
  8719. $this->file_get_contents_by_socket($file, $data); // needs full url?? even on local (never needed for local)
  8720. if ($data) { $type = $this->_imageTypeFromString($data); }
  8721. }
  8722. if ((!$data || !$type) && !ini_get('allow_url_fopen') && function_exists("curl_init")) {
  8723. $this->file_get_contents_by_curl($file, $data); // needs full url?? even on local (never needed for local)
  8724. if ($data) { $type = $this->_imageTypeFromString($data); }
  8725. }
  8726. }
  8727. if (!$data) { return $this->_imageError($file, $firsttime, 'Could not find image file'); }
  8728. if (empty($type)) { $type = $this->_imageTypeFromString($data); }
  8729. if (($type == 'wmf' || $type == 'svg') && !$allowvector) { return $this->_imageError($file, $firsttime, 'WMF or SVG image file not supported in this context'); }
  8730. // SVG
  8731. if ($type == 'svg') {
  8732. if (!class_exists('SVG', false)) { include(_MPDF_PATH .'classes/svg.php'); }
  8733. $svg = new SVG($this);
  8734. $family=$this->FontFamily;
  8735. $style=$this->FontStyle;
  8736. $size=$this->FontSizePt;
  8737. $info = $svg->ImageSVG($data);
  8738. //Restore font
  8739. if($family) $this->SetFont($family,$style,$size,false);
  8740. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing SVG file'); }
  8741. $info['type']='svg';
  8742. $info['i']=count($this->formobjects)+1;
  8743. $this->formobjects[$file]=$info;
  8744. return $info;
  8745. }
  8746. // JPEG
  8747. if ($type == 'jpeg' || $type == 'jpg') {
  8748. $hdr = $this->_jpgHeaderFromString($data);
  8749. if (!$hdr) { return $this->_imageError($file, $firsttime, 'Error parsing JPG header'); }
  8750. $a = $this->_jpgDataFromHeader($hdr);
  8751. $j = strpos($data,'JFIF');
  8752. if ($j) {
  8753. //Read resolution
  8754. $unitSp=ord(substr($data,($j+7),1));
  8755. if ($unitSp > 0) {
  8756. $ppUx=$this->_twobytes2int(substr($data,($j+8),2)); // horizontal pixels per meter, usually set to zero
  8757. if ($unitSp == 2) { // = dots per cm (if == 1 set as dpi)
  8758. $ppUx=round($ppUx/10 *25.4);
  8759. }
  8760. }
  8761. }
  8762. if ($a[2] == 'DeviceCMYK' && (($this->PDFA && $this->restrictColorSpace!=3) || $this->restrictColorSpace==2)) {
  8763. // convert to RGB image
  8764. if (!function_exists("gd_info")) { $this->Error("JPG image may not use CMYK color space (".$file.")."); }
  8765. if ($this->PDFA && !$this->PDFAauto) { $this->PDFAXwarnings[] = "JPG image may not use CMYK color space - ".$file." - (Image converted to RGB. NB This will alter the colour profile of the image.)"; }
  8766. $im = @imagecreatefromstring($data);
  8767. if ($im) {
  8768. $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
  8769. imageinterlace($im, false);
  8770. $check = @imagepng($im, $tempfile);
  8771. if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse JPG(CMYK) image'); }
  8772. $info = $this->_getImage($tempfile, false);
  8773. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse JPG(CMYK) image'); }
  8774. imagedestroy($im);
  8775. unlink($tempfile);
  8776. $info['type']='jpg';
  8777. if ($firsttime) {
  8778. $info['i']=count($this->images)+1;
  8779. $this->images[$file]=$info;
  8780. }
  8781. return $info;
  8782. }
  8783. else { return $this->_imageError($file, $firsttime, 'Error creating GD image file from JPG(CMYK) image'); }
  8784. }
  8785. else if ($a[2] == 'DeviceRGB' && ($this->PDFX || $this->restrictColorSpace==3)) {
  8786. // Convert to CMYK image stream - nominally returned as type='png'
  8787. $info = $this->_convImage($data, $a[2], 'DeviceCMYK', $a[0], $a[1], $ppUx, false);
  8788. if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "JPG image may not use RGB color space - ".$file." - (Image converted to CMYK. NB This will alter the colour profile of the image.)"; }
  8789. }
  8790. else if (($a[2] == 'DeviceRGB' || $a[2] == 'DeviceCMYK') && $this->restrictColorSpace==1) {
  8791. // Convert to Grayscale image stream - nominally returned as type='png'
  8792. $info = $this->_convImage($data, $a[2], 'DeviceGray', $a[0], $a[1], $ppUx, false);
  8793. }
  8794. else {
  8795. $info = array('w'=>$a[0],'h'=>$a[1],'cs'=>$a[2],'bpc'=>$a[3],'f'=>'DCTDecode','data'=>$data, 'type'=>'jpg');
  8796. if ($ppUx) { $info['set-dpi'] = $ppUx; }
  8797. }
  8798. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing or converting JPG image'); }
  8799. if ($firsttime) {
  8800. $info['i']=count($this->images)+1;
  8801. $this->images[$file]=$info;
  8802. }
  8803. return $info;
  8804. }
  8805. // PNG
  8806. else if ($type == 'png') {
  8807. //Check signature
  8808. if(substr($data,0,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
  8809. return $this->_imageError($file, $firsttime, 'Error parsing PNG identifier');
  8810. }
  8811. //Read header chunk
  8812. if(substr($data,12,4)!='IHDR') {
  8813. return $this->_imageError($file, $firsttime, 'Incorrect PNG file (no IHDR block found)');
  8814. }
  8815. $w=$this->_fourbytes2int(substr($data,16,4));
  8816. $h=$this->_fourbytes2int(substr($data,20,4));
  8817. $bpc=ord(substr($data,24,1));
  8818. $errpng = false;
  8819. $pngalpha = false;
  8820. if($bpc>8) { $errpng = 'not 8-bit depth'; }
  8821. $ct=ord(substr($data,25,1));
  8822. if($ct==0) { $colspace='DeviceGray'; }
  8823. elseif($ct==2) { $colspace='DeviceRGB'; }
  8824. elseif($ct==3) { $colspace='Indexed'; }
  8825. elseif($ct==4) { $colspace='DeviceGray'; $errpng = 'alpha channel'; $pngalpha = true; }
  8826. else { $colspace='DeviceRGB'; $errpng = 'alpha channel'; $pngalpha = true; }
  8827. if(ord(substr($data,26,1))!=0) { $errpng = 'compression method'; }
  8828. if(ord(substr($data,27,1))!=0) { $errpng = 'filter method'; }
  8829. if(ord(substr($data,28,1))!=0) { $errpng = 'interlaced file'; }
  8830. $j = strpos($data,'pHYs');
  8831. if ($j) {
  8832. //Read resolution
  8833. $unitSp=ord(substr($data,($j+12),1));
  8834. if ($unitSp == 1) {
  8835. $ppUx=$this->_fourbytes2int(substr($data,($j+4),4)); // horizontal pixels per meter, usually set to zero
  8836. $ppUx=round($ppUx/1000 *25.4);
  8837. }
  8838. }
  8839. if (($colspace == 'DeviceRGB' || $colspace == 'Indexed') && ($this->PDFX || $this->restrictColorSpace==3)) {
  8840. // Convert to CMYK image stream - nominally returned as type='png'
  8841. $info = $this->_convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha);
  8842. if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "PNG image may not use RGB color space - ".$file." - (Image converted to CMYK. NB This will alter the colour profile of the image.)"; }
  8843. }
  8844. else if (($colspace == 'DeviceRGB' || $colspace == 'Indexed') && $this->restrictColorSpace==1) {
  8845. // Convert to Grayscale image stream - nominally returned as type='png'
  8846. $info = $this->_convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha);
  8847. }
  8848. else if (($this->PDFA || $this->PDFX) && $pngalpha) {
  8849. // Remove alpha channel
  8850. if ($this->restrictColorSpace==1) { // Grayscale
  8851. $info = $this->_convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha);
  8852. }
  8853. else if ($this->restrictColorSpace==3) { // CMYK
  8854. $info = $this->_convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha);
  8855. }
  8856. else if ($this->PDFA ) { // RGB
  8857. $info = $this->_convImage($data, $colspace, 'DeviceRGB', $w, $h, $ppUx, $pngalpha);
  8858. }
  8859. if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Transparency (alpha channel) not permitted in PDFA or PDFX files - ".$file." - (Image converted to one without transparency.)"; }
  8860. }
  8861. else if ($errpng || $pngalpha) {
  8862. if (function_exists('gd_info')) { $gd = gd_info(); }
  8863. else {$gd = array(); }
  8864. if (!isset($gd['PNG Support'])) { return $this->_imageError($file, $firsttime, 'GD library required for PNG image ('.$errpng.')'); }
  8865. $im = imagecreatefromstring($data);
  8866. if (!$im) { return $this->_imageError($file, $firsttime, 'Error creating GD image from PNG file ('.$errpng.')'); }
  8867. $w = imagesx($im);
  8868. $h = imagesy($im);
  8869. if ($im) {
  8870. $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
  8871. // Alpha channel set
  8872. if ($pngalpha) {
  8873. if ($this->PDFA) { $this->Error("PDFA1-b does not permit images with alpha channel transparency (".$file.")."); }
  8874. $imgalpha = imagecreate($w, $h);
  8875. // generate gray scale pallete
  8876. for ($c = 0; $c < 256; ++$c) { ImageColorAllocate($imgalpha, $c, $c, $c); }
  8877. // extract alpha channel
  8878. $gammacorr = 2.2; // gamma correction
  8879. for ($xpx = 0; $xpx < $w; ++$xpx) {
  8880. for ($ypx = 0; $ypx < $h; ++$ypx) {
  8881. //$colorindex = imagecolorat($im, $xpx, $ypx);
  8882. //$col = imagecolorsforindex($im, $colorindex);
  8883. //$gamma2 = (pow((((127 - $col['alpha']) * 255 / 127) / 255), $gammacorr) * 255);
  8884. $alpha = (imagecolorat($im, $xpx, $ypx) & 0x7F000000) >> 24;
  8885. if ($alpha < 127) {
  8886. if ($alpha==0) { $gamma = 255; }
  8887. else
  8888. $gamma = (pow((((127 - $alpha) * 255 / 127) / 255), $gammacorr) * 255);
  8889. imagesetpixel($imgalpha, $xpx, $ypx, $gamma);
  8890. }
  8891. }
  8892. }
  8893. // create temp alpha file
  8894. $tempfile_alpha = _MPDF_TEMP_PATH.'_tempMskPNG'.RAND(1,10000).'.png';
  8895. if (!is_writable($tempfile_alpha)) {
  8896. ob_start();
  8897. $check = @imagepng($imgalpha);
  8898. if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
  8899. imagedestroy($imgalpha);
  8900. $this->_tempimg = ob_get_contents();
  8901. $this->_tempimglnk = 'var:_tempimg';
  8902. ob_end_clean();
  8903. // extract image without alpha channel
  8904. $imgplain = imagecreatetruecolor($w, $h);
  8905. imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
  8906. // create temp image file
  8907. $minfo = $this->_getImage($this->_tempimglnk, false);
  8908. if (!$minfo) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
  8909. ob_start();
  8910. $check = @imagepng($imgplain);
  8911. if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
  8912. $this->_tempimg = ob_get_contents();
  8913. $this->_tempimglnk = 'var:_tempimg';
  8914. ob_end_clean();
  8915. $info = $this->_getImage($this->_tempimglnk, false);
  8916. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
  8917. imagedestroy($imgplain);
  8918. $imgmask = count($this->images)+1;
  8919. $minfo['cs'] = 'DeviceGray';
  8920. $minfo['i']=$imgmask ;
  8921. $this->images[$tempfile_alpha] = $minfo;
  8922. }
  8923. else {
  8924. $check = @imagepng($imgalpha, $tempfile_alpha);
  8925. if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile_alpha.') parsing PNG image with alpha channel ('.$errpng.')'); }
  8926. imagedestroy($imgalpha);
  8927. // extract image without alpha channel
  8928. $imgplain = imagecreatetruecolor($w, $h);
  8929. imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
  8930. // create temp image file
  8931. $check = @imagepng($imgplain, $tempfile);
  8932. if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile.') parsing PNG image with alpha channel ('.$errpng.')'); }
  8933. imagedestroy($imgplain);
  8934. // embed mask image
  8935. $minfo = $this->_getImage($tempfile_alpha, false);
  8936. unlink($tempfile_alpha);
  8937. if (!$minfo) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile_alpha.') created with GD library to parse PNG image'); }
  8938. $imgmask = count($this->images)+1;
  8939. $minfo['cs'] = 'DeviceGray';
  8940. $minfo['i']=$imgmask ;
  8941. $this->images[$tempfile_alpha] = $minfo;
  8942. // embed image, masked with previously embedded mask
  8943. $info = $this->_getImage($tempfile, false);
  8944. unlink($tempfile);
  8945. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse PNG image'); }
  8946. }
  8947. $info['masked'] = $imgmask;
  8948. if ($ppUx) { $info['set-dpi'] = $ppUx; }
  8949. $info['type']='png';
  8950. if ($firsttime) {
  8951. $info['i']=count($this->images)+1;
  8952. $this->images[$file]=$info;
  8953. }
  8954. return $info;
  8955. }
  8956. else { // No alpha/transparency set
  8957. imagealphablending($im, false);
  8958. imagesavealpha($im, false);
  8959. imageinterlace($im, false);
  8960. if (!is_writable($tempfile)) {
  8961. ob_start();
  8962. $check = @imagepng($im);
  8963. if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
  8964. $this->_tempimg = ob_get_contents();
  8965. $this->_tempimglnk = 'var:_tempimg';
  8966. ob_end_clean();
  8967. $info = $this->_getImage($this->_tempimglnk, false);
  8968. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
  8969. imagedestroy($im);
  8970. }
  8971. else {
  8972. $check = @imagepng($im, $tempfile );
  8973. if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile.') parsing PNG image ('.$errpng.')'); }
  8974. imagedestroy($im);
  8975. $info = $this->_getImage($tempfile, false) ;
  8976. unlink($tempfile );
  8977. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse PNG image'); }
  8978. }
  8979. if ($ppUx) { $info['set-dpi'] = $ppUx; }
  8980. $info['type']='png';
  8981. if ($firsttime) {
  8982. $info['i']=count($this->images)+1;
  8983. $this->images[$file]=$info;
  8984. }
  8985. return $info;
  8986. }
  8987. }
  8988. }
  8989. else {
  8990. $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
  8991. //Scan chunks looking for palette, transparency and image data
  8992. $pal='';
  8993. $trns='';
  8994. $pngdata='';
  8995. $p = 33;
  8996. do {
  8997. $n=$this->_fourbytes2int(substr($data,$p,4)); $p += 4;
  8998. $type=substr($data,$p,4); $p += 4;
  8999. if($type=='PLTE') {
  9000. //Read palette
  9001. $pal=substr($data,$p,$n); $p += $n;
  9002. $p += 4;
  9003. }
  9004. elseif($type=='tRNS') {
  9005. //Read transparency info
  9006. $t=substr($data,$p,$n); $p += $n;
  9007. if($ct==0) $trns=array(ord(substr($t,1,1)));
  9008. elseif($ct==2) $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
  9009. else
  9010. {
  9011. $pos=strpos($t,chr(0));
  9012. if(is_int($pos)) $trns=array($pos);
  9013. }
  9014. $p += 4;
  9015. }
  9016. elseif($type=='IDAT') {
  9017. $pngdata.=substr($data,$p,$n); $p += $n;
  9018. $p += 4;
  9019. }
  9020. elseif($type=='IEND') { break; }
  9021. else if (preg_match('/[a-zA-Z]{4}/',$type)) { $p += $n+4; }
  9022. else { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data'); }
  9023. }
  9024. while($n);
  9025. if (!$pngdata) { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found'); }
  9026. if($colspace=='Indexed' and empty($pal)) { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data - missing colour palette'); }
  9027. $info = array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$pngdata);
  9028. $info['type']='png';
  9029. if ($ppUx) { $info['set-dpi'] = $ppUx; }
  9030. }
  9031. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing or converting PNG image'); }
  9032. if ($firsttime) {
  9033. $info['i']=count($this->images)+1;
  9034. $this->images[$file]=$info;
  9035. }
  9036. return $info;
  9037. }
  9038. // GIF
  9039. else if ($type == 'gif') {
  9040. if (function_exists('gd_info')) { $gd = gd_info(); }
  9041. else {$gd = array(); }
  9042. if (isset($gd['GIF Read Support']) && $gd['GIF Read Support']) {
  9043. $im = @imagecreatefromstring($data);
  9044. if ($im) {
  9045. $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
  9046. imagealphablending($im, false);
  9047. imagesavealpha($im, false);
  9048. imageinterlace($im, false);
  9049. if (!is_writable($tempfile)) {
  9050. ob_start();
  9051. $check = @imagepng($im);
  9052. if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse GIF image'); }
  9053. $this->_tempimg = ob_get_contents();
  9054. $this->_tempimglnk = 'var:_tempimg';
  9055. ob_end_clean();
  9056. $info = $this->_getImage($this->_tempimglnk, false);
  9057. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse GIF image'); }
  9058. imagedestroy($im);
  9059. }
  9060. else {
  9061. $check = @imagepng($im, $tempfile);
  9062. if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse GIF image'); }
  9063. $info = $this->_getImage($tempfile, false);
  9064. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse GIF image'); }
  9065. imagedestroy($im);
  9066. unlink($tempfile);
  9067. }
  9068. $info['type']='gif';
  9069. if ($firsttime) {
  9070. $info['i']=count($this->images)+1;
  9071. $this->images[$file]=$info;
  9072. }
  9073. return $info;
  9074. }
  9075. else { return $this->_imageError($file, $firsttime, 'Error creating GD image file from GIF image'); }
  9076. }
  9077. if (!class_exists('gif', false)) {
  9078. include_once(_MPDF_PATH.'classes/gif.php');
  9079. }
  9080. $gif=new CGIF();
  9081. $h=0;
  9082. $w=0;
  9083. $gif->loadFile($data, 0);
  9084. if(isset($gif->m_img->m_gih->m_bLocalClr) && $gif->m_img->m_gih->m_bLocalClr) {
  9085. $nColors = $gif->m_img->m_gih->m_nTableSize;
  9086. $pal = $gif->m_img->m_gih->m_colorTable->toString();
  9087. if($bgColor != -1) {
  9088. $bgColor = $gif->m_img->m_gih->m_colorTable->colorIndex($bgColor);
  9089. }
  9090. $colspace='Indexed';
  9091. } elseif(isset($gif->m_gfh->m_bGlobalClr) && $gif->m_gfh->m_bGlobalClr) {
  9092. $nColors = $gif->m_gfh->m_nTableSize;
  9093. $pal = $gif->m_gfh->m_colorTable->toString();
  9094. if((isset($bgColor)) and $bgColor != -1) {
  9095. $bgColor = $gif->m_gfh->m_colorTable->colorIndex($bgColor);
  9096. }
  9097. $colspace='Indexed';
  9098. } else {
  9099. $nColors = 0;
  9100. $bgColor = -1;
  9101. $colspace='DeviceGray';
  9102. $pal='';
  9103. }
  9104. $trns='';
  9105. if(isset($gif->m_img->m_bTrans) && $gif->m_img->m_bTrans && ($nColors > 0)) {
  9106. $trns=array($gif->m_img->m_nTrans);
  9107. }
  9108. $gifdata=$gif->m_img->m_data;
  9109. $w=$gif->m_gfh->m_nWidth;
  9110. $h=$gif->m_gfh->m_nHeight;
  9111. $gif->ClearData();
  9112. if($colspace=='Indexed' and empty($pal)) {
  9113. return $this->_imageError($file, $firsttime, 'Error parsing GIF image - missing colour palette');
  9114. }
  9115. if ($this->compress) {
  9116. $gifdata=gzcompress($gifdata);
  9117. $info = array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'f'=>'FlateDecode', 'pal'=>$pal, 'trns'=>$trns, 'data'=>$gifdata);
  9118. }
  9119. else {
  9120. $info = array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$gifdata);
  9121. }
  9122. $info['type']='gif';
  9123. if ($firsttime) {
  9124. $info['i']=count($this->images)+1;
  9125. $this->images[$file]=$info;
  9126. }
  9127. return $info;
  9128. }
  9129. /*-- IMAGES-BMP --*/
  9130. // BMP (Windows Bitmap)
  9131. else if ($type == 'bmp') {
  9132. if (!class_exists('bmp', false)) { include(_MPDF_PATH.'classes/bmp.php'); }
  9133. if (empty($this->bmp)) { $this->bmp = new bmp($this); }
  9134. $info = $this->bmp->_getBMPimage($data, $file);
  9135. if (isset($info['error'])) {
  9136. return $this->_imageError($file, $firsttime, $info['error']);
  9137. }
  9138. if ($firsttime) {
  9139. $info['i']=count($this->images)+1;
  9140. $this->images[$file]=$info;
  9141. }
  9142. return $info;
  9143. }
  9144. /*-- END IMAGES-BMP --*/
  9145. /*-- IMAGES-WMF --*/
  9146. // WMF
  9147. else if ($type == 'wmf') {
  9148. if (!class_exists('wmf', false)) { include(_MPDF_PATH.'classes/wmf.php'); }
  9149. if (empty($this->wmf)) { $this->wmf = new wmf($this); }
  9150. $wmfres = $this->wmf->_getWMFimage($data);
  9151. if ($wmfres[0]==0) {
  9152. if ($wmfres[1]) { return $this->_imageError($file, $firsttime, $wmfres[1]); }
  9153. return $this->_imageError($file, $firsttime, 'Error parsing WMF image');
  9154. }
  9155. $info = array('x'=>$wmfres[2][0],'y'=>$wmfres[2][1],'w'=>$wmfres[3][0],'h'=>$wmfres[3][1],'data'=>$wmfres[1]);
  9156. $info['i']=count($this->formobjects)+1;
  9157. $info['type']='wmf';
  9158. $this->formobjects[$file]=$info;
  9159. return $info;
  9160. }
  9161. /*-- END IMAGES-WMF --*/
  9162. // UNKNOWN TYPE - try GD imagecreatefromstring
  9163. else {
  9164. if (function_exists('gd_info')) { $gd = gd_info(); }
  9165. else {$gd = array(); }
  9166. if (isset($gd['PNG Support']) && $gd['PNG Support']) {
  9167. $im = @imagecreatefromstring($data);
  9168. if (!$im) { return $this->_imageError($file, $firsttime, 'Error parsing image file - image type not recognised, and not supported by GD imagecreate'); }
  9169. $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
  9170. imagealphablending($im, false);
  9171. imagesavealpha($im, false);
  9172. imageinterlace($im, false);
  9173. $check = @imagepng($im, $tempfile);
  9174. if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse unknown image type'); }
  9175. $info = $this->_getImage($tempfile, false);
  9176. imagedestroy($im);
  9177. unlink($tempfile);
  9178. if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse unknown image type'); }
  9179. $info['type']='png';
  9180. if ($firsttime) {
  9181. $info['i']=count($this->images)+1;
  9182. $this->images[$file]=$info;
  9183. }
  9184. return $info;
  9185. }
  9186. }
  9187. return $this->_imageError($file, $firsttime, 'Error parsing image file - image type not recognised');
  9188. }
  9189. //==============================================================
  9190. function _convImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask) {
  9191. if ($this->PDFA || $this->PDFX) { $mask=false; }
  9192. $im = @imagecreatefromstring($data);
  9193. $info = array();
  9194. if ($im) {
  9195. $imgdata = '';
  9196. $mimgdata = '';
  9197. $minfo = array();
  9198. //Read transparency info
  9199. $trns=array();
  9200. $trnsrgb = false;
  9201. if (!$this->PDFA && !$this->PDFX) {
  9202. $p = strpos($data,'tRNS');
  9203. if ($p) {
  9204. $n=$this->_fourbytes2int(substr($data,($p-4),4));
  9205. $t = substr($data,($p+4),$n);
  9206. if ($colspace=='DeviceGray') {
  9207. $trns=array(ord(substr($t,1,1)));
  9208. $trnsrgb = array($trns[0],$trns[0],$trns[0]);
  9209. }
  9210. else if ($colspace=='DeviceRGB') {
  9211. $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
  9212. $trnsrgb = $trns;
  9213. if ($targetcs=='DeviceCMYK') {
  9214. $col = $this->rgb2cmyk(array(3,$trns[0],$trns[1],$trns[2]));
  9215. $c1 = intval($col[1]*2.55);
  9216. $c2 = intval($col[2]*2.55);
  9217. $c3 = intval($col[3]*2.55);
  9218. $c4 = intval($col[4]*2.55);
  9219. $trns = array($c1,$c2,$c3,$c4);
  9220. }
  9221. else if ($targetcs=='DeviceGray') {
  9222. $c = intval(($trns[0] * .21) + ($trns[1] * .71) + ($trns[2] * .07));
  9223. $trns = array($c);
  9224. }
  9225. }
  9226. else { // Indexed
  9227. $pos = strpos($t,chr(0));
  9228. if (is_int($pos)) {
  9229. $pal = imagecolorsforindex($im, $pos);
  9230. $r = $pal['red'];
  9231. $g = $pal['green'];
  9232. $b = $pal['blue'];
  9233. $trns=array($r,$g,$b); // ****
  9234. $trnsrgb = $trns;
  9235. if ($targetcs=='DeviceCMYK') {
  9236. $col = $this->rgb2cmyk(array(3,$r,$g,$b));
  9237. $c1 = intval($col[1]*2.55);
  9238. $c2 = intval($col[2]*2.55);
  9239. $c3 = intval($col[3]*2.55);
  9240. $c4 = intval($col[4]*2.55);
  9241. $trns = array($c1,$c2,$c3,$c4);
  9242. }
  9243. else if ($targetcs=='DeviceGray') {
  9244. $c = intval(($r * .21) + ($g * .71) + ($b * .07));
  9245. $trns = array($c);
  9246. }
  9247. }
  9248. }
  9249. }
  9250. }
  9251. for ($i = 0; $i < $h; $i++) {
  9252. for ($j = 0; $j < $w; $j++) {
  9253. $rgb = imagecolorat($im, $j, $i);
  9254. $r = ($rgb >> 16) & 0xFF;
  9255. $g = ($rgb >> 8) & 0xFF;
  9256. $b = $rgb & 0xFF;
  9257. if ($colspace=='Indexed') {
  9258. $pal = imagecolorsforindex($im, $rgb);
  9259. $r = $pal['red'];
  9260. $g = $pal['green'];
  9261. $b = $pal['blue'];
  9262. }
  9263. if ($targetcs=='DeviceCMYK') {
  9264. $col = $this->rgb2cmyk(array(3,$r,$g,$b));
  9265. $c1 = intval($col[1]*2.55);
  9266. $c2 = intval($col[2]*2.55);
  9267. $c3 = intval($col[3]*2.55);
  9268. $c4 = intval($col[4]*2.55);
  9269. if ($trnsrgb) {
  9270. // original pixel was not set as transparent but processed color does match
  9271. if ($trnsrgb!=array($r,$g,$b) && $trns==array($c1,$c2,$c3,$c4)) {
  9272. if ($c4==0) { $c4=1; } else { $c4--; }
  9273. }
  9274. }
  9275. $imgdata .= chr($c1).chr($c2).chr($c3).chr($c4);
  9276. }
  9277. else if ($targetcs=='DeviceGray') {
  9278. $c = intval(($r * .21) + ($g * .71) + ($b * .07));
  9279. if ($trnsrgb) {
  9280. // original pixel was not set as transparent but processed color does match
  9281. if ($trnsrgb!=array($r,$g,$b) && $trns==array($c)) {
  9282. if ($c==0) { $c=1; } else { $c--; }
  9283. }
  9284. }
  9285. $imgdata .= chr($c);
  9286. }
  9287. else if ($targetcs=='DeviceRGB') {
  9288. $imgdata .= chr($r).chr($g).chr($b);
  9289. }
  9290. if ($mask) {
  9291. $col = imagecolorsforindex($im, $rgb);
  9292. $gammacorr = 2.2; // gamma correction
  9293. $gamma = intval((pow((((127 - $col['alpha']) * 255 / 127) / 255), $gammacorr) * 255));
  9294. $mimgdata .= chr($gamma);
  9295. }
  9296. }
  9297. }
  9298. if ($targetcs=='DeviceGray') { $ncols = 1; }
  9299. else if ($targetcs=='DeviceRGB') { $ncols = 3; }
  9300. else if ($targetcs=='DeviceCMYK') { $ncols = 4; }
  9301. $imgdata = gzcompress($imgdata);
  9302. $info = array('w'=>$w,'h'=>$h,'cs'=>$targetcs,'bpc'=>8,'f'=>'FlateDecode','data'=>$imgdata, 'type'=>'png',
  9303. 'parms'=>'/DecodeParms <</Colors '.$ncols.' /BitsPerComponent 8 /Columns '.$w.'>>');
  9304. if ($dpi) { $info['set-dpi'] = $dpi; }
  9305. if ($mask) {
  9306. $mimgdata = gzcompress($mimgdata);
  9307. $minfo = array('w'=>$w,'h'=>$h,'cs'=>'DeviceGray','bpc'=>8,'f'=>'FlateDecode','data'=>$mimgdata, 'type'=>'png',
  9308. 'parms'=>'/DecodeParms <</Colors '.$ncols.' /BitsPerComponent 8 /Columns '.$w.'>>');
  9309. if ($dpi) { $minfo['set-dpi'] = $dpi; }
  9310. $tempfile = '_tempImgPNG'.RAND(1,10000).'.png';
  9311. $imgmask = count($this->images)+1;
  9312. $minfo['i']=$imgmask ;
  9313. $this->images[$tempfile] = $minfo;
  9314. $info['masked'] = $imgmask;
  9315. }
  9316. else if ($trns) { $info['trns'] = $trns; }
  9317. imagedestroy($im);
  9318. }
  9319. return $info;
  9320. }
  9321. function _fourbytes2int($s) {
  9322. //Read a 4-byte integer from string
  9323. return (ord($s[0])<<24) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]);
  9324. }
  9325. function _twobytes2int($s) {
  9326. //Read a 2-byte integer from string
  9327. return (ord(substr($s, 0, 1))<<8) + ord(substr($s, 1, 1));
  9328. }
  9329. function _jpgHeaderFromString(&$data) {
  9330. $p = 4;
  9331. $p += $this->_twobytes2int(substr($data, $p, 2)); // Length of initial marker block
  9332. $marker = substr($data, $p, 2);
  9333. while($marker != chr(255).chr(192) && $marker != chr(255).chr(194) && $p<strlen($data)) {
  9334. // Start of frame marker (FFC0) or (FFC2) mPDF 4.4.004
  9335. $p += ($this->_twobytes2int(substr($data, $p+2, 2))) + 2; // Length of marker block
  9336. $marker = substr($data, $p, 2);
  9337. }
  9338. if ($marker != chr(255).chr(192) && $marker != chr(255).chr(194)) { return false; }
  9339. return substr($data, $p+2, 10);
  9340. }
  9341. function _jpgDataFromHeader($hdr) {
  9342. $bpc = ord(substr($hdr, 2, 1));
  9343. if (!$bpc) { $bpc = 8; }
  9344. $h = $this->_twobytes2int(substr($hdr, 3, 2));
  9345. $w = $this->_twobytes2int(substr($hdr, 5, 2));
  9346. $channels = ord(substr($hdr, 7, 1));
  9347. if ($channels==3) { $colspace='DeviceRGB'; }
  9348. elseif($channels==4) { $colspace='DeviceCMYK'; }
  9349. else { $colspace='DeviceGray'; }
  9350. return array($w, $h, $colspace, $bpc);
  9351. }
  9352. function file_get_contents_by_curl($url, &$data) {
  9353. $timeout = 5;
  9354. $ch = curl_init($url);
  9355. curl_setopt($ch, CURLOPT_HEADER, 0);
  9356. curl_setopt($ch, CURLOPT_NOBODY, 0);
  9357. curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
  9358. curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , $timeout );
  9359. $data = curl_exec($ch);
  9360. curl_close($ch);
  9361. }
  9362. function file_get_contents_by_socket($url, &$data) {
  9363. $timeout = 1;
  9364. $p = parse_url($url);
  9365. $file = $p['path'];
  9366. if ($p['query']) { $file .= '?'.$p['query']; }
  9367. if(!($fh = @fsockopen($p['host'], 80, $errno, $errstr, $timeout))) { return false; }
  9368. $getstring =
  9369. "GET ".$file." HTTP/1.0 \r\n" .
  9370. "Host: ".$p['host']." \r\n" .
  9371. "Connection: close\r\n\r\n";
  9372. fwrite($fh, $getstring);
  9373. // Get rid of HTTP header
  9374. $s = fgets($fh, 1024);
  9375. if (!$s) { return false; }
  9376. $httpheader .= $s;
  9377. while (!feof($fh)) {
  9378. $s = fgets($fh, 1024);
  9379. if ( $s == "\r\n" ) { break; }
  9380. }
  9381. $data = '';
  9382. while (!feof($fh)) {
  9383. $data .= fgets($fh, 1024);
  9384. }
  9385. fclose($fh);
  9386. }
  9387. //==============================================================
  9388. function _imageTypeFromString(&$data) {
  9389. $type = '';
  9390. if (substr($data, 6, 4)== 'JFIF' || substr($data, 6, 4)== 'Exif') {
  9391. $type = 'jpeg';
  9392. }
  9393. else if (substr($data, 0, 6)== "GIF87a" || substr($data, 0, 6)== "GIF89a") {
  9394. $type = 'gif';
  9395. }
  9396. else if (substr($data, 0, 8)== chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
  9397. $type = 'png';
  9398. }
  9399. /*-- IMAGES-WMF --*/
  9400. else if (substr($data, 0, 4)== chr(215).chr(205).chr(198).chr(154)) {
  9401. $type = 'wmf';
  9402. }
  9403. /*-- END IMAGES-WMF --*/
  9404. else if (preg_match('/<svg.*<\/svg>/is',$data)) {
  9405. $type = 'svg';
  9406. }
  9407. // BMP images
  9408. else if (substr($data, 0, 2)== "BM") {
  9409. $type = 'bmp';
  9410. }
  9411. return $type;
  9412. }
  9413. //==============================================================
  9414. // Moved outside WMF as also needed for SVG
  9415. function _putformobjects() {
  9416. reset($this->formobjects);
  9417. while(list($file,$info)=each($this->formobjects)) {
  9418. $this->_newobj();
  9419. $this->formobjects[$file]['n']=$this->n;
  9420. $this->_out('<</Type /XObject');
  9421. $this->_out('/Subtype /Form');
  9422. $this->_out('/Group '.($this->n+1).' 0 R');
  9423. $this->_out('/BBox ['.$info['x'].' '.$info['y'].' '.($info['w']+$info['x']).' '.($info['h']+$info['y']).']');
  9424. if ($this->compress)
  9425. $this->_out('/Filter /FlateDecode');
  9426. $data=($this->compress) ? gzcompress($info['data']) : $info['data'];
  9427. $this->_out('/Length '.strlen($data).'>>');
  9428. $this->_putstream($data);
  9429. unset($this->formobjects[$file]['data']);
  9430. $this->_out('endobj');
  9431. // Required for SVG transparency (opacity) to work
  9432. $this->_newobj();
  9433. $this->_out('<</Type /Group');
  9434. $this->_out('/S /Transparency');
  9435. $this->_out('>>');
  9436. $this->_out('endobj');
  9437. }
  9438. }
  9439. function _freadint($f)
  9440. {
  9441. //Read a 4-byte integer from file
  9442. $i=ord(fread($f,1))<<24;
  9443. $i+=ord(fread($f,1))<<16;
  9444. $i+=ord(fread($f,1))<<8;
  9445. $i+=ord(fread($f,1));
  9446. return $i;
  9447. }
  9448. function _UTF16BEtextstring($s) {
  9449. $s = $this->UTF8ToUTF16BE($s, true);
  9450. /*-- ENCRYPTION --*/
  9451. if ($this->encrypted) {
  9452. $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
  9453. }
  9454. /*-- END ENCRYPTION --*/
  9455. return '('. $this->_escape($s).')';
  9456. }
  9457. function _textstring($s) {
  9458. /*-- ENCRYPTION --*/
  9459. if ($this->encrypted) {
  9460. $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
  9461. }
  9462. /*-- END ENCRYPTION --*/
  9463. return '('. $this->_escape($s).')';
  9464. }
  9465. function _escape($s)
  9466. {
  9467. // the chr(13) substitution fixes the Bugs item #1421290.
  9468. return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r'));
  9469. }
  9470. function _putstream($s) {
  9471. /*-- ENCRYPTION --*/
  9472. if ($this->encrypted) {
  9473. $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
  9474. }
  9475. /*-- END ENCRYPTION --*/
  9476. $this->_out('stream');
  9477. $this->_out($s);
  9478. $this->_out('endstream');
  9479. }
  9480. function _out($s,$ln=true) {
  9481. if($this->state==2) {
  9482. if ($this->bufferoutput) {
  9483. $this->headerbuffer.= $s."\n";
  9484. }
  9485. /*-- COLUMNS --*/
  9486. else if (($this->ColActive) && !$this->processingHeader && !$this->processingFooter) {
  9487. // Captures everything in buffer for columns; Almost everything is sent from fn. Cell() except:
  9488. // Images sent from Image() or
  9489. // later sent as _out($textto) in printbuffer
  9490. // Line()
  9491. if (preg_match('/q \d+\.\d\d+ 0 0 (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ cm \/(I|FO)\d+ Do Q/',$s,$m)) { // Image data
  9492. $h = ($m[1]/_MPDFK);
  9493. // Update/overwrite the lowest bottom of printing y value for a column
  9494. $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$h;
  9495. }
  9496. /*-- TABLES --*/
  9497. else if (preg_match('/\d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ ([\-]{0,1}\d+\.\d\d+) re/',$s,$m) && $this->tableLevel>0) { // Rect in table
  9498. $h = ($m[1]/_MPDFK);
  9499. // Update/overwrite the lowest bottom of printing y value for a column
  9500. $this->ColDetails[$this->CurrCol]['bottom_margin'] = max($this->ColDetails[$this->CurrCol]['bottom_margin'],($this->y+$h));
  9501. }
  9502. /*-- END TABLES --*/
  9503. else { // Td Text Set in Cell()
  9504. if (isset($this->ColDetails[$this->CurrCol]['bottom_margin'])) { $h = $this->ColDetails[$this->CurrCol]['bottom_margin'] - $this->y; }
  9505. else { $h = 0; }
  9506. }
  9507. if ($h < 0) { $h = -$h; }
  9508. $this->columnbuffer[] = array(
  9509. 's' => $s, // Text string to output
  9510. 'col' => $this->CurrCol, // Column when printed
  9511. 'x' => $this->x, // x when printed
  9512. 'y' => $this->y, // this->y when printed (after column break)
  9513. 'h' => $h // actual y at bottom when printed = y+h
  9514. );
  9515. }
  9516. /*-- END COLUMNS --*/
  9517. /*-- TABLES --*/
  9518. else if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
  9519. // Captures eveything in buffer for rotated tables;
  9520. $this->tablebuffer .= $s . "\n";
  9521. }
  9522. /*-- END TABLES --*/
  9523. else if ($this->kwt && !$this->processingHeader && !$this->processingFooter) {
  9524. // Captures eveything in buffer for keep-with-table (h1-6);
  9525. $this->kwt_buffer[] = array(
  9526. 's' => $s, // Text string to output
  9527. 'x' => $this->x, // x when printed
  9528. 'y' => $this->y, // y when printed
  9529. );
  9530. }
  9531. else if (($this->keep_block_together) && !$this->processingHeader && !$this->processingFooter) {
  9532. if (!isset($this->ktBlock[$this->page]['bottom_margin'])) {
  9533. $this->ktBlock[$this->page]['bottom_margin'] = $this->y;
  9534. }
  9535. // Captures eveything in buffer;
  9536. if (preg_match('/q \d+\.\d\d+ 0 0 (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ cm \/(I|FO)\d+ Do Q/',$s,$m)) { // Image data
  9537. $h = ($m[1]/_MPDFK);
  9538. // Update/overwrite the lowest bottom of printing y value for Keep together block
  9539. $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$h;
  9540. }
  9541. else { // Td Text Set in Cell()
  9542. if (isset($this->ktBlock[$this->page]['bottom_margin'])) { $h = $this->ktBlock[$this->page]['bottom_margin'] - $this->y; }
  9543. else { $h = 0; }
  9544. }
  9545. if ($h < 0) { $h = -$h; }
  9546. $this->divbuffer[] = array(
  9547. 'page' => $this->page,
  9548. 's' => $s, // Text string to output
  9549. 'x' => $this->x, // x when printed
  9550. 'y' => $this->y, // y when printed (after column break)
  9551. 'h' => $h // actual y at bottom when printed = y+h
  9552. );
  9553. }
  9554. else {
  9555. $this->pages[$this->page] .= $s.($ln == true ? "\n" : '');
  9556. }
  9557. }
  9558. else {
  9559. $this->buffer .= $s.($ln == true ? "\n" : '');
  9560. }
  9561. }
  9562. /*-- WATERMARK --*/
  9563. // add a watermark
  9564. function watermark( $texte, $angle=45, $fontsize=96, $alpha=0.2 ) {
  9565. if ($this->PDFA || $this->PDFX) { $this->Error('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!'); }
  9566. if (!$this->watermark_font) { $this->watermark_font = $this->default_font; }
  9567. $this->SetFont( $this->watermark_font, "B", $fontsize, false ); // Don't output
  9568. $texte= $this->purify_utf8_text($texte);
  9569. if ($this->text_input_as_HTML) {
  9570. $texte= $this->all_entities_to_utf8($texte);
  9571. }
  9572. if ($this->usingCoreFont) { $texte = mb_convert_encoding($texte,$this->mb_enc,'UTF-8'); }
  9573. // DIRECTIONALITY
  9574. $this->magic_reverse_dir($texte, true, $this->directionality); // *RTL*
  9575. // Font-specific ligature substitution for Indic fonts
  9576. if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($texte); // *INDIC*
  9577. $this->SetAlpha($alpha);
  9578. $this->SetTColor($this->ConvertColor(0));
  9579. $szfont = $fontsize;
  9580. $loop = 0;
  9581. $maxlen = (min($this->w,$this->h) ); // sets max length of text as 7/8 width/height of page
  9582. while ( $loop == 0 )
  9583. {
  9584. $this->SetFont( $this->watermark_font, "B", $szfont, false ); // Don't output
  9585. $offset = ((sin(deg2rad($angle))) * ($szfont/_MPDFK));
  9586. $strlen = $this->GetStringWidth($texte);
  9587. if ( $strlen > $maxlen - $offset )
  9588. $szfont --;
  9589. else
  9590. $loop ++;
  9591. }
  9592. $this->SetFont( $this->watermark_font, "B", $szfont-0.1, true, true); // Output The -0.1 is because SetFont above is not written to PDF
  9593. // Repeating it will not output anything as mPDF thinks it is set
  9594. $adj = ((cos(deg2rad($angle))) * ($strlen/2));
  9595. $opp = ((sin(deg2rad($angle))) * ($strlen/2));
  9596. $wx = ($this->w/2) - $adj + $offset/3;
  9597. $wy = ($this->h/2) + $opp;
  9598. $this->Rotate($angle,$wx,$wy);
  9599. $this->Text($wx,$wy,$texte);
  9600. $this->Rotate(0);
  9601. $this->SetTColor($this->ConvertColor(0));
  9602. $this->SetAlpha(1);
  9603. }
  9604. function watermarkImg( $src, $alpha=0.2 ) {
  9605. if ($this->PDFA || $this->PDFX) { $this->Error('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!'); }
  9606. if ($this->watermarkImgBehind) { $this->watermarkImgAlpha = $this->SetAlpha($alpha, 'Normal', true); }
  9607. else { $this->SetAlpha($alpha, $this->watermarkImgAlphaBlend); }
  9608. $this->Image($src,0,0,0,0,'','', true, true, true);
  9609. if (!$this->watermarkImgBehind) { $this->SetAlpha(1); }
  9610. }
  9611. /*-- END WATERMARK --*/
  9612. function Rotate($angle,$x=-1,$y=-1)
  9613. {
  9614. if($x==-1)
  9615. $x=$this->x;
  9616. if($y==-1)
  9617. $y=$this->y;
  9618. if($this->angle!=0)
  9619. $this->_out('Q');
  9620. $this->angle=$angle;
  9621. if($angle!=0)
  9622. {
  9623. $angle*=M_PI/180;
  9624. $c=cos($angle);
  9625. $s=sin($angle);
  9626. $cx=$x*_MPDFK;
  9627. $cy=($this->h-$y)*_MPDFK;
  9628. $this->_out(sprintf('q %.5F %.5F %.5F %.5F %.3F %.3F cm 1 0 0 1 %.3F %.3F cm',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy));
  9629. }
  9630. }
  9631. function CircularText($x, $y, $r, $text, $align='top', $fontfamily='', $fontsize=0, $fontstyle='', $kerning=120, $fontwidth=100, $divider) { // mPDF 5.5.23
  9632. if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
  9633. if (empty($this->directw)) { $this->directw = new directw($this); }
  9634. $this->directw->CircularText($x, $y, $r, $text, $align, $fontfamily, $fontsize, $fontstyle, $kerning, $fontwidth, $divider); // mPDF 5.5.23
  9635. }
  9636. // From Invoice
  9637. function RoundedRect($x, $y, $w, $h, $r, $style = '')
  9638. {
  9639. $hp = $this->h;
  9640. if($style=='F')
  9641. $op='f';
  9642. elseif($style=='FD' or $style=='DF')
  9643. $op='B';
  9644. else
  9645. $op='S';
  9646. $MyArc = 4/3 * (sqrt(2) - 1);
  9647. $this->_out(sprintf('%.3F %.3F m',($x+$r)*_MPDFK,($hp-$y)*_MPDFK ));
  9648. $xc = $x+$w-$r ;
  9649. $yc = $y+$r;
  9650. $this->_out(sprintf('%.3F %.3F l', $xc*_MPDFK,($hp-$y)*_MPDFK ));
  9651. $this->_Arc($xc + $r*$MyArc, $yc - $r, $xc + $r, $yc - $r*$MyArc, $xc + $r, $yc);
  9652. $xc = $x+$w-$r ;
  9653. $yc = $y+$h-$r;
  9654. $this->_out(sprintf('%.3F %.3F l',($x+$w)*_MPDFK,($hp-$yc)*_MPDFK));
  9655. $this->_Arc($xc + $r, $yc + $r*$MyArc, $xc + $r*$MyArc, $yc + $r, $xc, $yc + $r);
  9656. $xc = $x+$r ;
  9657. $yc = $y+$h-$r;
  9658. $this->_out(sprintf('%.3F %.3F l',$xc*_MPDFK,($hp-($y+$h))*_MPDFK));
  9659. $this->_Arc($xc - $r*$MyArc, $yc + $r, $xc - $r, $yc + $r*$MyArc, $xc - $r, $yc);
  9660. $xc = $x+$r ;
  9661. $yc = $y+$r;
  9662. $this->_out(sprintf('%.3F %.3F l',($x)*_MPDFK,($hp-$yc)*_MPDFK ));
  9663. $this->_Arc($xc - $r, $yc - $r*$MyArc, $xc - $r*$MyArc, $yc - $r, $xc, $yc - $r);
  9664. $this->_out($op);
  9665. }
  9666. function _Arc($x1, $y1, $x2, $y2, $x3, $y3)
  9667. {
  9668. $h = $this->h;
  9669. $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x1*_MPDFK, ($h-$y1)*_MPDFK,
  9670. $x2*_MPDFK, ($h-$y2)*_MPDFK, $x3*_MPDFK, ($h-$y3)*_MPDFK));
  9671. }
  9672. //====================================================
  9673. /*-- DIRECTW --*/
  9674. function Shaded_box( $text,$font='',$fontstyle='B',$szfont='',$width='70%',$style='DF',$radius=2.5,$fill='#FFFFFF',$color='#000000',$pad=2 ) {
  9675. // F (shading - no line),S (line, no shading),DF (both)
  9676. if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
  9677. if (empty($this->directw)) { $this->directw = new directw($this); }
  9678. $this->directw->Shaded_box( $text,$font,$fontstyle,$szfont,$width,$style,$radius,$fill,$color,$pad);
  9679. }
  9680. /*-- END DIRECTW --*/
  9681. function UTF8StringToArray($str, $addSubset=true) {
  9682. $out = array();
  9683. $len = strlen($str);
  9684. for ($i = 0; $i < $len; $i++) {
  9685. $uni = -1;
  9686. $h = ord($str[$i]);
  9687. if ( $h <= 0x7F )
  9688. $uni = $h;
  9689. elseif ( $h >= 0xC2 ) {
  9690. if ( ($h <= 0xDF) && ($i < $len -1) )
  9691. $uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
  9692. elseif ( ($h <= 0xEF) && ($i < $len -2) )
  9693. $uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
  9694. elseif ( ($h <= 0xF4) && ($i < $len -3) )
  9695. $uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
  9696. }
  9697. if ($uni >= 0) {
  9698. $out[] = $uni;
  9699. if ($addSubset && isset($this->CurrentFont['subset'])) {
  9700. $this->CurrentFont['subset'][$uni] = $uni;
  9701. }
  9702. }
  9703. }
  9704. return $out;
  9705. }
  9706. //Convert utf-8 string to <HHHHHH> for Font Subsets
  9707. function UTF8toSubset($str) {
  9708. $ret = '<';
  9709. $str = preg_replace('/'.preg_quote($this->aliasNbPg,'/').'/', chr(7), $str );
  9710. $str = preg_replace('/'.preg_quote($this->aliasNbPgGp,'/').'/', chr(8), $str );
  9711. $unicode = $this->UTF8StringToArray($str);
  9712. $orig_fid = $this->CurrentFont['subsetfontids'][0];
  9713. $last_fid = $this->CurrentFont['subsetfontids'][0];
  9714. foreach($unicode as $c) {
  9715. if ($c == 7 || $c == 8) {
  9716. if ($orig_fid != $last_fid) {
  9717. $ret .= '> Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <';
  9718. $last_fid = $orig_fid;
  9719. }
  9720. if ($c == 7) { $ret .= $this->aliasNbPgHex; }
  9721. else { $ret .= $this->aliasNbPgGpHex; }
  9722. continue;
  9723. }
  9724. for ($i=0; $i<99; $i++) {
  9725. // return c as decimal char
  9726. $init = array_search($c, $this->CurrentFont['subsets'][$i]);
  9727. if ($init!==false) {
  9728. if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
  9729. $ret .= '> Tj /F'.$this->CurrentFont['subsetfontids'][$i].' '.$this->FontSizePt.' Tf <';
  9730. $last_fid = $this->CurrentFont['subsetfontids'][$i];
  9731. }
  9732. $ret .= sprintf("%02s", strtoupper(dechex($init)));
  9733. break;
  9734. }
  9735. // TrueType embedded SUBSETS
  9736. else if (count($this->CurrentFont['subsets'][$i]) < 255) {
  9737. $n = count($this->CurrentFont['subsets'][$i]);
  9738. $this->CurrentFont['subsets'][$i][$n] = $c;
  9739. if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
  9740. $ret .= '> Tj /F'.$this->CurrentFont['subsetfontids'][$i].' '.$this->FontSizePt.' Tf <';
  9741. $last_fid = $this->CurrentFont['subsetfontids'][$i];
  9742. }
  9743. $ret .= sprintf("%02s", strtoupper(dechex($n)));
  9744. break;
  9745. }
  9746. else if (!isset($this->CurrentFont['subsets'][($i+1)])) {
  9747. // TrueType embedded SUBSETS
  9748. $this->CurrentFont['subsets'][($i+1)] = array(0=>0);
  9749. $new_fid = count($this->fonts)+$this->extraFontSubsets+1;
  9750. $this->CurrentFont['subsetfontids'][($i+1)] = $new_fid;
  9751. $this->extraFontSubsets++;
  9752. }
  9753. }
  9754. }
  9755. $ret .= '>';
  9756. if ($last_fid != $orig_fid) {
  9757. $ret .= ' Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <> ';
  9758. }
  9759. return $ret;
  9760. }
  9761. // Converts UTF-8 strings to UTF16-BE.
  9762. function UTF8ToUTF16BE($str, $setbom=true) {
  9763. if ($this->checkSIP && preg_match("/([\x{20000}-\x{2FFFF}])/u", $str)) {
  9764. if (!in_array($this->currentfontfamily, array('gb','big5','sjis','uhc','gbB','big5B','sjisB','uhcB','gbI','big5I','sjisI','uhcI',
  9765. 'gbBI','big5BI','sjisBI','uhcBI'))) {
  9766. $str = preg_replace("/[\x{20000}-\x{2FFFF}]/u", chr(0), $str);
  9767. }
  9768. }
  9769. if ($this->checkSMP && preg_match("/([\x{10000}-\x{1FFFF}])/u", $str )) {
  9770. $str = preg_replace("/[\x{10000}-\x{1FFFF}]/u", chr(0), $str );
  9771. }
  9772. $outstr = ""; // string to be returned
  9773. if ($setbom) {
  9774. $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)
  9775. }
  9776. $outstr .= mb_convert_encoding($str, 'UTF-16BE', 'UTF-8');
  9777. return $outstr;
  9778. }
  9779. // ====================================================
  9780. // ====================================================
  9781. /*-- CJK-FONTS --*/
  9782. // from class PDF_Chinese CJK EXTENSIONS
  9783. function AddCIDFont($family,$style,$name,&$cw,$CMap,$registry,$desc)
  9784. {
  9785. $fontkey=strtolower($family).strtoupper($style);
  9786. if(isset($this->fonts[$fontkey]))
  9787. $this->Error("Font already added: $family $style");
  9788. $i=count($this->fonts)+$this->extraFontSubsets+1;
  9789. $name=str_replace(' ','',$name);
  9790. if ($family == 'sjis') { $up = -120; } else { $up = -130; }
  9791. // ? 'up' and 'ut' do not seem to be referenced anywhere
  9792. $this->fonts[$fontkey]=array('i'=>$i,'type'=>'Type0','name'=>$name,'up'=>$up,'ut'=>40,'cw'=>$cw,'CMap'=>$CMap,'registry'=>$registry,'MissingWidth'=>1000,'desc'=>$desc);
  9793. }
  9794. function AddCJKFont($family) {
  9795. if ($this->PDFA || $this->PDFX) {
  9796. $this->Error("Adobe CJK fonts cannot be embedded in mPDF (required for PDFA1-b and PDFX/1-a).");
  9797. }
  9798. if ($family == 'big5') { $this->AddBig5Font(); }
  9799. else if ($family == 'gb') { $this->AddGBFont(); }
  9800. else if ($family == 'sjis') { $this->AddSJISFont(); }
  9801. else if ($family == 'uhc') { $this->AddUHCFont(); }
  9802. }
  9803. function AddBig5Font()
  9804. {
  9805. //Add Big5 font with proportional Latin
  9806. $family='big5';
  9807. $name='MSungStd-Light-Acro';
  9808. $cw=$this->Big5_widths;
  9809. $CMap='UniCNS-UTF16-H';
  9810. $registry=array('ordering'=>'CNS1','supplement'=>4);
  9811. $desc = array(
  9812. 'Ascent' => 880,
  9813. 'Descent' => -120,
  9814. 'CapHeight' => 880,
  9815. 'Flags' => 6,
  9816. 'FontBBox' => '[-160 -249 1015 1071]',
  9817. 'ItalicAngle' => 0,
  9818. 'StemV' => 93,
  9819. );
  9820. $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
  9821. $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
  9822. $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
  9823. $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
  9824. }
  9825. function AddGBFont()
  9826. {
  9827. //Add GB font with proportional Latin
  9828. $family='gb';
  9829. $name='STSongStd-Light-Acro';
  9830. $cw=$this->GB_widths;
  9831. $CMap='UniGB-UTF16-H';
  9832. $registry=array('ordering'=>'GB1','supplement'=>4);
  9833. $desc = array(
  9834. 'Ascent' => 752,
  9835. 'Descent' => -271,
  9836. 'CapHeight' => 737,
  9837. 'Flags' => 6,
  9838. 'FontBBox' => '[-25 -254 1000 880]',
  9839. 'ItalicAngle' => 0,
  9840. 'StemV' => 58,
  9841. 'Style' => '<< /Panose <000000000400000000000000> >>',
  9842. );
  9843. $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
  9844. $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
  9845. $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
  9846. $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
  9847. }
  9848. function AddSJISFont()
  9849. {
  9850. //Add SJIS font with proportional Latin
  9851. $family='sjis';
  9852. $name='KozMinPro-Regular-Acro';
  9853. $cw=$this->SJIS_widths;
  9854. $CMap='UniJIS-UTF16-H';
  9855. $registry=array('ordering'=>'Japan1','supplement'=>5);
  9856. $desc = array(
  9857. 'Ascent' => 880,
  9858. 'Descent' => -120,
  9859. 'CapHeight' => 740,
  9860. 'Flags' => 6,
  9861. 'FontBBox' => '[-195 -272 1110 1075]',
  9862. 'ItalicAngle' => 0,
  9863. 'StemV' => 86,
  9864. 'XHeight' => 502,
  9865. );
  9866. $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
  9867. $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
  9868. $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
  9869. $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
  9870. }
  9871. function AddUHCFont()
  9872. {
  9873. //Add UHC font with proportional Latin
  9874. $family='uhc';
  9875. $name='HYSMyeongJoStd-Medium-Acro';
  9876. $cw=$this->UHC_widths;
  9877. $CMap='UniKS-UTF16-H';
  9878. $registry=array('ordering'=>'Korea1','supplement'=>2);
  9879. $desc = array(
  9880. 'Ascent' => 880,
  9881. 'Descent' => -120,
  9882. 'CapHeight' => 720,
  9883. 'Flags' => 6,
  9884. 'FontBBox' => '[-28 -148 1001 880]',
  9885. 'ItalicAngle' => 0,
  9886. 'StemV' => 60,
  9887. 'Style' => '<< /Panose <000000000600000000000000> >>',
  9888. );
  9889. $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
  9890. $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
  9891. $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
  9892. $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
  9893. }
  9894. /*-- END CJK-FONTS --*/
  9895. //////////////////////////////////////////////////////////////////////////////
  9896. //////////////////////////////////////////////////////////////////////////////
  9897. //////////////////////////////////////////////////////////////////////////////
  9898. //////////////////////////////////////////////////////////////////////////////
  9899. //////////////////////////////////////////////////////////////////////////////
  9900. //////////////////////////////////////////////////////////////////////////////
  9901. //////////////////////////////////////////////////////////////////////////////
  9902. function SetAutoFont($af = AUTOFONT_ALL) {
  9903. if ($this->onlyCoreFonts) { return false; }
  9904. if (!$af && $af !== 0) { $af = AUTOFONT_ALL; }
  9905. $this->autoFontGroups = $af;
  9906. if ($this->autoFontGroups ) {
  9907. $this->useLang = true;
  9908. }
  9909. }
  9910. function SetDefaultFont($font) {
  9911. // Disallow embedded fonts to be used as defaults in PDFA
  9912. if ($this->PDFA || $this->PDFX) {
  9913. if (strtolower($font) == 'ctimes') { $font = 'serif'; }
  9914. if (strtolower($font) == 'ccourier') { $font = 'monospace'; }
  9915. if (strtolower($font) == 'chelvetica') { $font = 'sans-serif'; }
  9916. }
  9917. $font = $this->SetFont($font); // returns substituted font if necessary
  9918. $this->default_font = $font;
  9919. $this->original_default_font = $font;
  9920. if (!$this->watermark_font ) { $this->watermark_font = $font; } // *WATERMARK*
  9921. $this->defaultCSS['BODY']['FONT-FAMILY'] = $font;
  9922. $this->cssmgr->CSS['BODY']['FONT-FAMILY'] = $font;
  9923. }
  9924. function SetDefaultFontSize($fontsize) {
  9925. $this->default_font_size = $fontsize;
  9926. $this->original_default_font_size = $fontsize;
  9927. $this->SetFontSize($fontsize);
  9928. $this->defaultCSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
  9929. $this->cssmgr->CSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
  9930. }
  9931. function SetDefaultBodyCSS($prop, $val) {
  9932. if ($prop) {
  9933. $this->defaultCSS['BODY'][strtoupper($prop)] = $val;
  9934. $this->cssmgr->CSS['BODY'][strtoupper($prop)] = $val;
  9935. }
  9936. }
  9937. function SetDirectionality($dir='ltr') {
  9938. /*-- RTL --*/
  9939. if (strtolower($dir) == 'rtl') {
  9940. if ($this->directionality != 'rtl') {
  9941. // Swop L/R Margins so page 1 RTL is an 'even' page
  9942. $tmp = $this->DeflMargin;
  9943. $this->DeflMargin = $this->DefrMargin;
  9944. $this->DefrMargin = $tmp;
  9945. $this->orig_lMargin = $this->DeflMargin;
  9946. $this->orig_rMargin = $this->DefrMargin;
  9947. $this->SetMargins($this->DeflMargin,$this->DefrMargin,$this->tMargin);
  9948. }
  9949. $this->directionality = 'rtl';
  9950. $this->defaultAlign = 'R';
  9951. $this->defaultTableAlign = 'R';
  9952. }
  9953. else {
  9954. /*-- END RTL --*/
  9955. $this->directionality = 'ltr';
  9956. $this->defaultAlign = 'L';
  9957. $this->defaultTableAlign = 'L';
  9958. } // *RTL*
  9959. $this->cssmgr->CSS['BODY']['DIRECTION'] = $this->directionality;
  9960. }
  9961. // Added to set line-height-correction
  9962. function SetLineHeightCorrection($val) {
  9963. if ($val > 0) { $this->default_lineheight_correction = $val; }
  9964. else { $this->default_lineheight_correction = 1.2; }
  9965. }
  9966. // Set a (fixed) lineheight to an actual value - either to named fontsize(pts) or default
  9967. function SetLineHeight($FontPt='',$spacing = '') {
  9968. if ($this->shrin_k > 1) { $k = $this->shrin_k; }
  9969. else { $k = 1; }
  9970. if ($spacing > 0) {
  9971. if (preg_match('/mm/',$spacing)) {
  9972. $this->lineheight = ($spacing + 0.0) / $k; // convert to number
  9973. }
  9974. else {
  9975. if ($FontPt) { $this->lineheight = (($FontPt/_MPDFK) *$spacing); }
  9976. else { $this->lineheight = (($this->FontSizePt/_MPDFK) *$spacing); }
  9977. }
  9978. }
  9979. else {
  9980. if ($FontPt) { $this->lineheight = (($FontPt/_MPDFK) *$this->normalLineheight); }
  9981. else { $this->lineheight = (($this->FontSizePt/_MPDFK) *$this->normalLineheight); }
  9982. }
  9983. }
  9984. function _computeLineheight($lh, $fs='') {
  9985. if ($this->shrin_k > 1) { $k = $this->shrin_k; }
  9986. else { $k = 1; }
  9987. if (!$fs) { $fs = $this->FontSize; }
  9988. if (preg_match('/mm/',$lh)) {
  9989. return (($lh + 0.0) / $k); // convert to number
  9990. }
  9991. else if ($lh > 0) {
  9992. return ($fs * $lh);
  9993. }
  9994. else if (isset($this->normalLineheight)) { return ($fs * $this->normalLineheight); }
  9995. else return ($fs * $this->default_lineheight_correction);
  9996. }
  9997. function SetBasePath($str='') {
  9998. if ( isset($_SERVER['HTTP_HOST']) ) { $host = $_SERVER['HTTP_HOST']; }
  9999. else if ( isset($_SERVER['SERVER_NAME']) ) { $host = $_SERVER['SERVER_NAME']; }
  10000. else { $host = ''; }
  10001. if (!$str) {
  10002. if ($_SERVER['SCRIPT_NAME']) { $currentPath = dirname($_SERVER['SCRIPT_NAME']); }
  10003. else { $currentPath = dirname($_SERVER['PHP_SELF']); }
  10004. $currentPath = str_replace("\\","/",$currentPath);
  10005. if ($currentPath == '/') { $currentPath = ''; }
  10006. if ($host) { $currpath = 'http://' . $host . $currentPath .'/'; }
  10007. else { $currpath = ''; }
  10008. $this->basepath = $currpath;
  10009. $this->basepathIsLocal = true;
  10010. return;
  10011. }
  10012. $str = preg_replace('/\?.*/','',$str);
  10013. if (!preg_match('/(http|https|ftp):\/\/.*\//i',$str)) { $str .= '/'; }
  10014. $str .= 'xxx'; // in case $str ends in / e.g. http://www.bbc.co.uk/
  10015. $this->basepath = dirname($str) . "/"; // returns e.g. e.g. http://www.google.com/dir1/dir2/dir3/
  10016. $this->basepath = str_replace("\\","/",$this->basepath); //If on Windows
  10017. $tr = parse_url($this->basepath);
  10018. if (isset($tr['host']) && ($tr['host'] == $host)) { $this->basepathIsLocal = true; }
  10019. else { $this->basepathIsLocal = false; }
  10020. }
  10021. function GetFullPath(&$path,$basepath='') {
  10022. // When parsing CSS need to pass temporary basepath - so links are relative to current stylesheet
  10023. if (!$basepath) { $basepath = $this->basepath; }
  10024. //Fix path value
  10025. $path = str_replace("\\","/",$path); //If on Windows
  10026. $path = preg_replace('/^\/\//','http://',$path); // mPDF 5.6.27
  10027. $regexp = '|^./|'; // Inadvertently corrects "./path/etc" and "//www.domain.com/etc"
  10028. $path = preg_replace($regexp,'',$path);
  10029. if(substr($path,0,1) == '#') { return; }
  10030. if (stristr($path,"mailto:") !== false) { return; }
  10031. if (strpos($path,"../") !== false ) { //It is a Relative Link
  10032. $backtrackamount = substr_count($path,"../");
  10033. $maxbacktrack = substr_count($basepath,"/") - 3; // mPDF 5.6.18
  10034. $filepath = str_replace("../",'',$path);
  10035. $path = $basepath;
  10036. //If it is an invalid relative link, then make it go to directory root
  10037. if ($backtrackamount > $maxbacktrack) $backtrackamount = $maxbacktrack;
  10038. //Backtrack some directories
  10039. for( $i = 0 ; $i < $backtrackamount + 1 ; $i++ ) $path = substr( $path, 0 , strrpos($path,"/") );
  10040. $path = $path . "/" . $filepath; //Make it an absolute path
  10041. }
  10042. else if( strpos($path,":/") === false || strpos($path,":/") > 10) { //It is a Local Link
  10043. if (substr($path,0,1) == "/") {
  10044. $tr = parse_url($basepath);
  10045. $root = $tr['scheme'].'://'.$tr['host'];
  10046. $path = $root . $path;
  10047. }
  10048. else { $path = $basepath . $path; }
  10049. }
  10050. //Do nothing if it is an Absolute Link
  10051. }
  10052. // Used for external CSS files
  10053. function _get_file($path) {
  10054. // If local file try using local path (? quicker, but also allowed even if allow_url_fopen false)
  10055. $contents = '';
  10056. $contents = @file_get_contents($path);
  10057. if ($contents) { return $contents; }
  10058. if ($this->basepathIsLocal) {
  10059. $tr = parse_url($path);
  10060. $lp=getenv("SCRIPT_NAME");
  10061. $ap=realpath($lp);
  10062. $ap=str_replace("\\","/",$ap);
  10063. $docroot=substr($ap,0,strpos($ap,$lp));
  10064. // WriteHTML parses all paths to full URLs; may be local file name
  10065. if ($tr['scheme'] && $tr['host'] && $_SERVER["DOCUMENT_ROOT"] ) {
  10066. $localpath = $_SERVER["DOCUMENT_ROOT"] . $tr['path'];
  10067. }
  10068. // DOCUMENT_ROOT is not returned on IIS
  10069. else if ($docroot) {
  10070. $localpath = $docroot . $tr['path'];
  10071. }
  10072. else { $localpath = $path; }
  10073. $contents = @file_get_contents($localpath);
  10074. }
  10075. // if not use full URL
  10076. else if (!$contents && !ini_get('allow_url_fopen') && function_exists("curl_init")) {
  10077. $ch = curl_init($path);
  10078. curl_setopt($ch, CURLOPT_HEADER, 0);
  10079. curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
  10080. $contents = curl_exec($ch);
  10081. curl_close($ch);
  10082. }
  10083. return $contents;
  10084. }
  10085. function docPageNum($num = 0, $extras = false) {
  10086. if ($num < 1) { $num = $this->page; }
  10087. $type = '1'; // set default decimal
  10088. $ppgno = $num;
  10089. $suppress = 0;
  10090. $offset = 0;
  10091. $lastreset = 0;
  10092. foreach($this->PageNumSubstitutions AS $psarr) {
  10093. if ($num >= $psarr['from']) {
  10094. if ($psarr['reset']) {
  10095. if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
  10096. $ppgno = $num - $psarr['from'] + 1 + $offset;
  10097. $lastreset = $psarr['from'];
  10098. }
  10099. if ($psarr['type']) { $type = $psarr['type']; }
  10100. if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
  10101. else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
  10102. }
  10103. }
  10104. if ($suppress) { return ''; }
  10105. foreach($this->pgsIns AS $k=>$v) {
  10106. if ($k>$lastreset && $k<$num) {
  10107. $ppgno -= $v;
  10108. }
  10109. }
  10110. if ($type=='A') { $ppgno = $this->dec2alpha($ppgno,true); }
  10111. else if ($type=='a') { $ppgno = $this->dec2alpha($ppgno,false);}
  10112. else if ($type=='I') { $ppgno = $this->dec2roman($ppgno,true); }
  10113. else if ($type=='i') { $ppgno = $this->dec2roman($ppgno,false); }
  10114. if ($extras) { $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix; }
  10115. return $ppgno;
  10116. }
  10117. function docPageSettings($num = 0) {
  10118. // Returns current type (numberstyle), suppression state for this page number;
  10119. // reset is only returned if set for this page number
  10120. if ($num < 1) { $num = $this->page; }
  10121. $type = '1'; // set default decimal
  10122. $ppgno = $num;
  10123. $suppress = 0;
  10124. $offset = 0;
  10125. $reset = '';
  10126. foreach($this->PageNumSubstitutions AS $psarr) {
  10127. if ($num >= $psarr['from']) {
  10128. if ($psarr['reset']) {
  10129. if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
  10130. $ppgno = $num - $psarr['from'] + 1 + $offset;
  10131. }
  10132. if ($psarr['type']) { $type = $psarr['type']; }
  10133. if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
  10134. else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
  10135. }
  10136. if ($num == $psarr['from']) { $reset = $psarr['reset']; }
  10137. }
  10138. if ($suppress) { $suppress = 'on'; }
  10139. else { $suppress = 'off'; }
  10140. return array($type, $suppress, $reset);
  10141. }
  10142. function docPageNumTotal($num = 0, $extras = false) {
  10143. if ($num < 1) { $num = $this->page; }
  10144. $type = '1'; // set default decimal
  10145. $ppgstart = 1;
  10146. $ppgend = count($this->pages)+1;
  10147. $suppress = 0;
  10148. $offset = 0;
  10149. foreach($this->PageNumSubstitutions AS $psarr) {
  10150. if ($num >= $psarr['from']) {
  10151. if ($psarr['reset']) {
  10152. if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
  10153. $ppgstart = $psarr['from'] + $offset;
  10154. $ppgend = count($this->pages)+1 + $offset;
  10155. }
  10156. if ($psarr['type']) { $type = $psarr['type']; }
  10157. if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
  10158. else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
  10159. }
  10160. if ($num < $psarr['from']) {
  10161. if ($psarr['reset']) {
  10162. $ppgend = $psarr['from'] + $offset;
  10163. break;
  10164. }
  10165. }
  10166. }
  10167. if ($suppress) { return ''; }
  10168. $ppgno = $ppgend-$ppgstart+$offset;
  10169. // mPDF 5.6.47
  10170. foreach($this->pgsIns AS $k => $v) {
  10171. if ($k>$ppgstart && $k<$ppgend) {
  10172. $ppgno -= $v;
  10173. }
  10174. }
  10175. if ($extras) { $ppgno = $this->nbpgPrefix . $ppgno . $this->nbpgSuffix; }
  10176. return $ppgno;
  10177. }
  10178. function RestartDocTemplate() {
  10179. $this->docTemplateStart = $this->page;
  10180. }
  10181. //Page header
  10182. function Header($content='') {
  10183. $this->cMarginL = 0;
  10184. $this->cMarginR = 0;
  10185. /*-- HTMLHEADERS-FOOTERS --*/
  10186. if (($this->mirrorMargins && ($this->page%2==0) && $this->HTMLHeaderE) || ($this->mirrorMargins && ($this->page%2==1) && $this->HTMLHeader) || (!$this->mirrorMargins && $this->HTMLHeader)) {
  10187. $this->writeHTMLHeaders();
  10188. return;
  10189. }
  10190. /*-- END HTMLHEADERS-FOOTERS --*/
  10191. $this->processingHeader=true;
  10192. $h = $this->headerDetails;
  10193. if(count($h)) {
  10194. if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
  10195. $this->_out(sprintf('q 0 -1 1 0 0 %.3F cm ',($this->h*_MPDFK)));
  10196. $yadj = $this->w - $this->h;
  10197. $headerpgwidth = $this->h - $this->orig_lMargin - $this->orig_rMargin;
  10198. if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
  10199. $headerlmargin = $this->orig_rMargin;
  10200. }
  10201. else {
  10202. $headerlmargin = $this->orig_lMargin;
  10203. }
  10204. }
  10205. else {
  10206. $yadj = 0;
  10207. $headerpgwidth = $this->pgwidth;
  10208. $headerlmargin = $this->lMargin;
  10209. }
  10210. $this->y = $this->margin_header - $yadj ;
  10211. $this->SetTColor($this->ConvertColor(0));
  10212. $this->SUP = false;
  10213. $this->SUB = false;
  10214. $this->bullet = false;
  10215. // only show pagenumber if numbering on
  10216. $pgno = $this->docPageNum($this->page, true);
  10217. if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
  10218. $side = 'even';
  10219. }
  10220. else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS = DEFAULT
  10221. $side = 'odd';
  10222. }
  10223. $maxfontheight = 0;
  10224. foreach(array('L','C','R') AS $pos) {
  10225. if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
  10226. if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
  10227. else { $hfsz = $this->default_font_size; }
  10228. $maxfontheight = max($maxfontheight,$hfsz);
  10229. }
  10230. }
  10231. // LEFT-CENTER-RIGHT
  10232. foreach(array('L','C','R') AS $pos) {
  10233. if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
  10234. $hd = str_replace('{PAGENO}',$pgno,$h[$side][$pos]['content']);
  10235. $hd = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->aliasNbPgGp.$this->nbpgSuffix,$hd);
  10236. $hd = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$hd);
  10237. if (isset($h[$side][$pos]['font-family']) && $h[$side][$pos]['font-family']) { $hff = $h[$side][$pos]['font-family']; }
  10238. else { $hff = $this->original_default_font; }
  10239. if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
  10240. else { $hfsz = $this->original_default_font_size; } // pts
  10241. $maxfontheight = max($maxfontheight,$hfsz);
  10242. $hfst = '';
  10243. if (isset($h[$side][$pos]['font-style']) && $h[$side][$pos]['font-style']) {
  10244. $hfst = $h[$side][$pos]['font-style'];
  10245. }
  10246. if (isset($h[$side][$pos]['color']) && $h[$side][$pos]['color']) {
  10247. $hfcol = $h[$side][$pos]['color'];
  10248. $cor = $this->ConvertColor($hfcol);
  10249. if ($cor) { $this->SetTColor($cor); }
  10250. }
  10251. else { $hfcol = ''; }
  10252. $this->SetFont($hff,$hfst,$hfsz,true,true);
  10253. $this->x = $headerlmargin ;
  10254. $this->y = $this->margin_header - $yadj ;
  10255. $hd = $this->purify_utf8_text($hd);
  10256. if ($this->text_input_as_HTML) {
  10257. $hd = $this->all_entities_to_utf8($hd);
  10258. }
  10259. // CONVERT CODEPAGE
  10260. if ($this->usingCoreFont) { $hd = mb_convert_encoding($hd,$this->mb_enc,'UTF-8'); }
  10261. // DIRECTIONALITY RTL
  10262. $this->magic_reverse_dir($hd, true, $this->directionality); // *RTL*
  10263. // Font-specific ligature substitution for Indic fonts
  10264. if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($hd); // *INDIC*
  10265. $align = $pos;
  10266. /*-- RTL --*/
  10267. if ($this->directionality == 'rtl') {
  10268. if ($pos == 'L') { $align = 'R'; }
  10269. else if ($pos == 'R') { $align = 'L'; }
  10270. }
  10271. /*-- END RTL --*/
  10272. if ($pos!='L' && (strpos($hd,$this->aliasNbPg)!==false || strpos($hd,$this->aliasNbPgGp)!==false)) {
  10273. if (strpos($hd,$this->aliasNbPgGp)!==false) { $type= 'nbpggp'; } else { $type= 'nbpg'; }
  10274. $this->_out('{mpdfheader'.$type.' '.$pos.' ff='.$hff.' fs='.$hfst.' fz='.$hfsz.'}');
  10275. $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
  10276. $this->_out('Q');
  10277. }
  10278. else {
  10279. $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
  10280. }
  10281. if ($hfcol) { $this->SetTColor($this->ConvertColor(0)); }
  10282. }
  10283. }
  10284. //Return Font to normal
  10285. $this->SetFont($this->default_font,'',$this->original_default_font_size);
  10286. // LINE
  10287. if (isset($h[$side]['line']) && $h[$side]['line']) {
  10288. $this->SetLineWidth(0.1);
  10289. $this->SetDColor($this->ConvertColor(0));
  10290. $this->Line($headerlmargin , $this->margin_header + ($maxfontheight*(1+$this->header_line_spacing)/_MPDFK) - $yadj , $headerlmargin + $headerpgwidth, $this->margin_header + ($maxfontheight*(1+$this->header_line_spacing)/_MPDFK) - $yadj );
  10291. }
  10292. if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
  10293. $this->_out('Q');
  10294. }
  10295. }
  10296. $this->SetY($this->tMargin);
  10297. if ($this->ColActive) { $this->pgwidth = $this->ColWidth; } // *COLUMNS*
  10298. $this->processingHeader=false;
  10299. }
  10300. /*-- TABLES --*/
  10301. function TableHeaderFooter($content='',$tablestartpage='',$tablestartcolumn ='',$horf = 'H',$level, $firstSpread=true, $finalSpread=true) {
  10302. if(($horf=='H' || $horf=='F') && !empty($content) && !empty($content[0])) { // mPDF 5.6.61
  10303. $table = &$this->table[1][1];
  10304. // Advance down page by half width of top border
  10305. if ($horf=='H') { // Only if header
  10306. if ($table['borders_separate']) { $adv = $table['border_spacing_V']/2 + $table['border_details']['T']['w'] + $table['padding']['T']; }
  10307. else { $adv = $table['max_cell_border_width']['T'] /2 ; }
  10308. if ($adv) {
  10309. if ($this->table_rotate) {
  10310. $this->y += ($adv);
  10311. }
  10312. else {
  10313. $this->DivLn($adv,$this->blklvl,true);
  10314. }
  10315. }
  10316. }
  10317. if ($horf=='F') { // Table Footer
  10318. $firstrow = count($table['cells']) - $table['footernrows'];
  10319. $lastrow = count($table['cells']) - 1;
  10320. }
  10321. else { // Table Header
  10322. $firstrow = 0;
  10323. $lastrow = $table['headernrows'] - 1;
  10324. }
  10325. $topy = $content[$firstrow][0]['y']-$this->y;
  10326. for ($i=$firstrow ; $i<=$lastrow; $i++) {
  10327. $y = $this->y;
  10328. /*-- COLUMNS --*/
  10329. // If outside columns, this is done in PaintDivBB
  10330. if ($this->ColActive) {
  10331. //OUTER FILL BGCOLOR of DIVS
  10332. if ($this->blklvl > 0) {
  10333. $firstblockfill = $this->GetFirstBlockFill();
  10334. if ($firstblockfill && $this->blklvl >= $firstblockfill) {
  10335. $divh = $content[$i][0]['h'];
  10336. $bak_x = $this->x;
  10337. $this->DivLn($divh,-3,false);
  10338. // Reset current block fill
  10339. $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
  10340. $this->SetFColor($bcor);
  10341. $this->x = $bak_x;
  10342. }
  10343. }
  10344. }
  10345. /*-- END COLUMNS --*/
  10346. $colctr = 0;
  10347. foreach($content[$i] as $tablehf) {
  10348. $colctr++;
  10349. $y = $tablehf['y'] - $topy;
  10350. $this->y = $y;
  10351. //Set some cell values
  10352. $x = $tablehf['x'];
  10353. if (($this->mirrorMargins) && ($tablestartpage == 'ODD') && (($this->page)%2==0)) { // EVEN
  10354. $x = $x +$this->MarginCorrection;
  10355. }
  10356. else if (($this->mirrorMargins) && ($tablestartpage == 'EVEN') && (($this->page)%2==1)) { // ODD
  10357. $x = $x +$this->MarginCorrection;
  10358. }
  10359. /*-- COLUMNS --*/
  10360. // Added to correct for Columns
  10361. if ($this->ColActive) {
  10362. if ($this->directionality == 'rtl') { // *RTL*
  10363. $x -= ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth+$this->ColGap); // *RTL*
  10364. } // *RTL*
  10365. else { // *RTL*
  10366. $x += ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth+$this->ColGap);
  10367. } // *RTL*
  10368. }
  10369. /*-- END COLUMNS --*/
  10370. if ($colctr==1) { $x0 = $x; }
  10371. // mPDF ITERATION
  10372. if ($this->iterationCounter) {
  10373. foreach($tablehf['textbuffer'] AS $k=>$t) {
  10374. if (!is_array($t[0]) && preg_match('/{iteration ([a-zA-Z0-9_]+)}/',$t[0], $m)) { // mPDF 5.5.06
  10375. $vname = '__'.$m[1].'_';
  10376. if (!isset($this->$vname)) { $this->$vname = 1; }
  10377. else { $this->$vname++; }
  10378. $tablehf['textbuffer'][$k][0] = preg_replace('/{iteration '.$m[1].'}/', $this->$vname, $tablehf['textbuffer'][$k][0]);
  10379. }
  10380. }
  10381. }
  10382. $w = $tablehf['w'];
  10383. $h = $tablehf['h'];
  10384. $va = $tablehf['va'];
  10385. $R = $tablehf['R'];
  10386. $mih = $tablehf['mih'];
  10387. $border = $tablehf['border'];
  10388. $border_details = $tablehf['border_details'];
  10389. $padding = $tablehf['padding'];
  10390. $this->tabletheadjustfinished = true;
  10391. $textbuffer = $tablehf['textbuffer'];
  10392. $align = $tablehf['a'];
  10393. //Align
  10394. $this->divalign=$align;
  10395. $this->x = $x;
  10396. if ($this->ColActive) {
  10397. if ($table['borders_separate']) {
  10398. $tablefill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
  10399. if ($tablefill) {
  10400. $color = $this->ConvertColor($tablefill);
  10401. if ($color) {
  10402. $xadj = ($table['border_spacing_H']/2);
  10403. $yadj = ($table['border_spacing_V']/2);
  10404. $wadj = $table['border_spacing_H'];
  10405. $hadj = $table['border_spacing_V'];
  10406. if ($i == $firstrow && $horf=='H') { // Top
  10407. $yadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
  10408. $hadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
  10409. }
  10410. if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i+$tablehf['rowspan']) == ($lastrow+1)) || (!isset($tablehf['rowspan']) && ($i+1) == ($lastrow+1))) && $horf=='F') { // Bottom
  10411. $hadj += $table['padding']['B'] + $table['border_details']['B']['w'] ;
  10412. }
  10413. if ($colctr == 1) { // Left
  10414. $xadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
  10415. $wadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
  10416. }
  10417. if ($colctr == count($content[$i]) ) { // Right
  10418. $wadj += $table['padding']['R'] + $table['border_details']['R']['w'] ;
  10419. }
  10420. $this->SetFColor($color);
  10421. $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
  10422. }
  10423. }
  10424. }
  10425. }
  10426. if ($table['empty_cells']!='hide' || !empty($textbuffer) || !$table['borders_separate']) { $paintcell = true; }
  10427. else { $paintcell = false; }
  10428. //Vertical align
  10429. if ($R && INTVAL($R) > 0 && isset($va) && $va!='B') { $va='B';}
  10430. if (!isset($va) || empty($va) || $va=='M') $this->y += ($h-$mih)/2;
  10431. elseif (isset($va) && $va=='B') $this->y += $h-$mih;
  10432. //TABLE ROW OR CELL FILL BGCOLOR
  10433. $fill = 0;
  10434. if (isset($tablehf['bgcolor']) && $tablehf['bgcolor'] && $tablehf['bgcolor']!='transparent') {
  10435. $fill = $tablehf['bgcolor'];
  10436. $leveladj = 6;
  10437. }
  10438. else if (isset($content[$i][0]['trbgcolor']) && $content[$i][0]['trbgcolor'] && $content[$i][0]['trbgcolor']!='transparent') { // Row color
  10439. $fill = $content[$i][0]['trbgcolor'];
  10440. $leveladj = 3;
  10441. }
  10442. if ($fill && $paintcell) {
  10443. $color = $this->ConvertColor($fill);
  10444. if ($color) {
  10445. if ($table['borders_separate']) {
  10446. if ($this->ColActive) {
  10447. $this->SetFColor($color);
  10448. $this->Rect($x+ ($table['border_spacing_H']/2), $y+ ($table['border_spacing_V']/2), $w- $table['border_spacing_H'], $h- $table['border_spacing_V'], 'F');
  10449. }
  10450. else {
  10451. $this->tableBackgrounds[$level*9+$leveladj][] = array('gradient'=>false, 'x'=>($x + ($table['border_spacing_H']/2)), 'y'=>($y + ($table['border_spacing_V']/2)), 'w'=>($w - $table['border_spacing_H']), 'h'=>($h - $table['border_spacing_V']), 'col'=>$color);
  10452. }
  10453. }
  10454. else {
  10455. if ($this->ColActive) {
  10456. $this->SetFColor($color);
  10457. $this->Rect($x, $y, $w, $h, 'F');
  10458. }
  10459. else {
  10460. $this->tableBackgrounds[$level*9+$leveladj][] = array('gradient'=>false, 'x'=>$x, 'y'=>$y, 'w'=>$w, 'h'=>$h, 'col'=>$color);
  10461. }
  10462. }
  10463. }
  10464. }
  10465. /*-- BACKGROUNDS --*/
  10466. if (isset($tablehf['gradient']) && $tablehf['gradient'] && $paintcell){
  10467. $g = $this->grad->parseBackgroundGradient($tablehf['gradient']);
  10468. if ($g) {
  10469. if ($table['borders_separate']) {
  10470. $px = $x+ ($table['border_spacing_H']/2);
  10471. $py = $y+ ($table['border_spacing_V']/2);
  10472. $pw = $w- $table['border_spacing_H'];
  10473. $ph = $h- $table['border_spacing_V'];
  10474. }
  10475. else {
  10476. $px = $x;
  10477. $py = $y;
  10478. $pw = $w;
  10479. $ph = $h;
  10480. }
  10481. if ($this->ColActive) {
  10482. $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
  10483. }
  10484. else {
  10485. $this->tableBackgrounds[$level*9+7][] = array('gradient'=>true, 'x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
  10486. }
  10487. }
  10488. }
  10489. if (isset($tablehf['background-image']) && $paintcell){
  10490. if ($tablehf['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $tablehf['background-image']['gradient'] )) {
  10491. $g = $this->grad->parseMozGradient( $tablehf['background-image']['gradient'] );
  10492. if ($g) {
  10493. if ($table['borders_separate']) {
  10494. $px = $x+ ($table['border_spacing_H']/2);
  10495. $py = $y+ ($table['border_spacing_V']/2);
  10496. $pw = $w- $table['border_spacing_H'];
  10497. $ph = $h- $table['border_spacing_V'];
  10498. }
  10499. else {
  10500. $px = $x;
  10501. $py = $y;
  10502. $pw = $w;
  10503. $ph = $h;
  10504. }
  10505. if ($this->ColActive) {
  10506. $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
  10507. }
  10508. else {
  10509. $this->tableBackgrounds[$level*9+7][] = array('gradient'=>true, 'x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
  10510. }
  10511. }
  10512. }
  10513. else if ($tablehf['background-image']['image_id']) { // Background pattern
  10514. $n = count($this->patterns)+1;
  10515. if ($table['borders_separate']) {
  10516. $px = $x+ ($table['border_spacing_H']/2);
  10517. $py = $y+ ($table['border_spacing_V']/2);
  10518. $pw = $w- $table['border_spacing_H'];
  10519. $ph = $h- $table['border_spacing_V'];
  10520. }
  10521. else {
  10522. $px = $x;
  10523. $py = $y;
  10524. $pw = $w;
  10525. $ph = $h;
  10526. }
  10527. if ($this->ColActive) {
  10528. list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($tablehf['background-image']['orig_w'], $tablehf['background-image']['orig_h'], $pw, $ph, $tablehf['background-image']['resize'], $tablehf['background-image']['x_repeat'] , $tablehf['background-image']['y_repeat']);
  10529. $this->patterns[$n] = array('x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'pgh'=>$this->h, 'image_id'=>$tablehf['background-image']['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$tablehf['background-image']['x_pos'] , 'y_pos'=>$tablehf['background-image']['y_pos'] , 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$tablehf['background-image']['itype']);
  10530. if ($tablehf['background-image']['opacity']>0 && $tablehf['background-image']['opacity']<1) { $opac = $this->SetAlpha($tablehf['background-image']['opacity'],'Normal',true); }
  10531. else { $opac = ''; }
  10532. $this->_out(sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $px*_MPDFK, ($this->h-$py)*_MPDFK, $pw*_MPDFK, -$ph*_MPDFK));
  10533. }
  10534. else {
  10535. $this->tableBackgrounds[$level*9+8][] = array('x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'image_id'=>$tablehf['background-image']['image_id'], 'orig_w'=>$tablehf['background-image']['orig_w'], 'orig_h'=>$tablehf['background-image']['orig_h'], 'x_pos'=>$tablehf['background-image']['x_pos'], 'y_pos'=>$tablehf['background-image']['y_pos'], 'x_repeat'=>$tablehf['background-image']['x_repeat'], 'y_repeat'=>$tablehf['background-image']['y_repeat'], 'clippath'=>'', 'resize'=>$tablehf['background-image']['resize'], 'opacity'=>$tablehf['background-image']['opacity'], 'itype'=>$tablehf['background-image']['itype']);
  10536. }
  10537. }
  10538. }
  10539. /*-- END BACKGROUNDS --*/
  10540. //Cell Border
  10541. if ($table['borders_separate'] && $paintcell && $border) {
  10542. $this->_tableRect($x+ ($table['border_spacing_H']/2)+($border_details['L']['w'] /2), $y+ ($table['border_spacing_V']/2)+($border_details['T']['w'] /2), $w-$table['border_spacing_H']-($border_details['L']['w'] /2)-($border_details['R']['w'] /2), $h- $table['border_spacing_V']-($border_details['T']['w'] /2)-($border_details['B']['w']/2), $border, $border_details, false, $table['borders_separate']);
  10543. }
  10544. else if ($paintcell && $border) {
  10545. $this->_tableRect($x, $y, $w, $h, $border, $border_details, true, $table['borders_separate']); // true causes buffer
  10546. }
  10547. //Print cell content
  10548. //$this->divheight = $this->table_lineheight*$this->lineheight;
  10549. if (!empty($textbuffer)) {
  10550. if ($horf=='F' && preg_match('/{colsum([0-9]*)[_]*}/', $textbuffer[0][0], $m)) {
  10551. $rep = sprintf("%01.".intval($m[1])."f", $this->colsums[$colctr-1]);
  10552. $textbuffer[0][0] = preg_replace('/{colsum[0-9_]*}/', $rep ,$textbuffer[0][0]);
  10553. }
  10554. if ($R) {
  10555. $cellPtSize = $textbuffer[0][11] / $this->shrin_k;
  10556. if (!$cellPtSize) { $cellPtSize = $this->default_font_size; }
  10557. $cellFontHeight = ($cellPtSize/_MPDFK);
  10558. $opx = $this->x;
  10559. $opy = $this->y;
  10560. $angle = INTVAL($R);
  10561. // Only allow 45 - 90 degrees (when bottom-aligned) or -90
  10562. if ($angle > 90) { $angle = 90; }
  10563. else if ($angle > 0 && (isset($va) && $va!='B')) { $angle = 90; }
  10564. else if ($angle > 0 && $angle <45) { $angle = 45; }
  10565. else if ($angle < 0) { $angle = -90; }
  10566. $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
  10567. if (isset($align) && $align =='R') {
  10568. $this->x += ($w) + ($offset) - ($cellFontHeight/3) - ($padding['R'] + $border_details['R']['w']);
  10569. }
  10570. else if (!isset($align ) || $align =='C') {
  10571. $this->x += ($w/2) + ($offset);
  10572. }
  10573. else {
  10574. $this->x += ($offset) + ($cellFontHeight/3)+($padding['L'] + $border_details['L']['w']);
  10575. }
  10576. $str = '';
  10577. foreach($tablehf['textbuffer'] AS $t) { $str .= $t[0].' '; }
  10578. $str = trim($str);
  10579. if (!isset($va) || $va=='M') {
  10580. $this->y -= ($h-$mih)/2; //Undo what was added earlier VERTICAL ALIGN
  10581. if ($angle > 0) { $this->y += (($h-$mih)/2)+($padding['T'] + $border_details['T']['w']) + ($mih-($padding['T'] + $border_details['T']['w']+$border_details['B']['w']+$padding['B'])); }
  10582. else if ($angle < 0) { $this->y += (($h-$mih)/2)+($padding['T'] + $border_details['T']['w']); }
  10583. }
  10584. else if (isset($va) && $va=='B') {
  10585. $this->y -= $h-$mih; //Undo what was added earlier VERTICAL ALIGN
  10586. if ($angle > 0) { $this->y += $h-($border_details['B']['w']+$padding['B']); }
  10587. else if ($angle < 0) { $this->y += $h-$mih+($padding['T'] + $border_details['T']['w']); }
  10588. }
  10589. else if (isset($va) && $va=='T') {
  10590. if ($angle > 0) { $this->y += $mih-($border_details['B']['w']+$padding['B']); }
  10591. else if ($angle < 0) { $this->y += ($padding['T'] + $border_details['T']['w']); }
  10592. }
  10593. $this->Rotate($angle,$this->x,$this->y);
  10594. $s_fs = $this->FontSizePt;
  10595. $s_f = $this->FontFamily;
  10596. $s_st = $this->FontStyle;
  10597. if (!empty($textbuffer[0][3])) { //Font Color
  10598. $cor = $textbuffer[0][3];
  10599. $this->SetTColor($cor);
  10600. }
  10601. $s_str = $this->strike;
  10602. $this->strike = $textbuffer[0][8]; //Strikethrough
  10603. $this->SetFont($textbuffer[0][4],$textbuffer[0][2],$cellPtSize,true,true);
  10604. $this->Text($this->x,$this->y,$str);
  10605. $this->Rotate(0);
  10606. $this->SetFont($s_f,$s_st,$s_fs,true,true);
  10607. $this->SetTColor(0);
  10608. $this->strike = $s_str;
  10609. $this->x = $opx;
  10610. $this->y = $opy;
  10611. }
  10612. else {
  10613. if ($table['borders_separate']) { // NB twice border width
  10614. $xadj = $border_details['L']['w'] + $padding['L'] +($table['border_spacing_H']/2);
  10615. $wadj = $border_details['L']['w'] + $border_details['R']['w'] + $padding['L'] +$padding['R'] + $table['border_spacing_H'];
  10616. $yadj = $border_details['T']['w'] + $padding['T'] + ($table['border_spacing_H']/2);
  10617. }
  10618. else {
  10619. $xadj = $border_details['L']['w']/2 + $padding['L'];
  10620. $wadj = ($border_details['L']['w'] + $border_details['R']['w'])/2 + $padding['L'] + $padding['R'];
  10621. $yadj = $border_details['T']['w']/2 + $padding['T'];
  10622. }
  10623. $this->divwidth=$w-($wadj);
  10624. $this->x += $xadj;
  10625. $this->y += $yadj;
  10626. $this->printbuffer($textbuffer,'',true);
  10627. }
  10628. }
  10629. $textbuffer = array();
  10630. /*-- BACKGROUNDS --*/
  10631. if (!$this->ColActive) {
  10632. if (isset($content[$i][0]['trgradients']) && ($colctr==1 || $table['borders_separate'])) {
  10633. $g = $this->grad->parseBackgroundGradient($content[$i][0]['trgradients']);
  10634. if ($g) {
  10635. $gx = $x0;
  10636. $gy = $y;
  10637. $gh = $h;
  10638. $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
  10639. if ($table['borders_separate']) {
  10640. $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
  10641. $s = '';
  10642. $clx = $x+ ($table['border_spacing_H']/2);
  10643. $cly = $y+ ($table['border_spacing_V']/2);
  10644. $clw = $w- $table['border_spacing_H'];
  10645. $clh = $h- $table['border_spacing_V'];
  10646. // Set clipping path
  10647. $s = ' q 0 w '; // Line width=0
  10648. $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
  10649. $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
  10650. $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
  10651. $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
  10652. $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
  10653. $s .= ' W n '; // Ends path no-op & Sets the clipping path
  10654. $this->tableBackgrounds[$level*9+4][] = array('gradient'=>true, 'x'=>$gx + ($table['border_spacing_H']/2), 'y'=>$gy + ($table['border_spacing_V']/2), 'w'=>$gw - $table['border_spacing_V'], 'h'=>$gh - $table['border_spacing_H'], 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>$s);
  10655. }
  10656. else {
  10657. $this->tableBackgrounds[$level*9+4][] = array('gradient'=>true, 'x'=>$gx, 'y'=>$gy, 'w'=>$gw, 'h'=>$gh, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
  10658. }
  10659. }
  10660. }
  10661. if (isset($content[$i][0]['trbackground-images']) && ($colctr==1 || $table['borders_separate'])) {
  10662. if ($content[$i][0]['trbackground-images']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $content[$i][0]['trbackground-images']['gradient'] )) {
  10663. $g = $this->grad->parseMozGradient( $content[$i][0]['trbackground-images']['gradient'] );
  10664. if ($g) {
  10665. $gx = $x0;
  10666. $gy = $y;
  10667. $gh = $h;
  10668. $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
  10669. if ($table['borders_separate']) {
  10670. $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
  10671. $s = '';
  10672. $clx = $x+ ($table['border_spacing_H']/2);
  10673. $cly = $y+ ($table['border_spacing_V']/2);
  10674. $clw = $w- $table['border_spacing_H'];
  10675. $clh = $h- $table['border_spacing_V'];
  10676. // Set clipping path
  10677. $s = ' q 0 w '; // Line width=0
  10678. $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
  10679. $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
  10680. $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
  10681. $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
  10682. $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
  10683. $s .= ' W n '; // Ends path no-op & Sets the clipping path
  10684. $this->tableBackgrounds[$level*9+4][] = array('gradient'=>true, 'x'=>$gx + ($table['border_spacing_H']/2), 'y'=>$gy + ($table['border_spacing_V']/2), 'w'=>$gw - $table['border_spacing_V'], 'h'=>$gh - $table['border_spacing_H'], 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>$s);
  10685. }
  10686. else {
  10687. $this->tableBackgrounds[$level*9+4][] = array('gradient'=>true, 'x'=>$gx, 'y'=>$gy, 'w'=>$gw, 'h'=>$gh, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
  10688. }
  10689. }
  10690. }
  10691. else {
  10692. $image_id = $content[$i][0]['trbackground-images']['image_id'];
  10693. $orig_w = $content[$i][0]['trbackground-images']['orig_w'];
  10694. $orig_h = $content[$i][0]['trbackground-images']['orig_h'];
  10695. $x_pos = $content[$i][0]['trbackground-images']['x_pos'];
  10696. $y_pos = $content[$i][0]['trbackground-images']['y_pos'];
  10697. $x_repeat = $content[$i][0]['trbackground-images']['x_repeat'];
  10698. $y_repeat = $content[$i][0]['trbackground-images']['y_repeat'];
  10699. $resize = $content[$i][0]['trbackground-images']['resize'];
  10700. $opacity = $content[$i][0]['trbackground-images']['opacity'];
  10701. $itype = $content[$i][0]['trbackground-images']['itype'];
  10702. $clippath = '';
  10703. $gx = $x0;
  10704. $gy = $y;
  10705. $gh = $h;
  10706. $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
  10707. if ($table['borders_separate']) {
  10708. $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
  10709. $s = '';
  10710. $clx = $x+ ($table['border_spacing_H']/2);
  10711. $cly = $y+ ($table['border_spacing_V']/2);
  10712. $clw = $w- $table['border_spacing_H'];
  10713. $clh = $h- $table['border_spacing_V'];
  10714. // Set clipping path
  10715. $s = ' q 0 w '; // Line width=0
  10716. $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
  10717. $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
  10718. $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
  10719. $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
  10720. $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
  10721. $s .= ' W n '; // Ends path no-op & Sets the clipping path
  10722. $this->tableBackgrounds[$level*9+5][] = array('x'=>$gx + ($table['border_spacing_H']/2), 'y'=>$gy + ($table['border_spacing_V']/2), 'w'=>$gw - $table['border_spacing_V'], 'h'=>$gh - $table['border_spacing_H'], 'image_id'=>$image_id, 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$x_pos, 'y_pos'=>$y_pos, 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'clippath'=>$s, 'resize'=>$resize, 'opacity'=>$opacity, 'itype'=>$itype);
  10723. }
  10724. else {
  10725. $this->tableBackgrounds[$level*9+5][] = array('x'=>$gx, 'y'=>$gy, 'w'=>$gw, 'h'=>$gh, 'image_id'=>$image_id, 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$x_pos, 'y_pos'=>$y_pos, 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'clippath'=>'', 'resize'=>$resize, 'opacity'=>$opacity, 'itype'=>$itype);
  10726. }
  10727. }
  10728. }
  10729. }
  10730. /*-- END BACKGROUNDS --*/
  10731. // TABLE BORDER - if separate OR collapsed and only table border
  10732. if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
  10733. $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H']/2);
  10734. $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H']/2);
  10735. $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V']/2);
  10736. $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V']/2);
  10737. $tbx = $x;
  10738. $tby = $y;
  10739. $tbw = $w;
  10740. $tbh = $h;
  10741. $tab_bord = 0;
  10742. $corner = '';
  10743. if ($i == $firstrow && $horf=='H') { // Top
  10744. $tby -= $halfspaceT + ($table['border_details']['T']['w']/2);
  10745. $tbh += $halfspaceT + ($table['border_details']['T']['w']/2);
  10746. $this->setBorder($tab_bord , _BORDER_TOP);
  10747. $corner .= 'T';
  10748. }
  10749. if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i+$tablehf['rowspan']) == ($lastrow+1))) && $horf=='F') { // Bottom
  10750. $tbh += $halfspaceB + ($table['border_details']['B']['w']/2);
  10751. $this->setBorder($tab_bord , _BORDER_BOTTOM);
  10752. $corner .= 'B';
  10753. }
  10754. if ($colctr == 1 && $firstSpread) { // Left
  10755. $tbx -= $halfspaceL + ($table['border_details']['L']['w']/2);
  10756. $tbw += $halfspaceL + ($table['border_details']['L']['w']/2);
  10757. $this->setBorder($tab_bord , _BORDER_LEFT);
  10758. $corner .= 'L';
  10759. }
  10760. if ($colctr == count($content[$i]) && $finalSpread) { // Right
  10761. $tbw += $halfspaceR + ($table['border_details']['R']['w']/2);
  10762. $this->setBorder($tab_bord , _BORDER_RIGHT);
  10763. $corner .= 'R';
  10764. }
  10765. $this->_tableRect($tbx, $tby, $tbw, $tbh, $tab_bord , $table['border_details'], false, $table['borders_separate'], 'table', $corner, $table['border_spacing_V'], $table['border_spacing_H'] );
  10766. }
  10767. }// end column $content
  10768. $this->y = $y + $h; //Update y coordinate
  10769. }// end row $i
  10770. unset($table );
  10771. $this->colsums = array();
  10772. }
  10773. }
  10774. /*-- END TABLES --*/
  10775. /*-- HTMLHEADERS-FOOTERS --*/
  10776. function SetHTMLHeader($header='',$OE='',$write=false) {
  10777. $height = 0;
  10778. if (is_array($header) && isset($header['html']) && $header['html']) {
  10779. $Hhtml = $header['html'];
  10780. if ($this->setAutoTopMargin) {
  10781. if (isset($header['h'])) { $height = $header['h']; }
  10782. else { $height = $this->_gethtmlheight($Hhtml); }
  10783. }
  10784. }
  10785. else if (!is_array($header) && $header) {
  10786. $Hhtml = $header;
  10787. if ($this->setAutoTopMargin) { $height = $this->_gethtmlheight($Hhtml); }
  10788. }
  10789. else { $Hhtml = ''; }
  10790. if ($OE != 'E') { $OE = 'O'; }
  10791. if ($OE == 'E') {
  10792. if ($Hhtml) {
  10793. $this->HTMLHeaderE['html'] = $Hhtml;
  10794. $this->HTMLHeaderE['h'] = $height;
  10795. }
  10796. else { $this->HTMLHeaderE = ''; }
  10797. }
  10798. else {
  10799. if ($Hhtml) {
  10800. $this->HTMLHeader['html'] = $Hhtml;
  10801. $this->HTMLHeader['h'] = $height;
  10802. }
  10803. else { $this->HTMLHeader = ''; }
  10804. }
  10805. if (!$this->mirrorMargins && $OE == 'E') { return; }
  10806. if ($Hhtml=='') { return; }
  10807. if ($OE == 'E') {
  10808. $this->headerDetails['even'] = array(); // override and clear any other non-HTML header/footer
  10809. }
  10810. else {
  10811. $this->headerDetails['odd'] = array(); // override and clear any non-HTML other header/footer
  10812. }
  10813. if ($this->setAutoTopMargin=='pad') {
  10814. $this->tMargin = $this->margin_header + $height + $this->orig_tMargin;
  10815. if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; }
  10816. }
  10817. else if ($this->setAutoTopMargin=='stretch') {
  10818. $this->tMargin = max($this->orig_tMargin, $this->margin_header + $height + $this->autoMarginPadding);
  10819. if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; }
  10820. }
  10821. if ($write && $this->state!=0 && (($this->mirrorMargins && $OE == 'E' && ($this->page)%2==0) || ($this->mirrorMargins && $OE != 'E' && ($this->page)%2==1) || !$this->mirrorMargins)) { $this->writeHTMLHeaders(); }
  10822. }
  10823. function SetHTMLFooter($footer='',$OE='') {
  10824. $height = 0;
  10825. if (is_array($footer) && isset($footer['html']) && $footer['html']) {
  10826. $Fhtml = $footer['html'];
  10827. if ($this->setAutoBottomMargin) {
  10828. if (isset($footer['h'])) { $height = $footer['h']; }
  10829. else { $height = $this->_gethtmlheight($Fhtml); }
  10830. }
  10831. }
  10832. else if (!is_array($footer) && $footer) {
  10833. $Fhtml = $footer;
  10834. if ($this->setAutoBottomMargin) { $height = $this->_gethtmlheight($Fhtml); }
  10835. }
  10836. else { $Fhtml = ''; }
  10837. if ($OE != 'E') { $OE = 'O'; }
  10838. if ($OE == 'E') {
  10839. if ($Fhtml) {
  10840. $this->HTMLFooterE['html'] = $Fhtml;
  10841. $this->HTMLFooterE['h'] = $height;
  10842. }
  10843. else { $this->HTMLFooterE = ''; }
  10844. }
  10845. else {
  10846. if ($Fhtml) {
  10847. $this->HTMLFooter['html'] = $Fhtml;
  10848. $this->HTMLFooter['h'] = $height;
  10849. }
  10850. else { $this->HTMLFooter = ''; }
  10851. }
  10852. if (!$this->mirrorMargins && $OE == 'E') { return; }
  10853. if ($Fhtml=='') { return false; }
  10854. if ($OE == 'E') {
  10855. $this->footerDetails['even'] = array(); // override and clear any other header/footer
  10856. }
  10857. else {
  10858. $this->footerDetails['odd'] = array(); // override and clear any other header/footer
  10859. }
  10860. if ($this->setAutoBottomMargin=='pad') {
  10861. $this->bMargin = $this->margin_footer + $height + $this->orig_bMargin;
  10862. $this->PageBreakTrigger=$this->h-$this->bMargin ;
  10863. if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; }
  10864. }
  10865. else if ($this->setAutoBottomMargin=='stretch') {
  10866. $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $height + $this->autoMarginPadding);
  10867. $this->PageBreakTrigger=$this->h-$this->bMargin ;
  10868. if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; }
  10869. }
  10870. }
  10871. function _getHtmlHeight($html) {
  10872. $save_state = $this->state;
  10873. if($this->state==0) {
  10874. $this->AddPage($this->CurOrientation);
  10875. }
  10876. $this->state = 2;
  10877. $this->Reset();
  10878. $this->pageoutput[$this->page] = array();
  10879. $save_x = $this->x;
  10880. $save_y = $this->y;
  10881. $this->x = $this->lMargin;
  10882. $this->y = $this->margin_header;
  10883. $html = str_replace('{PAGENO}',$this->pagenumPrefix.$this->docPageNum($this->page).$this->pagenumSuffix,$html);
  10884. $html = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->docPageNumTotal($this->page).$this->nbpgSuffix,$html );
  10885. $html = str_replace($this->aliasNbPg,$this->page,$html );
  10886. $html = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$html );
  10887. $this->HTMLheaderPageLinks = array();
  10888. $this->HTMLheaderPageAnnots = array();
  10889. $this->HTMLheaderPageForms = array();
  10890. $savepb = $this->pageBackgrounds;
  10891. $this->writingHTMLheader = true;
  10892. $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
  10893. $this->writingHTMLheader = false;
  10894. $h = ($this->y - $this->margin_header);
  10895. $this->Reset();
  10896. $this->pageoutput[$this->page] = array();
  10897. $this->headerbuffer = '';
  10898. $this->pageBackgrounds = $savepb;
  10899. $this->x = $save_x;
  10900. $this->y = $save_y;
  10901. $this->state = $save_state;
  10902. if($save_state==0) {
  10903. unset($this->pages[1]);
  10904. $this->page = 0;
  10905. }
  10906. return $h;
  10907. }
  10908. // Called internally from Header
  10909. function writeHTMLHeaders() {
  10910. if ($this->mirrorMargins && ($this->page)%2==0) { $OE = 'E'; } // EVEN
  10911. else { $OE = 'O'; }
  10912. if ($OE == 'E') {
  10913. $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeaderE['html'] ;
  10914. }
  10915. else {
  10916. $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeader['html'] ;
  10917. }
  10918. if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
  10919. $this->saveHTMLHeader[$this->page][$OE]['rotate'] = true;
  10920. $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->tMargin;
  10921. $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->bMargin;
  10922. $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
  10923. $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
  10924. $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->h;
  10925. $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->w;
  10926. }
  10927. else {
  10928. $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->lMargin;
  10929. $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->rMargin;
  10930. $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
  10931. $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
  10932. $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->w;
  10933. $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->h;
  10934. }
  10935. }
  10936. function writeHTMLFooters() {
  10937. if ($this->mirrorMargins && ($this->page)%2==0) { $OE = 'E'; } // EVEN
  10938. else { $OE = 'O'; }
  10939. if ($OE == 'E') {
  10940. $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooterE['html'] ;
  10941. }
  10942. else {
  10943. $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooter['html'] ;
  10944. }
  10945. if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
  10946. $this->saveHTMLFooter[$this->page][$OE]['rotate'] = true;
  10947. $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->tMargin;
  10948. $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->bMargin;
  10949. $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->rMargin;
  10950. $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->lMargin;
  10951. $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header;
  10952. $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer;
  10953. $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->h;
  10954. $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->w;
  10955. }
  10956. else {
  10957. $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->lMargin;
  10958. $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->rMargin;
  10959. $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->tMargin;
  10960. $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->bMargin;
  10961. $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header;
  10962. $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer;
  10963. $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->w;
  10964. $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->h;
  10965. }
  10966. }
  10967. /*-- END HTMLHEADERS-FOOTERS --*/
  10968. function DefHeaderByName($name,$arr) {
  10969. if (!$name) { $name = '_default'; }
  10970. $this->pageheaders[$name] = $arr;
  10971. }
  10972. function DefFooterByName($name,$arr) {
  10973. if (!$name) { $name = '_default'; }
  10974. $this->pagefooters[$name] = $arr;
  10975. }
  10976. function SetHeaderByName($name,$side='O',$write=false) {
  10977. if (!$name) { $name = '_default'; }
  10978. if ($side=='E') { $this->headerDetails['even'] = $this->pageheaders[$name]; }
  10979. else { $this->headerDetails['odd'] = $this->pageheaders[$name]; }
  10980. if ($write) { $this->Header(); }
  10981. }
  10982. function SetFooterByName($name,$side='O') {
  10983. if (!$name) { $name = '_default'; }
  10984. if ($side=='E') { $this->footerDetails['even'] = $this->pagefooters[$name]; }
  10985. else { $this->footerDetails['odd'] = $this->pagefooters[$name]; }
  10986. }
  10987. /*-- HTMLHEADERS-FOOTERS --*/
  10988. function DefHTMLHeaderByName($name,$html) {
  10989. if (!$name) { $name = '_default'; }
  10990. $this->pageHTMLheaders[$name]['html'] = $html;
  10991. $this->pageHTMLheaders[$name]['h'] = $this->_gethtmlheight($html);
  10992. }
  10993. function DefHTMLFooterByName($name,$html) {
  10994. if (!$name) { $name = '_default'; }
  10995. $this->pageHTMLfooters[$name]['html'] = $html;
  10996. $this->pageHTMLfooters[$name]['h'] = $this->_gethtmlheight($html);
  10997. }
  10998. function SetHTMLHeaderByName($name,$side='O',$write=false) {
  10999. if (!$name) { $name = '_default'; }
  11000. $this->SetHTMLHeader($this->pageHTMLheaders[$name],$side,$write);
  11001. }
  11002. function SetHTMLFooterByName($name,$side='O') {
  11003. if (!$name) { $name = '_default'; }
  11004. $this->SetHTMLFooter($this->pageHTMLfooters[$name],$side,$write);
  11005. }
  11006. /*-- END HTMLHEADERS-FOOTERS --*/
  11007. function SetHeader($Harray=array(),$side='',$write=false) {
  11008. if (is_string($Harray)) {
  11009. if (strlen($Harray)==0) {
  11010. if ($side=='O') { $this->headerDetails['odd'] = array(); }
  11011. else if ($side=='E') { $this->headerDetails['even'] = array(); }
  11012. else { $this->headerDetails = array(); }
  11013. }
  11014. else if (strpos($Harray,'|') || strpos($Harray,'|')===0) {
  11015. $hdet = explode('|',$Harray);
  11016. $this->headerDetails = array (
  11017. 'odd' => array (
  11018. 'L' => array ('content' => $hdet[0], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
  11019. 'C' => array ('content' => $hdet[1], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
  11020. 'R' => array ('content' => $hdet[2], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
  11021. 'line' => $this->defaultheaderline,
  11022. ),
  11023. 'even' => array (
  11024. 'R' => array ('content' => $hdet[0], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
  11025. 'C' => array ('content' => $hdet[1], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
  11026. 'L' => array ('content' => $hdet[2], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
  11027. 'line' => $this->defaultheaderline,
  11028. )
  11029. );
  11030. }
  11031. else {
  11032. $this->headerDetails = array (
  11033. 'odd' => array (
  11034. 'R' => array ('content' => $Harray, 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
  11035. 'line' => $this->defaultheaderline,
  11036. ),
  11037. 'even' => array (
  11038. 'L' => array ('content' => $Harray, 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
  11039. 'line' => $this->defaultheaderline,
  11040. )
  11041. );
  11042. }
  11043. }
  11044. else if (is_array($Harray)) {
  11045. if ($side=='O') { $this->headerDetails['odd'] = $Harray; }
  11046. else if ($side=='E') { $this->headerDetails['even'] = $Harray; }
  11047. else { $this->headerDetails = $Harray; }
  11048. }
  11049. /*-- HTMLHEADERS-FOOTERS --*/
  11050. // Overwrite any HTML Header previously set
  11051. if ($side=='E') { $this->SetHTMLHeader('','E'); }
  11052. else if ($side=='O') { $this->SetHTMLHeader(''); }
  11053. else {
  11054. $this->SetHTMLHeader('');
  11055. $this->SetHTMLHeader('','E');
  11056. }
  11057. /*-- END HTMLHEADERS-FOOTERS --*/
  11058. if ($write) {
  11059. $save_y = $this->y;
  11060. $this->Header();
  11061. $this->SetY($save_y) ;
  11062. }
  11063. }
  11064. function SetFooter($Farray=array(),$side='') {
  11065. if (is_string($Farray)) {
  11066. if (strlen($Farray)==0) {
  11067. if ($side=='O') { $this->footerDetails['odd'] = array(); }
  11068. else if ($side=='E') { $this->footerDetails['even'] = array(); }
  11069. else { $this->footerDetails = array(); }
  11070. }
  11071. else if (strpos($Farray,'|') || strpos($Farray,'|')===0) {
  11072. $fdet = explode('|',$Farray);
  11073. $this->footerDetails = array (
  11074. 'odd' => array (
  11075. 'L' => array ('content' => $fdet[0], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
  11076. 'C' => array ('content' => $fdet[1], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
  11077. 'R' => array ('content' => $fdet[2], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
  11078. 'line' => $this->defaultfooterline,
  11079. ),
  11080. 'even' => array (
  11081. 'R' => array ('content' => $fdet[0], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
  11082. 'C' => array ('content' => $fdet[1], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
  11083. 'L' => array ('content' => $fdet[2], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
  11084. 'line' => $this->defaultfooterline,
  11085. )
  11086. );
  11087. }
  11088. else {
  11089. $this->footerDetails = array (
  11090. 'odd' => array (
  11091. 'R' => array ('content' => $Farray, 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
  11092. 'line' => $this->defaultfooterline,
  11093. ),
  11094. 'even' => array (
  11095. 'L' => array ('content' => $Farray, 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
  11096. 'line' => $this->defaultfooterline,
  11097. )
  11098. );
  11099. }
  11100. }
  11101. else if (is_array($Farray)) {
  11102. if ($side=='O') { $this->footerDetails['odd'] = $Farray; }
  11103. else if ($side=='E') { $this->footerDetails['even'] = $Farray; }
  11104. else { $this->footerDetails = $Farray; }
  11105. }
  11106. /*-- HTMLHEADERS-FOOTERS --*/
  11107. // Overwrite any HTML Footer previously set
  11108. if ($side=='E') { $this->SetHTMLFooter('','E'); }
  11109. else if ($side=='O') { $this->SetHTMLFooter(''); }
  11110. else {
  11111. $this->SetHTMLFooter('');
  11112. $this->SetHTMLFooter('','E');
  11113. }
  11114. /*-- END HTMLHEADERS-FOOTERS --*/
  11115. }
  11116. /*-- WATERMARK --*/
  11117. function setUnvalidatedText($txt='', $alpha=-1) {
  11118. if ($alpha>=0) $this->watermarkTextAlpha = $alpha;
  11119. $this->watermarkText = $txt;
  11120. }
  11121. function SetWatermarkText($txt='', $alpha=-1) {
  11122. if ($alpha>=0) $this->watermarkTextAlpha = $alpha;
  11123. $this->watermarkText = $txt;
  11124. }
  11125. function SetWatermarkImage($src, $alpha=-1, $size='D', $pos='F') {
  11126. if ($alpha>=0) $this->watermarkImageAlpha = $alpha;
  11127. $this->watermarkImage = $src;
  11128. $this->watermark_size = $size;
  11129. $this->watermark_pos = $pos;
  11130. }
  11131. /*-- END WATERMARK --*/
  11132. //Page footer
  11133. function Footer() {
  11134. /*-- CSS-PAGE --*/
  11135. // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
  11136. if ($this->show_marks == 'CROP' || $this->show_marks == 'CROPCROSS') {
  11137. // Show TICK MARKS
  11138. $this->SetLineWidth(0.1); // = 0.1 mm
  11139. $this->SetDColor($this->ConvertColor(0));
  11140. $l = $this->cropMarkLength;
  11141. $m = $this->cropMarkMargin; // Distance of crop mark from margin
  11142. $b = $this->nonPrintMargin; // Non-printable border at edge of paper sheet
  11143. $ax1 = $b;
  11144. $bx = $this->page_box['outer_width_LR'] - $m;
  11145. $ax = max($ax1, $bx-$l);
  11146. $cx1 = $this->w - $b;
  11147. $dx = $this->w - $this->page_box['outer_width_LR'] + $m;
  11148. $cx = min($cx1, $dx+$l);
  11149. $ay1 = $b;
  11150. $by = $this->page_box['outer_width_TB'] - $m;
  11151. $ay = max($ay1, $by-$l);
  11152. $cy1 = $this->h - $b;
  11153. $dy = $this->h - $this->page_box['outer_width_TB'] + $m;
  11154. $cy = min($cy1, $dy+$l);
  11155. $this->Line($ax, $this->page_box['outer_width_TB'], $bx, $this->page_box['outer_width_TB']);
  11156. $this->Line($cx, $this->page_box['outer_width_TB'], $dx, $this->page_box['outer_width_TB']);
  11157. $this->Line($ax, $this->h - $this->page_box['outer_width_TB'], $bx, $this->h - $this->page_box['outer_width_TB']);
  11158. $this->Line($cx, $this->h - $this->page_box['outer_width_TB'], $dx, $this->h - $this->page_box['outer_width_TB']);
  11159. $this->Line($this->page_box['outer_width_LR'], $ay, $this->page_box['outer_width_LR'], $by);
  11160. $this->Line($this->page_box['outer_width_LR'], $cy, $this->page_box['outer_width_LR'], $dy);
  11161. $this->Line($this->w - $this->page_box['outer_width_LR'], $ay, $this->w - $this->page_box['outer_width_LR'], $by);
  11162. $this->Line($this->w - $this->page_box['outer_width_LR'], $cy, $this->w - $this->page_box['outer_width_LR'], $dy);
  11163. if ($this->printers_info) {
  11164. $hd = date('Y-m-d H:i').' Page '.$this->page.' of {nb}';
  11165. $this->SetTColor($this->ConvertColor(0));
  11166. $this->SetFont('arial','',7.5,true,true);
  11167. $this->x = $this->page_box['outer_width_LR'] + 1.5;
  11168. $this->y = 1;
  11169. $this->Cell($headerpgwidth ,$this->FontSize,$hd,0,0,'L',0,'',0,0,0,'M');
  11170. $this->SetFont($this->default_font,'',$this->original_default_font_size);
  11171. }
  11172. }
  11173. if ($this->show_marks == 'CROSS' || $this->show_marks == 'CROPCROSS') {
  11174. $this->SetLineWidth(0.1); // = 0.1 mm
  11175. $this->SetDColor($this->ConvertColor(0));
  11176. $l = 14 /2; // longer length of the cross line (half)
  11177. $w = 6 /2; // shorter width of the cross line (half)
  11178. $r = 1.2; // radius of circle
  11179. $m = $this->crossMarkMargin; // Distance of cross mark from margin
  11180. $x1 = $this->page_box['outer_width_LR'] - $m;
  11181. $x2 = $this->w - $this->page_box['outer_width_LR'] + $m;
  11182. $y1 = $this->page_box['outer_width_TB'] - $m;
  11183. $y2 = $this->h - $this->page_box['outer_width_TB'] + $m;
  11184. // Left
  11185. $this->Circle($x1, $this->h/2, $r, 'S') ;
  11186. $this->Line($x1-$w, $this->h/2, $x1+$w, $this->h/2);
  11187. $this->Line($x1, $this->h/2-$l, $x1, $this->h/2+$l);
  11188. // Right
  11189. $this->Circle($x2, $this->h/2, $r, 'S') ;
  11190. $this->Line($x2-$w, $this->h/2, $x2+$w, $this->h/2);
  11191. $this->Line($x2, $this->h/2-$l, $x2, $this->h/2+$l);
  11192. // Top
  11193. $this->Circle($this->w/2, $y1, $r, 'S') ;
  11194. $this->Line($this->w/2, $y1-$w, $this->w/2, $y1+$w);
  11195. $this->Line($this->w/2-$l, $y1, $this->w/2+$l, $y1);
  11196. // Bottom
  11197. $this->Circle($this->w/2, $y2, $r, 'S') ;
  11198. $this->Line($this->w/2, $y2-$w, $this->w/2, $y2+$w);
  11199. $this->Line($this->w/2-$l, $y2, $this->w/2+$l, $y2);
  11200. }
  11201. // If @page set non-HTML headers/footers named, they were not read until later in the HTML code - so now set them
  11202. if ($this->page==1) {
  11203. if ($this->firstPageBoxHeader) {
  11204. $this->headerDetails['odd'] = $this->pageheaders[$this->firstPageBoxHeader];
  11205. $this->Header();
  11206. }
  11207. if ($this->firstPageBoxFooter) {
  11208. $this->footerDetails['odd'] = $this->pagefooters[$this->firstPageBoxFooter];
  11209. }
  11210. $this->firstPageBoxHeader='';
  11211. $this->firstPageBoxFooter='';
  11212. }
  11213. /*-- END CSS-PAGE --*/
  11214. /*-- HTMLHEADERS-FOOTERS --*/
  11215. if (($this->mirrorMargins && ($this->page%2==0) && $this->HTMLFooterE) || ($this->mirrorMargins && ($this->page%2==1) && $this->HTMLFooter) || (!$this->mirrorMargins && $this->HTMLFooter)) {
  11216. $this->writeHTMLFooters();
  11217. /*-- WATERMARK --*/
  11218. if (($this->watermarkText) && ($this->showWatermarkText)) {
  11219. $this->watermark( $this->watermarkText, 45, 120, $this->watermarkTextAlpha); // Watermark text
  11220. }
  11221. if (($this->watermarkImage) && ($this->showWatermarkImage)) {
  11222. $this->watermarkImg( $this->watermarkImage, $this->watermarkImageAlpha); // Watermark image
  11223. }
  11224. /*-- END WATERMARK --*/
  11225. return;
  11226. }
  11227. /*-- END HTMLHEADERS-FOOTERS --*/
  11228. $this->processingHeader=true;
  11229. $this->ResetMargins(); // necessary after columns
  11230. $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
  11231. /*-- WATERMARK --*/
  11232. if (($this->watermarkText) && ($this->showWatermarkText)) {
  11233. $this->watermark( $this->watermarkText, 45, 120, $this->watermarkTextAlpha); // Watermark text
  11234. }
  11235. if (($this->watermarkImage) && ($this->showWatermarkImage)) {
  11236. $this->watermarkImg( $this->watermarkImage, $this->watermarkImageAlpha); // Watermark image
  11237. }
  11238. /*-- END WATERMARK --*/
  11239. $h = $this->footerDetails;
  11240. if(count($h)) {
  11241. if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
  11242. $this->_out(sprintf('q 0 -1 1 0 0 %.3F cm ',($this->h*_MPDFK)));
  11243. $headerpgwidth = $this->h - $this->orig_lMargin - $this->orig_rMargin;
  11244. if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
  11245. $headerlmargin = $this->orig_rMargin;
  11246. }
  11247. else {
  11248. $headerlmargin = $this->orig_lMargin;
  11249. }
  11250. }
  11251. else {
  11252. $yadj = 0;
  11253. $headerpgwidth = $this->pgwidth;
  11254. $headerlmargin = $this->lMargin;
  11255. }
  11256. $this->SetY(-$this->margin_footer);
  11257. $this->SetTColor($this->ConvertColor(0));
  11258. $this->SUP = false;
  11259. $this->SUB = false;
  11260. $this->bullet = false;
  11261. // only show pagenumber if numbering on
  11262. $pgno = $this->docPageNum($this->page, true);
  11263. if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
  11264. $side = 'even';
  11265. }
  11266. else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS = DEFAULT
  11267. $side = 'odd';
  11268. }
  11269. $maxfontheight = 0;
  11270. foreach(array('L','C','R') AS $pos) {
  11271. if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
  11272. if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
  11273. else { $hfsz = $this->default_font_size; }
  11274. $maxfontheight = max($maxfontheight,$hfsz);
  11275. }
  11276. }
  11277. // LEFT-CENTER-RIGHT
  11278. foreach(array('L','C','R') AS $pos) {
  11279. if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
  11280. $hd = str_replace('{PAGENO}',$pgno,$h[$side][$pos]['content']);
  11281. $hd = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->aliasNbPgGp.$this->nbpgSuffix,$hd);
  11282. $hd = preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$hd);
  11283. if (isset($h[$side][$pos]['font-family']) && $h[$side][$pos]['font-family']) { $hff = $h[$side][$pos]['font-family']; }
  11284. else { $hff = $this->original_default_font; }
  11285. if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
  11286. else { $hfsz = $this->original_default_font_size; }
  11287. $maxfontheight = max($maxfontheight,$hfsz);
  11288. if (isset($h[$side][$pos]['font-style']) && $h[$side][$pos]['font-style']) { $hfst = $h[$side][$pos]['font-style']; }
  11289. else { $hfst = ''; }
  11290. if (isset($h[$side][$pos]['color']) && $h[$side][$pos]['color']) {
  11291. $hfcol = $h[$side][$pos]['color'];
  11292. $cor = $this->ConvertColor($hfcol);
  11293. if ($cor) { $this->SetTColor($cor); }
  11294. }
  11295. else { $hfcol = ''; }
  11296. $this->SetFont($hff,$hfst,$hfsz,true,true);
  11297. $this->x = $headerlmargin ;
  11298. $this->y = $this->h - $this->margin_footer - ($maxfontheight/_MPDFK);
  11299. $hd = $this->purify_utf8_text($hd);
  11300. if ($this->text_input_as_HTML) {
  11301. $hd = $this->all_entities_to_utf8($hd);
  11302. }
  11303. // CONVERT CODEPAGE
  11304. if ($this->usingCoreFont) { $hd = mb_convert_encoding($hd,$this->mb_enc,'UTF-8'); }
  11305. // DIRECTIONALITY RTL
  11306. $this->magic_reverse_dir($hd, true, $this->directionality); // *RTL*
  11307. // Font-specific ligature substitution for Indic fonts
  11308. if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($hd); // *INDIC*
  11309. $align = $pos;
  11310. if ($this->directionality == 'rtl') {
  11311. if ($pos == 'L') { $align = 'R'; }
  11312. else if ($pos == 'R') { $align = 'L'; }
  11313. }
  11314. if ($pos!='L' && (strpos($hd,$this->aliasNbPg)!==false || strpos($hd,$this->aliasNbPgGp)!==false)) {
  11315. if (strpos($hd,$this->aliasNbPgGp)!==false) { $type= 'nbpggp'; } else { $type= 'nbpg'; }
  11316. $this->_out('{mpdfheader'.$type.' '.$pos.' ff='.$hff.' fs='.$hfst.' fz='.$hfsz.'}');
  11317. $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
  11318. $this->_out('Q');
  11319. }
  11320. else {
  11321. $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
  11322. }
  11323. if ($hfcol) { $this->SetTColor($this->ConvertColor(0)); }
  11324. }
  11325. }
  11326. // Return Font to normal
  11327. $this->SetFont($this->default_font,'',$this->original_default_font_size);
  11328. // LINE
  11329. if (isset($h[$side]['line']) && $h[$side]['line']) {
  11330. $this->SetLineWidth(0.1);
  11331. $this->SetDColor($this->ConvertColor(0));
  11332. $this->Line($headerlmargin , $this->y-($maxfontheight*($this->footer_line_spacing)/_MPDFK), $headerlmargin +$headerpgwidth, $this->y-($maxfontheight*($this->footer_line_spacing)/_MPDFK));
  11333. }
  11334. if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
  11335. $this->_out('Q');
  11336. }
  11337. }
  11338. $this->processingHeader=false;
  11339. }
  11340. ///////////////////
  11341. // HYPHENATION
  11342. ///////////////////
  11343. // mPDF 5.6.21
  11344. // Hard hyphens
  11345. function hardHyphenate($word, $maxWidth) {
  11346. // Don't hyphenate web addresses
  11347. if (preg_match('/^(http:|www\.)/',$word)) { return array(false,'','',''); }
  11348. // Get dictionary
  11349. $poss = array();
  11350. $softhyphens = array();
  11351. $offset = 0;
  11352. $p = true;
  11353. if ($this->usingCoreFont) {
  11354. $wl = strlen($word);
  11355. }
  11356. else {
  11357. $wl = mb_strlen($word,'UTF-8');
  11358. }
  11359. while($offset < $wl) {
  11360. if (!$this->usingCoreFont) {
  11361. $p = mb_strpos($word, "-", $offset, 'UTF-8');
  11362. }
  11363. else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
  11364. $p = strpos($word, "-", $offset);
  11365. }
  11366. if ($p !== false) { $poss[] = $p - count($poss); }
  11367. else { break; }
  11368. $offset = $p+1;
  11369. }
  11370. $success = false;
  11371. foreach($poss AS $i) {
  11372. if ($this->usingCoreFont) {
  11373. $a = substr($word,0,$i);
  11374. if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
  11375. $pre = $a;
  11376. $post = substr($word,$i,strlen($word));
  11377. $prelength = strlen($pre);
  11378. }
  11379. else {
  11380. $a = mb_substr($word,0,$i,'UTF-8');
  11381. if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
  11382. $pre = $a;
  11383. $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8');
  11384. $prelength = mb_strlen($pre, 'UTF-8');
  11385. }
  11386. $success = true;
  11387. }
  11388. return array($success,$pre,$post,$prelength);
  11389. }
  11390. /*-- HYPHENATION --*/
  11391. ///////////////////
  11392. ///////////////////
  11393. // HYPHENATION
  11394. ///////////////////
  11395. // Soft hyphs
  11396. function softHyphenate($word, $maxWidth) {
  11397. // Don't hyphenate web addresses
  11398. if (preg_match('/^(http:|www\.)/',$word)) { return array(false,'','',''); }
  11399. // Get dictionary
  11400. $poss = array();
  11401. $softhyphens = array();
  11402. $offset = 0;
  11403. $p = true;
  11404. if ($this->usingCoreFont) {
  11405. $wl = strlen($word);
  11406. }
  11407. else {
  11408. $wl = mb_strlen($word,'UTF-8');
  11409. }
  11410. while($offset < $wl) {
  11411. // Soft Hyphens chr(173)
  11412. if (!$this->usingCoreFont) {
  11413. $p = mb_strpos($word, "\xc2\xad", $offset, 'UTF-8');
  11414. }
  11415. else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
  11416. $p = strpos($word, chr(173), $offset);
  11417. }
  11418. if ($p !== false) { $poss[] = $p - count($poss); }
  11419. else { break; }
  11420. $offset = $p+1;
  11421. }
  11422. $success = false;
  11423. foreach($poss AS $i) {
  11424. if ($this->usingCoreFont) {
  11425. $a = substr($word,0,$i);
  11426. if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
  11427. $pre = $a;
  11428. $post = substr($word,$i,strlen($word));
  11429. $prelength = strlen($pre);
  11430. }
  11431. else {
  11432. $a = mb_substr($word,0,$i,'UTF-8');
  11433. if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
  11434. $pre = $a;
  11435. $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8');
  11436. $prelength = mb_strlen($pre, 'UTF-8');
  11437. }
  11438. $success = true;
  11439. }
  11440. return array($success,$pre,$post,$prelength);
  11441. }
  11442. ///////////////////
  11443. // Word hyphenation
  11444. function hyphenateWord($word, $maxWidth) {
  11445. // Do everything inside this function in utf-8
  11446. // Don't hyphenate web addresses
  11447. if (preg_match('/^(http:|www\.)/',$word)) { return array(false,'','',''); }
  11448. // Get dictionary
  11449. if (!$this->loadedSHYdictionary) {
  11450. if (file_exists(_MPDF_PATH.'patterns/dictionary.txt')) {
  11451. $this->SHYdictionary = file(_MPDF_PATH.'patterns/dictionary.txt',FILE_SKIP_EMPTY_LINES);
  11452. foreach($this->SHYdictionary as $entry) {
  11453. $entry = trim($entry);
  11454. $poss = array();
  11455. $offset = 0;
  11456. $p = true;
  11457. $wl = mb_strlen($entry ,'UTF-8');
  11458. while($offset < $wl) {
  11459. $p = mb_strpos($entry, '/', $offset, 'UTF-8');
  11460. if ($p !== false) { $poss[] = $p - count($poss); }
  11461. else { break; }
  11462. $offset = $p+1;
  11463. }
  11464. if (count($poss)) { $this->SHYdictionaryWords[str_replace('/', '', mb_strtolower($entry))] = $poss; }
  11465. }
  11466. }
  11467. $this->loadedSHYdictionary = true;
  11468. }
  11469. if (!in_array($this->SHYlang,$this->SHYlanguages)) { return array(false,'','',''); }
  11470. // If no pattern loaded or not the best one
  11471. if (count($this->SHYpatterns) < 1 || ($this->loadedSHYpatterns && $this->loadedSHYpatterns != $this->SHYlang)) {
  11472. include(_MPDF_PATH."patterns/" . $this->SHYlang . ".php");
  11473. $patterns = explode(' ', $patterns);
  11474. $new_patterns = array();
  11475. for($i = 0; $i < count($patterns); $i++) {
  11476. $value = $patterns[$i];
  11477. $new_patterns[preg_replace('/[0-9]/', '', $value)] = $value;
  11478. }
  11479. $this->SHYpatterns = $new_patterns;
  11480. $this->loadedSHYpatterns = $this->SHYlang;
  11481. }
  11482. if ($this->usingCoreFont) { $word = mb_convert_encoding($word,'UTF-8',$this->mb_enc); }
  11483. $prepre = '';
  11484. $postpost = '';
  11485. $startpunctuation = "\xc2\xab\xc2\xbf\xe2\x80\x98\xe2\x80\x9b\xe2\x80\x9c\xe2\x80\x9f";
  11486. $endpunctuation = "\xe2\x80\x9e\xe2\x80\x9d\xe2\x80\x9a\xe2\x80\x99\xc2\xbb";
  11487. $pre = '';
  11488. $post = '';
  11489. if (preg_match('/^(["\''.$startpunctuation .'])+(.{'.$this->SHYcharmin.',})$/u',$word,$m)) {
  11490. $prepre = $m[1];
  11491. $word = $m[2];
  11492. }
  11493. if (preg_match('/^(.{'.$this->SHYcharmin.',})([\'\.,;:!?"'.$endpunctuation .']+)$/u',$word,$m)) {
  11494. $word = $m[1];
  11495. $postpost = $m[2];
  11496. }
  11497. if(mb_strlen($word,'UTF-8') < $this->SHYcharmin) {
  11498. return array(false,'','','');
  11499. }
  11500. $success = false;
  11501. if(isset($this->SHYdictionaryWords[mb_strtolower($word)])) {
  11502. foreach($this->SHYdictionaryWords[mb_strtolower($word)] AS $i) {
  11503. $a = $prepre . mb_substr($word,0,$i,'UTF-8');
  11504. if ($this->usingCoreFont) { $testa = mb_convert_encoding($a,$this->mb_enc,'UTF-8'); }
  11505. else { $testa = $a; }
  11506. if ($this->GetStringWidth($testa.'-') > $maxWidth) { break ; }
  11507. $pre = $a;
  11508. $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8') . $postpost;
  11509. $success = true;
  11510. }
  11511. }
  11512. if (!$success) {
  11513. $text_word = '_' . $word . '_';
  11514. $word_length = mb_strlen($text_word,'UTF-8');
  11515. $single_character = preg_split('//u', $text_word);
  11516. $text_word = mb_strtolower($text_word,'UTF-8');
  11517. $hyphenated_word = array();
  11518. $numb3rs = array('0' => true, '1' => true, '2' => true, '3' => true, '4' => true, '5' => true, '6' => true, '7' => true, '8' => true, '9' => true);
  11519. for($position = 0; $position <= ($word_length - $this->SHYcharmin); $position++) {
  11520. $maxwins = min(($word_length - $position), $this->SHYcharmax);
  11521. for($win = $this->SHYcharmin; $win <= $maxwins; $win++) {
  11522. if(isset($this->SHYpatterns[mb_substr($text_word, $position, $win,'UTF-8')])) {
  11523. $pattern = $this->SHYpatterns[mb_substr($text_word, $position, $win,'UTF-8')];
  11524. $digits = 1;
  11525. $pattern_length = mb_strlen($pattern,'UTF-8');
  11526. for($i = 0; $i < $pattern_length; $i++) {
  11527. $char = $pattern[$i];
  11528. if(isset($numb3rs[$char])) {
  11529. $zero = ($i == 0) ? $position - 1 : $position + $i - $digits;
  11530. if(!isset($hyphenated_word[$zero]) || $hyphenated_word[$zero] != $char) $hyphenated_word[$zero] = $char;
  11531. $digits++;
  11532. }
  11533. }
  11534. }
  11535. }
  11536. }
  11537. for($i = $this->SHYleftmin; $i <= (mb_strlen($word,'UTF-8') - $this->SHYrightmin); $i++) {
  11538. if(isset($hyphenated_word[$i]) && $hyphenated_word[$i] % 2 != 0) {
  11539. $a = $prepre . mb_substr($word,0,$i,'UTF-8');
  11540. if ($this->usingCoreFont) { $testa = mb_convert_encoding($a,$this->mb_enc,'UTF-8'); }
  11541. else { $testa = $a; }
  11542. if ($this->GetStringWidth($testa.'-') > $maxWidth + 0.0001) { break ; }
  11543. $pre = $a;
  11544. $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8') . $postpost;
  11545. $success = true;
  11546. }
  11547. }
  11548. }
  11549. if ($this->usingCoreFont) {
  11550. $pre = mb_convert_encoding($pre,$this->mb_enc,'UTF-8');
  11551. $post = mb_convert_encoding($post,$this->mb_enc,'UTF-8');
  11552. $prelength = strlen($pre);
  11553. }
  11554. else {
  11555. $prelength = mb_strlen($pre);
  11556. }
  11557. return array($success,$pre,$post,$prelength);
  11558. }
  11559. /*-- END HYPHENATION --*/
  11560. /*-- HTML-CSS --*/
  11561. ///////////////////
  11562. /// HTML parser ///
  11563. ///////////////////
  11564. function WriteHTML($html,$sub=0,$init=true,$close=true) {
  11565. // $sub ADDED - 0 = default; 1=headerCSS only; 2=HTML body (parts) only; 3 - HTML parses only
  11566. // 4 - writes HTML headers
  11567. // $close Leaves buffers etc. in current state, so that it can continue a block etc.
  11568. // $init - Clears and sets buffers to Top level block etc.
  11569. if (empty($html)) { $html = ''; }
  11570. if ($this->progressBar) { $this->UpdateProgressBar(1,0,'Parsing CSS & Headers'); } // *PROGRESS-BAR*
  11571. if ($init) {
  11572. $this->headerbuffer='';
  11573. $this->textbuffer = array();
  11574. $this->fixedPosBlockSave = array();
  11575. }
  11576. if ($sub == 1) { $html = '<style> '.$html.' </style>'; } // stylesheet only
  11577. if ($this->allow_charset_conversion) {
  11578. if ($sub < 1) {
  11579. $this->ReadCharset($html);
  11580. }
  11581. if ($this->charset_in && $sub!=4) { // mPDF 5.4.14
  11582. $success = iconv($this->charset_in,'UTF-8//TRANSLIT',$html);
  11583. if ($success) { $html = $success; }
  11584. }
  11585. }
  11586. $html = $this->purify_utf8($html,false);
  11587. if ($init) {
  11588. $this->blklvl = 0;
  11589. $this->lastblocklevelchange = 0;
  11590. $this->blk = array();
  11591. $this->initialiseBlock($this->blk[0]);
  11592. $this->blk[0]['width'] =& $this->pgwidth;
  11593. $this->blk[0]['inner_width'] =& $this->pgwidth;
  11594. $this->blk[0]['blockContext'] = $this->blockContext;
  11595. }
  11596. $zproperties = array();
  11597. if ($sub < 2) {
  11598. $this->ReadMetaTags($html);
  11599. // mPDF 5.6.18
  11600. if (preg_match('/<base[^>]*href=["\']([^"\'>]*)["\']/i', $html, $m)) {
  11601. $this->SetBasePath($m[1]);
  11602. }
  11603. // NB default stylesheet now in mPDF.css - read on initialising class
  11604. $html = $this->cssmgr->ReadCSS($html);
  11605. if ($this->useLang && !$this->usingCoreFont && preg_match('/<html [^>]*lang=[\'\"](.*?)[\'\"]/ism',$html,$m)) {
  11606. $html_lang = $m[1];
  11607. }
  11608. if (preg_match('/<html [^>]*dir=[\'\"]\s*rtl\s*[\'\"]/ism',$html)) {
  11609. $zproperties['DIRECTION'] = 'rtl';
  11610. }
  11611. // allow in-line CSS for body tag to be parsed // Get <body> tag inline CSS
  11612. if (preg_match('/<body([^>]*)>(.*?)<\/body>/ism',$html,$m) || preg_match('/<body([^>]*)>(.*)$/ism',$html,$m)) {
  11613. $html = $m[2];
  11614. // Changed to allow style="background: url('bg.jpg')"
  11615. if (preg_match('/style=[\"](.*?)[\"]/ism',$m[1],$mm) || preg_match('/style=[\'](.*?)[\']/ism',$m[1],$mm)) {
  11616. $zproperties = $this->cssmgr->readInlineCSS($mm[1]);
  11617. }
  11618. if (preg_match('/dir=[\'\"]\s*rtl\s*[\'\"]/ism',$m[1])) {
  11619. $zproperties['DIRECTION'] = 'rtl';
  11620. }
  11621. if (isset($html_lang) && $html_lang) { $zproperties['LANG'] = $html_lang; }
  11622. if ($this->useLang && !$this->onlyCoreFonts && preg_match('/lang=[\'\"](.*?)[\'\"]/ism',$m[1],$mm)) {
  11623. $zproperties['LANG'] = $mm[1];
  11624. }
  11625. }
  11626. }
  11627. $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
  11628. if ($zproperties) { $properties = $this->cssmgr->array_merge_recursive_unique($properties,$zproperties); }
  11629. if (isset($properties['DIRECTION']) && $properties['DIRECTION']) {
  11630. $this->cssmgr->CSS['BODY']['DIRECTION'] = $properties['DIRECTION'];
  11631. }
  11632. if (!isset($this->cssmgr->CSS['BODY']['DIRECTION'])) {
  11633. $this->cssmgr->CSS['BODY']['DIRECTION'] = $this->directionality;
  11634. }
  11635. else { $this->SetDirectionality($this->cssmgr->CSS['BODY']['DIRECTION']); }
  11636. $this->setCSS($properties,'','BODY');
  11637. $this->blk[0]['InlineProperties'] = $this->saveInlineProperties();
  11638. if ($sub == 1) { return ''; }
  11639. if (!isset($this->cssmgr->CSS['BODY'])) { $this->cssmgr->CSS['BODY'] = array(); }
  11640. /*-- BACKGROUNDS --*/
  11641. if (isset($properties['BACKGROUND-GRADIENT'])) {
  11642. $this->bodyBackgroundGradient = $properties['BACKGROUND-GRADIENT'];
  11643. }
  11644. if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE']) {
  11645. $ret = $this->SetBackground($properties, $this->pgwidth);
  11646. if ($ret) { $this->bodyBackgroundImage = $ret; }
  11647. }
  11648. /*-- END BACKGROUNDS --*/
  11649. /*-- CSS-PAGE --*/
  11650. // If page-box is set
  11651. if ($this->state==0 && isset($this->cssmgr->CSS['@PAGE']) && $this->cssmgr->CSS['@PAGE'] ) {
  11652. $this->page_box['current'] = '';
  11653. $this->page_box['using'] = true;
  11654. list($pborientation,$pbmgl,$pbmgr,$pbmgt,$pbmgb,$pbmgh,$pbmgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS('', false, 'O');
  11655. $this->DefOrientation = $this->CurOrientation = $pborientation;
  11656. $this->orig_lMargin = $this->DeflMargin = $pbmgl;
  11657. $this->orig_rMargin = $this->DefrMargin = $pbmgr;
  11658. $this->orig_tMargin = $this->tMargin = $pbmgt;
  11659. $this->orig_bMargin = $this->bMargin = $pbmgb;
  11660. $this->orig_hMargin = $this->margin_header = $pbmgh;
  11661. $this->orig_fMargin = $this->margin_footer = $pbmgf;
  11662. list($pborientation,$pbmgl,$pbmgr,$pbmgt,$pbmgb,$pbmgh,$pbmgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS('', true, 'O'); // first page
  11663. $this->show_marks = $marks;
  11664. if ($hname && !preg_match('/^html_(.*)$/i',$hname)) $this->firstPageBoxHeader = $hname;
  11665. if ($fname && !preg_match('/^html_(.*)$/i',$fname)) $this->firstPageBoxFooter = $fname;
  11666. }
  11667. /*-- END CSS-PAGE --*/
  11668. $parseonly = false;
  11669. $this->bufferoutput = false;
  11670. if ($sub == 3) {
  11671. $parseonly = true;
  11672. // Close any open block tags
  11673. for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
  11674. // Output any text left in buffer
  11675. if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); }
  11676. $this->textbuffer=array();
  11677. }
  11678. else if ($sub == 4) {
  11679. // Close any open block tags
  11680. for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
  11681. // Output any text left in buffer
  11682. if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); }
  11683. $this->bufferoutput = true;
  11684. $this->textbuffer=array();
  11685. $this->headerbuffer='';
  11686. $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
  11687. $this->setCSS($properties,'','BODY');
  11688. }
  11689. mb_internal_encoding('UTF-8');
  11690. $html = $this->AdjustHTML($html, $this->tabSpaces); //Try to make HTML look more like XHTML
  11691. if ($this->autoFontGroups) { $html = $this->AutoFont($html); }
  11692. /*-- HTMLHEADERS-FOOTERS --*/
  11693. preg_match_all('/<htmlpageheader([^>]*)>(.*?)<\/htmlpageheader>/si',$html,$h);
  11694. for($i=0;$i<count($h[1]);$i++) {
  11695. if (preg_match('/name=[\'|\"](.*?)[\'|\"]/',$h[1][$i],$n)) {
  11696. $this->pageHTMLheaders[$n[1]]['html'] = $h[2][$i];
  11697. $this->pageHTMLheaders[$n[1]]['h'] = $this->_gethtmlheight($h[2][$i]);
  11698. }
  11699. }
  11700. preg_match_all('/<htmlpagefooter([^>]*)>(.*?)<\/htmlpagefooter>/si',$html,$f);
  11701. for($i=0;$i<count($f[1]);$i++) {
  11702. if (preg_match('/name=[\'|\"](.*?)[\'|\"]/',$f[1][$i],$n)) {
  11703. $this->pageHTMLfooters[$n[1]]['html'] = $f[2][$i];
  11704. $this->pageHTMLfooters[$n[1]]['h'] = $this->_gethtmlheight($f[2][$i]);
  11705. }
  11706. }
  11707. /*-- END HTMLHEADERS-FOOTERS --*/
  11708. $html = preg_replace('/<htmlpageheader.*?<\/htmlpageheader>/si','',$html);
  11709. $html = preg_replace('/<htmlpagefooter.*?<\/htmlpagefooter>/si','',$html);
  11710. if($this->state==0 && $sub!=1 && $sub!=3 && $sub!=4) {
  11711. $this->AddPage($this->CurOrientation);
  11712. }
  11713. /*-- HTMLHEADERS-FOOTERS --*/
  11714. if (isset($hname) && preg_match('/^html_(.*)$/i',$hname,$n)) $this->SetHTMLHeader($this->pageHTMLheaders[$n[1]],'O',true);
  11715. if (isset($fname) && preg_match('/^html_(.*)$/i',$fname,$n)) $this->SetHTMLFooter($this->pageHTMLfooters[$n[1]],'O');
  11716. /*-- END HTMLHEADERS-FOOTERS --*/
  11717. $html=str_replace('<?','< ',$html); //Fix '<?XML' bug from HTML code generated by MS Word
  11718. $this->checkSIP = false;
  11719. $this->checkSMP = false;
  11720. $this->checkCJK = false;
  11721. if ($this->onlyCoreFonts) { $html = $this->SubstituteChars($html); }
  11722. else {
  11723. if (preg_match("/([".$this->pregRTLchars."])/u", $html)) { $this->biDirectional = true; } // *RTL*
  11724. if (preg_match("/([\x{20000}-\x{2FFFF}])/u", $html)) { $this->checkSIP = true; }
  11725. if (preg_match("/([\x{10000}-\x{1FFFF}])/u", $html)) { $this->checkSMP = true; }
  11726. /*-- CJK-FONTS --*/
  11727. if (preg_match("/([".$this->pregCJKchars."])/u", $html)) { $this->checkCJK = true; }
  11728. /*-- END CJK-FONTS --*/
  11729. }
  11730. // Don't allow non-breaking spaces that are converted to substituted chars or will break anyway and mess up table width calc.
  11731. $html = str_replace('<tta>160</tta>',chr(32),$html);
  11732. $html = str_replace('</tta><tta>','|',$html);
  11733. $html = str_replace('</tts><tts>','|',$html);
  11734. $html = str_replace('</ttz><ttz>','|',$html);
  11735. //Add new supported tags in the DisableTags function
  11736. $html=strip_tags($html,$this->enabledtags); //remove all unsupported tags, but the ones inside the 'enabledtags' string
  11737. //Explode the string in order to parse the HTML code
  11738. $a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
  11739. // ? more accurate regexp that allows e.g. <a name="Silly <name>">
  11740. // if changing - also change in fn.SubstituteChars()
  11741. // $a = preg_split ('/<((?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+)>/ms', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
  11742. if ($this->mb_enc) {
  11743. mb_internal_encoding($this->mb_enc);
  11744. }
  11745. $pbc = 0;
  11746. if ($this->progressBar) { $this->UpdateProgressBar(1,0); } // *PROGRESS-BAR*
  11747. $this->subPos = -1;
  11748. $cnt = count($a);
  11749. for($i=0;$i<$cnt; $i++) {
  11750. $e = $a[$i];
  11751. if($i%2==0) {
  11752. //TEXT
  11753. if ($this->blk[$this->blklvl]['hide']) { continue; }
  11754. if ($this->inlineDisplayOff) { continue; }
  11755. if ($this->inMeter) { continue; } // mPDF 5.5.09
  11756. if ($this->inFixedPosBlock) { $this->fixedPosBlock .= $e; continue; } // *CSS-POSITION*
  11757. if (strlen($e) == 0) { continue; }
  11758. $e = strcode2utf($e);
  11759. $e = $this->lesser_entity_decode($e);
  11760. if ($this->usingCoreFont) {
  11761. // If core font is selected in document which is not onlyCoreFonts - substitute with non-core font
  11762. if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->subPos<$i && !$this->specialcontent) {
  11763. $cnt += $this->SubstituteCharsNonCore($a, $i, $e);
  11764. }
  11765. // CONVERT ENCODING
  11766. $e = mb_convert_encoding($e,$this->mb_enc,'UTF-8');
  11767. // mPDF 5.6.41
  11768. if ($this->toupper) { $e = mb_strtoupper($e,$this->mb_enc); }
  11769. if ($this->tolower) { $e = mb_strtolower($e,$this->mb_enc); }
  11770. if ($this->capitalize) { $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); }
  11771. }
  11772. else {
  11773. if ($this->checkSIP && $this->CurrentFont['sipext'] && $this->subPos<$i && !$this->specialcontent) {
  11774. $cnt += $this->SubstituteCharsSIP($a, $i, $e);
  11775. }
  11776. if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->CurrentFont['type']!='Type0' && $this->subPos<$i && !$this->specialcontent) {
  11777. // mPDF 5.6.62 removes U+200E/U+200F LTR and RTL mark and U+200C/U+200D Zero-width Joiner and Non-joiner
  11778. $e = preg_replace("/[\xe2\x80\x8c\xe2\x80\x8d\xe2\x80\x8e\xe2\x80\x8f]/u",'',$e);
  11779. $cnt += $this->SubstituteCharsMB($a, $i, $e);
  11780. }
  11781. if ($this->biDirectional) { // *RTL*
  11782. $e = preg_replace("/([".$this->pregRTLchars."]+)/ue", '$this->ArabJoin(stripslashes(\'\\1\'))', $e); // *RTL*
  11783. } // *RTL*
  11784. // Font-specific ligature substitution for Indic fonts
  11785. if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($e); // *INDIC*
  11786. // mPDF 5.6.62 removes U+200E/U+200F LTR and RTL mark and U+200C/U+200D Zero-width Joiner and Non-joiner
  11787. $e = preg_replace("/[\xe2\x80\x8c\xe2\x80\x8d\xe2\x80\x8e\xe2\x80\x8f]/u",'',$e);
  11788. if ($this->toupper) { $e = mb_strtoupper($e,$this->mb_enc); }
  11789. if ($this->tolower) { $e = mb_strtolower($e,$this->mb_enc); }
  11790. if ($this->capitalize) { $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); }
  11791. }
  11792. if (($this->tts) || ($this->ttz) || ($this->tta)) {
  11793. $es = explode('|',$e);
  11794. $e = '';
  11795. foreach($es AS $val) {
  11796. $e .= chr($val);
  11797. }
  11798. }
  11799. //Adjust lineheight
  11800. // FORM ELEMENTS
  11801. if ($this->specialcontent) {
  11802. /*-- FORMS --*/
  11803. //SELECT tag (form element)
  11804. if ($this->specialcontent == "type=select") {
  11805. $e = ltrim($e);
  11806. $stringwidth = $this->GetStringWidth($e);
  11807. if (!isset($this->selectoption['MAXWIDTH']) || $stringwidth > $this->selectoption['MAXWIDTH']) { $this->selectoption['MAXWIDTH'] = $stringwidth; }
  11808. if (!isset($this->selectoption['SELECTED']) || $this->selectoption['SELECTED'] == '') { $this->selectoption['SELECTED'] = $e; }
  11809. // mPDD 1.4 Active Forms
  11810. if (isset($this->selectoption['ACTIVE']) && $this->selectoption['ACTIVE']) {
  11811. $this->selectoption['ITEMS'][]=array('exportValue'=>$this->selectoption['currentVAL'], 'content'=>$e, 'selected'=>$this->selectoption['currentSEL']);
  11812. }
  11813. }
  11814. // TEXTAREA
  11815. else {
  11816. $objattr = unserialize($this->specialcontent);
  11817. $objattr['text'] = $e;
  11818. $te = "\xbb\xa4\xactype=textarea,objattr=".serialize($objattr)."\xbb\xa4\xac";
  11819. if ($this->tdbegin) {
  11820. $this->_saveCellTextBuffe